Skip to content

Commit 83ffe88

Browse files
committed
Support flags on GEP constant expressions as well
1 parent eb27a1b commit 83ffe88

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
@@ -11347,6 +11347,10 @@ These rules are based on the assumption that no allocated object may cross
1134711347
the unsigned address space boundary, and no allocated object may be larger
1134811348
than half the pointer index type space.
1134911349

11350+
If ``inbounds`` is present on a ``getelementptr`` instruction, the ``nusw``
11351+
attribute will be automatically set as well. For this reason, the ``nusw``
11352+
will also not be printed in textual IR if ``inbounds`` is already present.
11353+
1135011354
If the ``inrange(Start, End)`` attribute is present, loading from or
1135111355
storing to any pointer derived from the ``getelementptr`` has undefined
1135211356
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

@@ -980,7 +982,9 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
980982
NewIdxs.push_back(ConstantInt::get(
981983
Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index));
982984

985+
// TODO(gep_nowrap): Preserve NUSW/NUW.
983986
return ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds,
987+
/*NUSW=*/InBounds, /*NUW=*/false,
984988
InRange);
985989
}
986990

@@ -1028,8 +1032,10 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
10281032
if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI))
10291033
return C;
10301034

1031-
return ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], Ops.slice(1),
1032-
GEP->isInBounds(), GEP->getInRange());
1035+
return ConstantExpr::getGetElementPtr(
1036+
SrcElemTy, Ops[0], Ops.slice(1), GEP->isInBounds(),
1037+
GEP->hasNoUnsignedSignedWrap(), GEP->hasNoUnsignedWrap(),
1038+
GEP->getInRange());
10331039
}
10341040

10351041
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
@@ -1613,9 +1613,11 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
16131613
C = ConstantExpr::getCompare(BC->Flags, ConstOps[0], ConstOps[1]);
16141614
break;
16151615
case Instruction::GetElementPtr:
1616-
C = ConstantExpr::getGetElementPtr(BC->SrcElemTy, ConstOps[0],
1617-
ArrayRef(ConstOps).drop_front(),
1618-
BC->Flags, BC->getInRange());
1616+
C = ConstantExpr::getGetElementPtr(
1617+
BC->SrcElemTy, ConstOps[0], ArrayRef(ConstOps).drop_front(),
1618+
(BC->Flags & (1 << bitc::GEP_INBOUNDS)) != 0,
1619+
(BC->Flags & (1 << bitc::GEP_NUSW)) != 0,
1620+
(BC->Flags & (1 << bitc::GEP_NUW)) != 0, BC->getInRange());
16191621
break;
16201622
case Instruction::ExtractElement:
16211623
C = ConstantExpr::getExtractElement(ConstOps[0], ConstOps[1]);
@@ -1699,8 +1701,12 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID,
16991701
I = GetElementPtrInst::Create(BC->SrcElemTy, Ops[0],
17001702
ArrayRef(Ops).drop_front(), "constexpr",
17011703
InsertBB);
1702-
if (BC->Flags)
1704+
if (BC->Flags & (1 << bitc::GEP_INBOUNDS))
17031705
cast<GetElementPtrInst>(I)->setIsInBounds();
1706+
if (BC->Flags & (1 << bitc::GEP_NUSW))
1707+
cast<GetElementPtrInst>(I)->setHasNoUnsignedSignedWrap();
1708+
if (BC->Flags & (1 << bitc::GEP_NUW))
1709+
cast<GetElementPtrInst>(I)->setHasNoUnsignedWrap();
17041710
break;
17051711
case Instruction::Select:
17061712
I = SelectInst::Create(Ops[0], Ops[1], Ops[2], "constexpr", InsertBB);
@@ -3320,37 +3326,40 @@ Error BitcodeReader::parseConstants() {
33203326
break;
33213327
}
33223328
case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
3323-
case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
3329+
case bitc::CST_CODE_CE_GEP_OLD: // [ty, n x operands]
33243330
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD: // [ty, flags, n x
33253331
// operands]
3332+
case bitc::CST_CODE_CE_GEP: // [ty, flags, n x operands]
33263333
case bitc::CST_CODE_CE_GEP_WITH_INRANGE: { // [ty, flags, start, end, n x
33273334
// operands]
33283335
if (Record.size() < 2)
33293336
return error("Constant GEP record must have at least two elements");
33303337
unsigned OpNum = 0;
33313338
Type *PointeeType = nullptr;
33323339
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD ||
3333-
BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE || Record.size() % 2)
3340+
BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE ||
3341+
BitCode == bitc::CST_CODE_CE_GEP || Record.size() % 2)
33343342
PointeeType = getTypeByID(Record[OpNum++]);
33353343

3336-
bool InBounds = false;
3344+
uint64_t Flags = 0;
33373345
std::optional<ConstantRange> InRange;
33383346
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD) {
33393347
uint64_t Op = Record[OpNum++];
3340-
InBounds = Op & 1;
3348+
Flags = Op & 1; // inbounds
33413349
unsigned InRangeIndex = Op >> 1;
33423350
// "Upgrade" inrange by dropping it. The feature is too niche to
33433351
// bother.
33443352
(void)InRangeIndex;
33453353
} else if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE) {
3346-
uint64_t Op = Record[OpNum++];
3347-
InBounds = Op & 1;
3354+
Flags = Record[OpNum++];
33483355
Expected<ConstantRange> MaybeInRange = readConstantRange(Record, OpNum);
33493356
if (!MaybeInRange)
33503357
return MaybeInRange.takeError();
33513358
InRange = MaybeInRange.get();
3359+
} else if (BitCode == bitc::CST_CODE_CE_GEP) {
3360+
Flags = Record[OpNum++];
33523361
} else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
3353-
InBounds = true;
3362+
Flags = (1 << bitc::GEP_INBOUNDS);
33543363

33553364
SmallVector<unsigned, 16> Elts;
33563365
unsigned BaseTypeID = Record[OpNum];
@@ -3383,7 +3392,8 @@ Error BitcodeReader::parseConstants() {
33833392

33843393
V = BitcodeConstant::create(
33853394
Alloc, CurTy,
3386-
{Instruction::GetElementPtr, InBounds, PointeeType, InRange}, Elts);
3395+
{Instruction::GetElementPtr, uint8_t(Flags), PointeeType, InRange},
3396+
Elts);
33873397
break;
33883398
}
33893399
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
@@ -1711,6 +1711,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
17111711
for (unsigned i = 0, e = Idxs.size(); i != e; ++i)
17121712
if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]);
17131713
return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds,
1714+
/*NUSW=*/InBounds, /*NUW=*/false,
17141715
InRange);
17151716
}
17161717

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

17261729
return nullptr;
17271730
}

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)