[llvm-branch-commits] [clang] [llvm] [IRBuilder] Add getByteTy and use it in CreatePtrAdd (PR #106539)
Sergei Barannikov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat May 2 06:50:33 PDT 2026
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/106539
>From 68d0d2be068545f1a58b71ff51279dc91e902a9b Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Thu, 22 Aug 2024 15:10:58 +0300
Subject: [PATCH 1/2] [IRBuilder] Add getByteTy and use it in CreatePtrAdd
The change requires DataLayout instance to be available, which, in turn,
requires insertion point to be set. In-tree tests detected only one case
when the function was called without setting an insertion point, it was
changed to create a constant expression directly.
---
llvm/include/llvm/IR/IRBuilder.h | 10 +++++++--
.../Instrumentation/SanitizerCoverage.cpp | 5 ++---
llvm/unittests/IR/IRBuilderTest.cpp | 22 +++++++++++++++++++
3 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 84a588023826d..3bc6195b55004 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -549,6 +549,12 @@ class IRBuilderBase {
// Type creation methods
//===--------------------------------------------------------------------===//
+ /// Fetch the type representing a byte.
+ IntegerType *getByteTy() {
+ const DataLayout &DL = BB->getDataLayout();
+ return Type::getIntNTy(Context, DL.getByteWidth());
+ }
+
/// Fetch the type representing an 8-bit byte.
ByteType *getByte8Ty() { return Type::getByte8Ty(Context); }
@@ -2083,12 +2089,12 @@ class IRBuilderBase {
Value *CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name = "",
GEPNoWrapFlags NW = GEPNoWrapFlags::none()) {
- return CreateGEP(getInt8Ty(), Ptr, Offset, Name, NW);
+ return CreateGEP(getByteTy(), Ptr, Offset, Name, NW);
}
Value *CreateInBoundsPtrAdd(Value *Ptr, Value *Offset,
const Twine &Name = "") {
- return CreateGEP(getInt8Ty(), Ptr, Offset, Name,
+ return CreateGEP(getByteTy(), Ptr, Offset, Name,
GEPNoWrapFlags::inBounds());
}
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index df9675a02824e..c1a7dedc5c8ef 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -379,14 +379,13 @@ ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, const char *Section,
GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr,
getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility);
- IRBuilder<> IRB(M.getContext());
if (!TargetTriple.isOSBinFormatCOFF())
return std::make_pair(SecStart, SecEnd);
// Account for the fact that on windows-msvc __start_* symbols actually
// point to a uint64_t before the start of the array.
- auto GEP =
- IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
+ Constant *GEP = ConstantExpr::getGetElementPtr(
+ Int8Ty, SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
return std::make_pair(GEP, SecEnd);
}
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp
index b4f1c97f03aca..4f1a7ea33266d 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -591,6 +591,14 @@ TEST_F(IRBuilderTest, DataLayout) {
EXPECT_FALSE(M->getDataLayout().isLegalInteger(32));
}
+TEST_F(IRBuilderTest, GetByteTy) {
+ IRBuilder<> Builder(BB);
+
+ EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(8));
+ M->setDataLayout("b:32");
+ EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(32));
+}
+
TEST_F(IRBuilderTest, GetIntTy) {
IRBuilder<> Builder(BB);
IntegerType *Ty1 = Builder.getInt1Ty();
@@ -602,6 +610,20 @@ TEST_F(IRBuilderTest, GetIntTy) {
EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
}
+TEST_F(IRBuilderTest, CreatePtrAdd) {
+ IRBuilder<> Builder(BB);
+
+ M->setDataLayout("b:16-p:32:32");
+ Value *V = Builder.CreatePtrAdd(GV, ConstantInt::get(Ctx, APInt(32, 42)));
+ ASSERT_TRUE(isa<GEPOperator>(V));
+ EXPECT_TRUE(cast<GEPOperator>(V)->getResultElementType()->isIntegerTy(16));
+
+ M->setDataLayout("b:32-p:64:32");
+ V = Builder.CreateInBoundsPtrAdd(GV, ConstantInt::get(Ctx, APInt(64, 42)));
+ ASSERT_TRUE(isa<GEPOperator>(V));
+ EXPECT_TRUE(cast<GEPOperator>(V)->getResultElementType()->isIntegerTy(32));
+}
+
TEST_F(IRBuilderTest, UnaryOperators) {
IRBuilder<NoFolder> Builder(BB);
Value *V = Builder.CreateLoad(GV->getValueType(), GV);
>From 6950e52b5f5087b4e1a31262cf8779d535e1e472 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 22 Feb 2026 20:17:40 +0300
Subject: [PATCH 2/2] Use DL in ConstantExpr::getPtrAdd() /
ConstantExpr::getInBoundsPtrAdd()
---
clang/lib/CodeGen/CGExprConstant.cpp | 2 +-
clang/lib/CodeGen/CGObjCMac.cpp | 2 +-
clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 ++-
llvm/include/llvm/IR/Constants.h | 18 +++++++++---------
llvm/lib/Analysis/ConstantFolding.cpp | 2 +-
llvm/lib/Analysis/ScalarEvolution.cpp | 18 +++++++++---------
llvm/lib/IR/Constants.cpp | 9 +++++++++
llvm/lib/Transforms/IPO/GlobalSplit.cpp | 2 +-
llvm/lib/Transforms/IPO/LowerTypeTests.cpp | 8 +++++---
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp | 2 +-
.../Instrumentation/IndirectCallPromotion.cpp | 2 +-
llvm/unittests/IR/PatternMatch.cpp | 3 ++-
.../Utils/CallPromotionUtilsTest.cpp | 2 +-
13 files changed, 43 insertions(+), 30 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 17a10dd40eba2..949ea99d8ce6f 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -2170,7 +2170,7 @@ class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
if (!hasNonZeroOffset())
return C;
- return llvm::ConstantExpr::getPtrAdd(C, getOffset());
+ return llvm::ConstantExpr::getPtrAdd(CGM.getDataLayout(), C, getOffset());
}
};
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 69c5e88f3c768..2feabd50c88e0 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -8329,7 +8329,7 @@ CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
// Stub classes are pointer-aligned. Classrefs pointing at stub classes
// must set the least significant bit set to 1.
auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
- return llvm::ConstantExpr::getPtrAdd(ClassGV, Idx);
+ return llvm::ConstantExpr::getPtrAdd(CGM.getDataLayout(), ClassGV, Idx);
}
llvm::Value *
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 6069d39f520ef..d16fe7b7254bb 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -4104,7 +4104,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
// The vtable address point is 8 bytes after its start:
// 4 for the offset to top + 4 for the relative offset to rtti.
llvm::Constant *Eight = llvm::ConstantInt::get(CGM.Int32Ty, 8);
- VTable = llvm::ConstantExpr::getInBoundsPtrAdd(VTable, Eight);
+ VTable = llvm::ConstantExpr::getInBoundsPtrAdd(CGM.getDataLayout(), VTable,
+ Eight);
} else {
llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(CGM.GlobalsInt8PtrTy,
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 2b3f4119e50e2..7d334cb532065 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -1467,15 +1467,13 @@ class ConstantExpr : public Constant {
std::optional<ConstantRange> InRange = std::nullopt,
Type *OnlyIfReducedTy = nullptr);
- /// Create a getelementptr i8, ptr, offset constant expression.
+ /// Create a getelementptr iN, ptr, offset constant expression,
+ /// where iN is a byte-sized integer type.
static Constant *
- getPtrAdd(Constant *Ptr, Constant *Offset,
+ getPtrAdd(const DataLayout &DL, Constant *Ptr, Constant *Offset,
GEPNoWrapFlags NW = GEPNoWrapFlags::none(),
std::optional<ConstantRange> InRange = std::nullopt,
- Type *OnlyIfReduced = nullptr) {
- return getGetElementPtr(Type::getInt8Ty(Ptr->getContext()), Ptr, Offset, NW,
- InRange, OnlyIfReduced);
- }
+ Type *OnlyIfReduced = nullptr);
/// Create an "inbounds" getelementptr. See the documentation for the
/// "inbounds" flag in LangRef.html for details.
@@ -1495,9 +1493,11 @@ class ConstantExpr : public Constant {
return getGetElementPtr(Ty, C, IdxList, GEPNoWrapFlags::inBounds());
}
- /// Create a getelementptr inbounds i8, ptr, offset constant expression.
- static Constant *getInBoundsPtrAdd(Constant *Ptr, Constant *Offset) {
- return getPtrAdd(Ptr, Offset, GEPNoWrapFlags::inBounds());
+ /// Create a getelementptr inbounds iN, ptr, offset constant expression,
+ /// where iN is a byte-sized integer type.
+ static Constant *getInBoundsPtrAdd(const DataLayout &DL, Constant *Ptr,
+ Constant *Offset) {
+ return getPtrAdd(DL, Ptr, Offset, GEPNoWrapFlags::inBounds());
}
LLVM_ABI static Constant *getExtractElement(Constant *Vec, Constant *Idx,
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index e035cd1bc1ac0..45556cda3ddcc 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1118,7 +1118,7 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
// Otherwise canonicalize this to a single ptradd.
LLVMContext &Ctx = Ptr->getContext();
- return ConstantExpr::getPtrAdd(Ptr, ConstantInt::get(Ctx, Offset), NW,
+ return ConstantExpr::getPtrAdd(DL, Ptr, ConstantInt::get(Ctx, Offset), NW,
InRange);
}
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 676292ebe0346..c89ddaa75b80c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -10150,7 +10150,7 @@ const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
/// will return Constants for objects which aren't represented by a
/// SCEVConstant, because SCEVConstant is restricted to ConstantInt.
/// Returns NULL if the SCEV isn't representable as a Constant.
-static Constant *BuildConstantFromSCEV(const SCEV *V) {
+static Constant *BuildConstantFromSCEV(const SCEV *V, const DataLayout &DL) {
switch (V->getSCEVType()) {
case scCouldNotCompute:
case scAddRecExpr:
@@ -10162,21 +10162,21 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
return dyn_cast<Constant>(cast<SCEVUnknown>(V)->getValue());
case scPtrToAddr: {
const SCEVPtrToAddrExpr *P2I = cast<SCEVPtrToAddrExpr>(V);
- if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
+ if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand(), DL))
return ConstantExpr::getPtrToAddr(CastOp, P2I->getType());
return nullptr;
}
case scPtrToInt: {
const SCEVPtrToIntExpr *P2I = cast<SCEVPtrToIntExpr>(V);
- if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand()))
+ if (Constant *CastOp = BuildConstantFromSCEV(P2I->getOperand(), DL))
return ConstantExpr::getPtrToInt(CastOp, P2I->getType());
return nullptr;
}
case scTruncate: {
const SCEVTruncateExpr *ST = cast<SCEVTruncateExpr>(V);
- if (Constant *CastOp = BuildConstantFromSCEV(ST->getOperand()))
+ if (Constant *CastOp = BuildConstantFromSCEV(ST->getOperand(), DL))
return ConstantExpr::getTrunc(CastOp, ST->getType());
return nullptr;
}
@@ -10184,7 +10184,7 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
const SCEVAddExpr *SA = cast<SCEVAddExpr>(V);
Constant *C = nullptr;
for (const SCEV *Op : SA->operands()) {
- Constant *OpC = BuildConstantFromSCEV(Op);
+ Constant *OpC = BuildConstantFromSCEV(Op, DL);
if (!OpC)
return nullptr;
if (!C) {
@@ -10194,9 +10194,9 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
assert(!C->getType()->isPointerTy() &&
"Can only have one pointer, and it must be last");
if (OpC->getType()->isPointerTy()) {
- // The offsets have been converted to bytes. We can add bytes using
- // an i8 GEP.
- C = ConstantExpr::getPtrAdd(OpC, C);
+ // The offsets have been converted to bytes. We can add bytes using
+ // a ptradd.
+ C = ConstantExpr::getPtrAdd(DL, OpC, C);
} else {
C = ConstantExpr::getAdd(C, OpC);
}
@@ -10428,7 +10428,7 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) {
const SCEV *OpV = getSCEVAtScope(OrigV, L);
MadeImprovement |= OrigV != OpV;
- Constant *C = BuildConstantFromSCEV(OpV);
+ Constant *C = BuildConstantFromSCEV(OpV, DL);
if (!C)
return V;
assert(C->getType() == Op->getType() && "Type mismatch");
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index f07ce527c1240..00aed3e9076e2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -2741,6 +2741,15 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C,
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
+Constant *ConstantExpr::getPtrAdd(const DataLayout &DL, Constant *Ptr,
+ Constant *Offset, GEPNoWrapFlags NW,
+ std::optional<ConstantRange> InRange,
+ Type *OnlyIfReduced) {
+ unsigned ByteWidth = DL.getByteWidth();
+ return getGetElementPtr(Type::getIntNTy(Ptr->getContext(), ByteWidth), Ptr,
+ Offset, NW, InRange, OnlyIfReduced);
+}
+
Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx,
Type *OnlyIfReducedTy) {
assert(Val->getType()->isVectorTy() &&
diff --git a/llvm/lib/Transforms/IPO/GlobalSplit.cpp b/llvm/lib/Transforms/IPO/GlobalSplit.cpp
index ccc91cc355787..ec1618eea9bfd 100644
--- a/llvm/lib/Transforms/IPO/GlobalSplit.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalSplit.cpp
@@ -154,7 +154,7 @@ static bool splitGlobal(GlobalVariable &GV) {
for (const GEPInfo &Info : Infos) {
assert(Info.MemberIndex < SplitGlobals.size() && "Invalid member");
auto *NewGEP = ConstantExpr::getPtrAdd(
- SplitGlobals[Info.MemberIndex],
+ DL, SplitGlobals[Info.MemberIndex],
ConstantInt::get(GV.getContext(), Info.MemberRelativeOffset),
Info.GEP->isInBounds());
Info.GEP->replaceAllUsesWith(NewGEP);
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index a57e0c59726a3..9954b23d434f6 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -637,7 +637,8 @@ void LowerTypeTestsModule::allocateByteArrays() {
for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) {
ByteArrayInfo *BAI = &ByteArrayInfos[I];
Constant *GEP = ConstantExpr::getInBoundsPtrAdd(
- ByteArray, ConstantInt::get(IntPtrTy, ByteArrayOffsets[I]));
+ M.getDataLayout(), ByteArray,
+ ConstantInt::get(IntPtrTy, ByteArrayOffsets[I]));
// Create an alias instead of RAUW'ing the gep directly. On x86 this ensures
// that the pc-relative displacement is folded into the lea instead of the
@@ -1184,8 +1185,9 @@ void LowerTypeTestsModule::lowerTypeTestCalls(
uint64_t GlobalOffset =
BSI.ByteOffset + ((BSI.BitSize - 1) << BSI.AlignLog2);
- TIL.OffsetedGlobal = ConstantExpr::getPtrAdd(
- CombinedGlobalAddr, ConstantInt::get(IntPtrTy, GlobalOffset)),
+ TIL.OffsetedGlobal =
+ ConstantExpr::getPtrAdd(M.getDataLayout(), CombinedGlobalAddr,
+ ConstantInt::get(IntPtrTy, GlobalOffset)),
TIL.AlignLog2 = ConstantInt::get(IntPtrTy, BSI.AlignLog2);
TIL.SizeM1 = ConstantInt::get(IntPtrTy, BSI.BitSize - 1);
if (BSI.isAllOnes()) {
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index 5b2391a6a7b67..13ff178e70fd0 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -1818,7 +1818,7 @@ void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
}
Constant *DevirtModule::getMemberAddr(const TypeMemberInfo *M) {
- return ConstantExpr::getPtrAdd(M->Bits->GV,
+ return ConstantExpr::getPtrAdd(this->M.getDataLayout(), M->Bits->GV,
ConstantInt::get(Int64Ty, M->Offset));
}
diff --git a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
index f3cdb3518ddcb..4b19159e89f66 100644
--- a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
+++ b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
@@ -217,7 +217,7 @@ static Constant *getVTableAddressPointOffset(GlobalVariable *VTable,
"Out-of-bound access");
return ConstantExpr::getInBoundsPtrAdd(
- VTable,
+ M.getDataLayout(), VTable,
llvm::ConstantInt::get(Type::getInt32Ty(Context), AddressPointOffset));
}
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 3f81739ef3c7b..4b50a935ae61e 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -2708,7 +2708,8 @@ TEST_F(PatternMatchTest, PtrAdd) {
Constant *Offset = ConstantInt::get(IdxTy, 42);
Value *PtrAdd = IRB.CreatePtrAdd(Null, Offset);
Value *OtherGEP = IRB.CreateGEP(IdxTy, Null, Offset);
- Value *PtrAddConst = ConstantExpr::getPtrAdd(Null, Offset);
+ Value *PtrAddConst =
+ ConstantExpr::getPtrAdd(M->getDataLayout(), Null, Offset);
Value *A, *B;
EXPECT_TRUE(match(PtrAdd, m_PtrAdd(m_Value(A), m_Value(B))));
diff --git a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp
index c859b0c799f08..7951db904d71d 100644
--- a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp
@@ -44,7 +44,7 @@ static Constant *getVTableAddressPointOffset(GlobalVariable *VTable,
"Out-of-bound access");
return ConstantExpr::getInBoundsPtrAdd(
- VTable,
+ M.getDataLayout(), VTable,
llvm::ConstantInt::get(Type::getInt32Ty(Context), AddressPointOffset));
}
More information about the llvm-branch-commits
mailing list