Refactor the cfg and dominance stuff to make it a lot nicer.
This commit is contained in:
parent
7f901aa4d0
commit
ee93389c5f
|
@ -1,123 +0,0 @@
|
||||||
#include "mcg.h"
|
|
||||||
|
|
||||||
struct array postorder;
|
|
||||||
struct array preorder;
|
|
||||||
struct pmap dominators;
|
|
||||||
|
|
||||||
static void recursively_walk_blocks(struct basicblock* bb);
|
|
||||||
|
|
||||||
static void recursively_walk_graph(struct basicblock* bb)
|
|
||||||
{
|
|
||||||
static ARRAYOF(struct basicblock) pending;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (array_contains(&postorder, bb) || array_contains(&pending, bb))
|
|
||||||
return;
|
|
||||||
|
|
||||||
array_appendu(&preorder, bb);
|
|
||||||
array_appendu(&pending, bb);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
for (i=0; i<bb->nexts.count; i++)
|
|
||||||
recursively_walk_graph(bb->nexts.item[i]);
|
|
||||||
|
|
||||||
array_remove(&pending, bb);
|
|
||||||
bb->order = postorder.count;
|
|
||||||
array_appendu(&postorder, bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void walk_graph_postorder(struct basicblock* entry)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
preorder.count = 0;
|
|
||||||
postorder.count = 0;
|
|
||||||
recursively_walk_graph(entry);
|
|
||||||
|
|
||||||
for (i=0; i<postorder.count; i++)
|
|
||||||
{
|
|
||||||
tracef('D', "D: postorder: %s\n",
|
|
||||||
((struct basicblock*)postorder.item[i])->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct basicblock* intersect(struct basicblock* p1, struct basicblock* p2)
|
|
||||||
{
|
|
||||||
while (p1 != p2)
|
|
||||||
{
|
|
||||||
while (p1->order < p2->order)
|
|
||||||
p1 = pmap_get(&dominators, p1);
|
|
||||||
|
|
||||||
while (p2->order < p1->order)
|
|
||||||
p2 = pmap_get(&dominators, p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return p1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void calculate_dominance_graph(struct procedure* proc)
|
|
||||||
{
|
|
||||||
/* This is the algorithm described here:
|
|
||||||
*
|
|
||||||
* Cooper, Keith D., Timothy J. Harvey, and Ken Kennedy.
|
|
||||||
* "A simple, fast dominance algorithm."
|
|
||||||
* Software Practice & Experience 4.1-10 (2001): 1-8.
|
|
||||||
*
|
|
||||||
* https://www.cs.rice.edu/~keith/EMBED/dom.pdf
|
|
||||||
*/
|
|
||||||
|
|
||||||
int i, j;
|
|
||||||
bool changed;
|
|
||||||
struct basicblock* entry = proc->blocks.item[0];
|
|
||||||
|
|
||||||
entry = proc->blocks.item[0];
|
|
||||||
walk_graph_postorder(entry);
|
|
||||||
assert(postorder.count == proc->blocks.count);
|
|
||||||
|
|
||||||
dominators.count = 0;
|
|
||||||
|
|
||||||
/* The entry block dominates itself. */
|
|
||||||
|
|
||||||
pmap_put(&dominators, entry, entry);
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
changed = false;
|
|
||||||
|
|
||||||
for (i = postorder.count-2; i >= 0; i--)
|
|
||||||
{
|
|
||||||
struct basicblock* b = postorder.item[i];
|
|
||||||
struct basicblock* new_idom = NULL;
|
|
||||||
for (j=0; j<b->prevs.count; j++)
|
|
||||||
{
|
|
||||||
struct basicblock* p = b->prevs.item[j];
|
|
||||||
|
|
||||||
/* Skip unprocessed blocks. */
|
|
||||||
if (!pmap_get(&dominators, p))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!new_idom)
|
|
||||||
new_idom = p;
|
|
||||||
else if (pmap_get(&dominators, p))
|
|
||||||
new_idom = intersect(p, new_idom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pmap_get(&dominators, b) != new_idom)
|
|
||||||
{
|
|
||||||
pmap_put(&dominators, b, new_idom);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (changed);
|
|
||||||
|
|
||||||
for (i=0; i<dominators.count; i++)
|
|
||||||
{
|
|
||||||
tracef('D', "D: domination: %s -> %s\n",
|
|
||||||
((struct basicblock*)dominators.item[i].left)->name,
|
|
||||||
((struct basicblock*)dominators.item[i].right)->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
#ifndef DOMINANCE_H
|
|
||||||
#define DOMINANCE_H
|
|
||||||
|
|
||||||
extern struct array postorder;
|
|
||||||
extern struct array preorder;
|
|
||||||
extern struct pmap dominators;
|
|
||||||
|
|
||||||
extern void calculate_dominance_graph(struct procedure* proc);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
|
||||||
|
|
208
mach/proto/mcg/graph.c
Normal file
208
mach/proto/mcg/graph.c
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
#include "mcg.h"
|
||||||
|
|
||||||
|
struct graph_data cfg;
|
||||||
|
struct dominance_data dominance;
|
||||||
|
|
||||||
|
static ARRAYOF(struct basicblock) pending;
|
||||||
|
|
||||||
|
static bool collect_outputs_cb(struct ir* ir, void* user)
|
||||||
|
{
|
||||||
|
struct basicblock* caller = user;
|
||||||
|
|
||||||
|
if (ir->opcode == IR_BLOCK)
|
||||||
|
{
|
||||||
|
array_appendu(&caller->nexts, ir->u.bvalue);
|
||||||
|
array_appendu(&ir->u.bvalue->prevs, caller);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_block_pointers_from_ir(struct procedure* proc)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i=0; i<proc->blocks.count; i++)
|
||||||
|
{
|
||||||
|
struct basicblock* bb = proc->blocks.item[i];
|
||||||
|
bb->prevs.count = bb->nexts.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<proc->blocks.count; i++)
|
||||||
|
{
|
||||||
|
struct basicblock* bb = proc->blocks.item[i];
|
||||||
|
for (j=0; j<bb->irs.count; j++)
|
||||||
|
ir_walk(bb->irs.item[j], collect_outputs_cb, bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<proc->blocks.count; i++)
|
||||||
|
{
|
||||||
|
struct basicblock* bb = proc->blocks.item[i];
|
||||||
|
|
||||||
|
for (j=0; j<bb->nexts.count; j++)
|
||||||
|
{
|
||||||
|
tracef('D', "D: cfg graph %s -> %s\n",
|
||||||
|
bb->name,
|
||||||
|
bb->nexts.item[j]->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recursively_walk_cfg_graph(struct basicblock* bb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (array_contains(&cfg.postorder, bb) || array_contains(&pending, bb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
array_appendu(&cfg.preorder, bb);
|
||||||
|
array_appendu(&pending, bb);
|
||||||
|
|
||||||
|
for (i=0; i<bb->nexts.count; i++)
|
||||||
|
recursively_walk_cfg_graph(bb->nexts.item[i]);
|
||||||
|
|
||||||
|
array_remove(&pending, bb);
|
||||||
|
bb->order = cfg.postorder.count;
|
||||||
|
array_appendu(&cfg.postorder, bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void walk_cfg_graph(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cfg.preorder.count = 0;
|
||||||
|
cfg.postorder.count = 0;
|
||||||
|
pending.count = 0;
|
||||||
|
recursively_walk_cfg_graph(cfg.entry);
|
||||||
|
|
||||||
|
for (i=0; i<cfg.preorder.count; i++)
|
||||||
|
{
|
||||||
|
tracef('G', "G: cfg preorder: %s\n",
|
||||||
|
cfg.preorder.item[i]->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct basicblock* intersect(struct basicblock* p1, struct basicblock* p2)
|
||||||
|
{
|
||||||
|
while (p1 != p2)
|
||||||
|
{
|
||||||
|
while (p1->order < p2->order)
|
||||||
|
p1 = pmap_get(&dominance.graph, p1);
|
||||||
|
|
||||||
|
while (p2->order < p1->order)
|
||||||
|
p2 = pmap_get(&dominance.graph, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void calculate_dominance_graph(void)
|
||||||
|
{
|
||||||
|
/* This is the algorithm described here:
|
||||||
|
*
|
||||||
|
* Cooper, Keith D., Timothy J. Harvey, and Ken Kennedy.
|
||||||
|
* "A simple, fast dominance algorithm."
|
||||||
|
* Software Practice & Experience 4.1-10 (2001): 1-8.
|
||||||
|
*
|
||||||
|
* https://www.cs.rice.edu/~keith/EMBED/dom.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
|
dominance.graph.count = 0;
|
||||||
|
|
||||||
|
/* The entry block dominates itself. */
|
||||||
|
|
||||||
|
pmap_put(&dominance.graph, cfg.entry, cfg.entry);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
for (i = cfg.postorder.count-2; i >= 0; i--)
|
||||||
|
{
|
||||||
|
struct basicblock* b = cfg.postorder.item[i];
|
||||||
|
struct basicblock* new_idom = NULL;
|
||||||
|
for (j=0; j<b->prevs.count; j++)
|
||||||
|
{
|
||||||
|
struct basicblock* p = b->prevs.item[j];
|
||||||
|
|
||||||
|
/* Skip unprocessed blocks. */
|
||||||
|
if (!pmap_get(&dominance.graph, p))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!new_idom)
|
||||||
|
new_idom = p;
|
||||||
|
else if (pmap_get(&dominance.graph, p))
|
||||||
|
new_idom = intersect(p, new_idom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pmap_get(&dominance.graph, b) != new_idom)
|
||||||
|
{
|
||||||
|
pmap_put(&dominance.graph, b, new_idom);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (changed);
|
||||||
|
|
||||||
|
for (i=0; i<dominance.graph.count; i++)
|
||||||
|
{
|
||||||
|
tracef('G', "G: dominance graph: %s -> %s\n",
|
||||||
|
dominance.graph.item[i].right->name,
|
||||||
|
dominance.graph.item[i].left->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recursively_walk_dominance_graph(struct basicblock* bb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (array_contains(&dominance.postorder, bb) || array_contains(&pending, bb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
array_appendu(&dominance.preorder, bb);
|
||||||
|
array_appendu(&pending, bb);
|
||||||
|
|
||||||
|
for (i=0; i<dominance.graph.count; i++)
|
||||||
|
if (dominance.graph.item[i].right == bb)
|
||||||
|
recursively_walk_dominance_graph(dominance.graph.item[i].left);
|
||||||
|
|
||||||
|
array_remove(&pending, bb);
|
||||||
|
array_appendu(&dominance.postorder, bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void walk_dominance_graph(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dominance.preorder.count = 0;
|
||||||
|
dominance.postorder.count = 0;
|
||||||
|
pending.count = 0;
|
||||||
|
recursively_walk_dominance_graph(cfg.entry);
|
||||||
|
|
||||||
|
for (i=0; i<dominance.preorder.count; i++)
|
||||||
|
{
|
||||||
|
tracef('G', "G: dominance preorder: %s\n",
|
||||||
|
dominance.preorder.item[i]->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_graph_data(struct procedure* proc)
|
||||||
|
{
|
||||||
|
cfg.entry = proc->blocks.item[0];
|
||||||
|
update_block_pointers_from_ir(proc);
|
||||||
|
|
||||||
|
walk_cfg_graph();
|
||||||
|
assert(cfg.postorder.count == proc->blocks.count);
|
||||||
|
assert(cfg.preorder.count == proc->blocks.count);
|
||||||
|
|
||||||
|
calculate_dominance_graph();
|
||||||
|
|
||||||
|
walk_dominance_graph();
|
||||||
|
assert(dominance.postorder.count == dominance.graph.count);
|
||||||
|
assert(dominance.preorder.count == dominance.graph.count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
26
mach/proto/mcg/graph.h
Normal file
26
mach/proto/mcg/graph.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef GRAPH_H
|
||||||
|
#define GRAPH_H
|
||||||
|
|
||||||
|
struct graph_data
|
||||||
|
{
|
||||||
|
struct basicblock* entry;
|
||||||
|
ARRAYOF(struct basicblock) preorder;
|
||||||
|
ARRAYOF(struct basicblock) postorder;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dominance_data
|
||||||
|
{
|
||||||
|
PMAPOF(struct basicblock, struct basicblock) graph;
|
||||||
|
ARRAYOF(struct basicblock) preorder;
|
||||||
|
ARRAYOF(struct basicblock) postorder;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct graph_data cfg;
|
||||||
|
extern struct dominance_data dominance;
|
||||||
|
|
||||||
|
extern void update_graph_data(struct procedure* proc);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
#include "basicblock.h"
|
#include "basicblock.h"
|
||||||
#include "procedure.h"
|
#include "procedure.h"
|
||||||
#include "dominance.h"
|
#include "graph.h"
|
||||||
|
|
||||||
extern char em_pseu[][4];
|
extern char em_pseu[][4];
|
||||||
extern char em_mnem[][4];
|
extern char em_mnem[][4];
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
static PMAPOF(struct basicblock, struct basicblock) graph;
|
|
||||||
static ARRAYOF(struct ir) pops;
|
static ARRAYOF(struct ir) pops;
|
||||||
static ARRAYOF(struct ir) pushes;
|
static ARRAYOF(struct ir) pushes;
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,10 @@ static void recursively_walk_dominance_graph(struct basicblock* bb)
|
||||||
|
|
||||||
/* Skip the entry block (which is its own dominator). */
|
/* Skip the entry block (which is its own dominator). */
|
||||||
|
|
||||||
for (i=1; i<dominators.count; i++)
|
for (i=1; i<dominance.graph.count; i++)
|
||||||
{
|
{
|
||||||
struct basicblock* left = dominators.item[i].left;
|
struct basicblock* left = dominance.graph.item[i].left;
|
||||||
struct basicblock* right = dominators.item[i].right;
|
struct basicblock* right = dominance.graph.item[i].right;
|
||||||
if (right == bb)
|
if (right == bb)
|
||||||
recursively_walk_dominance_graph(left);
|
recursively_walk_dominance_graph(left);
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,8 @@ static void recursively_walk_dominance_graph(struct basicblock* bb)
|
||||||
|
|
||||||
void pass_register_allocator(struct procedure* proc)
|
void pass_register_allocator(struct procedure* proc)
|
||||||
{
|
{
|
||||||
calculate_dominance_graph(proc);
|
|
||||||
|
|
||||||
blocks.count = 0;
|
blocks.count = 0;
|
||||||
recursively_walk_dominance_graph(proc->blocks.item[0]);
|
recursively_walk_dominance_graph(cfg.entry);
|
||||||
assert(blocks.count == proc->blocks.count);
|
assert(blocks.count == proc->blocks.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,13 +36,15 @@ static void split_edge(struct basicblock* source, struct basicblock* sink)
|
||||||
struct rewrite_params rwp;
|
struct rewrite_params rwp;
|
||||||
struct basicblock* bb = bb_get(NULL);
|
struct basicblock* bb = bb_get(NULL);
|
||||||
|
|
||||||
array_append(&bb->irs,
|
struct ir* jump =
|
||||||
new_ir1(
|
new_ir1(
|
||||||
IR_JUMP, 0,
|
IR_JUMP, 0,
|
||||||
new_bbir(sink)
|
new_bbir(sink)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jump->root = jump->left->root = jump;
|
||||||
|
array_append(&bb->irs, jump);
|
||||||
|
|
||||||
rwp.find = sink;
|
rwp.find = sink;
|
||||||
rwp.replace = bb;
|
rwp.replace = bb;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "mcg.h"
|
#include "mcg.h"
|
||||||
|
|
||||||
static struct basicblock* entry;
|
|
||||||
static PMAPOF(struct basicblock, struct basicblock) dominancefrontiers;
|
static PMAPOF(struct basicblock, struct basicblock) dominancefrontiers;
|
||||||
|
|
||||||
static struct local* current_local;
|
static struct local* current_local;
|
||||||
|
@ -24,10 +23,10 @@ static void calculate_dominance_frontier_graph(void)
|
||||||
|
|
||||||
dominancefrontiers.count = 0;
|
dominancefrontiers.count = 0;
|
||||||
|
|
||||||
for (i=0; i<postorder.count; i++)
|
for (i=0; i<cfg.postorder.count; i++)
|
||||||
{
|
{
|
||||||
struct basicblock* b = postorder.item[i];
|
struct basicblock* b = cfg.postorder.item[i];
|
||||||
struct basicblock* dominator = pmap_get(&dominators, b);
|
struct basicblock* dominator = pmap_get(&dominance.graph, b);
|
||||||
if (b->prevs.count >= 2)
|
if (b->prevs.count >= 2)
|
||||||
{
|
{
|
||||||
for (j=0; j<b->prevs.count; j++)
|
for (j=0; j<b->prevs.count; j++)
|
||||||
|
@ -38,7 +37,7 @@ static void calculate_dominance_frontier_graph(void)
|
||||||
tracef('S', "S: %s is in %s's dominance frontier\n",
|
tracef('S', "S: %s is in %s's dominance frontier\n",
|
||||||
b->name, runner->name);
|
b->name, runner->name);
|
||||||
pmap_add(&dominancefrontiers, runner, b);
|
pmap_add(&dominancefrontiers, runner, b);
|
||||||
runner = pmap_get(&dominators, runner);
|
runner = pmap_get(&dominance.graph, runner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +157,7 @@ static void ssa_convert(void)
|
||||||
ir->left->root = ir;
|
ir->left->root = ir;
|
||||||
ir->right->root = ir;
|
ir->right->root = ir;
|
||||||
ir->right->left->root = ir;
|
ir->right->left->root = ir;
|
||||||
array_insert(&entry->irs, ir, 0);
|
array_insert(&cfg.entry->irs, ir, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
defining.count = 0;
|
defining.count = 0;
|
||||||
|
@ -166,9 +165,9 @@ static void ssa_convert(void)
|
||||||
|
|
||||||
/* Find everwhere where the variable is *defined*. */
|
/* Find everwhere where the variable is *defined*. */
|
||||||
|
|
||||||
for (i=0; i<postorder.count; i++)
|
for (i=0; i<cfg.postorder.count; i++)
|
||||||
{
|
{
|
||||||
struct basicblock* bb = postorder.item[i];
|
struct basicblock* bb = cfg.postorder.item[i];
|
||||||
for (j=0; j<bb->irs.count; j++)
|
for (j=0; j<bb->irs.count; j++)
|
||||||
{
|
{
|
||||||
struct ir* ir = bb->irs.item[j];
|
struct ir* ir = bb->irs.item[j];
|
||||||
|
@ -210,15 +209,13 @@ static void ssa_convert(void)
|
||||||
|
|
||||||
definitions.count = 0;
|
definitions.count = 0;
|
||||||
rewritten.count = 0;
|
rewritten.count = 0;
|
||||||
recursively_rewrite_tree(entry);
|
recursively_rewrite_tree(cfg.entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pass_convert_locals_to_ssa(struct procedure* proc)
|
void pass_convert_locals_to_ssa(struct procedure* proc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
entry = proc->blocks.item[0];
|
|
||||||
calculate_dominance_graph(proc);
|
|
||||||
calculate_dominance_frontier_graph();
|
calculate_dominance_frontier_graph();
|
||||||
|
|
||||||
for (i=0; i<proc->locals.count; i++)
|
for (i=0; i<proc->locals.count; i++)
|
||||||
|
|
|
@ -48,66 +48,26 @@ void procedure_compile(struct procedure* proc)
|
||||||
pass_eliminate_trivial_blocks(proc);
|
pass_eliminate_trivial_blocks(proc);
|
||||||
pass_remove_dead_blocks(proc);
|
pass_remove_dead_blocks(proc);
|
||||||
|
|
||||||
procedure_update_bb_graph(proc);
|
update_graph_data(proc);
|
||||||
|
|
||||||
/* Passes from here on can't alter the BB graph without also updating prevs
|
/* Passes from here on can't alter the BB graph without also updating prevs
|
||||||
* and nexts. */
|
* and nexts (and then calling update_graph_data()). */
|
||||||
|
|
||||||
print_blocks('2', proc);
|
print_blocks('2', proc);
|
||||||
pass_convert_stack_ops(proc);
|
pass_convert_stack_ops(proc);
|
||||||
print_blocks('3', proc);
|
print_blocks('3', proc);
|
||||||
pass_convert_locals_to_ssa(proc);
|
pass_convert_locals_to_ssa(proc);
|
||||||
print_blocks('4', proc);
|
print_blocks('4', proc);
|
||||||
pass_split_critical_edges(proc);
|
|
||||||
print_blocks('5', proc);
|
|
||||||
pass_promote_float_ops(proc);
|
pass_promote_float_ops(proc);
|
||||||
|
print_blocks('5', proc);
|
||||||
|
pass_split_critical_edges(proc);
|
||||||
print_blocks('6', proc);
|
print_blocks('6', proc);
|
||||||
|
|
||||||
|
update_graph_data(proc);
|
||||||
|
|
||||||
pass_instruction_selector(proc);
|
pass_instruction_selector(proc);
|
||||||
pass_register_allocator(proc);
|
pass_register_allocator(proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool collect_outputs_cb(struct ir* ir, void* user)
|
|
||||||
{
|
|
||||||
struct basicblock* caller = user;
|
|
||||||
|
|
||||||
if (ir->opcode == IR_BLOCK)
|
|
||||||
{
|
|
||||||
array_appendu(&caller->nexts, ir->u.bvalue);
|
|
||||||
array_appendu(&ir->u.bvalue->prevs, caller);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void procedure_update_bb_graph(struct procedure* proc)
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
for (i=0; i<proc->blocks.count; i++)
|
|
||||||
{
|
|
||||||
struct basicblock* bb = proc->blocks.item[i];
|
|
||||||
bb->prevs.count = bb->nexts.count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<proc->blocks.count; i++)
|
|
||||||
{
|
|
||||||
struct basicblock* bb = proc->blocks.item[i];
|
|
||||||
for (j=0; j<bb->irs.count; j++)
|
|
||||||
ir_walk(bb->irs.item[j], collect_outputs_cb, bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<proc->blocks.count; i++)
|
|
||||||
{
|
|
||||||
struct basicblock* bb = proc->blocks.item[i];
|
|
||||||
|
|
||||||
for (j=0; j<bb->nexts.count; j++)
|
|
||||||
{
|
|
||||||
tracef('G', "G: graph %s -> %s\n",
|
|
||||||
bb->name,
|
|
||||||
bb->nexts.item[j]->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim: set sw=4 ts=4 expandtab : */
|
/* vim: set sw=4 ts=4 expandtab : */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue