Skip to content

Commit 187e897

Browse files
committed
Support flags on GEP constant expressions as well
1 parent b74cc98 commit 187e897

File tree

13 files changed

+126
-42
lines changed

13 files changed

+126
-42
lines changed

clang/lib/CodeGen/CGVTT.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
8787
unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
8888
llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
8989
llvm::APInt(32, VTableSize - Offset, true));
90+
// TODO(gep_nowrap): Set nuw as well.
9091
llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
91-
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
92+
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, /*NUSW=*/true,
93+
/*NUW=*/false, InRange);
9294

9395
VTTComponents.push_back(Init);
9496
}

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1901,8 +1901,10 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
19011901
unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex;
19021902
llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true),
19031903
llvm::APInt(32, VTableSize - Offset, true));
1904+
// TODO(gep_nowrap): Set nuw as well.
19041905
return llvm::ConstantExpr::getGetElementPtr(
1905-
VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
1906+
VTable->getValueType(), VTable, Indices, /*InBounds=*/true, /*NUSW=*/true,
1907+
/*NUW=*/false, InRange);
19061908
}
19071909

19081910
// Check whether all the non-inline virtual methods for the class have the

llvm/docs/LangRef.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11351,6 +11351,10 @@ These rules are based on the assumption that no allocated object may cross
1135111351
the unsigned address space boundary, and no allocated object may be larger
1135211352
than half the pointer index type space.
1135311353

11354+
If ``inbounds`` is present on a ``getelementptr`` instruction, the ``nusw``
11355+
attribute will be automatically set as well. For this reason, the ``nusw``
11356+
will also not be printed in textual IR if ``inbounds`` is already present.
11357+
1135411358
If the ``inrange(Start, End)`` attribute is present, loading from or
1135511359
storing to any pointer derived from the ``getelementptr`` has undefined
1135611360
behavior if the load or store would access memory outside the half-open range

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ enum ConstantsCodes {
385385
CST_CODE_CSTRING = 9, // CSTRING: [values]
386386
CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval]
387387
CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval]
388-
CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands]
388+
CST_CODE_CE_GEP_OLD = 12, // CE_GEP: [n x operands]
389389
CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval]
390390
CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval]
391391
CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval]
@@ -412,6 +412,7 @@ enum ConstantsCodes {
412412
// asmdialect|unwind,
413413
// asmstr,conststr]
414414
CST_CODE_CE_GEP_WITH_INRANGE = 31, // [opty, flags, range, n x operands]
415+
CST_CODE_CE_GEP = 32, // [opty, flags, n x operands]
415416
};
416417

417418
/// CastOpcodes - These are values used in the bitcode files to encode which

llvm/include/llvm/IR/Constants.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,26 +1198,27 @@ class ConstantExpr : public Constant {
11981198
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
11991199
static Constant *
12001200
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList,
1201-
bool InBounds = false,
1201+
bool InBounds = false, bool NUSW = false, bool NUW = false,
12021202
std::optional<ConstantRange> InRange = std::nullopt,
12031203
Type *OnlyIfReducedTy = nullptr) {
12041204
return getGetElementPtr(
12051205
Ty, C, ArrayRef((Value *const *)IdxList.data(), IdxList.size()),
1206-
InBounds, InRange, OnlyIfReducedTy);
1206+
InBounds, NUSW, NUW, InRange, OnlyIfReducedTy);
12071207
}
12081208
static Constant *
12091209
getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false,
1210+
bool NUSW = false, bool NUW = false,
12101211
std::optional<ConstantRange> InRange = std::nullopt,
12111212
Type *OnlyIfReducedTy = nullptr) {
12121213
// This form of the function only exists to avoid ambiguous overload
12131214
// warnings about whether to convert Idx to ArrayRef<Constant *> or
12141215
// ArrayRef<Value *>.
1215-
return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, InRange,
1216-
OnlyIfReducedTy);
1216+
return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, NUSW, NUW,
1217+
InRange, OnlyIfReducedTy);
12171218
}
12181219
static Constant *
12191220
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList,
1220-
bool InBounds = false,
1221+
bool InBounds = false, bool NUSW = false, bool NUW = false,
12211222
std::optional<ConstantRange> InRange = std::nullopt,
12221223
Type *OnlyIfReducedTy = nullptr);
12231224

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,10 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
856856
if (!Any)
857857
return nullptr;
858858

