[IRBuilder] Add IsInBounds parameter to CreateGEP()

We commonly want to create either an inbounds or non-inbounds GEP
based on a boolean value, e.g. when preserving inbounds from
existing GEPs. Directly accept such a boolean in the API, rather
than requiring a ternary between CreateGEP and CreateInBoundsGEP.

This change is not entirely NFC, because we now preserve an
inbounds flag in a constant expression edge-case in InstCombine.
This commit is contained in:
Nikita Popov 2022-05-13 12:48:52 +02:00
parent 8e6d481f3b
commit ed1cb01baf
8 changed files with 48 additions and 97 deletions

View File

@ -1723,17 +1723,18 @@ public:
}
Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, /*IsInBounds=*/false))
const Twine &Name = "", bool IsInBounds = false) {
if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, IsInBounds))
return V;
return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name);
return Insert(IsInBounds
? GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList)
: GetElementPtrInst::Create(Ty, Ptr, IdxList),
Name);
}
Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
if (auto *V = Folder.FoldGEP(Ty, Ptr, IdxList, /*IsInBounds=*/true))
return V;
return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name);
return CreateGEP(Ty, Ptr, IdxList, Name, /* IsInBounds */ true);
}
Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0,

View File

@ -5324,11 +5324,8 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
// SDAG consecutive load/store merging.
if (ResultPtr->getType() != I8PtrTy)
ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy);
ResultPtr =
AddrMode.InBounds
? Builder.CreateInBoundsGEP(I8Ty, ResultPtr, ResultIndex,
"sunkaddr")
: Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr");
ResultPtr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex,
"sunkaddr", AddrMode.InBounds);
}
ResultIndex = V;
@ -5339,11 +5336,8 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
} else {
if (ResultPtr->getType() != I8PtrTy)
ResultPtr = Builder.CreatePointerCast(ResultPtr, I8PtrTy);
SunkAddr =
AddrMode.InBounds
? Builder.CreateInBoundsGEP(I8Ty, ResultPtr, ResultIndex,
"sunkaddr")
: Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr");
SunkAddr = Builder.CreateGEP(I8Ty, ResultPtr, ResultIndex, "sunkaddr",
AddrMode.InBounds);
}
if (SunkAddr->getType() != Addr->getType())

View File

@ -278,15 +278,10 @@ Value *GenericToNVVM::remapConstantExpr(Module *M, Function *F, ConstantExpr *C,
C->getIndices());
case Instruction::GetElementPtr:
// GetElementPtrConstantExpr
return cast<GEPOperator>(C)->isInBounds()
? Builder.CreateGEP(
cast<GEPOperator>(C)->getSourceElementType(),
NewOperands[0],
makeArrayRef(&NewOperands[1], NumOperands - 1))
: Builder.CreateInBoundsGEP(
cast<GEPOperator>(C)->getSourceElementType(),
NewOperands[0],
makeArrayRef(&NewOperands[1], NumOperands - 1));
return Builder.CreateGEP(cast<GEPOperator>(C)->getSourceElementType(),
NewOperands[0],
makeArrayRef(&NewOperands[1], NumOperands - 1), "",
cast<GEPOperator>(C)->isInBounds());
case Instruction::Select:
// SelectConstantExpr
return Builder.CreateSelect(NewOperands[0], NewOperands[1], NewOperands[2]);

View File

