INLINE Unit &getUnit(void) { return unit; }
/*! Get the current processed function */
Function &getFunction(void);
+ /*! Get the current processed block */
+ BasicBlock *getBlock(void) { return bb; }
/*! Set the SIMD width of the function */
void setSimdWidth(uint32_t width) const {
GBE_ASSERT(width == 8 || width == 16);
functor(*curr);
}
}
+ set <Register> undefPhiRegs;
private:
friend class Function; //!< Owns the basic blocks
BlockSet predecessors; //!< Incoming blocks
for (auto prev : currInfo->bb.getPredecessorSet()) {
BlockInfo *prevInfo = liveness[prev];
for (auto currInVar : currInfo->upwardUsed) {
- auto changed = prevInfo->liveOut.insert(currInVar);
- if (changed.second) isChanged = true;
+ if (!prevInfo->bb.undefPhiRegs.contains(currInVar)) {
+ auto changed = prevInfo->liveOut.insert(currInVar);
+ if (changed.second) isChanged = true;
+ }
}
if (isChanged )
workSet.insert(prevInfo);
});
#endif
}
-
/*
As we run in SIMD mode with prediction mask to indicate active lanes.
If a vreg is defined in a loop, and there are som uses of the vreg out of the loop,
killed period, and the instructions before kill point were re-executed with different prediction,
the inactive lanes of vreg maybe over-written. Then the out-of-loop use will got wrong data.
*/
-
void Liveness::computeExtraLiveInOut(void) {
const vector<Loop *> &loops = fn.getLoops();
if(loops.size() == 0) return;
// Iterate over all the predecessors
const auto &preds = bb.getPredecessorSet();
for (const auto &pred : preds) {
+ if (pred->undefPhiRegs.contains(reg))
+ continue;
RegDefSet &predDef = this->getDefSet(pred, reg);
for (auto def : predDef) udChain.insert(def);
}
for (BasicBlock::iterator I = succ->begin(); isa<PHINode>(I); ++I) {
PHINode *PN = cast<PHINode>(I);
Value *IV = PN->getIncomingValueForBlock(curr);
+ Type *llvmType = PN->getType();
+ const ir::Type type = getType(ctx, llvmType);
+ Value *PHICopy = this->getPHICopy(PN);
+ const ir::Register dst = this->getRegister(PHICopy);
if (!isa<UndefValue>(IV)) {
- Type *llvmType = PN->getType();
- const ir::Type type = getType(ctx, llvmType);
// Emit the MOV required by the PHI function. We do it simple and do not
// try to optimize them. A next data flow analysis pass on the Gen IR
// will remove them
- Value *PHICopy = this->getPHICopy(PN);
- const ir::Register dst = this->getRegister(PHICopy);
Constant *CP = dyn_cast<Constant>(IV);
if (CP) {
GBE_ASSERT(isa<GlobalValue>(CP) == false);
const ir::Register src = this->getRegister(IV);
ctx.MOV(type, dst, src);
}
+ assert(!ctx.getBlock()->undefPhiRegs.contains(dst));
+ } else {
+ // If this is an undefined value, we don't need emit phi copy here.
+ // But we need to record it. As latter, at liveness's backward analysis,
+ // we don't need to pass the phi value/register to this BB which the phi
+ // value is undefined. Otherwise, the phi value's liveness will be extent
+ // incorrectly and may be extent to the basic block zero which is really bad.
+ ctx.getBlock()->undefPhiRegs.insert(dst);
}
}
}