859+
// TODO(gep_nowrap): Preserve NUSW/NUW here.
859860
Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs,
860-
InBounds, InRange);
861+
InBounds, /*NUSW=*/InBounds,
862+
/*NUW=*/false, InRange);
861863
return ConstantFoldConstant(C, DL, TLI);
862864
}
863865

@@ -953,8 +955,10 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
953955

954956
// Otherwise canonicalize this to a single ptradd.
955957
LLVMContext &Ctx = Ptr->getContext();
958+
// TODO(gep_nowrap): Preserve NUSW/NUW.
956959
return ConstantExpr::getGetElementPtr(Type::getInt8Ty(Ctx), Ptr,
957960
ConstantInt::get(Ctx, Offset), InBounds,
961+
/*NUSW=*/InBounds, /*NUW=*/false,
958962
InRange);
959963
}
960964

@@ -1004,8 +1008,10 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
10041008
if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI))
10051009
return C;
10061010

1007-
return ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], Ops.slice(1),
1008-
GEP->isInBounds(), GEP->getInRange());
1011+
return ConstantExpr::getGetElementPtr(
1012+
SrcElemTy, Ops[0], Ops.slice(1), GEP->isInBounds(),
1013+
GEP->hasNoUnsignedSignedWrap(), GEP->hasNoUnsignedWrap(),
1014+
GEP->getInRange());
10091015
}
10101016

