diff options
-rw-r--r-- | backend/src/ir/function.cpp | 19 | ||||
-rw-r--r-- | backend/src/ir/function.hpp | 5 | ||||
-rw-r--r-- | backend/src/ir/structural_analysis.cpp | 28 |
3 files changed, 38 insertions, 14 deletions
diff --git a/backend/src/ir/function.cpp b/backend/src/ir/function.cpp index deb65ef..3767d9c 100644 --- a/backend/src/ir/function.cpp +++ b/backend/src/ir/function.cpp @@ -260,14 +260,23 @@ namespace ir { jumpToNext = &bb; return; } - const BranchInstruction &insn = cast<BranchInstruction>(*last); - if (insn.getOpcode() == OP_BRA) { + ir::BasicBlock::iterator it = --bb.end(); + uint32_t handledInsns = 0; + while ((handledInsns < 2 && it != bb.end()) && + static_cast<ir::BranchInstruction *>(&*it)->getOpcode() == OP_BRA) { + const BranchInstruction &insn = cast<BranchInstruction>(*it); + if (insn.getOpcode() != OP_BRA) + break; const LabelIndex label = insn.getLabelIndex(); BasicBlock *target = this->blocks[label]; GBE_ASSERT(target != NULL); target->predecessors.insert(&bb); bb.successors.insert(target); - if ( insn.isPredicated() == true) jumpToNext = &bb; + if (insn.isPredicated() == true) jumpToNext = &bb; + // If we are going to handle the second bra, this bra must be a predicated bra + GBE_ASSERT(handledInsns == 0 || insn.isPredicated() == true); + --it; + ++handledInsns; } }); } @@ -324,7 +333,9 @@ namespace ir { BasicBlock::BasicBlock(Function &fn) : needEndif(true), needIf(true), endifLabel(0), matchingEndifLabel(0), matchingElseLabel(0), thisElseLabel(0), belongToStructure(false), - isStructureExit(false), matchingStructureEntry(NULL), + isStructureExit(false), isLoopExit(false), + hasExtraBra(false), + matchingStructureEntry(NULL), fn(fn) { this->nextBlock = this->prevBlock = NULL; } diff --git a/backend/src/ir/function.hpp b/backend/src/ir/function.hpp index d0b595e..0f145c5 100644 --- a/backend/src/ir/function.hpp +++ b/backend/src/ir/function.hpp @@ -122,6 +122,11 @@ namespace ir { * identified structure. so if isStructureExit is false then matchingStructureEntry * is meaningless. */ bool isStructureExit; + /* This block is an exit point of a loop block. It may not be exit point of + the large structure block. */ + bool isLoopExit; + /* This block has an extra branch in the end of the block. */ + bool hasExtraBra; BasicBlock *matchingStructureEntry; /* variable liveout is for if-else structure liveness analysis. eg. we have an sequence of * bbs of 0, 1, 2, 3, 4 and the CFG is as below: diff --git a/backend/src/ir/structural_analysis.cpp b/backend/src/ir/structural_analysis.cpp index 040a7e0..1e98629 100644 --- a/backend/src/ir/structural_analysis.cpp +++ b/backend/src/ir/structural_analysis.cpp @@ -59,20 +59,24 @@ namespace analysis } void ControlTree::handleSelfLoopNode(Node *loopnode, ir::LabelIndex& whileLabel) { + //NodeList::iterator child_iter = (*it)->children.begin(); ir::BasicBlock *pbb = loopnode->getExit(); - ir::BranchInstruction* pinsn = static_cast<ir::BranchInstruction *>(pbb->getLastInstruction()); - ir::Register reg = pinsn->getPredicateIndex(); + GBE_ASSERT(pbb->isLoopExit); ir::BasicBlock::iterator it = pbb->end(); it--; + if (pbb->hasExtraBra) + it--; + ir::BranchInstruction* pinsn = static_cast<ir::BranchInstruction *>(&*it); + ir::Register reg = pinsn->getPredicateIndex(); /* since this node is an while node, so we remove the BRA instruction at the bottom of the exit BB of 'node', * and insert WHILE instead */ - pbb->erase(it); whileLabel = pinsn->getLabelIndex(); ir::Instruction insn = ir::WHILE(whileLabel, reg); ir::Instruction* p_new_insn = pbb->getParent().newInstruction(insn); - pbb->append(*p_new_insn); + pbb->insertAt(it, *p_new_insn); pbb->whileLabel = whileLabel; + pbb->erase(it); } /* recursive mark the bbs' variable needEndif, the bbs all belong to node.*/ @@ -257,11 +261,15 @@ namespace analysis for(size_t i = 0; i < blocks.size(); ++i) { bbs[i] = blocks[i]; - if(bbs[i]->getLastInstruction()->getOpcode() != ir::OP_BRA && i != blocks.size() - 1) + if(i != blocks.size() -1 && + (bbs[i]->getLastInstruction()->getOpcode() != ir::OP_BRA || + (bbs[i]->isStructureExit && bbs[i]->isLoopExit))) { ir::Instruction insn = ir::BRA(bbs[i]->getNextBlock()->getLabelIndex()); ir::Instruction* pNewInsn = bbs[i]->getParent().newInstruction(insn); bbs[i]->append(*pNewInsn); + if (bbs[i]->isStructureExit && bbs[i]->isLoopExit) + bbs[i]->hasExtraBra = true; } } @@ -337,6 +345,9 @@ namespace analysis it--; bbs[i]->erase(it); + + if (bbs[i]->hasExtraBra) + bbs[i]->hasExtraBra = false; } } } @@ -346,7 +357,6 @@ namespace analysis fn->sortLabels(); fn->computeCFG(); -#if 1 it = begin; while(it != end) { @@ -384,9 +394,8 @@ namespace analysis case SelfLoop: { - NodeList::iterator child_iter = (*it)->children.begin(); ir::LabelIndex whilelabel; - handleSelfLoopNode(*child_iter, whilelabel); + handleSelfLoopNode(*it, whilelabel); } break; @@ -397,7 +406,6 @@ namespace analysis it++; } -#endif } @@ -868,7 +876,7 @@ namespace analysis Node* p = new SelfLoopNode(node); p->canBeHandled = true; - + node->getExit()->isLoopExit = true; return insertNode(p); } else |