@ -1943,10 +1943,8 @@ static Instruction *foldSelectGEP(GetElementPtrInst &GEP,
SmallVector<Value *, 4> IndexC(GEP.indices());
bool IsInBounds = GEP.isInBounds();
Type *Ty = GEP.getSourceElementType();
Value *NewTrueC = IsInBounds ? Builder.CreateInBoundsGEP(Ty, TrueC, IndexC)
: Builder.CreateGEP(Ty, TrueC, IndexC);
Value *NewFalseC = IsInBounds ? Builder.CreateInBoundsGEP(Ty, FalseC, IndexC)
: Builder.CreateGEP(Ty, FalseC, IndexC);
Value *NewTrueC = Builder.CreateGEP(Ty, TrueC, IndexC, "", IsInBounds);
Value *NewFalseC = Builder.CreateGEP(Ty, FalseC, IndexC, "", IsInBounds);
return SelectInst::Create(Cond, NewTrueC, NewFalseC, "", nullptr, Sel);
}
@ -2000,11 +1998,9 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
// -- have to recreate %src & %gep
// put NewSrc at same location as %src
Builder.SetInsertPoint(cast<Instruction>(Src));
Value *NewSrc = Builder.CreateGEP(
GEP.getSourceElementType(), SO0, GO1, Src->getName());
// Propagate 'inbounds' if the new source was not constant-folded.
if (auto *NewSrcGEPI = dyn_cast<GetElementPtrInst>(NewSrc))
NewSrcGEPI->setIsInBounds(Src->isInBounds());
Value *NewSrc =
Builder.CreateGEP(GEP.getSourceElementType(), SO0, GO1,
Src->getName(), Src->isInBounds());
GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
GEP.getSourceElementType(), NewSrc, {SO1});
NewGEP->setIsInBounds(GEP.isInBounds());
@ -2178,9 +2174,8 @@ Instruction *InstCombinerImpl::visitGEPOfBitcast(BitCastInst *BCI,
// existing GEP Value. Causing issues if this Value is accessed when
// constructing an AddrSpaceCastInst
SmallVector<Value *, 8> Indices(GEP.indices());
Value *NGEP = GEP.isInBounds()
? Builder.CreateInBoundsGEP(SrcEltType, SrcOp, Indices)
: Builder.CreateGEP(SrcEltType, SrcOp, Indices);
Value *NGEP =
Builder.CreateGEP(SrcEltType, SrcOp, Indices, "", GEP.isInBounds());
NGEP->takeName(&GEP);
// Preserve GEP address space to satisfy users
@ -2231,12 +2226,10 @@ Instruction *InstCombinerImpl::visitGEPOfBitcast(BitCastInst *BCI,
// Otherwise, if the offset is non-zero, we need to find out if there is a
// field at Offset in 'A's type. If so, we can pull the cast through the
// GEP.
SmallVector<Value*, 8> NewIndices;
SmallVector<Value *, 8> NewIndices;
if (findElementAtOffset(SrcType, Offset.getSExtValue(), NewIndices, DL)) {
Value *NGEP =
GEP.isInBounds()
? Builder.CreateInBoundsGEP(SrcEltType, SrcOp, NewIndices)
: Builder.CreateGEP(SrcEltType, SrcOp, NewIndices);
Value *NGEP = Builder.CreateGEP(SrcEltType, SrcOp, NewIndices, "",
GEP.isInBounds());
if (NGEP->getType() == GEP.getType())
return replaceInstUsesWith(GEP, NGEP);
@ -2539,11 +2532,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// addrspacecast i8 addrspace(1)* %0 to i8*
SmallVector<Value *, 8> Idx(GEP.indices());
Value *NewGEP =
GEP.isInBounds()
? Builder.CreateInBoundsGEP(StrippedPtrEltTy, StrippedPtr,
Idx, GEP.getName())
: Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Idx,
GEP.getName());
Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Idx,
GEP.getName(), GEP.isInBounds());
return new AddrSpaceCastInst(NewGEP, GEPType);
}
}
@ -2558,13 +2548,9 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
DL.getTypeAllocSize(StrippedPtrEltTy->getArrayElementType()) ==
DL.getTypeAllocSize(GEPEltType)) {
Type *IdxType = DL.getIndexType(GEPType);
Value *Idx[2] = { Constant::getNullValue(IdxType), GEP.getOperand(1) };
Value *NewGEP =
GEP.isInBounds()
? Builder.CreateInBoundsGEP(StrippedPtrEltTy, StrippedPtr, Idx,
GEP.getName())
: Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Idx,
GEP.getName());
Value *Idx[2] = {Constant::getNullValue(IdxType), GEP.getOperand(1)};
Value *NewGEP = Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Idx,
GEP.getName(), GEP.isInBounds());
// V and GEP are both pointer types --> BitCast
return CastInst::CreatePointerBitCastOrAddrSpaceCast(NewGEP, GEPType);
@ -2596,11 +2582,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// If the multiplication NewIdx * Scale may overflow then the new
// GEP may not be "inbounds".
Value *NewGEP =
GEP.isInBounds() && NSW
? Builder.CreateInBoundsGEP(StrippedPtrEltTy, StrippedPtr,
NewIdx, GEP.getName())
: Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, NewIdx,
GEP.getName());
Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, NewIdx,
GEP.getName(), GEP.isInBounds() && NSW);
// The NewGEP must be pointer typed, so must the old one -> BitCast
return CastInst::CreatePointerBitCastOrAddrSpaceCast(NewGEP,
@ -2641,11 +2624,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Value *Off[2] = {Constant::getNullValue(IndTy), NewIdx};
Value *NewGEP =
GEP.isInBounds() && NSW
? Builder.CreateInBoundsGEP(StrippedPtrEltTy, StrippedPtr,
Off, GEP.getName())
: Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Off,
GEP.getName());
Builder.CreateGEP(StrippedPtrEltTy, StrippedPtr, Off,
GEP.getName(), GEP.isInBounds() && NSW);
// The NewGEP must be pointer typed, so must the old one -> BitCast
return CastInst::CreatePointerBitCastOrAddrSpaceCast(NewGEP,
GEPType);