10111017
if (auto *CE = dyn_cast<ConstantExpr>(InstOrCE)) {

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4216,15 +4216,25 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
42164216
case lltok::kw_extractelement: {
42174217
unsigned Opc = Lex.getUIntVal();
42184218
SmallVector<Constant*, 16> Elts;
4219-
bool InBounds = false;
4219+
bool InBounds = false, HasNUSW = false, HasNUW = false;
42204220
bool HasInRange = false;
42214221
APSInt InRangeStart;
42224222
APSInt InRangeEnd;
42234223
Type *Ty;
42244224
Lex.Lex();
42254225

42264226
if (Opc == Instruction::GetElementPtr) {
4227-
InBounds = EatIfPresent(lltok::kw_inbounds);
4227+
while (true) {
4228+
if (EatIfPresent(lltok::kw_inbounds))
4229+
InBounds = true;
4230+
else if (EatIfPresent(lltok::kw_nusw))
4231+
HasNUSW = true;
4232+
else if (EatIfPresent(lltok::kw_nuw))
4233+
HasNUW = true;
4234+
else
4235+
break;
4236+
}
4237+
42284238
if (EatIfPresent(lltok::kw_inrange)) {
42294239
if (parseToken(lltok::lparen, "expected '('"))
42304240
return true;
@@ -4303,8 +4313,8 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
43034313
if (!GetElementPtrInst::getIndexedType(Ty, Indices))
43044314
return error(ID.Loc, "invalid getelementptr indices");
43054315

4306-
ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices,
4307-
InBounds, InRange);
4316+
ID.ConstantVal = ConstantExpr::getGetElementPtr(
4317+
Ty, Elts[0], Indices, InBounds, HasNUSW, HasNUW, InRange);
43084318
} else if (Opc == Instruction::ShuffleVector) {
43094319
if (Elts.size() != 3)
43104320
return error(ID.Loc, "expected three operands to shufflevector");

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1614,9 +1614,11 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
16141614
C = ConstantExpr::getCompare(BC->Flags, ConstOps[0], ConstOps[1]);
16151615
break;
16161616
case Instruction::GetElementPtr:
1617-
C = ConstantExpr::getGetElementPtr(BC->SrcElemTy, ConstOps[0],
1618-
ArrayRef(ConstOps).drop_front(),
1619-
BC->Flags, BC->getInRange());
1617+
C = ConstantExpr::getGetElementPtr(
1618+
BC->SrcElemTy, ConstOps[0], ArrayRef(ConstOps).drop_front(),
1619+
(BC->Flags & (1 << bitc::GEP_INBOUNDS)) != 0,
1620+
(BC->Flags & (1 << bitc::GEP_NUSW)) != 0,
1621+
(BC->Flags & (1 << bitc::GEP_NUW)) != 0, BC->getInRange());
16201622
break;
16211623
case Instruction::ExtractElement:
16221624
C = ConstantExpr::getExtractElement(ConstOps[0], ConstOps[1]);
@@ -1700,8 +1702,12 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
17001702
I = GetElementPtrInst::Create(BC->SrcElemTy, Ops[0],
17011703
ArrayRef(Ops).drop_front(), "constexpr",
17021704
InsertBB);
1703-
if (BC->Flags)
1705+
if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
17041706
cast<GetElementPtrInst>(I)->setIsInBounds();
1707+
if (BC->Flags & (1 << bitc::GEP_NUSW))
1708+
cast<GetElementPtrInst>(I)->setHasNoUnsignedSignedWrap();
1709+
if (BC->Flags & (1 << bitc::GEP_NUW))
1710+
cast<GetElementPtrInst>(I)->setHasNoUnsignedWrap();
17051711
break;
17061712
case Instruction::Select:
17071713
I = SelectInst::Create(Ops[0], Ops[1], Ops[2], "constexpr", InsertBB);
@@ -3321,37 +3327,40 @@ Error BitcodeReader::parseConstants() {
33213327
break;
33223328
}
33233329
case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
3324-
case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
3330+
case bitc::CST_CODE_CE_GEP_OLD: // [ty, n x operands]
33253331
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD: // [ty, flags, n x
33263332
// operands]
3333+
case bitc::CST_CODE_CE_GEP: // [ty, flags, n x operands]
33273334
case bitc::CST_CODE_CE_GEP_WITH_INRANGE: { // [ty, flags, start, end, n x
33283335
// operands]
33293336
if (Record.size() < 2)
33303337
return error("Constant GEP record must have at least two elements");
33313338
unsigned OpNum = 0;
33323339
Type *PointeeType = nullptr;
33333340
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD ||
3334-
BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE || Record.size() % 2)
3341+
BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE ||
3342+
BitCode == bitc::CST_CODE_CE_GEP || Record.size() % 2)
33353343
PointeeType = getTypeByID(Record[OpNum++]);
33363344

3337-
bool InBounds = false;
3345+
uint64_t Flags = 0;
33383346
std::optional<ConstantRange> InRange;
33393347
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD) {
33403348
uint64_t Op = Record[OpNum++];
3341-
InBounds = Op & 1;
3349+
Flags = Op & 1; // inbounds
33423350
unsigned InRangeIndex = Op >> 1;
33433351
// "Upgrade" inrange by dropping it. The feature is too niche to
33443352
// bother.
33453353
(void)InRangeIndex;
33463354
} else if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE) {
3347-
uint64_t Op = Record[OpNum++];
3348-
InBounds = Op & 1;
3355+
Flags = Record[OpNum++];
33493356
Expected<ConstantRange> MaybeInRange = readConstantRange(Record, OpNum);
33503357
if (!MaybeInRange)
33513358
return MaybeInRange.takeError();
33523359
InRange = MaybeInRange.get();
3360+
} else if (BitCode == bitc::CST_CODE_CE_GEP) {
3361+
Flags = Record[OpNum++];
33533362
} else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
3354-
InBounds = true;
3363+
Flags = (1 << bitc::GEP_INBOUNDS);
33553364

