6 Function::Function(Program
*p
, const char *fnName
)
32 for (ArrayList::Iterator BBs
= allBBlocks
.iterator(); !BBs
.end(); BBs
.next())
33 delete reinterpret_cast<BasicBlock
*>(BBs
.get());
36 BasicBlock::BasicBlock(Function
*fn
) : cfg(this), dom(this), func(fn
)
38 program
= func
->getProgram();
40 joinAt
= phi
= entry
= exit
= NULL
;
48 func
->add(this, this->id
);
51 BasicBlock::~BasicBlock()
57 BasicBlock::idom() const
59 Graph::Node
*dn
= dom
.parent();
60 return dn
? BasicBlock::get(dn
) : NULL
;
64 BasicBlock::insertHead(Instruction
*inst
)
66 assert(inst
->next
== 0 && inst
->prev
== 0);
68 if (inst
->op
== OP_PHI
) {
70 insertBefore(phi
, inst
);
73 insertBefore(entry
, phi
);
83 insertBefore(entry
, inst
);
86 insertAfter(phi
, inst
);
98 BasicBlock::insertTail(Instruction
*inst
)
100 assert(inst
->next
== 0 && inst
->prev
== 0);
102 if (inst
->op
== OP_PHI
) {
104 insertBefore(entry
, inst
);
108 insertAfter(exit
, inst
);
117 insertAfter(exit
, inst
);
128 BasicBlock::insertBefore(Instruction
*q
, Instruction
*p
)
132 assert(p
->next
== 0 && p
->prev
== 0);
135 if (p
->op
== OP_PHI
) {
143 assert(p
->op
== OP_PHI
);
158 BasicBlock::insertAfter(Instruction
*p
, Instruction
*q
)
161 assert(q
->op
!= OP_PHI
|| p
->op
== OP_PHI
);
163 assert(q
->next
== 0 && q
->prev
== 0);
167 if (p
->op
== OP_PHI
&& q
->op
!= OP_PHI
)
181 BasicBlock::remove(Instruction
*insn
)
183 assert(insn
->bb
== this);
186 insn
->prev
->next
= insn
->next
;
189 insn
->next
->prev
= insn
->prev
;
194 entry
= insn
->next
? insn
->next
: insn
->prev
;
197 phi
= (insn
->next
&& insn
->next
->op
== OP_PHI
) ? insn
->next
: 0;
205 void BasicBlock::permuteAdjacent(Instruction
*a
, Instruction
*b
)
207 assert(a
->bb
== b
->bb
);
214 assert(a
->next
== b
);
215 assert(a
->op
!= OP_PHI
&& b
->op
!= OP_PHI
);
234 BasicBlock::dominatedBy(BasicBlock
*that
)
236 Graph::Node
*bn
= &that
->dom
;
237 Graph::Node
*dn
= &this->dom
;
239 while (dn
&& dn
!= bn
)
246 BasicBlock::initiatesSimpleConditional() const
250 Graph::Edge::Type eR
;
252 if (cfg
.outgoingCount() != 2) // -> if and -> else/endif
256 for (Graph::EdgeIterator ei
= cfg
.outgoing(); !ei
.end(); ei
.next())
257 out
[n
++] = ei
.getNode();
258 eR
= out
[1]->outgoing().getType();
260 // IF block is out edge to the right
261 if (eR
== Graph::Edge::CROSS
|| eR
== Graph::Edge::BACK
)
264 if (out
[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence
266 // do they reconverge immediately ?
267 if (out
[1]->outgoing().getNode() == out
[0])
269 if (out
[0]->outgoingCount() == 1)
270 if (out
[0]->outgoing().getNode() == out
[1]->outgoing().getNode())
277 Function::setEntry(BasicBlock
*bb
)
281 cfg
.insert(&bb
->cfg
);
286 Function::setExit(BasicBlock
*bb
)
295 Function::orderInstructions(ArrayList
&result
)
298 for (iter
= cfg
.iteratorCFG(); !iter
->end(); iter
->next())
299 for (Instruction
*insn
= BasicBlock::get(*iter
)->getFirst();
300 insn
; insn
= insn
->next
)
301 result
.insert(insn
, insn
->serial
);
302 cfg
.putIterator(iter
);
303 return result
.getSize();
307 Pass::run(Program
*prog
, bool ordered
, bool skipPhi
)
311 return doRun(prog
, ordered
, skipPhi
);
315 Pass::doRun(Program
*prog
, bool ordered
, bool skipPhi
)
317 for (ArrayList::Iterator fi
= prog
->allFuncs
.iterator();
318 !fi
.end(); fi
.next()) {
319 Function
*fn
= reinterpret_cast<Function
*>(fi
.get());
320 if (!doRun(fn
, ordered
, skipPhi
))
327 Pass::run(Function
*func
, bool ordered
, bool skipPhi
)
329 prog
= func
->getProgram();
331 return doRun(func
, ordered
, skipPhi
);
335 Pass::doRun(Function
*func
, bool ordered
, bool skipPhi
)
339 Instruction
*insn
, *next
;
345 bbIter
= ordered
? func
->cfg
.iteratorCFG() : func
->cfg
.iteratorDFS();
347 for (; !bbIter
->end(); bbIter
->next()) {
348 bb
= BasicBlock::get(reinterpret_cast<Graph::Node
*>(bbIter
->get()));
351 for (insn
= skipPhi
? bb
->getEntry() : bb
->getFirst(); insn
!= NULL
;
358 func
->cfg
.putIterator(bbIter
);
363 Function::printCFGraph(const char *filePath
)
365 FILE *out
= fopen(filePath
, "a");
367 ERROR("failed to open file: %s\n", filePath
);
370 INFO("printing control flow graph to: %s\n", filePath
);
372 fprintf(out
, "digraph G {\n");
375 for (iter
= cfg
.iteratorDFS(); !iter
->end(); iter
->next()) {
376 BasicBlock
*bb
= BasicBlock::get(
377 reinterpret_cast<Graph::Node
*>(iter
->get()));
378 int idA
= bb
->getId();
379 for (Graph::EdgeIterator ei
= bb
->cfg
.outgoing(); !ei
.end(); ei
.next()) {
380 int idB
= BasicBlock::get(ei
.getNode())->getId();
381 switch (ei
.getType()) {
382 case Graph::Edge::TREE
:
383 fprintf(out
, "\t%i -> %i;\n", idA
, idB
);
385 case Graph::Edge::FORWARD
:
386 fprintf(out
, "\t%i -> %i [color=green];\n", idA
, idB
);
388 case Graph::Edge::CROSS
:
389 fprintf(out
, "\t%i -> %i [color=red];\n", idA
, idB
);
391 case Graph::Edge::BACK
:
392 fprintf(out
, "\t%i -> %i;\n", idA
, idB
);
394 case Graph::Edge::DUMMY
:
395 fprintf(out
, "\t%i -> %i [style=dotted];\n", idA
, idB
);
403 cfg
.putIterator(iter
);
409 } // namespace nv50_ir