Skip to content

Commit 7cbf99b

Browse files
committed
Introduce GEPNoWrapFlags class
1 parent 7df7bd5 commit 7cbf99b

File tree

19 files changed

+195
-184
lines changed

19 files changed

+195
-184
lines changed

clang/lib/CodeGen/CGVTT.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,8 @@ 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.
9190
llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr(
92-
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, /*NUSW=*/true,
93-
/*NUW=*/false, InRange);
91+
VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange);
9492

9593
VTTComponents.push_back(Init);
9694
}

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,10 +1901,8 @@ 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.
19051904
return llvm::ConstantExpr::getGetElementPtr(
1906-
VTable->getValueType(), VTable, Indices, /*InBounds=*/true, /*NUSW=*/true,
1907-
/*NUW=*/false, InRange);
1905+
VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange);
19081906
}
19091907

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

llvm/include/llvm/IR/Constants.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "llvm/IR/Constant.h"
2929
#include "llvm/IR/ConstantRange.h"
3030
#include "llvm/IR/DerivedTypes.h"
31+
#include "llvm/IR/GEPNoWrapFlags.h"
3132
#include "llvm/IR/Intrinsics.h"
3233
#include "llvm/IR/OperandTraits.h"
3334
#include "llvm/IR/User.h"
@@ -1198,46 +1199,46 @@ class ConstantExpr : public Constant {
11981199
/// \param OnlyIfReducedTy see \a getWithOperands() docs.
11991200
static Constant *
12001201
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList,
1201-
bool InBounds = false, bool NUSW = false, bool NUW = false,
1202+
GEPNoWrapFlags NW = GEPNoWrapFlags::none(),
12021203
std::optional<ConstantRange> InRange = std::nullopt,
12031204
Type *OnlyIfReducedTy = nullptr) {
12041205
return getGetElementPtr(
1205-
Ty, C, ArrayRef((Value *const *)IdxList.data(), IdxList.size()),
1206-
InBounds, NUSW, NUW, InRange, OnlyIfReducedTy);
1206+
Ty, C, ArrayRef((Value *const *)IdxList.data(), IdxList.size()), NW,
1207+
InRange, OnlyIfReducedTy);
12071208
}
12081209
static Constant *
1209-
getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false,
1210-
bool NUSW = false, bool NUW = false,
1210+
getGetElementPtr(Type *Ty, Constant *C, Constant *Idx,
1211+
GEPNoWrapFlags NW = GEPNoWrapFlags::none(),
12111212
std::optional<ConstantRange> InRange = std::nullopt,
12121213
Type *OnlyIfReducedTy = nullptr) {
12131214
// This form of the function only exists to avoid ambiguous overload
12141215
// warnings about whether to convert Idx to ArrayRef<Constant *> or
12151216
// ArrayRef<Value *>.
1216-
return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, NUSW, NUW,
1217-
InRange, OnlyIfReducedTy);
1217+
return getGetElementPtr(Ty, C, cast<Value>(Idx), NW, InRange,
1218+
OnlyIfReducedTy);
12181219
}
12191220
static Constant *
12201221
getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList,
1221-
bool InBounds = false, bool NUSW = false, bool NUW = false,
1222+
GEPNoWrapFlags NW = GEPNoWrapFlags::none(),
12221223
std::optional<ConstantRange> InRange = std::nullopt,
12231224
Type *OnlyIfReducedTy = nullptr);
12241225

12251226
/// Create an "inbounds" getelementptr. See the documentation for the
12261227
/// "inbounds" flag in LangRef.html for details.
12271228
static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
12281229
ArrayRef<Constant *> IdxList) {
1229-
return getGetElementPtr(Ty, C, IdxList, true);
1230+
return getGetElementPtr(Ty, C, IdxList, GEPNoWrapFlags::inBounds());
12301231
}
12311232
static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
12321233
Constant *Idx) {
12331234
// This form of the function only exists to avoid ambiguous overload
12341235
// warnings about whether to convert Idx to ArrayRef<Constant *> or
12351236
// ArrayRef<Value *>.
1236-
return getGetElementPtr(Ty, C, Idx, true);
1237+
return getGetElementPtr(Ty, C, Idx, GEPNoWrapFlags::inBounds());
12371238
}
12381239
static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C,
12391240
ArrayRef<Value *> IdxList) {
1240-
return getGetElementPtr(Ty, C, IdxList, true);
1241+
return getGetElementPtr(Ty, C, IdxList, GEPNoWrapFlags::inBounds());
12411242
}
12421243