33563365
SmallVector<unsigned, 16> Elts;
33573366
unsigned BaseTypeID = Record[OpNum];
@@ -3384,7 +3393,8 @@ Error BitcodeReader::parseConstants() {
33843393

33853394
V = BitcodeConstant::create(
33863395
Alloc, CurTy,
3387-
{Instruction::GetElementPtr, InBounds, PointeeType, InRange}, Elts);
3396+
{Instruction::GetElementPtr, uint8_t(Flags), PointeeType, InRange},
3397+
Elts);
33883398
break;
33893399
}
33903400
case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,13 @@ static uint64_t getOptimizationFlags(const Value *V) {
16561656
Flags |= 1 << bitc::TIO_NO_SIGNED_WRAP;
16571657
if (TI->hasNoUnsignedWrap())
16581658
Flags |= 1 << bitc::TIO_NO_UNSIGNED_WRAP;
1659+
} else if (const auto *GEP = dyn_cast<GEPOperator>(V)) {
1660+
if (GEP->isInBounds())
1661+
Flags |= 1 << bitc::GEP_INBOUNDS;
1662+
if (GEP->hasNoUnsignedSignedWrap())
1663+
Flags |= 1 << bitc::GEP_NUSW;
1664+
if (GEP->hasNoUnsignedWrap())
1665+
Flags |= 1 << bitc::GEP_NUW;
16591666
}
16601667

16611668
return Flags;
@@ -2767,12 +2774,11 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal,
27672774
Code = bitc::CST_CODE_CE_GEP;
27682775
const auto *GO = cast<GEPOperator>(C);
27692776
Record.push_back(VE.getTypeID(GO->getSourceElementType()));
2777+
Record.push_back(getOptimizationFlags(GO));
27702778
if (std::optional<ConstantRange> Range = GO->getInRange()) {
27712779
Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE;
2772-
Record.push_back(GO->isInBounds());
27732780
emitConstantRange(Record, *Range);
2774-
} else if (GO->isInBounds())
2775-
Code = bitc::CST_CODE_CE_INBOUNDS_GEP;
2781+
}
27762782
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
27772783
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
27782784
Record.push_back(VE.getValueID(C->getOperand(i)));
@@ -2961,14 +2967,7 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I,
29612967
Code = bitc::FUNC_CODE_INST_GEP;
29622968
AbbrevToUse = FUNCTION_INST_GEP_ABBREV;
29632969
auto &GEPInst = cast<GetElementPtrInst>(I);
2964-
uint64_t Flags = 0;
2965-
if (GEPInst.isInBounds())
2966-
Flags |= 1 << bitc::GEP_INBOUNDS;
2967-
if (GEPInst.hasNoUnsignedSignedWrap())
2968-
Flags |= 1 << bitc::GEP_NUSW;
2969-
if (GEPInst.hasNoUnsignedWrap())
2970-
Flags |= 1 << bitc::GEP_NUW;
2971-
Vals.push_back(Flags);
2970+
Vals.push_back(getOptimizationFlags(&I));
29722971
Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType()));
29732972
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
29742973
pushValueAndType(I.getOperand(i), InstID, Vals);

llvm/lib/IR/ConstantFold.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
17121712
for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
17131713
if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]);
17141714
return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds,
1715+
/*NUSW=*/InBounds, /*NUW=*/false,
17151716
InRange);
17161717
}
17171718

@@ -1721,8 +1722,10 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
17211722
if (auto *GV = dyn_cast<GlobalVariable>(C))
17221723
if (!GV->hasExternalWeakLinkage() && GV->getValueType() == PointeeTy &&
17231724
isInBoundsIndices(Idxs))
1725+
// TODO(gep_nowrap): Can also set NUW here.
17241726
return ConstantExpr::getGetElementPtr(PointeeTy, C, Idxs,
1725-
/*InBounds=*/true, InRange);
1727+
/*InBounds=*/true, /*NUSW=*/true,
1728+
/*NUW=*/false, InRange);
17261729

17271730
return nullptr;
17281731
}

llvm/lib/IR/Constants.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,8 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
15681568
assert(SrcTy || (Ops[0]->getType() == getOperand(0)->getType()));
15691569
return ConstantExpr::getGetElementPtr(
15701570
SrcTy ? SrcTy : GEPO->getSourceElementType(), Ops[0], Ops.slice(1),
1571-
GEPO->isInBounds(), GEPO->getInRange(), OnlyIfReducedTy);
1571+
GEPO->isInBounds(), GEPO->hasNoUnsignedSignedWrap(),
1572+
GEPO->hasNoUnsignedWrap(), GEPO->getInRange(), OnlyIfReducedTy);
15721573
}
15731574
case Instruction::ICmp:
15741575
case Instruction::FCmp:
@@ -2349,6 +2350,7 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1,
23492350

