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
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