View File

@ -3474,19 +3474,13 @@ private:
Type *Ty = GEPI.getSourceElementType();
Value *True = Sel->getTrueValue();
Value *NTrue =
IsInBounds
? IRB.CreateInBoundsGEP(Ty, True, Index,
True->getName() + ".sroa.gep")
: IRB.CreateGEP(Ty, True, Index, True->getName() + ".sroa.gep");
Value *NTrue = IRB.CreateGEP(Ty, True, Index, True->getName() + ".sroa.gep",
IsInBounds);
Value *False = Sel->getFalseValue();
Value *NFalse =
IsInBounds
? IRB.CreateInBoundsGEP(Ty, False, Index,
False->getName() + ".sroa.gep")
: IRB.CreateGEP(Ty, False, Index, False->getName() + ".sroa.gep");
Value *NFalse = IRB.CreateGEP(Ty, False, Index,
False->getName() + ".sroa.gep", IsInBounds);
Value *NSel = IRB.CreateSelect(Sel->getCondition(), NTrue, NFalse,
Sel->getName() + ".sroa.sel");
@ -3540,10 +3534,8 @@ private:
IRB.SetInsertPoint(In->getParent(), std::next(In->getIterator()));
Type *Ty = GEPI.getSourceElementType();
NewVal = IsInBounds ? IRB.CreateInBoundsGEP(Ty, In, Index,
In->getName() + ".sroa.gep")
: IRB.CreateGEP(Ty, In, Index,
In->getName() + ".sroa.gep");
NewVal = IRB.CreateGEP(Ty, In, Index, In->getName() + ".sroa.gep",
IsInBounds);
}
NewPN->addIncoming(NewVal, B);
}

View File

@ -682,24 +682,16 @@ void StraightLineStrengthReduce::rewriteCandidateWithBasis(
unsigned AS = Basis.Ins->getType()->getPointerAddressSpace();
Type *CharTy = Type::getInt8PtrTy(Basis.Ins->getContext(), AS);
Reduced = Builder.CreateBitCast(Basis.Ins, CharTy);
if (InBounds)
Reduced =
Builder.CreateInBoundsGEP(Builder.getInt8Ty(), Reduced, Bump);
else
Reduced = Builder.CreateGEP(Builder.getInt8Ty(), Reduced, Bump);
Reduced =
Builder.CreateGEP(Builder.getInt8Ty(), Reduced, Bump, "", InBounds);
Reduced = Builder.CreateBitCast(Reduced, C.Ins->getType());
} else {
// C = gep Basis, Bump
// Canonicalize bump to pointer size.
Bump = Builder.CreateSExtOrTrunc(Bump, IntPtrTy);
if (InBounds)
Reduced = Builder.CreateInBoundsGEP(
cast<GetElementPtrInst>(Basis.Ins)->getResultElementType(),
Basis.Ins, Bump);
else
Reduced = Builder.CreateGEP(
cast<GetElementPtrInst>(Basis.Ins)->getResultElementType(),
Basis.Ins, Bump);
Reduced = Builder.CreateGEP(
cast<GetElementPtrInst>(Basis.Ins)->getResultElementType(),
Basis.Ins, Bump, "", InBounds);
}
break;
}

View File

@ -9469,11 +9469,8 @@ void VPWidenGEPRecipe::execute(VPTransformState &State) {
// Create the new GEP. Note that this GEP may be a scalar if VF == 1,
// but it should be a vector, otherwise.
auto *NewGEP = IsInBounds
? State.Builder.CreateInBoundsGEP(
GEP->getSourceElementType(), Ptr, Indices)
: State.Builder.CreateGEP(GEP->getSourceElementType(),
Ptr, Indices);
auto *NewGEP = State.Builder.CreateGEP(GEP->getSourceElementType(), Ptr,
Indices, "", IsInBounds);
assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) &&
"NewGEP is not a pointer vector");
State.set(this, NewGEP, Part);

View File

@ -195,7 +195,7 @@ define void @PR51485(<2 x i64> %v) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[SL1:%.*]] = shl nuw nsw <2 x i64> [[V:%.*]], <i64 7, i64 7>
; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, i8* getelementptr (i8, i8* bitcast (void (<2 x i64>)* @PR51485 to i8*), i64 80), <2 x i64> [[SL1]]
; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, i8* getelementptr inbounds (i8, i8* bitcast (void (<2 x i64>)* @PR51485 to i8*), i64 80), <2 x i64> [[SL1]]
; CHECK-NEXT: call void @blackhole(<2 x i8*> [[E6]])
; CHECK-NEXT: br label [[LOOP]]
;