Constant *computeLoadValue(LoadInst *LI, unsigned Iteration) { if (!LI) return nullptr; Value *BaseAddr = LoadBaseAddresses[LI]; if (!BaseAddr) return nullptr; auto GV = dyn_cast<GlobalVariable>(BaseAddr); if (!GV) return nullptr; ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer()); if (!CDS) return nullptr; const SCEV *BaseAddrSE = SE.getSCEV(BaseAddr); const SCEV *S = SE.getSCEV(LI->getPointerOperand()); const SCEV *OffSE = SE.getMinusSCEV(S, BaseAddrSE); APInt StepC, StartC; const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(OffSE); if (!AR) return nullptr; if (const SCEVConstant *StepSE = dyn_cast<SCEVConstant>(AR->getStepRecurrence(SE))) StepC = StepSE->getValue()->getValue(); else return nullptr; if (const SCEVConstant *StartSE = dyn_cast<SCEVConstant>(AR->getStart())) StartC = StartSE->getValue()->getValue(); else return nullptr; unsigned ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U; unsigned Start = StartC.getLimitedValue(); unsigned Step = StepC.getLimitedValue(); unsigned Index = (Start + Step * Iteration) / ElemSize; if (Index >= CDS->getNumElements()) return nullptr; Constant *CV = CDS->getElementAsConstant(Index); return CV; }
/// Try to fold load I. bool UnrolledInstAnalyzer::visitLoad(LoadInst &I) { Value *AddrOp = I.getPointerOperand(); auto AddressIt = SimplifiedAddresses.find(AddrOp); if (AddressIt == SimplifiedAddresses.end()) return false; ConstantInt *SimplifiedAddrOp = AddressIt->second.Offset; auto *GV = dyn_cast<GlobalVariable>(AddressIt->second.Base); // We're only interested in loads that can be completely folded to a // constant. if (!GV || !GV->hasDefinitiveInitializer() || !GV->isConstant()) return false; ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(GV->getInitializer()); if (!CDS) return false; // We might have a vector load from an array. FIXME: for now we just bail // out in this case, but we should be able to resolve and simplify such // loads. if(!CDS->isElementTypeCompatible(I.getType())) return false; int ElemSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8U; if (SimplifiedAddrOp->getValue().getActiveBits() >= 64) return false; int64_t Index = SimplifiedAddrOp->getSExtValue() / ElemSize; if (Index >= CDS->getNumElements()) { // FIXME: For now we conservatively ignore out of bound accesses, but // we're allowed to perform the optimization in this case. return false; } Constant *CV = CDS->getElementAsConstant(Index); assert(CV && "Constant expected."); SimplifiedValues[&I] = CV; return true; }