this->p = NULL;
this->sel = NULL;
this->ra = NULL;
+ this->ifEndifFix = false;
}
GenContext::~GenContext(void) {
this->branchPos2.clear();
this->branchPos3.clear();
this->labelPos.clear();
+ this->errCode = NO_ERROR;
}
void GenContext::emitInstructionStream(void) {
p->NOP();
}
- void GenContext::patchBranches(void) {
+ bool GenContext::patchBranches(void) {
using namespace ir;
for (auto pair : branchPos2) {
const LabelIndex label = pair.first;
for (auto pair : branchPos3) {
const LabelPair labelPair = pair.first;
const int32_t insnID = pair.second;
- // FIXME the 'labelPair' implementation must be fixed, as it is hard to
- // convert InstructionSelection offset to ASM offset since asm maybe compacted
const int32_t jip = labelPos.find(labelPair.l0)->second;
const int32_t uip = labelPos.find(labelPair.l1)->second;
- assert((jip - insnID) < 32767 && (jip - insnID) > -32768);
- assert((uip - insnID) < 32767 && (uip - insnID) > -32768);
+ if (((jip - insnID) > 32767 || (jip - insnID) < -32768) ||
+ ((uip - insnID) > 32768 || (uip - insnID) < -32768)) {
+ // The only possible error instruction is if/endif here.
+ errCode = OUT_OF_RANGE_IF_ENDIF;
+ return false;
+ }
p->patchJMPI(insnID, (((uip - insnID)) << 16) | ((jip - insnID)));
}
+ return true;
}
void GenContext::clearFlagRegister(void) {
this->clearFlagRegister();
this->emitStackPointer();
this->emitInstructionStream();
- this->patchBranches();
+ if (this->patchBranches() == false)
+ return false;
genKernel->insnNum = p->store.size();
genKernel->insns = GBE_NEW_ARRAY_NO_ARG(GenInstruction, genKernel->insnNum);
std::memcpy(genKernel->insns, &p->store[0], genKernel->insnNum * sizeof(GenInstruction));
GenNativeInstruction insn;
std::cout << " L0:" << std::endl;
for (uint32_t insnID = 0; insnID < genKernel->insnNum; ) {
- if (labelPos.find((ir::LabelIndex)(curLabel + 1))->second == insnID) {
+ if (labelPos.find((ir::LabelIndex)(curLabel + 1))->second == insnID &&
+ curLabel < this->getFunction().labelNum()) {
std::cout << " L" << curLabel + 1 << ":" << std::endl;
curLabel = (ir::LabelIndex)(curLabel + 1);
}
class SelectionInstruction; // Pre-RA Gen instruction
class SelectionReg; // Pre-RA Gen register
class GenRegister;
+ typedef enum {
+ NO_ERROR,
+ REGISTER_ALLOCATION_FAIL,
+ REGISTER_SPILL_EXCEED_THRESHOLD,
+ REGISTER_SPILL_FAIL,
+ OUT_OF_RANGE_IF_ENDIF,
+ } CompileErrorCode;
/*! Context is the helper structure to build the Gen ISA or simulation code
* from GenIR
/*! Emit the instructions */
void emitInstructionStream(void);
/*! Set the correct target values for the branches */
- void patchBranches(void);
+ bool patchBranches(void);
/*! Forward ir::Function isSpecialReg method */
INLINE bool isSpecialReg(ir::Register reg) const {
return fn.isSpecialReg(reg);
uint32_t reservedSpillRegs;
bool limitRegisterPressure;
bool relaxMath;
+ const bool getIFENDIFFix(void) const { return ifEndifFix; }
+ void setIFENDIFFix(bool fix) { ifEndifFix = fix; }
+ const CompileErrorCode getErrCode() { return errCode; }
private:
+ CompileErrorCode errCode;
+ bool ifEndifFix;
/*! Build the curbe patch list for the given kernel */
void buildPatchList(void);
/*! allocate a new curbe register and insert to curbe pool. */
void allocCurbeReg(ir::Register reg, gbe_curbe_type value, uint32_t subValue = 0);
+ friend GenRegAllocator; //!< need to access errCode directly.
+
};
} /* namespace gbe */
// SelectionBlock
///////////////////////////////////////////////////////////////////////////
- SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb) {}
+ SelectionBlock::SelectionBlock(const ir::BasicBlock *bb) : bb(bb), endifLabel( (ir::LabelIndex) 0){}
void SelectionBlock::append(ir::Register reg) { tmp.push_back(reg); }
this->LABEL(this->block->endifLabel);
SelectionInstruction *insn = this->appendInsn(SEL_OP_ENDIF, 0, 1);
insn->src(0) = src;
- insn->index = uint16_t(jip);
+ insn->index = uint16_t(this->block->endifLabel);
}
void Selection::Opaque::CMP(uint32_t conditional, Reg src0, Reg src1, Reg dst) {
// If there is no branch at the end of this block.
// Try all the patterns from best to worst
-
do {
if ((*it)->emit(*this, dag))
break;
++it;
} while (it != end);
GBE_ASSERT(it != end);
+ // If we are in if/endif fix mode, and this block is
+ // large enough, we need to insert endif/if pair to eliminate
+ // the too long if/endif block.
+ if (this->ctx.getIFENDIFFix() &&
+ this->block->insnList.size() != 0 &&
+ this->block->insnList.size() % 1000 == 0 &&
+ (uint16_t)this->block->endifLabel != 0) {
+ ir::LabelIndex jip = this->block->endifLabel;
+ this->ENDIF(GenRegister::immd(0), jip);
+ this->push();
+ this->curr.predicate = GEN_PREDICATE_NORMAL;
+ this->IF(GenRegister::immd(0), jip, jip);
+ this->pop();
+ }
if (needEndif) {
const ir::BasicBlock *curr = insn.getParent();
ctx->startNewCG(simdWidth, reservedSpillRegs, limitRegisterPressure);
kernel = ctx->compileKernel();
if (kernel != NULL) {
+ GBE_ASSERT(ctx->getErrCode() == NO_ERROR);
break;
}
fn->getImageSet()->clearInfo();
+ // If we get a out of range if/endif error.
+ // We need to set the context to if endif fix mode and restart the previous compile.
+ if ( ctx->getErrCode() == OUT_OF_RANGE_IF_ENDIF && !ctx->getIFENDIFFix() ) {
+ ctx->setIFENDIFFix(true);
+ codeGen--;
+ } else
+ GBE_ASSERT(!(ctx->getErrCode() == OUT_OF_RANGE_IF_ENDIF && ctx->getIFENDIFFix()));
}
GBE_ASSERTM(kernel != NULL, "Fail to compile kernel, may need to increase reserved registers for spilling.");
IVAR(OCL_SIMD16_SPILL_THRESHOLD, 0, 16, 256);
bool GenRegAllocator::Opaque::allocateGRFs(Selection &selection) {
// Perform the linear scan allocator
+ ctx.errCode = REGISTER_ALLOCATION_FAIL;
const uint32_t regNum = ctx.sel->getRegNum();
for (uint32_t startID = 0; startID < regNum; ++startID) {
const GenRegInterval &interval = *this->starting[startID];
GBE_ASSERT(reservedReg != 0);
if (ctx.getSimdWidth() == 16) {
if (spilledRegs.size() > (unsigned int)OCL_SIMD16_SPILL_THRESHOLD) {
- if (GBE_DEBUG)
- std::cerr << "WARN: exceed simd 16 spill threshold ("
- << spilledRegs.size() << ">" << OCL_SIMD16_SPILL_THRESHOLD
- << ")" << std::endl;
+ ctx.errCode = REGISTER_SPILL_EXCEED_THRESHOLD;
return false;
}
}
allocateScratchForSpilled();
bool success = selection.spillRegs(spilledRegs, reservedReg);
if (!success) {
- if (GBE_DEBUG)
- std::cerr << "Fail to spill registers." << std::endl;
+ ctx.errCode = REGISTER_SPILL_FAIL;
return false;
}
}
+ ctx.errCode = NO_ERROR;
return true;
}