// Returns a clone of `I` with its operands converted to those specified in // ValueWithNewAddrSpace. Due to potential cycles in the data flow graph, an // operand whose address space needs to be modified might not exist in // ValueWithNewAddrSpace. In that case, uses undef as a placeholder operand and // adds that operand use to UndefUsesToFix so that caller can fix them later. // // Note that we do not necessarily clone `I`, e.g., if it is an addrspacecast // from a pointer whose type already matches. Therefore, this function returns a // Value* instead of an Instruction*. static Value *cloneInstructionWithNewAddressSpace( Instruction *I, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace, SmallVectorImpl<const Use *> *UndefUsesToFix) { Type *NewPtrType = I->getType()->getPointerElementType()->getPointerTo(NewAddrSpace); if (I->getOpcode() == Instruction::AddrSpaceCast) { Value *Src = I->getOperand(0); // Because `I` is flat, the source address space must be specific. // Therefore, the inferred address space must be the source space, according // to our algorithm. assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace); if (Src->getType() != NewPtrType) return new BitCastInst(Src, NewPtrType); return Src; } // Computes the converted pointer operands. SmallVector<Value *, 4> NewPointerOperands; for (const Use &OperandUse : I->operands()) { if (!OperandUse.get()->getType()->isPointerTy()) NewPointerOperands.push_back(nullptr); else NewPointerOperands.push_back(operandWithNewAddressSpaceOrCreateUndef( OperandUse, NewAddrSpace, ValueWithNewAddrSpace, UndefUsesToFix)); } switch (I->getOpcode()) { case Instruction::BitCast: return new BitCastInst(NewPointerOperands[0], NewPtrType); case Instruction::PHI: { assert(I->getType()->isPointerTy()); PHINode *PHI = cast<PHINode>(I); PHINode *NewPHI = PHINode::Create(NewPtrType, PHI->getNumIncomingValues()); for (unsigned Index = 0; Index < PHI->getNumIncomingValues(); ++Index) { unsigned OperandNo = PHINode::getOperandNumForIncomingValue(Index); NewPHI->addIncoming(NewPointerOperands[OperandNo], PHI->getIncomingBlock(Index)); } return NewPHI; } case Instruction::GetElementPtr: { GetElementPtrInst *GEP = cast<GetElementPtrInst>(I); GetElementPtrInst *NewGEP = GetElementPtrInst::Create( GEP->getSourceElementType(), NewPointerOperands[0], SmallVector<Value *, 4>(GEP->idx_begin(), GEP->idx_end())); NewGEP->setIsInBounds(GEP->isInBounds()); return NewGEP; } case Instruction::Select: { assert(I->getType()->isPointerTy()); return SelectInst::Create(I->getOperand(0), NewPointerOperands[1], NewPointerOperands[2], "", nullptr, I); } default: llvm_unreachable("Unexpected opcode"); } }
TEST(CloneInstruction, Inbounds) { LLVMContext context; Value *V = new Argument(Type::getInt32PtrTy(context)); Constant *Z = Constant::getNullValue(Type::getInt32Ty(context)); std::vector<Value *> ops; ops.push_back(Z); GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops.begin(), ops.end()); EXPECT_FALSE(cast<GetElementPtrInst>(GEP->clone())->isInBounds()); GEP->setIsInBounds(); EXPECT_TRUE(cast<GetElementPtrInst>(GEP->clone())->isInBounds()); }
Value *NVPTXFavorNonGenericAddrSpaces::hoistAddrSpaceCastFromGEP( GEPOperator *GEP, int Depth) { Value *NewOperand = hoistAddrSpaceCastFrom(GEP->getPointerOperand(), Depth + 1); if (NewOperand == nullptr) return nullptr; // hoistAddrSpaceCastFrom returns an eliminable addrspacecast or nullptr. assert(isEliminableAddrSpaceCast(NewOperand)); Operator *Cast = cast<Operator>(NewOperand); SmallVector<Value *, 8> Indices(GEP->idx_begin(), GEP->idx_end()); Value *NewASC; if (Instruction *GEPI = dyn_cast<Instruction>(GEP)) { // GEP = gep (addrspacecast X), indices // => // NewGEP = gep X, indices // NewASC = addrspacecast NewGEP GetElementPtrInst *NewGEP = GetElementPtrInst::Create( GEP->getSourceElementType(), Cast->getOperand(0), Indices, "", GEPI); NewGEP->setIsInBounds(GEP->isInBounds()); NewASC = new AddrSpaceCastInst(NewGEP, GEP->getType(), "", GEPI); NewASC->takeName(GEP); // Without RAUWing GEP, the compiler would visit GEP again and emit // redundant instructions. This is exercised in test @rauw in // access-non-generic.ll. GEP->replaceAllUsesWith(NewASC); } else { // GEP is a constant expression. Constant *NewGEP = ConstantExpr::getGetElementPtr( GEP->getSourceElementType(), cast<Constant>(Cast->getOperand(0)), Indices, GEP->isInBounds()); NewASC = ConstantExpr::getAddrSpaceCast(NewGEP, GEP->getType()); } return NewASC; }
/// InsertPHITranslatedPointer - Insert a computation of the PHI translated /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB /// block. All newly created instructions are added to the NewInsts list. /// This returns null on failure. /// Value *PHITransAddr:: InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree &DT, SmallVectorImpl<Instruction*> &NewInsts) { // See if we have a version of this value already available and dominating // PredBB. If so, there is no need to insert a new instance of it. PHITransAddr Tmp(InVal, DL, AC); if (!Tmp.PHITranslateValue(CurBB, PredBB, &DT, /*MustDominate=*/true)) return Tmp.getAddr(); // We don't need to PHI translate values which aren't instructions. auto *Inst = dyn_cast<Instruction>(InVal); if (!Inst) return nullptr; // Handle cast of PHI translatable value. if (CastInst *Cast = dyn_cast<CastInst>(Inst)) { if (!isSafeToSpeculativelyExecute(Cast)) return nullptr; Value *OpVal = InsertPHITranslatedSubExpr(Cast->getOperand(0), CurBB, PredBB, DT, NewInsts); if (!OpVal) return nullptr; // Otherwise insert a cast at the end of PredBB. CastInst *New = CastInst::Create(Cast->getOpcode(), OpVal, InVal->getType(), InVal->getName() + ".phi.trans.insert", PredBB->getTerminator()); New->setDebugLoc(Inst->getDebugLoc()); NewInsts.push_back(New); return New; } // Handle getelementptr with at least one PHI operand. if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) { SmallVector<Value*, 8> GEPOps; BasicBlock *CurBB = GEP->getParent(); for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { Value *OpVal = InsertPHITranslatedSubExpr(GEP->getOperand(i), CurBB, PredBB, DT, NewInsts); if (!OpVal) return nullptr; GEPOps.push_back(OpVal); } GetElementPtrInst *Result = GetElementPtrInst::Create( GEP->getSourceElementType(), GEPOps[0], makeArrayRef(GEPOps).slice(1), InVal->getName() + ".phi.trans.insert", PredBB->getTerminator()); Result->setDebugLoc(Inst->getDebugLoc()); Result->setIsInBounds(GEP->isInBounds()); NewInsts.push_back(Result); return Result; } #if 0 // FIXME: This code works, but it is unclear that we actually want to insert // a big chain of computation in order to make a value available in a block. // This needs to be evaluated carefully to consider its cost trade offs. // Handle add with a constant RHS. if (Inst->getOpcode() == Instruction::Add && isa<ConstantInt>(Inst->getOperand(1))) { // PHI translate the LHS. Value *OpVal = InsertPHITranslatedSubExpr(Inst->getOperand(0), CurBB, PredBB, DT, NewInsts); if (OpVal == 0) return 0; BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1), InVal->getName()+".phi.trans.insert", PredBB->getTerminator()); Res->setHasNoSignedWrap(cast<BinaryOperator>(Inst)->hasNoSignedWrap()); Res->setHasNoUnsignedWrap(cast<BinaryOperator>(Inst)->hasNoUnsignedWrap()); NewInsts.push_back(Res); return Res; } #endif return nullptr; }
GetElementPtrInst * NaryReassociate::tryReassociateGEPAtIndex(GetElementPtrInst *GEP, unsigned I, Value *LHS, Value *RHS, Type *IndexedType) { // Look for GEP's closest dominator that has the same SCEV as GEP except that // the I-th index is replaced with LHS. SmallVector<const SCEV *, 4> IndexExprs; for (auto Index = GEP->idx_begin(); Index != GEP->idx_end(); ++Index) IndexExprs.push_back(SE->getSCEV(*Index)); // Replace the I-th index with LHS. IndexExprs[I] = SE->getSCEV(LHS); const SCEV *CandidateExpr = SE->getGEPExpr( GEP->getSourceElementType(), SE->getSCEV(GEP->getPointerOperand()), IndexExprs, GEP->isInBounds()); auto *Candidate = findClosestMatchingDominator(CandidateExpr, GEP); if (Candidate == nullptr) return nullptr; PointerType *TypeOfCandidate = dyn_cast<PointerType>(Candidate->getType()); // Pretty rare but theoretically possible when a numeric value happens to // share CandidateExpr. if (TypeOfCandidate == nullptr) return nullptr; // NewGEP = (char *)Candidate + RHS * sizeof(IndexedType) uint64_t IndexedSize = DL->getTypeAllocSize(IndexedType); Type *ElementType = TypeOfCandidate->getElementType(); uint64_t ElementSize = DL->getTypeAllocSize(ElementType); // Another less rare case: because I is not necessarily the last index of the // GEP, the size of the type at the I-th index (IndexedSize) is not // necessarily divisible by ElementSize. For example, // // #pragma pack(1) // struct S { // int a[3]; // int64 b[8]; // }; // #pragma pack() // // sizeof(S) = 100 is indivisible by sizeof(int64) = 8. // // TODO: bail out on this case for now. We could emit uglygep. if (IndexedSize % ElementSize != 0) return nullptr; // NewGEP = &Candidate[RHS * (sizeof(IndexedType) / sizeof(Candidate[0]))); IRBuilder<> Builder(GEP); Type *IntPtrTy = DL->getIntPtrType(TypeOfCandidate); if (RHS->getType() != IntPtrTy) RHS = Builder.CreateSExtOrTrunc(RHS, IntPtrTy); if (IndexedSize != ElementSize) { RHS = Builder.CreateMul( RHS, ConstantInt::get(IntPtrTy, IndexedSize / ElementSize)); } GetElementPtrInst *NewGEP = cast<GetElementPtrInst>(Builder.CreateGEP(Candidate, RHS)); NewGEP->setIsInBounds(GEP->isInBounds()); NewGEP->takeName(GEP); return NewGEP; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Find all GEPs, and simplify them. // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool SimplifyGEP::runOnModule(Module& M) { TD = &getAnalysis<TargetData>(); preprocess(M); for (Module::iterator F = M.begin(); F != M.end(); ++F){ for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) { if(!(isa<GetElementPtrInst>(I))) continue; GetElementPtrInst *GEP = cast<GetElementPtrInst>(I); Value *PtrOp = GEP->getOperand(0); Value *StrippedPtr = PtrOp->stripPointerCasts(); // Check if the GEP base pointer is enclosed in a cast if (StrippedPtr != PtrOp) { const PointerType *StrippedPtrTy =cast<PointerType>(StrippedPtr->getType()); bool HasZeroPointerIndex = false; if (ConstantInt *C = dyn_cast<ConstantInt>(GEP->getOperand(1))) HasZeroPointerIndex = C->isZero(); // Transform: GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... // into : GEP [10 x i8]* X, i32 0, ... // // Likewise, transform: GEP (bitcast i8* X to [0 x i8]*), i32 0, ... // into : GEP i8* X, ... // // This occurs when the program declares an array extern like "int X[];" if (HasZeroPointerIndex) { const PointerType *CPTy = cast<PointerType>(PtrOp->getType()); if (const ArrayType *CATy = dyn_cast<ArrayType>(CPTy->getElementType())) { // GEP (bitcast i8* X to [0 x i8]*), i32 0, ... ? if (CATy->getElementType() == StrippedPtrTy->getElementType()) { // -> GEP i8* X, ... SmallVector<Value*, 8> Idx(GEP->idx_begin()+1, GEP->idx_end()); GetElementPtrInst *Res = GetElementPtrInst::Create(StrippedPtr, Idx, GEP->getName(), GEP); Res->setIsInBounds(GEP->isInBounds()); GEP->replaceAllUsesWith(Res); continue; } if (const ArrayType *XATy = dyn_cast<ArrayType>(StrippedPtrTy->getElementType())){ // GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ? if (CATy->getElementType() == XATy->getElementType()) { // -> GEP [10 x i8]* X, i32 0, ... // At this point, we know that the cast source type is a pointer // to an array of the same type as the destination pointer // array. Because the array type is never stepped over (there // is a leading zero) we can fold the cast into this GEP. GEP->setOperand(0, StrippedPtr); continue; } } } } else if (GEP->getNumOperands() == 2) { // Transform things like: // %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V // into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast Type *SrcElTy = StrippedPtrTy->getElementType(); Type *ResElTy=cast<PointerType>(PtrOp->getType())->getElementType(); if (TD && SrcElTy->isArrayTy() && TD->getTypeAllocSize(cast<ArrayType>(SrcElTy)->getElementType()) == TD->getTypeAllocSize(ResElTy)) { Value *Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext())); Idx[1] = GEP->getOperand(1); Value *NewGEP = GetElementPtrInst::Create(StrippedPtr, Idx, GEP->getName(), GEP); // V and GEP are both pointer types --> BitCast GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP)); continue; } // Transform things like: // getelementptr i8* bitcast ([100 x double]* X to i8*), i32 %tmp // (where tmp = 8*tmp2) into: // getelementptr [100 x double]* %arr, i32 0, i32 %tmp2; bitcast if (TD && SrcElTy->isArrayTy() && ResElTy->isIntegerTy(8)) { uint64_t ArrayEltSize = TD->getTypeAllocSize(cast<ArrayType>(SrcElTy)->getElementType()); // Check to see if "tmp" is a scale by a multiple of ArrayEltSize. We // allow either a mul, shift, or constant here. Value *NewIdx = 0; ConstantInt *Scale = 0; if (ArrayEltSize == 1) { NewIdx = GEP->getOperand(1); Scale = ConstantInt::get(cast<IntegerType>(NewIdx->getType()), 1); } else if (ConstantInt *CI = dyn_cast<ConstantInt>(GEP->getOperand(1))) { NewIdx = ConstantInt::get(CI->getType(), 1); Scale = CI; } else if (Instruction *Inst =dyn_cast<Instruction>(GEP->getOperand(1))){ if (Inst->getOpcode() == Instruction::Shl && isa<ConstantInt>(Inst->getOperand(1))) { ConstantInt *ShAmt = cast<ConstantInt>(Inst->getOperand(1)); uint32_t ShAmtVal = ShAmt->getLimitedValue(64); Scale = ConstantInt::get(cast<IntegerType>(Inst->getType()), 1ULL << ShAmtVal); NewIdx = Inst->getOperand(0); } else if (Inst->getOpcode() == Instruction::Mul && isa<ConstantInt>(Inst->getOperand(1))) { Scale = cast<ConstantInt>(Inst->getOperand(1)); NewIdx = Inst->getOperand(0); } } // If the index will be to exactly the right offset with the scale taken // out, perform the transformation. Note, we don't know whether Scale is // signed or not. We'll use unsigned version of division/modulo // operation after making sure Scale doesn't have the sign bit set. if (ArrayEltSize && Scale && Scale->getSExtValue() >= 0LL && Scale->getZExtValue() % ArrayEltSize == 0) { Scale = ConstantInt::get(Scale->getType(), Scale->getZExtValue() / ArrayEltSize); if (Scale->getZExtValue() != 1) { Constant *C = ConstantExpr::getIntegerCast(Scale, NewIdx->getType(), false /*ZExt*/); NewIdx = BinaryOperator::Create(BinaryOperator::Mul, NewIdx, C, "idxscale"); } // Insert the new GEP instruction. Value *Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext())); Idx[1] = NewIdx; Value *NewGEP = GetElementPtrInst::Create(StrippedPtr, Idx, GEP->getName(), GEP); GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP)); continue; } } } } } } } return true; }
bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { bool MadeChange = false; // Only prep. the inner-most loop if (!L->empty()) return MadeChange; DEBUG(dbgs() << "PIP: Examining: " << *L << "\n"); BasicBlock *Header = L->getHeader(); const PPCSubtarget *ST = TM ? TM->getSubtargetImpl(*Header->getParent()) : nullptr; unsigned HeaderLoopPredCount = std::distance(pred_begin(Header), pred_end(Header)); // Collect buckets of comparable addresses used by loads and stores. SmallVector<Bucket, 16> Buckets; for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); I != IE; ++I) { for (BasicBlock::iterator J = (*I)->begin(), JE = (*I)->end(); J != JE; ++J) { Value *PtrValue; Instruction *MemI; if (LoadInst *LMemI = dyn_cast<LoadInst>(J)) { MemI = LMemI; PtrValue = LMemI->getPointerOperand(); } else if (StoreInst *SMemI = dyn_cast<StoreInst>(J)) { MemI = SMemI; PtrValue = SMemI->getPointerOperand(); } else if (IntrinsicInst *IMemI = dyn_cast<IntrinsicInst>(J)) { if (IMemI->getIntrinsicID() == Intrinsic::prefetch) { MemI = IMemI; PtrValue = IMemI->getArgOperand(0); } else continue; } else continue; unsigned PtrAddrSpace = PtrValue->getType()->getPointerAddressSpace(); if (PtrAddrSpace) continue; // There are no update forms for Altivec vector load/stores. if (ST && ST->hasAltivec() && PtrValue->getType()->getPointerElementType()->isVectorTy()) continue; if (L->isLoopInvariant(PtrValue)) continue; const SCEV *LSCEV = SE->getSCEVAtScope(PtrValue, L); if (const SCEVAddRecExpr *LARSCEV = dyn_cast<SCEVAddRecExpr>(LSCEV)) { if (LARSCEV->getLoop() != L) continue; } else { continue; } bool FoundBucket = false; for (auto &B : Buckets) { const SCEV *Diff = SE->getMinusSCEV(LSCEV, B.BaseSCEV); if (const auto *CDiff = dyn_cast<SCEVConstant>(Diff)) { B.Elements.push_back(BucketElement(CDiff, MemI)); FoundBucket = true; break; } } if (!FoundBucket) { if (Buckets.size() == MaxVars) return MadeChange; Buckets.push_back(Bucket(LSCEV, MemI)); } } } if (Buckets.empty()) return MadeChange; BasicBlock *LoopPredecessor = L->getLoopPredecessor(); // If there is no loop predecessor, or the loop predecessor's terminator // returns a value (which might contribute to determining the loop's // iteration space), insert a new preheader for the loop. if (!LoopPredecessor || !LoopPredecessor->getTerminator()->getType()->isVoidTy()) { LoopPredecessor = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA); if (LoopPredecessor) MadeChange = true; } if (!LoopPredecessor) return MadeChange; DEBUG(dbgs() << "PIP: Found " << Buckets.size() << " buckets\n"); SmallSet<BasicBlock *, 16> BBChanged; for (unsigned i = 0, e = Buckets.size(); i != e; ++i) { // The base address of each bucket is transformed into a phi and the others // are rewritten as offsets of that variable. // We have a choice now of which instruction's memory operand we use as the // base for the generated PHI. Always picking the first instruction in each // bucket does not work well, specifically because that instruction might // be a prefetch (and there are no pre-increment dcbt variants). Otherwise, // the choice is somewhat arbitrary, because the backend will happily // generate direct offsets from both the pre-incremented and // post-incremented pointer values. Thus, we'll pick the first non-prefetch // instruction in each bucket, and adjust the recurrence and other offsets // accordingly. for (int j = 0, je = Buckets[i].Elements.size(); j != je; ++j) { if (auto *II = dyn_cast<IntrinsicInst>(Buckets[i].Elements[j].Instr)) if (II->getIntrinsicID() == Intrinsic::prefetch) continue; // If we'd otherwise pick the first element anyway, there's nothing to do. if (j == 0) break; // If our chosen element has no offset from the base pointer, there's // nothing to do. if (!Buckets[i].Elements[j].Offset || Buckets[i].Elements[j].Offset->isZero()) break; const SCEV *Offset = Buckets[i].Elements[j].Offset; Buckets[i].BaseSCEV = SE->getAddExpr(Buckets[i].BaseSCEV, Offset); for (auto &E : Buckets[i].Elements) { if (E.Offset) E.Offset = cast<SCEVConstant>(SE->getMinusSCEV(E.Offset, Offset)); else E.Offset = cast<SCEVConstant>(SE->getNegativeSCEV(Offset)); } std::swap(Buckets[i].Elements[j], Buckets[i].Elements[0]); break; } const SCEVAddRecExpr *BasePtrSCEV = cast<SCEVAddRecExpr>(Buckets[i].BaseSCEV); if (!BasePtrSCEV->isAffine()) continue; DEBUG(dbgs() << "PIP: Transforming: " << *BasePtrSCEV << "\n"); assert(BasePtrSCEV->getLoop() == L && "AddRec for the wrong loop?"); // The instruction corresponding to the Bucket's BaseSCEV must be the first // in the vector of elements. Instruction *MemI = Buckets[i].Elements.begin()->Instr; Value *BasePtr = GetPointerOperand(MemI); assert(BasePtr && "No pointer operand"); Type *I8Ty = Type::getInt8Ty(MemI->getParent()->getContext()); Type *I8PtrTy = Type::getInt8PtrTy(MemI->getParent()->getContext(), BasePtr->getType()->getPointerAddressSpace()); const SCEV *BasePtrStartSCEV = BasePtrSCEV->getStart(); if (!SE->isLoopInvariant(BasePtrStartSCEV, L)) continue; const SCEVConstant *BasePtrIncSCEV = dyn_cast<SCEVConstant>(BasePtrSCEV->getStepRecurrence(*SE)); if (!BasePtrIncSCEV) continue; BasePtrStartSCEV = SE->getMinusSCEV(BasePtrStartSCEV, BasePtrIncSCEV); if (!isSafeToExpand(BasePtrStartSCEV, *SE)) continue; DEBUG(dbgs() << "PIP: New start is: " << *BasePtrStartSCEV << "\n"); PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount, MemI->hasName() ? MemI->getName() + ".phi" : "", Header->getFirstNonPHI()); SCEVExpander SCEVE(*SE, Header->getModule()->getDataLayout(), "pistart"); Value *BasePtrStart = SCEVE.expandCodeFor(BasePtrStartSCEV, I8PtrTy, LoopPredecessor->getTerminator()); // Note that LoopPredecessor might occur in the predecessor list multiple // times, and we need to add it the right number of times. for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); PI != PE; ++PI) { if (*PI != LoopPredecessor) continue; NewPHI->addIncoming(BasePtrStart, LoopPredecessor); } Instruction *InsPoint = &*Header->getFirstInsertionPt(); GetElementPtrInst *PtrInc = GetElementPtrInst::Create( I8Ty, NewPHI, BasePtrIncSCEV->getValue(), MemI->hasName() ? MemI->getName() + ".inc" : "", InsPoint); PtrInc->setIsInBounds(IsPtrInBounds(BasePtr)); for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); PI != PE; ++PI) { if (*PI == LoopPredecessor) continue; NewPHI->addIncoming(PtrInc, *PI); } Instruction *NewBasePtr; if (PtrInc->getType() != BasePtr->getType()) NewBasePtr = new BitCastInst(PtrInc, BasePtr->getType(), PtrInc->hasName() ? PtrInc->getName() + ".cast" : "", InsPoint); else NewBasePtr = PtrInc; if (Instruction *IDel = dyn_cast<Instruction>(BasePtr)) BBChanged.insert(IDel->getParent()); BasePtr->replaceAllUsesWith(NewBasePtr); RecursivelyDeleteTriviallyDeadInstructions(BasePtr); // Keep track of the replacement pointer values we've inserted so that we // don't generate more pointer values than necessary. SmallPtrSet<Value *, 16> NewPtrs; NewPtrs.insert( NewBasePtr); for (auto I = std::next(Buckets[i].Elements.begin()), IE = Buckets[i].Elements.end(); I != IE; ++I) { Value *Ptr = GetPointerOperand(I->Instr); assert(Ptr && "No pointer operand"); if (NewPtrs.count(Ptr)) continue; Instruction *RealNewPtr; if (!I->Offset || I->Offset->getValue()->isZero()) { RealNewPtr = NewBasePtr; } else { Instruction *PtrIP = dyn_cast<Instruction>(Ptr); if (PtrIP && isa<Instruction>(NewBasePtr) && cast<Instruction>(NewBasePtr)->getParent() == PtrIP->getParent()) PtrIP = nullptr; else if (isa<PHINode>(PtrIP)) PtrIP = &*PtrIP->getParent()->getFirstInsertionPt(); else if (!PtrIP) PtrIP = I->Instr; GetElementPtrInst *NewPtr = GetElementPtrInst::Create( I8Ty, PtrInc, I->Offset->getValue(), I->Instr->hasName() ? I->Instr->getName() + ".off" : "", PtrIP); if (!PtrIP) NewPtr->insertAfter(cast<Instruction>(PtrInc)); NewPtr->setIsInBounds(IsPtrInBounds(Ptr)); RealNewPtr = NewPtr; } if (Instruction *IDel = dyn_cast<Instruction>(Ptr)) BBChanged.insert(IDel->getParent()); Instruction *ReplNewPtr; if (Ptr->getType() != RealNewPtr->getType()) { ReplNewPtr = new BitCastInst(RealNewPtr, Ptr->getType(), Ptr->hasName() ? Ptr->getName() + ".cast" : ""); ReplNewPtr->insertAfter(RealNewPtr); } else ReplNewPtr = RealNewPtr; Ptr->replaceAllUsesWith(ReplNewPtr); RecursivelyDeleteTriviallyDeadInstructions(Ptr); NewPtrs.insert(RealNewPtr); } MadeChange = true; } for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); I != IE; ++I) { if (BBChanged.count(*I)) DeleteDeadPHIs(*I); } return MadeChange; }
/// Rebuild a new instruction just like 'I' but with the new operands given. /// In the event of type mismatch, the type of the operands is correct. static Value *BuildNew(Instruction *I, ArrayRef<Value*> NewOps) { // We don't want to use the IRBuilder here because we want the replacement // instructions to appear next to 'I', not the builder's insertion point. switch (I->getOpcode()) { case Instruction::Add: case Instruction::FAdd: case Instruction::Sub: case Instruction::FSub: case Instruction::Mul: case Instruction::FMul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::FDiv: case Instruction::URem: case Instruction::SRem: case Instruction::FRem: case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: case Instruction::And: case Instruction::Or: case Instruction::Xor: { BinaryOperator *BO = cast<BinaryOperator>(I); assert(NewOps.size() == 2 && "binary operator with #ops != 2"); BinaryOperator *New = BinaryOperator::Create(cast<BinaryOperator>(I)->getOpcode(), NewOps[0], NewOps[1], "", BO); if (isa<OverflowingBinaryOperator>(BO)) { New->setHasNoUnsignedWrap(BO->hasNoUnsignedWrap()); New->setHasNoSignedWrap(BO->hasNoSignedWrap()); } if (isa<PossiblyExactOperator>(BO)) { New->setIsExact(BO->isExact()); } return New; } case Instruction::ICmp: assert(NewOps.size() == 2 && "icmp with #ops != 2"); return new ICmpInst(I, cast<ICmpInst>(I)->getPredicate(), NewOps[0], NewOps[1]); case Instruction::FCmp: assert(NewOps.size() == 2 && "fcmp with #ops != 2"); return new FCmpInst(I, cast<FCmpInst>(I)->getPredicate(), NewOps[0], NewOps[1]); case Instruction::Trunc: case Instruction::ZExt: case Instruction::SExt: case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::UIToFP: case Instruction::SIToFP: case Instruction::FPTrunc: case Instruction::FPExt: { // It's possible that the mask has a different number of elements from // the original cast. We recompute the destination type to match the mask. Type *DestTy = VectorType::get(I->getType()->getScalarType(), NewOps[0]->getType()->getVectorNumElements()); assert(NewOps.size() == 1 && "cast with #ops != 1"); return CastInst::Create(cast<CastInst>(I)->getOpcode(), NewOps[0], DestTy, "", I); } case Instruction::GetElementPtr: { Value *Ptr = NewOps[0]; ArrayRef<Value*> Idx = NewOps.slice(1); GetElementPtrInst *GEP = GetElementPtrInst::Create(Ptr, Idx, "", I); GEP->setIsInBounds(cast<GetElementPtrInst>(I)->isInBounds()); return GEP; } } llvm_unreachable("failed to rebuild vector instructions"); }
bool PPCLoopPreIncPrep::runOnLoop(Loop *L) { bool MadeChange = false; if (!DL) return MadeChange; // Only prep. the inner-most loop if (!L->empty()) return MadeChange; BasicBlock *Header = L->getHeader(); const PPCSubtarget *ST = TM ? TM->getSubtargetImpl(*Header->getParent()) : nullptr; unsigned HeaderLoopPredCount = 0; for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); PI != PE; ++PI) { ++HeaderLoopPredCount; } // Collect buckets of comparable addresses used by loads and stores. typedef std::multimap<const SCEV *, Instruction *, SCEVLess> Bucket; SmallVector<Bucket, 16> Buckets; for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); I != IE; ++I) { for (BasicBlock::iterator J = (*I)->begin(), JE = (*I)->end(); J != JE; ++J) { Value *PtrValue; Instruction *MemI; if (LoadInst *LMemI = dyn_cast<LoadInst>(J)) { MemI = LMemI; PtrValue = LMemI->getPointerOperand(); } else if (StoreInst *SMemI = dyn_cast<StoreInst>(J)) { MemI = SMemI; PtrValue = SMemI->getPointerOperand(); } else if (IntrinsicInst *IMemI = dyn_cast<IntrinsicInst>(J)) { if (IMemI->getIntrinsicID() == Intrinsic::prefetch) { MemI = IMemI; PtrValue = IMemI->getArgOperand(0); } else continue; } else continue; unsigned PtrAddrSpace = PtrValue->getType()->getPointerAddressSpace(); if (PtrAddrSpace) continue; // There are no update forms for Altivec vector load/stores. if (ST && ST->hasAltivec() && PtrValue->getType()->getPointerElementType()->isVectorTy()) continue; if (L->isLoopInvariant(PtrValue)) continue; const SCEV *LSCEV = SE->getSCEV(PtrValue); if (!isa<SCEVAddRecExpr>(LSCEV)) continue; bool FoundBucket = false; for (unsigned i = 0, e = Buckets.size(); i != e; ++i) for (Bucket::iterator K = Buckets[i].begin(), KE = Buckets[i].end(); K != KE; ++K) { const SCEV *Diff = SE->getMinusSCEV(K->first, LSCEV); if (isa<SCEVConstant>(Diff)) { Buckets[i].insert(std::make_pair(LSCEV, MemI)); FoundBucket = true; break; } } if (!FoundBucket) { Buckets.push_back(Bucket(SCEVLess(SE))); Buckets[Buckets.size()-1].insert(std::make_pair(LSCEV, MemI)); } } } if (Buckets.empty() || Buckets.size() > MaxVars) return MadeChange; BasicBlock *LoopPredecessor = L->getLoopPredecessor(); // If there is no loop predecessor, or the loop predecessor's terminator // returns a value (which might contribute to determining the loop's // iteration space), insert a new preheader for the loop. if (!LoopPredecessor || !LoopPredecessor->getTerminator()->getType()->isVoidTy()) LoopPredecessor = InsertPreheaderForLoop(L, this); if (!LoopPredecessor) return MadeChange; SmallSet<BasicBlock *, 16> BBChanged; for (unsigned i = 0, e = Buckets.size(); i != e; ++i) { // The base address of each bucket is transformed into a phi and the others // are rewritten as offsets of that variable. const SCEVAddRecExpr *BasePtrSCEV = cast<SCEVAddRecExpr>(Buckets[i].begin()->first); if (!BasePtrSCEV->isAffine()) continue; Instruction *MemI = Buckets[i].begin()->second; Value *BasePtr = GetPointerOperand(MemI); assert(BasePtr && "No pointer operand"); Type *I8PtrTy = Type::getInt8PtrTy(MemI->getParent()->getContext(), BasePtr->getType()->getPointerAddressSpace()); const SCEV *BasePtrStartSCEV = BasePtrSCEV->getStart(); if (!SE->isLoopInvariant(BasePtrStartSCEV, L)) continue; const SCEVConstant *BasePtrIncSCEV = dyn_cast<SCEVConstant>(BasePtrSCEV->getStepRecurrence(*SE)); if (!BasePtrIncSCEV) continue; BasePtrStartSCEV = SE->getMinusSCEV(BasePtrStartSCEV, BasePtrIncSCEV); if (!isSafeToExpand(BasePtrStartSCEV, *SE)) continue; PHINode *NewPHI = PHINode::Create(I8PtrTy, HeaderLoopPredCount, MemI->hasName() ? MemI->getName() + ".phi" : "", Header->getFirstNonPHI()); SCEVExpander SCEVE(*SE, "pistart"); Value *BasePtrStart = SCEVE.expandCodeFor(BasePtrStartSCEV, I8PtrTy, LoopPredecessor->getTerminator()); // Note that LoopPredecessor might occur in the predecessor list multiple // times, and we need to add it the right number of times. for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); PI != PE; ++PI) { if (*PI != LoopPredecessor) continue; NewPHI->addIncoming(BasePtrStart, LoopPredecessor); } Instruction *InsPoint = Header->getFirstInsertionPt(); GetElementPtrInst *PtrInc = GetElementPtrInst::Create(NewPHI, BasePtrIncSCEV->getValue(), MemI->hasName() ? MemI->getName() + ".inc" : "", InsPoint); PtrInc->setIsInBounds(IsPtrInBounds(BasePtr)); for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); PI != PE; ++PI) { if (*PI == LoopPredecessor) continue; NewPHI->addIncoming(PtrInc, *PI); } Instruction *NewBasePtr; if (PtrInc->getType() != BasePtr->getType()) NewBasePtr = new BitCastInst(PtrInc, BasePtr->getType(), PtrInc->hasName() ? PtrInc->getName() + ".cast" : "", InsPoint); else NewBasePtr = PtrInc; if (Instruction *IDel = dyn_cast<Instruction>(BasePtr)) BBChanged.insert(IDel->getParent()); BasePtr->replaceAllUsesWith(NewBasePtr); RecursivelyDeleteTriviallyDeadInstructions(BasePtr); Value *LastNewPtr = NewBasePtr; for (Bucket::iterator I = std::next(Buckets[i].begin()), IE = Buckets[i].end(); I != IE; ++I) { Value *Ptr = GetPointerOperand(I->second); assert(Ptr && "No pointer operand"); if (Ptr == LastNewPtr) continue; Instruction *RealNewPtr; const SCEVConstant *Diff = cast<SCEVConstant>(SE->getMinusSCEV(I->first, BasePtrSCEV)); if (Diff->isZero()) { RealNewPtr = NewBasePtr; } else { Instruction *PtrIP = dyn_cast<Instruction>(Ptr); if (PtrIP && isa<Instruction>(NewBasePtr) && cast<Instruction>(NewBasePtr)->getParent() == PtrIP->getParent()) PtrIP = 0; else if (isa<PHINode>(PtrIP)) PtrIP = PtrIP->getParent()->getFirstInsertionPt(); else if (!PtrIP) PtrIP = I->second; GetElementPtrInst *NewPtr = GetElementPtrInst::Create(PtrInc, Diff->getValue(), I->second->hasName() ? I->second->getName() + ".off" : "", PtrIP); if (!PtrIP) NewPtr->insertAfter(cast<Instruction>(PtrInc)); NewPtr->setIsInBounds(IsPtrInBounds(Ptr)); RealNewPtr = NewPtr; } if (Instruction *IDel = dyn_cast<Instruction>(Ptr)) BBChanged.insert(IDel->getParent()); Instruction *ReplNewPtr; if (Ptr->getType() != RealNewPtr->getType()) { ReplNewPtr = new BitCastInst(RealNewPtr, Ptr->getType(), Ptr->hasName() ? Ptr->getName() + ".cast" : ""); ReplNewPtr->insertAfter(RealNewPtr); } else ReplNewPtr = RealNewPtr; Ptr->replaceAllUsesWith(ReplNewPtr); RecursivelyDeleteTriviallyDeadInstructions(Ptr); LastNewPtr = RealNewPtr; } MadeChange = true; } for (Loop::block_iterator I = L->block_begin(), IE = L->block_end(); I != IE; ++I) { if (BBChanged.count(*I)) DeleteDeadPHIs(*I); } return MadeChange; }
void FaultInjectionPass::insertInjectionFuncCall( std::map<Instruction*, std::list< int >* > *inst_regs_map, Module &M) { for (std::map<Instruction*, std::list< int >* >::iterator inst_reg_it = inst_regs_map->begin(); inst_reg_it != inst_regs_map->end(); ++inst_reg_it) { Instruction *fi_inst = inst_reg_it->first; std::list<int> *fi_reg_pos_list = inst_reg_it->second; unsigned reg_index = 0; unsigned total_reg_num = fi_reg_pos_list->size(); for (std::list<int>::iterator reg_pos_it = fi_reg_pos_list->begin(); reg_pos_it != fi_reg_pos_list->end(); ++reg_pos_it, ++reg_index) { if(isa<GetElementPtrInst>(fi_inst)){ GetElementPtrInst* gepi = dyn_cast<GetElementPtrInst>(fi_inst); gepi->setIsInBounds(false); } if(isa<CallInst>(fi_inst)){ CallInst* ci = dyn_cast<CallInst>(fi_inst); ci->setTailCall(false); } Value* fi_reg = NULL; if(*reg_pos_it == DST_REG_POS) fi_reg = fi_inst; else fi_reg = fi_inst->getOperand(*reg_pos_it); //if(isa<Constant>(fi_reg)) continue; Type *returntype = fi_reg->getType(); LLVMContext &context = M.getContext(); Type *i64type = Type::getInt64Ty(context); Type *i32type = Type::getInt32Ty(context); // function declaration std::vector<Type*> paramtypes(7); paramtypes[0] = i64type; // llfi index paramtypes[1] = returntype; // the instruction to be injected paramtypes[2] = i32type; // opcode paramtypes[3] = i32type; // current fi reg index paramtypes[4] = i32type; // total fi reg number //======== Add reg_pos QINING @DEC 23rd ========== paramtypes[5] = i32type; //================================================ //======== Add opcode_str QINING @MAR 11th======== paramtypes[6] = PointerType::get(Type::getInt8Ty(context), 0); //================================================ //LLVM 3.3 Upgrade ArrayRef<Type*> paramtypes_array_ref(paramtypes); FunctionType* injectfunctype = FunctionType::get(returntype, paramtypes_array_ref, false); std::string funcname = getFIFuncNameforType(returntype); Constant *injectfunc = M.getOrInsertFunction(funcname, injectfunctype); // argument preparation for calling function // since the source register is another way of simulating fault // injection into "the instruction", use instruction's index instead Value *indexval = ConstantInt::get(i64type, getLLFIIndexofInst(fi_inst)); std::vector<Value*> args(7); args[0] = indexval; //llfi index args[1] = fi_reg; // target register args[2] = ConstantInt::get(i32type, fi_inst->getOpcode()); // opcode in i32 args[3] = ConstantInt::get(i32type, reg_index); // reg_index not reg_pos args[4] = ConstantInt::get(i32type, total_reg_num); // total_reg_num //======== Add reg_pos QINING @DEC 23rd ========== args[5] = ConstantInt::get(i32type, *reg_pos_it+1); // dstreg->0, operand0->1, operand1->2 ... //================================================ //======== Add opcode_str QINING @MAR 11th======== std::string opcode_str = fi_inst->getOpcodeName(); GlobalVariable* opcode_str_gv = findOrCreateGlobalNameString(M, opcode_str); std::vector<Constant*> indices_for_gep(2); indices_for_gep[0] = ConstantInt::get(Type::getInt32Ty(context),0); indices_for_gep[1] = ConstantInt::get(Type::getInt32Ty(context),0); ArrayRef<Constant*> indices_for_gep_array_ref(indices_for_gep); Constant* gep_expr = ConstantExpr::getGetElementPtr(opcode_str_gv, indices_for_gep_array_ref, true); args[6] = gep_expr; // opcode in string //================================================ // LLVM 3.3 Upgrade ArrayRef<Value*> args_array_ref(args); Instruction *insertptr = getInsertPtrforRegsofInst(fi_reg, fi_inst); Instruction* ficall = CallInst::Create( injectfunc, args_array_ref, "fi", insertptr); setInjectFaultInst(fi_reg, fi_inst, ficall); // sets the instruction metadata // redirect the data dependencies if (fi_reg == fi_inst) { // inject into destination std::list<User*> inst_uses; for (Value::use_iterator use_it = fi_inst->use_begin(); use_it != fi_inst->use_end(); ++use_it) { User *user = *use_it; if (user != ficall) { inst_uses.push_back(user); } } for (std::list<User*>::iterator use_it = inst_uses.begin(); use_it != inst_uses.end(); ++use_it) { User *user = *use_it; user->replaceUsesOfWith(fi_inst, ficall); // update the selected inst pool /*if (Instruction *use_inst = dyn_cast<Instruction>(user)) { if (inst_regs_map->find(use_inst) != inst_regs_map->end()) { std::list<int> *reg_pos_list = (*inst_regs_map)[use_inst]; for (std::list<int>::iterator reg_pos_it = reg_pos_list->begin(); reg_pos_it != reg_pos_list->end(); ++reg_pos_it) { if (use_inst->getOperand(*reg_pos_it) == fi_inst) { use_inst->setOperand(*reg_pos_it, ficall); } } } }*/ } } else { // inject into source //fi_inst->replaceUsesOfWith(fi_reg, ficall); fi_inst->setOperand(*reg_pos_it, ficall); } } } }
/// InsertPHITranslatedPointer - Insert a computation of the PHI translated /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB /// block. All newly created instructions are added to the NewInsts list. /// This returns null on failure. /// Value *PHITransAddr:: InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, BasicBlock *PredBB, const DominatorTree &DT, SmallVectorImpl<Instruction*> &NewInsts) { // See if we have a version of this value already available and dominating // PredBB. If so, there is no need to insert a new instance of it. PHITransAddr Tmp(InVal, TD); if (!Tmp.PHITranslateValue(CurBB, PredBB, &DT)) return Tmp.getAddr(); // If we don't have an available version of this value, it must be an // instruction. Instruction *Inst = cast<Instruction>(InVal); // Handle bitcast of PHI translatable value. if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) { Value *OpVal = InsertPHITranslatedSubExpr(BC->getOperand(0), CurBB, PredBB, DT, NewInsts); if (OpVal == 0) return 0; // Otherwise insert a bitcast at the end of PredBB. BitCastInst *New = new BitCastInst(OpVal, InVal->getType(), InVal->getName()+".phi.trans.insert", PredBB->getTerminator()); NewInsts.push_back(New); return New; } // Handle getelementptr with at least one PHI operand. if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) { SmallVector<Value*, 8> GEPOps; BasicBlock *CurBB = GEP->getParent(); for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { Value *OpVal = InsertPHITranslatedSubExpr(GEP->getOperand(i), CurBB, PredBB, DT, NewInsts); if (OpVal == 0) return 0; GEPOps.push_back(OpVal); } GetElementPtrInst *Result = GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(), InVal->getName()+".phi.trans.insert", PredBB->getTerminator()); Result->setIsInBounds(GEP->isInBounds()); NewInsts.push_back(Result); return Result; } #if 0 // FIXME: This code works, but it is unclear that we actually want to insert // a big chain of computation in order to make a value available in a block. // This needs to be evaluated carefully to consider its cost trade offs. // Handle add with a constant RHS. if (Inst->getOpcode() == Instruction::Add && isa<ConstantInt>(Inst->getOperand(1))) { // PHI translate the LHS. Value *OpVal = InsertPHITranslatedSubExpr(Inst->getOperand(0), CurBB, PredBB, DT, NewInsts); if (OpVal == 0) return 0; BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1), InVal->getName()+".phi.trans.insert", PredBB->getTerminator()); Res->setHasNoSignedWrap(cast<BinaryOperator>(Inst)->hasNoSignedWrap()); Res->setHasNoUnsignedWrap(cast<BinaryOperator>(Inst)->hasNoUnsignedWrap()); NewInsts.push_back(Res); return Res; } #endif return 0; }
GetElementPtrInst * NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *GEP, unsigned I, Value *LHS, Value *RHS, Type *IndexedType) { // Look for GEP's closest dominator that has the same SCEV as GEP except that // the I-th index is replaced with LHS. SmallVector<const SCEV *, 4> IndexExprs; for (auto Index = GEP->idx_begin(); Index != GEP->idx_end(); ++Index) IndexExprs.push_back(SE->getSCEV(*Index)); // Replace the I-th index with LHS. IndexExprs[I] = SE->getSCEV(LHS); if (isKnownNonNegative(LHS, *DL, 0, AC, GEP, DT) && DL->getTypeSizeInBits(LHS->getType()) < DL->getTypeSizeInBits(GEP->getOperand(I)->getType())) { // Zero-extend LHS if it is non-negative. InstCombine canonicalizes sext to // zext if the source operand is proved non-negative. We should do that // consistently so that CandidateExpr more likely appears before. See // @reassociate_gep_assume for an example of this canonicalization. IndexExprs[I] = SE->getZeroExtendExpr(IndexExprs[I], GEP->getOperand(I)->getType()); } const SCEV *CandidateExpr = SE->getGEPExpr(cast<GEPOperator>(GEP), IndexExprs); Value *Candidate = findClosestMatchingDominator(CandidateExpr, GEP); if (Candidate == nullptr) return nullptr; IRBuilder<> Builder(GEP); // Candidate does not necessarily have the same pointer type as GEP. Use // bitcast or pointer cast to make sure they have the same type, so that the // later RAUW doesn't complain. Candidate = Builder.CreateBitOrPointerCast(Candidate, GEP->getType()); assert(Candidate->getType() == GEP->getType()); // NewGEP = (char *)Candidate + RHS * sizeof(IndexedType) uint64_t IndexedSize = DL->getTypeAllocSize(IndexedType); Type *ElementType = GEP->getResultElementType(); uint64_t ElementSize = DL->getTypeAllocSize(ElementType); // Another less rare case: because I is not necessarily the last index of the // GEP, the size of the type at the I-th index (IndexedSize) is not // necessarily divisible by ElementSize. For example, // // #pragma pack(1) // struct S { // int a[3]; // int64 b[8]; // }; // #pragma pack() // // sizeof(S) = 100 is indivisible by sizeof(int64) = 8. // // TODO: bail out on this case for now. We could emit uglygep. if (IndexedSize % ElementSize != 0) return nullptr; // NewGEP = &Candidate[RHS * (sizeof(IndexedType) / sizeof(Candidate[0]))); Type *IntPtrTy = DL->getIntPtrType(GEP->getType()); if (RHS->getType() != IntPtrTy) RHS = Builder.CreateSExtOrTrunc(RHS, IntPtrTy); if (IndexedSize != ElementSize) { RHS = Builder.CreateMul( RHS, ConstantInt::get(IntPtrTy, IndexedSize / ElementSize)); } GetElementPtrInst *NewGEP = cast<GetElementPtrInst>(Builder.CreateGEP(Candidate, RHS)); NewGEP->setIsInBounds(GEP->isInBounds()); NewGEP->takeName(GEP); return NewGEP; }