Turn the depth-first traversal into a pass to discover the graph's basic
block structure. Record basic-block predecessors in the block entry
instructions. Also record the last instruction in a block in the block
entry instruction (giving constant-time access to the block's successors).
Also, record the depth-first spanning tree of the traversal to be used for
dominator computation.
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9730003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5655 260f80e4-7a28-3924-810f-c04153c831b5
The Lengauer-Tarjan dominator/dominance frontier algorithm needs to
visit the blocks in reverse preorder (in the first pass) and preorder
(in the second). Compute that at the same time as postorder (e.g.,
using the same spanning tree).
Take this chance to make the flow graph visitors always operate on a
forward block ordering.
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9719003
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5598 260f80e4-7a28-3924-810f-c04153c831b5
and the constructor case, as suggested in my review of
https://chromiumcodereview.appspot.com/9700003/
Examples of generated IL (first factory, second non-factory).
foo() { return new List<T>(); }
moo() { return new A<T>(); }
==== file:///home/regis/test.dart_A_foo
0: [target]
t0 <- LoadLocal(this)
t0 <- NativeLoadField(t0, 16)
t0 <- ExtractFactoryTypeArguments(t0)
t0 <- StaticCall(List., t0)
return t0
==== file:///home/regis/test.dart_A_moo
0: [target]
t0 <- #null
t1 <- LoadLocal(this)
t1 <- NativeLoadField(t1, 16)
t2 <- Pick(t1)
t2 <- ExtractConstructorTypeArguments(t2)
t0 := t2
t1 <- ExtractConstructorInstantiator(t1, t2)
t0 <- AllocateObject(Library:'file:///home/regis/test.dart' Class: A, t0, t1)
t1 <- Pick(t0)
t2 <- #3
StaticCall(A., t1, t2)
return t0
This change removes the computation that previously returned two values at the
cost of a some small code duplication. We could address this duplication by
exposing the computation recognizing the identity vector at the IL level and
implement a branch.
Review URL: https://chromiumcodereview.appspot.com//9703080
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5537 260f80e4-7a28-3924-810f-c04153c831b5
Chosen because of its wartiness. A pair of new computations are introduced
to allow the IL to express duplication of temporaries and storing to
temporaries. These will be translated away by the optimizing compiler, but
allow the instruction stream to represent exactly the deoptimization state
we are intereseted in (with at most one deopt point per instruction).
Translation of:
test(a, i) {
return a[i]++;
}
is
0: [target]
t0 <-#0
t1 <-LoadLocal(a)
t2 <-LoadLocal(i)
t3 <-CopyTemp(-1)
t4 <-CopyTemp(-1)
t3 <-InstanceCall([], t3, t4)
SetTemp(-3)
t4 <-#1
t3 <-InstanceCall(+, t3, t4)
InstanceCall([]=, t1, t2, t3)
return t0
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9601011
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@5012 260f80e4-7a28-3924-810f-c04153c831b5
These can be supported as instance calls. In the case of instance
setters and indexed stores, there is a new computation type because of
the semantics of preserving the value. For the example program:
void test(e) {
print(e.forty_two);
print(e.forty_two = 41);
}
we generate the graph:
0: [target]
t0 <-LoadLocal(e)
t0 <-InstanceCall(get:forty_two, t0)
StaticCall(print, t0)
t0 <-#0
t1 <-LoadLocal(e)
t2 <-#41
t0 <-InstanceSetter(t0, t1, t2)
StaticCall(print, t0)
return #null
and emit the correct code.
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9570015
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4861 260f80e4-7a28-3924-810f-c04153c831b5
Implement a simple compilation visitor for the intermediate language. Copy
code from the x64 code generator to support compilation of functions with no
arguments, no locals, and that return a literal.
Compiled code is not used, but it can be disassembled and visually checked
against the code from the old code generator.
R=srdjan@google.com
BUG=
TEST=expected to pass all tests on x64
Review URL: https://chromiumcodereview.appspot.com//9464009
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4601 260f80e4-7a28-3924-810f-c04153c831b5
This keeps the IL simple for the benefit of the optimizing compiler.
It intentionally relies on a particular temporary allocation strategy
for the non-optimizing compiler.
For the dart function
main() {
var x = 2;
hukairs(1, x, 3);
}
The flow graph is:
0: [target]
StoreLocal(x, #2)
t0 <-#1
t1 <-LoadLocal(x)
t2 <-#3
StaticCall(hukairs, t0, t1, t2)
return #null
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9463007
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4600 260f80e4-7a28-3924-810f-c04153c831b5
Also, instead of keeping a list of all instructions, keep a list of only
block entries. The printing implementation is changed (for the better) to
use the new representation. With --use_new_compiler and --print_flow_graph
the function:
main() {
var f = 1;
var n = 5;
while (n > 0) {
f = f * n;
n = n - 1;
}
print(f);
}
prints as:
0: [target]
StoreLocal(f, #1)
StoreLocal(n, #5) goto 1
1: [join]
t0 <-LoadLocal(n)
t0 <-InstanceCall(>, t0, #0)
if t0 goto(2, 3)
2: [target]
t0 <-LoadLocal(f)
t1 <-LoadLocal(n)
t0 <-InstanceCall(*, t0, t1)
StoreLocal(f, t0)
t0 <-LoadLocal(n)
t0 <-InstanceCall(-, t0, #1)
StoreLocal(n, t0) goto 1
3: [target]
t0 <-LoadLocal(f)
StaticCall(print, t0)
return #null
R=srdjan@google.com
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com//9429056
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4515 260f80e4-7a28-3924-810f-c04153c831b5