12431244
static Constant *getExtractElement(Constant *Vec, Constant *Idx,

llvm/include/llvm/IR/GEPNoWrapFlags.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//===-- llvm/GEPNoWrapFlags.h - NoWrap flags for GEPs -----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the nowrap flags for getelementptr operators.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_IR_GEPNOWRAPFLAGS_H
14+
#define LLVM_IR_GEPNOWRAPFLAGS_H
15+
16+
namespace llvm {
17+
18+
class GEPNoWrapFlags {
19+
enum : unsigned{
20+
InBoundsFlag = (1 << 0),
21+
NUSWFlag = (1 << 1),
22+
NUWFlag = (1 << 2),
23+
};
24+
25+
unsigned Flags;
26+
GEPNoWrapFlags(unsigned Flags) : Flags(Flags) {
27+
assert((!isInBounds() || hasNoUnsignedSignedWrap()) &&
28+
"inbounds implies nusw");
29+
}
30+
31+
public:
32+
GEPNoWrapFlags() : Flags(0) {}
33+
// For historical reasons, interpret plain boolean as InBounds.
34+
GEPNoWrapFlags(bool IsInBounds)
35+
: Flags(IsInBounds ? (InBoundsFlag | NUSWFlag) : 0) {}
36+
37+
static GEPNoWrapFlags none() { return GEPNoWrapFlags(); }
38+
static GEPNoWrapFlags inBounds() {
39+
return GEPNoWrapFlags(InBoundsFlag | NUSWFlag);
40+
}
41+
static GEPNoWrapFlags noUnsignedSignedWrap() {
42+
return GEPNoWrapFlags(NUSWFlag);
43+
}
44+
static GEPNoWrapFlags noUnsignedWrap() { return GEPNoWrapFlags(NUWFlag); }
45+
46+
static GEPNoWrapFlags fromRaw(unsigned Flags) {
47+
return GEPNoWrapFlags(Flags);
48+
}
49+
unsigned getRaw() const { return Flags; }
50+
51+
bool isInBounds() const { return Flags & InBoundsFlag; }
52+
bool hasNoUnsignedSignedWrap() const { return Flags & NUSWFlag; }
53+
bool hasNoUnsignedWrap() const { return Flags & NUWFlag; }
54+
55+
GEPNoWrapFlags withoutInBounds() const {
56+
return GEPNoWrapFlags(Flags & ~InBoundsFlag);
57+
}
58+
GEPNoWrapFlags withoutNoUnsignedSignedWrap() const {
59+
return GEPNoWrapFlags(Flags & ~(InBoundsFlag|NUSWFlag));
60+
}
61+
GEPNoWrapFlags withoutNoUnsignedWrap() const {
62+
return GEPNoWrapFlags(Flags & ~NUWFlag);
63+
}
64+
65+
bool operator==(GEPNoWrapFlags Other) const { return Flags == Other.Flags; }
66+
bool operator!=(GEPNoWrapFlags Other) const { return !(*this == Other); }
67+
68+
GEPNoWrapFlags operator&(GEPNoWrapFlags Other) const {
69+
return GEPNoWrapFlags(Flags & Other.Flags);
70+
}
71+
GEPNoWrapFlags operator|(GEPNoWrapFlags Other) const {
72+
return GEPNoWrapFlags(Flags | Other.Flags);
73+
}
74+
GEPNoWrapFlags &operator&=(GEPNoWrapFlags Other) {
75+
Flags &= Other.Flags;
76+
return *this;
77+
}
78+
GEPNoWrapFlags &operator|=(GEPNoWrapFlags Other) {
79+
Flags |= Other.Flags;
80+
return *this;
81+
}
82+
};
83+
84+
} // end namespace llvm
85+
86+
#endif // LLVM_IR_GEPNOWRAPFLAGS_H

llvm/include/llvm/IR/Instructions.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/IR/CFG.h"
2727
#include "llvm/IR/Constant.h"
2828
#include "llvm/IR/DerivedTypes.h"
29+
#include "llvm/IR/GEPNoWrapFlags.h"
2930
#include "llvm/IR/InstrTypes.h"
3031
#include "llvm/IR/Instruction.h"
3132
#include "llvm/IR/OperandTraits.h"
@@ -1167,17 +1168,16 @@ class GetElementPtrInst : public Instruction {
11671168
/// a constant offset between them.
11681169
bool hasAllConstantIndices() const;
11691170

1171+
/// Set nowrap flags for GEP instruction.
1172+
void setNoWrapFlags(GEPNoWrapFlags NW);
1173+
11701174
/// Set or clear the inbounds flag on this GEP instruction.
11711175
/// See LangRef.html for the meaning of inbounds on a getelementptr.
1176+
/// TODO: Remove this method in favor of setNoWrapFlags().
11721177
void setIsInBounds(bool b = true);
11731178

1174-
/// Set or clear the nusw flag on this GEP instruction.
1175-
/// See LangRef.html for the meaning of nusw on a getelementptr.
1176-
void setHasNoUnsignedSignedWrap(bool B = true);
1177-
1178-
/// Set or clear the nuw flag on this GEP instruction.
1179-
/// See LangRef.html for the meaning of nuw on a getelementptr.
1180-
void setHasNoUnsignedWrap(bool B = true);
1179+
/// Get the nowrap flags for the GEP instruction.
1180+
GEPNoWrapFlags getNoWrapFlags() const;
11811181

11821182
/// Determine whether the GEP has the inbounds flag.
11831183
bool isInBounds() const;

llvm/include/llvm/IR/Operator.h

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/MapVector.h"
1818
#include "llvm/IR/Constants.h"
1919
#include "llvm/IR/FMF.h"
20+
#include "llvm/IR/GEPNoWrapFlags.h"
2021
#include "llvm/IR/Instruction.h"
2122
#include "llvm/IR/Type.h"
2223
#include "llvm/IR/Value.h"
@@ -399,50 +400,24 @@ class LShrOperator
399400
};
400401

401402
class GEPOperator
402-
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
403-
friend class GetElementPtrInst;
404-
friend class ConstantExpr;
405-
406-
enum {
407-
IsInBounds = (1 << 0),
408-
HasNoUnsignedSignedWrap = (1 << 1),
409-
HasNoUnsignedWrap = (1 << 2),
410-
};
411-
412-
void setIsInBounds(bool B) {
413-
// Also set nusw when inbounds is set.
414-
SubclassOptionalData = (SubclassOptionalData & ~IsInBounds) |
415-
(B * (IsInBounds | HasNoUnsignedSignedWrap));
416-
}
417-
418-
void setHasNoUnsignedSignedWrap(bool B) {
419-
// Also unset inbounds when nusw is unset.
420-
if (B)
421-
SubclassOptionalData |= HasNoUnsignedSignedWrap;
422-
else
423-
SubclassOptionalData &= ~(IsInBounds | HasNoUnsignedSignedWrap);
424-
}
425-
426-
void setHasNoUnsignedWrap(bool B) {
427-
SubclassOptionalData =
428-
(SubclassOptionalData & ~HasNoUnsignedWrap) | (B * HasNoUnsignedWrap);
429-
}
430-
403+
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
431404
public:
432405
/// Transparently provide more efficient getOperand methods.
433406
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
434407

435-
/// Test whether this is an inbounds GEP, as defined by LangRef.html.
436-
bool isInBounds() const {
437-
return SubclassOptionalData & IsInBounds;
408+
GEPNoWrapFlags getNoWrapFlags() const {
409+
return GEPNoWrapFlags::fromRaw(SubclassOptionalData);
438410
}
439411

412+
/// Test whether this is an inbounds GEP, as defined by LangRef.html.
413+
bool isInBounds() const { return getNoWrapFlags().isInBounds(); }
414+
440415
bool hasNoUnsignedSignedWrap() const {
441-
return SubclassOptionalData & HasNoUnsignedSignedWrap;
416+
return getNoWrapFlags().hasNoUnsignedSignedWrap();
442417
}
443418

444419
bool hasNoUnsignedWrap() const {
445-
return SubclassOptionalData & HasNoUnsignedWrap;
420+
return getNoWrapFlags().hasNoUnsignedWrap();
446421
}
447422

448423
/// Returns the offset of the index with an inrange attachment, or

llvm/lib/Analysis/ConstantFolding.cpp

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

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

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

956954
// Otherwise canonicalize this to a single ptradd.
957955
LLVMContext &Ctx = Ptr->getContext();
958-
// TODO(gep_nowrap): Preserve NUSW/NUW.
959956
return ConstantExpr::getGetElementPtr(Type::getInt8Ty(Ctx), Ptr,
960957
ConstantInt::get(Ctx, Offset), InBounds,
961-
/*NUSW=*/InBounds, /*NUW=*/false,
962958
InRange);
963959
}
964960

@@ -1009,8 +1005,7 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
10091005
return C;
10101006

10111007
return ConstantExpr::getGetElementPtr(
1012-
SrcElemTy, Ops[0], Ops.slice(1), GEP->isInBounds(),
1013-
GEP->hasNoUnsignedSignedWrap(), GEP->hasNoUnsignedWrap(),
1008+
SrcElemTy, Ops[0], Ops.slice(1), GEP->getNoWrapFlags(),
10141009
GEP->getInRange());
10151010
}
10161011

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4216,7 +4216,7 @@ 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, HasNUSW = false, HasNUW = false;
4219+
GEPNoWrapFlags NW;
42204220
bool HasInRange = false;
42214221
APSInt InRangeStart;
42224222
APSInt InRangeEnd;
@@ -4226,11 +4226,11 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
42264226
if (Opc == Instruction::GetElementPtr) {
42274227
while (true) {
42284228
if (EatIfPresent(lltok::kw_inbounds))
4229-
InBounds = true;
4229+
NW |= GEPNoWrapFlags::inBounds();
42304230
else if (EatIfPresent(lltok::kw_nusw))
4231-
HasNUSW = true;
4231+
NW |= GEPNoWrapFlags::noUnsignedSignedWrap();
42324232
else if (EatIfPresent(lltok::kw_nuw))
4233-
HasNUW = true;
4233+
NW |= GEPNoWrapFlags::noUnsignedWrap();
42344234
else
42354235
break;
42364236
}
@@ -4314,7 +4314,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
43144314
return error(ID.Loc, "invalid getelementptr indices");
43154315

43164316
ID.ConstantVal = ConstantExpr::getGetElementPtr(
4317-
Ty, Elts[0], Indices, InBounds, HasNUSW, HasNUW, InRange);
4317+
Ty, Elts[0], Indices, NW, InRange);
43184318
} else if (Opc == Instruction::ShuffleVector) {
43194319
if (Elts.size() != 3)
43204320
return error(ID.Loc, "expected three operands to shufflevector");
@@ -8349,15 +8349,15 @@ int LLParser::parseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
83498349
Value *Ptr = nullptr;
83508350
Value *Val = nullptr;
83518351
LocTy Loc, EltLoc;
8352+
GEPNoWrapFlags NW;
83528353

8353-
bool InBounds = false, NUSW = false, NUW = false;
83548354
while (true) {
83558355
if (EatIfPresent(lltok::kw_inbounds))
8356-
InBounds = true;
8356+
NW |= GEPNoWrapFlags::inBounds();
83578357
else if (EatIfPresent(lltok::kw_nusw))
8358-
NUSW = true;
8358+
NW |= GEPNoWrapFlags::noUnsignedSignedWrap();
83598359
else if (EatIfPresent(lltok::kw_nuw))
8360-
NUW = true;
8360+
NW |= GEPNoWrapFlags::noUnsignedWrap();
83618361
else
83628362
break;
83638363
}
@@ -8415,12 +8415,7 @@ int LLParser::parseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
84158415
return error(Loc, "invalid getelementptr indices");
84168416
GetElementPtrInst *GEP = GetElementPtrInst::Create(Ty, Ptr, Indices);
84178417
Inst = GEP;
8418-
if (InBounds)
8419-
GEP->setIsInBounds(true);
8420-
if (NUSW)
8421-
GEP->setHasNoUnsignedSignedWrap(true);
8422-
if (NUW)
8423-
GEP->setHasNoUnsignedWrap(true);
8418+
GEP->setNoWrapFlags(NW);
84248419
return AteExtraComma ? InstExtraComma : InstNormal;
84258420
}
84268421

0 commit comments

Comments
 (0)