23502351
Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
23512352
ArrayRef<Value *> Idxs, bool InBounds,
2353+
bool NUSW, bool NUW,
23522354
std::optional<ConstantRange> InRange,
23532355
Type *OnlyIfReducedTy) {
23542356
assert(Ty && "Must specify element type");
@@ -2390,7 +2392,14 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
23902392
ArgVec.push_back(Idx);
23912393
}
23922394

2393-
unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0;
2395+
unsigned SubClassOptionalData = 0;
2396+
if (InBounds)
2397+
SubClassOptionalData |=
2398+
GEPOperator::IsInBounds | GEPOperator::HasNoUnsignedSignedWrap;
2399+
if (NUSW)
2400+
SubClassOptionalData |= GEPOperator::HasNoUnsignedSignedWrap;
2401+
if (NUW)
2402+
SubClassOptionalData |= GEPOperator::HasNoUnsignedWrap;
23942403
const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
23952404
SubClassOptionalData, std::nullopt, Ty,
23962405
InRange);

llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@ Value *FatPtrConstMaterializer::materialize(Value *V) {
801801
Ops.push_back(cast<Constant>(U.get()));
802802
auto *NewGEP = ConstantExpr::getGetElementPtr(
803803
NewSrcTy, Ops[0], ArrayRef<Constant *>(Ops).slice(1),
804-
GEPO->isInBounds(), GEPO->getInRange());
804+
GEPO->isInBounds(), GEPO->hasNoUnsignedSignedWrap(),
805+
GEPO->hasNoUnsignedWrap(), GEPO->getInRange());
805806
LLVM_DEBUG(dbgs() << "p7-getting GEP: " << *GEPO << " becomes " << *NewGEP
806807
<< "\n");
807808
Value *FurtherMap = materialize(NewGEP);

llvm/test/Assembler/flags.ll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,39 @@ define ptr @gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
359359
%gep = getelementptr nuw nusw inbounds i8, ptr %p, i64 %idx
360360
ret ptr %gep
361361
}
362+
363+
define ptr @const_gep_nuw(ptr %p, i64 %idx) {
364+
; CHECK: ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
365+
ret ptr getelementptr nuw (i8, ptr @addr, i64 100)
366+
}
367+
368+
define ptr @const_gep_inbounds_nuw(ptr %p, i64 %idx) {
369+
; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
370+
ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
371+
}
372+
373+
define ptr @const_gep_nusw(ptr %p, i64 %idx) {
374+
; CHECK: ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
375+
ret ptr getelementptr nusw (i8, ptr @addr, i64 100)
376+
}
377+
378+
; inbounds implies nusw, so the flag is not printed back.
379+
define ptr @const_gep_inbounds_nusw(ptr %p, i64 %idx) {
380+
; CHECK: ret ptr getelementptr inbounds (i8, ptr @addr, i64 100)
381+
ret ptr getelementptr inbounds nusw (i8, ptr @addr, i64 100)
382+
}
383+
384+
define ptr @const_gep_nusw_nuw(ptr %p, i64 %idx) {
385+
; CHECK: ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
386+
ret ptr getelementptr nusw nuw (i8, ptr @addr, i64 100)
387+
}
388+
389+
define ptr @const_gep_inbounds_nusw_nuw(ptr %p, i64 %idx) {
390+
; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
391+
ret ptr getelementptr inbounds nusw nuw (i8, ptr @addr, i64 100)
392+
}
393+
394+
define ptr @const_gep_nuw_nusw_inbounds(ptr %p, i64 %idx) {
395+
; CHECK: ret ptr getelementptr inbounds nuw (i8, ptr @addr, i64 100)
396+
ret ptr getelementptr nuw nusw inbounds (i8, ptr @addr, i64 100)
397+
}

0 commit comments

Comments
 (0)