for (int32_t blockID = 0; blockID < blockNum; ++blockID) {
const LabelIndex ownLabel = braTargets[blockID].first;
const LabelIndex target = braTargets[blockID].second;
+ const BasicBlock &bb = fn.getBlock(ownLabel);
+ const Instruction *insn = bb.getLastInstruction();
if (ownLabel == noTarget) continue; // unused block
if (target == noTarget) continue; // no branch at all
- if (target <= ownLabel) continue; // bwd branch: nothing to do
+ GBE_ASSERT(insn->isMemberOf<BranchInstruction>() == true);
+ if (target <= ownLabel) { // bwd branch: we always jump
+ JIPs.insert(std::make_pair(insn, LabelIndex(target)));
+ continue;
+ }
// Traverse all previous blocks and see if we bypass their target
uint32_t bypassedNum = 0;
}
// We now have the (possibly) updated JIP for the branch
- const BasicBlock &bb = fn.getBlock(ownLabel);
- const Instruction *insn = bb.getLastInstruction();
- GBE_ASSERT(insn->isMemberOf<BranchInstruction>() == true);
JIPs.insert(std::make_pair(insn, LabelIndex(JIP)));
// No bypassed targets
// When we have several bypassed targets, we must simply sort them and
// chain them such target_n points to target_{n+1}
- bypassedLabels[bypassedNum++] = ownLabel;
+ bypassedLabels[bypassedNum++] = target;
std::sort(&bypassedLabels[0], &bypassedLabels[bypassedNum]);
// Bypassed labels have a JIP now. However, we will only insert the
{
using namespace ir;
const GenReg ip = this->genReg(blockIPReg, TYPE_U16);
+ const LabelIndex jip = JIPs.find(&insn)->second;
+
+ // We will not emit any jump if we must go the next block anyway
+ const BasicBlock *curr = insn.getParent();
+ const BasicBlock *next = curr->getNextBlock();
+ const LabelIndex nextLabel = next->getLabelIndex();
// Inefficient code. If the instruction is predicated, we build the flag
// register from the boolean vector
p->MOV(ip, GenReg::immuw(uint16_t(dst)));
p->pop();
- // We do not emit any jump if we must jump to the next instruction
- const BasicBlock *curr = insn.getParent();
- const BasicBlock *next = curr->getNextBlock();
- const LabelIndex nextLabel = next->getLabelIndex();
- if (nextLabel == dst) return;
+ if (nextLabel == jip) return;
// It is slightly more complicated than for backward jump. We check that
// all PcIPs are greater than the next block IP to be sure that we can
// jump
p->push();
+ p->curr.predicate = GEN_PREDICATE_NONE;
p->curr.flag = 0;
p->curr.subFlag = 1;
p->CMP(GenReg::null(), GEN_CONDITIONAL_G, ip, GenReg::immuw(nextLabel));
// Update the PcIPs
p->MOV(ip, GenReg::immuw(uint16_t(dst)));
- // Branch to the jump target
+ // Do not emit branch when we go to the next block anyway
+ if (nextLabel == jip) return;
this->branchPos.insert(std::make_pair(&insn, p->insnNum));
p->push();
p->curr.execWidth = 1;
p->curr.flag = 0;
p->CMP(dst, GEN_CONDITIONAL_LE, GenReg::retype(src0, GEN_TYPE_UW), src1);
p->pop();
+
+ // If it is required, insert a JUMP to bypass the block
+ auto it = JIPs.find(&insn);
+ if (it != JIPs.end()) {
+ p->push();
+ this->branchPos.insert(std::make_pair(&insn, p->insnNum));
+ if (simdWidth == 8)
+ p->curr.predicate = GEN_PREDICATE_ALIGN1_ANY8H;
+ else if (simdWidth == 16)
+ p->curr.predicate = GEN_PREDICATE_ALIGN1_ANY16H;
+ else
+ NOT_IMPLEMENTED;
+ p->curr.inversePredicate = 1;
+ p->curr.execWidth = 1;
+ p->curr.flag = 0;
+ p->curr.subFlag = 0;
+ p->curr.noMask = 1;
+ p->JMPI(GenReg::immd(0));
+ p->pop();
+ }
}
void GenContext::emitInstructionStream(void) {
void GenContext::patchBranches(void) {
using namespace ir;
for (auto pair : branchPos) {
- const BranchInstruction *insn = cast<BranchInstruction>(pair.first);
- const LabelIndex label = insn->getLabelIndex();
+ const Instruction *insn = pair.first;
+ const LabelIndex label = JIPs.find(insn)->second;
const int32_t insnID = pair.second;
const int32_t targetID = labelPos.find(label)->second;
p->patchJMPI(insnID, (targetID-insnID-1) * 2);
this->setSrc1(&insn, GenReg::immd(jumpDistance));
}
- /* To integrate with the above, it makes sense that the comparison
- * instruction should populate the flag register. It might be simpler
- * just to use the flag reg for most WM tasks?
- */
void GenEmitter::CMP(GenReg dest, uint32_t conditional, GenReg src0, GenReg src1)
{
GenInstruction *insn = this->next(GEN_OPCODE_CMP);
this->setSrc1(insn, src1);
}
- /* Issue 'wait' instruction for n1, host could program MMIO
- to wake up thread. */
void GenEmitter::WAIT(void)
{
GenInstruction *insn = this->next(GEN_OPCODE_WAIT);