});
}
+ /* Because of the structural analysis, control flow of blocks inside a structure
+ * is manipulated by if, else and endif. so these blocks don't need jips. so here
+ * treats all the blocks belong to the same structure as a whole.
+ */
void Context::buildJIPs(void) {
using namespace ir;
-
// Linearly store the branch target for each block and its own label
const LabelIndex noTarget(fn.labelNum());
vector<std::pair<LabelIndex, LabelIndex>> braTargets;
- int32_t curr = 0, blockNum = fn.blockNum();
- braTargets.resize(blockNum);
-
+ int32_t curr = 0;
// If some blocks are unused we mark them as such by setting their own label
// as "invalid" (== noTarget)
+ int blockCount = 0;
+ // because some blocks maybe belong to the same structure, so the number of
+ // blocks we are dealing with may be less than the number of basic blocks.
+ // here calculate the actual block number we would handle.
+ fn.foreachBlock([&](const BasicBlock &bb)
+ {
+ if(bb.belongToStructure && bb.isStructureExit)
+ blockCount++;
+ else if(!bb.belongToStructure)
+ blockCount++;
+ });
+ braTargets.resize(blockCount);
+
+ LabelIndex structureExitLabel;
+ LabelIndex structureEntryLabel;
+ bool flag;
+ set<uint32_t> pos;
+ map<uint32_t, LabelIndex> exitMap;
+ map<uint32_t, LabelIndex> entryMap;
for (auto &bb : braTargets) bb = std::make_pair(noTarget, noTarget);
fn.foreachBlock([&](const BasicBlock &bb) {
- const LabelIndex ownLabel = bb.getLabelIndex();
- const Instruction *last = bb.getLastInstruction();
- if (last->getOpcode() != OP_BRA)
- braTargets[curr++] = std::make_pair(ownLabel, noTarget);
- else {
- const BranchInstruction *bra = cast<BranchInstruction>(last);
- braTargets[curr++] = std::make_pair(ownLabel, bra->getLabelIndex());
+ LabelIndex ownLabel;
+ Instruction *last;
+ flag = false;
+ // bb belongs to a structure and it's not the structure's exit, just simply insert
+ // the target of bra to JIPs.
+ if(bb.belongToStructure && !bb.isStructureExit)
+ {
+ last = bb.getLastInstruction();
+ if(last->getOpcode() == OP_BRA)
+ {
+ BranchInstruction *bra = cast<BranchInstruction>(last);
+ JIPs.insert(std::make_pair(bra, bra->getLabelIndex()));
+ }
+ return;
}
- });
+ else
+ {
+ // bb belongs to a structure and it's the strucutre's exit, we treat this bb
+ // as the structure it belongs to, use the label of structure's entry as this
+ // structure's label and last instruction of structure's exit as this structure's
+ // last instruction.
+ if(bb.belongToStructure && bb.isStructureExit)
+ {
+ ownLabel = (bb.matchingStructureEntry)->getLabelIndex();
+ last = bb.getLastInstruction();
+ structureExitLabel = bb.getLabelIndex();
+ structureEntryLabel = ownLabel;
+ flag = true;
+ }
+ // bb belongs to no structure.
+ else
+ {
+ ownLabel = bb.getLabelIndex();
+ last = bb.getLastInstruction();
+ }
+ if (last->getOpcode() != OP_BRA)
+ {
+ braTargets[curr++] = std::make_pair(ownLabel, noTarget);
+ if(flag)
+ {
+ pos.insert(curr-1);
+ exitMap[curr-1] = structureExitLabel;
+ entryMap[curr-1] = structureEntryLabel;
+ }
+ }
+ else {
+ const BranchInstruction *bra = cast<BranchInstruction>(last);
+ braTargets[curr++] = std::make_pair(ownLabel, bra->getLabelIndex());
+ if(flag)
+ {
+ exitMap[curr-1] = structureExitLabel;
+ entryMap[curr-1] = structureEntryLabel;
+ pos.insert(curr-1);
+ }
+ }
+ }
+ });
// Backward jumps are special. We must insert the label of the next block
// when we hit the "DO" i.e. the target label of the backward branch (as in
// do { } while) . So, we store the bwd jumps per targets
// XXX does not use custom allocator
std::multimap<LabelIndex, LabelIndex> bwdTargets;
- for (int32_t blockID = 0; blockID < blockNum; ++blockID) {
+ for (int32_t blockID = 0; blockID <curr; ++blockID) {
const LabelIndex ownLabel = braTargets[blockID].first;
const LabelIndex target = braTargets[blockID].second;
if (ownLabel == noTarget) continue; // unused block
if (target == noTarget) continue; // no branch
if (target <= ownLabel) { // This is a backward jump
// Last block is just "RET". So, it cannot be the last block
- GBE_ASSERT(blockID < blockNum - 1);
+ GBE_ASSERT(blockID < curr - 1);
const LabelIndex fallThrough = braTargets[blockID+1].first;
bwdTargets.insert(std::make_pair(target, fallThrough));
}
// Stores the current forward targets
set<LabelIndex> fwdTargets;
-
// Now retraverse the blocks and figure out all JIPs
- for (int32_t blockID = 0; blockID < blockNum; ++blockID) {
+ for (int32_t blockID = 0; blockID <curr; ++blockID) {
+
const LabelIndex ownLabel = braTargets[blockID].first;
const LabelIndex target = braTargets[blockID].second;
- const BasicBlock &bb = fn.getBlock(ownLabel);
- const Instruction *label = bb.getFirstInstruction();
+ LabelIndex tmp;
+ if(pos.find(blockID)!=pos.end())
+ tmp = exitMap[blockID];
+ else
+ tmp = ownLabel;
+ BasicBlock &bb = fn.getBlock(tmp);
+ Instruction *label = bb.getFirstInstruction();
+ if(pos.find(blockID)!=pos.end())
+ label = fn.getBlock(entryMap[blockID]).getFirstInstruction();
const Instruction *bra = bb.getLastInstruction();
-
// Expires the branches that point to us (if any)
auto it = fwdTargets.find(ownLabel);
if (it != fwdTargets.end()) fwdTargets.erase(it);
auto jip = fwdTargets.lower_bound(LabelIndex(0));
JIPs.insert(std::make_pair(bra, *jip));
}
+
}
void Context::handleSLM(void) {
{
// Bottom up code generation
bool needEndif = this->block->hasBranch == false && !this->block->hasBarrier;
-
- if(needEndif) {
- const ir::BasicBlock *next = bb.getNextBlock();
- this->ENDIF(GenRegister::immd(0), next->getLabelIndex());
+ needEndif = needEndif && bb.needEndif;
+ if (needEndif) {
+ if(!bb.needIf) // this basic block is the exit of a structure
+ this->ENDIF(GenRegister::immd(0), bb.endifLabel, bb.endifLabel);
+ else {
+ const ir::BasicBlock *next = bb.getNextBlock();
+ this->ENDIF(GenRegister::immd(0), next->getLabelIndex());
+ needEndif = false;
+ }
}
for (int32_t insnID = insnNum-1; insnID >= 0; --insnID) {
this->pop();
this->block->isLargeBlock = true;
}
-
// Output the code in the current basic block
this->endBackwardGeneration();
}
GBE_ASSERTM(label < GEN_MAX_LABEL, "We reached the maximum label number which is reserved for barrier handling");
sel.LABEL(label);
+ if(!insn.getParent()->needIf)
+ return true;
+
// Do not emit any code for the "returning" block. There is no need for it
if (insn.getParent() == &sel.ctx.getFunction().getBottomBlock())
return true;
}
sel.push();
sel.curr.predicate = GEN_PREDICATE_NORMAL;
- sel.IF(GenRegister::immd(0), sel.block->endifLabel, sel.block->endifLabel);
+ if(!insn.getParent()->needEndif && insn.getParent()->needIf) {
+ ir::LabelIndex label = insn.getParent()->endifLabel;
+ sel.IF(GenRegister::immd(0), label, label);
+ }
+ else
+ sel.IF(GenRegister::immd(0), sel.block->endifLabel, sel.block->endifLabel);
sel.pop();
}
} else {
// Update the PcIPs
const LabelIndex jip = sel.ctx.getLabelIndex(&insn);
- sel.MOV(ip, GenRegister::immuw(uint16_t(dst)));
- if (!sel.block->hasBarrier)
- sel.ENDIF(GenRegister::immd(0), nextLabel);
+ if(insn.getParent()->needEndif)
+ sel.MOV(ip, GenRegister::immuw(uint16_t(dst)));
+
+ if (!sel.block->hasBarrier) {
+ if(insn.getParent()->needEndif && !insn.getParent()->needIf)
+ sel.ENDIF(GenRegister::immd(0), insn.getParent()->endifLabel, insn.getParent()->endifLabel);
+ else if(insn.getParent()->needEndif)
+ sel.ENDIF(GenRegister::immd(0), nextLabel);
+ }
sel.block->endifOffset = -1;
if (nextLabel == jip) return;
// Branch to the jump target
} else {
const LabelIndex next = bb.getNextBlock()->getLabelIndex();
// Update the PcIPs
- sel.MOV(ip, GenRegister::immuw(uint16_t(dst)));
+ if(insn.getParent()->needEndif)
+ sel.MOV(ip, GenRegister::immuw(uint16_t(dst)));
sel.block->endifOffset = -1;
- if (!sel.block->hasBarrier)
- sel.ENDIF(GenRegister::immd(0), next);
+ if (!sel.block->hasBarrier) {
+ if(insn.getParent()->needEndif && !insn.getParent()->needIf)
+ sel.ENDIF(GenRegister::immd(0), insn.getParent()->endifLabel, insn.getParent()->endifLabel);
+ else if(insn.getParent()->needEndif)
+ sel.ENDIF(GenRegister::immd(0), next);
+ }
// Branch to the jump target
sel.push();
sel.curr.execWidth = 1;
else
this->emitForwardBranch(sel, insn, dst, src);
sel.pop();
+ }
+ else if(opcode == OP_IF) {
+ const Register pred = insn.getPredicateIndex();
+ const LabelIndex jip = insn.getLabelIndex();
+ LabelIndex uip;
+ if(insn.getParent()->matchingEndifLabel != 0)
+ uip = insn.getParent()->matchingEndifLabel;
+ else
+ uip = jip;
+ sel.push();
+ sel.curr.physicalFlag = 0;
+ sel.curr.flagIndex = (uint64_t)pred;
+ sel.curr.externFlag = 1;
+ sel.curr.inversePredicate = 1;
+ sel.curr.predicate = GEN_PREDICATE_NORMAL;
+ sel.IF(GenRegister::immd(0), jip, uip);
+ sel.curr.inversePredicate = 0;
+ sel.pop();
+ } else if(opcode == OP_ENDIF) {
+ const LabelIndex label = insn.getLabelIndex();
+ sel.push();
+ sel.curr.noMask = 1;
+ sel.curr.predicate = GEN_PREDICATE_NONE;
+ sel.ENDIF(GenRegister::immd(0), label, label);
+ sel.pop();
+ } else if(opcode == OP_ELSE) {
+ const LabelIndex label = insn.getLabelIndex();
+ sel.ELSE(GenRegister::immd(0), label, insn.getParent()->thisElseLabel);
} else
NOT_IMPLEMENTED;