[llvm] [C API] Add accessors for new no-wrap flags on GEP instructions (PR #97970)
Benji Smith via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 8 07:18:17 PDT 2024
https://github.com/Benjins updated https://github.com/llvm/llvm-project/pull/97970
>From 0171a6b03cb62061d304b1e4929ae861d9b540ed Mon Sep 17 00:00:00 2001
From: Benji Smith <benjsith at gmail.com>
Date: Sun, 7 Jul 2024 14:04:26 -0400
Subject: [PATCH 1/2] [C API] Add accessors for new no-wrap flags on GEP
instructions
Previously, only the inbounds flag was accessible via the C API. This adds
support for any no-wrap related flags (currently nuw and nusw)
---
llvm/docs/ReleaseNotes.rst | 6 ++++++
llvm/include/llvm-c/Core.h | 28 +++++++++++++++++++++++++
llvm/lib/IR/Core.cpp | 34 +++++++++++++++++++++++++++++++
llvm/test/Bindings/llvm-c/echo.ll | 9 ++++++++
llvm/tools/llvm-c-test/echo.cpp | 8 +++-----
5 files changed, 80 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index a6bfd55119398..a0b76a8cb1526 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -293,6 +293,12 @@ They are described in detail in the `debug info migration guide <https://llvm.or
* ``LLVMGetTargetExtTypeNumTypeParams``/``LLVMGetTargetExtTypeTypeParam``
* ``LLVMGetTargetExtTypeNumIntParams``/``LLVMGetTargetExtTypeIntParam``
+* Added the following functions for accessing/changing the no-wrap flags for a
+ GetElementPtr instruction
+
+ * ``LLVMGEPGetNoWrapFlags``
+ * ``LLVMGEPSetNoWrapFlags``
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 9867db4839fe1..db7cebadf20f8 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -510,6 +510,20 @@ enum {
*/
typedef unsigned LLVMFastMathFlags;
+enum {
+ LLVMGEPFlagInBounds = (1 << 0),
+ LLVMGEPFlagNUSW = (1 << 1),
+ LLVMGEPFlagNUW = (1 << 2),
+};
+
+/**
+ * Flags that constrain the allowed wrap semantics of a getelementptr
+ * instruction.
+ *
+ * See https://llvm.org/docs/LangRef.html#getelementptr-instruction
+ */
+typedef unsigned LLVMGEPNoWrapFlags;
+
/**
* @}
*/
@@ -3904,6 +3918,20 @@ void LLVMSetIsInBounds(LLVMValueRef GEP, LLVMBool InBounds);
*/
LLVMTypeRef LLVMGetGEPSourceElementType(LLVMValueRef GEP);
+/**
+ * Get the no-wrap related flags for the given GEP instruction.
+ *
+ * @see llvm::GetElementPtrInst::getNoWrapFlags
+ */
+LLVMGEPNoWrapFlags LLVMGEPGetNoWrapFlags(LLVMValueRef GEP);
+
+/**
+ * Get the no-wrap related flags for the given GEP instruction.
+ *
+ * @see llvm::GetElementPtrInst::setNoWrapFlags
+ */
+void LLVMGEPSetNoWrapFlags(LLVMValueRef GEP, LLVMGEPNoWrapFlags WrapFlags);
+
/**
* @}
*/
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 9ba7873106043..a9da24e816b2a 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -3090,6 +3090,30 @@ LLVMTypeRef LLVMGetAllocatedType(LLVMValueRef Alloca) {
/*--.. Operations on gep instructions (only) ...............................--*/
+static GEPNoWrapFlags mapFromLLVMGEPNoWrapFlags(LLVMGEPNoWrapFlags GEPFlags) {
+ GEPNoWrapFlags NewGEPFlags;
+ if ((GEPFlags & LLVMGEPFlagInBounds) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::inBounds();
+ if ((GEPFlags & LLVMGEPFlagNUSW) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap();
+ if ((GEPFlags & LLVMGEPFlagNUW) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap();
+
+ return NewGEPFlags;
+}
+
+static LLVMGEPNoWrapFlags mapToLLVMGEPNoWrapFlags(GEPNoWrapFlags GEPFlags) {
+ LLVMGEPNoWrapFlags NewGEPFlags = 0;
+ if (GEPFlags.isInBounds())
+ NewGEPFlags |= LLVMGEPFlagInBounds;
+ if (GEPFlags.hasNoUnsignedSignedWrap())
+ NewGEPFlags |= LLVMGEPFlagNUSW;
+ if (GEPFlags.hasNoUnsignedWrap())
+ NewGEPFlags |= LLVMGEPFlagNUW;
+
+ return NewGEPFlags;
+}
+
LLVMBool LLVMIsInBounds(LLVMValueRef GEP) {
return unwrap<GEPOperator>(GEP)->isInBounds();
}
@@ -3102,6 +3126,16 @@ LLVMTypeRef LLVMGetGEPSourceElementType(LLVMValueRef GEP) {
return wrap(unwrap<GEPOperator>(GEP)->getSourceElementType());
}
+LLVMGEPNoWrapFlags LLVMGEPGetNoWrapFlags(LLVMValueRef GEP) {
+ GEPOperator *GEPOp = unwrap<GEPOperator>(GEP);
+ return mapToLLVMGEPNoWrapFlags(GEPOp->getNoWrapFlags());
+}
+
+void LLVMGEPSetNoWrapFlags(LLVMValueRef GEP, LLVMGEPNoWrapFlags WrapFlags) {
+ GetElementPtrInst *GEPInst = unwrap<GetElementPtrInst>(GEP);
+ GEPInst->setNoWrapFlags(mapFromLLVMGEPNoWrapFlags(WrapFlags));
+}
+
/*--.. Operations on phi nodes .............................................--*/
void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues,
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index dc6f2a9e7d206..5dcaa04f4f72c 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -391,6 +391,15 @@ bb_03:
ret void
}
+define ptr @test_gep_no_wrap_flags(ptr %0) {
+ %gep.1 = getelementptr i8, ptr %0, i32 4
+ %gep.inbounds = getelementptr inbounds i8, ptr %0, i32 4
+ %gep.nuw = getelementptr nuw i8, ptr %0, i32 4
+ %gep.nuw.inbounds = getelementptr inbounds nuw i8, ptr %0, i32 4
+ %gep.nusw = getelementptr nusw i8, ptr %0, i32 4
+ ret ptr %gep.nusw
+}
+
!llvm.dbg.cu = !{!0, !2}
!llvm.module.flags = !{!3}
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 6fa36421810f0..3c7169efde412 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -767,11 +767,9 @@ struct FunCloner {
int NumIdx = LLVMGetNumIndices(Src);
for (int i = 1; i <= NumIdx; i++)
Idx.push_back(CloneValue(LLVMGetOperand(Src, i)));
- if (LLVMIsInBounds(Src))
- Dst = LLVMBuildInBoundsGEP2(Builder, ElemTy, Ptr, Idx.data(), NumIdx,
- Name);
- else
- Dst = LLVMBuildGEP2(Builder, ElemTy, Ptr, Idx.data(), NumIdx, Name);
+
+ Dst = LLVMBuildGEP2(Builder, ElemTy, Ptr, Idx.data(), NumIdx, Name);
+ LLVMGEPSetNoWrapFlags(Dst, LLVMGEPGetNoWrapFlags(Src));
break;
}
case LLVMAtomicRMW: {
>From 0aecc8f9beadf4bb8061bee92a2c0bb26f7a6f71 Mon Sep 17 00:00:00 2001
From: Benji Smith <benjsith at gmail.com>
Date: Mon, 8 Jul 2024 10:13:34 -0400
Subject: [PATCH 2/2] Update PR based on feedback: add BuildGEP and ConstGEP
variants that take an explicit set of GEPNoWrapFlags. Also, actually clone
the no-wrap flags for constant GEP expressions, and add a test to verify this
---
llvm/docs/ReleaseNotes.rst | 4 +-
llvm/include/llvm-c/Core.h | 9 ++++
llvm/lib/IR/Core.cpp | 71 ++++++++++++++++++++-----------
llvm/test/Bindings/llvm-c/echo.ll | 3 ++
llvm/tools/llvm-c-test/echo.cpp | 12 +++---
5 files changed, 68 insertions(+), 31 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index a0b76a8cb1526..bceb00981726f 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -293,9 +293,11 @@ They are described in detail in the `debug info migration guide <https://llvm.or
* ``LLVMGetTargetExtTypeNumTypeParams``/``LLVMGetTargetExtTypeTypeParam``
* ``LLVMGetTargetExtTypeNumIntParams``/``LLVMGetTargetExtTypeIntParam``
-* Added the following functions for accessing/changing the no-wrap flags for a
+* Added the following functions for accessing/setting the no-wrap flags for a
GetElementPtr instruction
+ * ``LLVMBuildGEPWithWrapFlags``
+ * ``LLVMConstGEPWithWrapFlags``
* ``LLVMGEPGetNoWrapFlags``
* ``LLVMGEPSetNoWrapFlags``
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index db7cebadf20f8..771032e102198 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2409,6 +2409,10 @@ LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices,
unsigned NumIndices);
+LLVMValueRef LLVMConstGEPWithWrapFlags(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices,
+ unsigned NumIndices,
+ LLVMGEPNoWrapFlags WrapFlags);
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType);
@@ -4391,6 +4395,11 @@ LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, LLVMValueRef *Indices,
unsigned NumIndices, const char *Name);
+LLVMValueRef LLVMBuildGEPWithWrapFlags(LLVMBuilderRef B, LLVMTypeRef Ty,
+ LLVMValueRef Pointer,
+ LLVMValueRef *Indices,
+ unsigned NumIndices, const char *Name,
+ LLVMGEPNoWrapFlags WrapFlags);
LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, unsigned Idx,
const char *Name);
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index a9da24e816b2a..61b81df1f7ab4 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1685,6 +1685,32 @@ static int map_from_llvmopcode(LLVMOpcode code)
llvm_unreachable("Unhandled Opcode.");
}
+/*-- GEP wrap flag conversions*/
+
+static GEPNoWrapFlags mapFromLLVMGEPNoWrapFlags(LLVMGEPNoWrapFlags GEPFlags) {
+ GEPNoWrapFlags NewGEPFlags;
+ if ((GEPFlags & LLVMGEPFlagInBounds) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::inBounds();
+ if ((GEPFlags & LLVMGEPFlagNUSW) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap();
+ if ((GEPFlags & LLVMGEPFlagNUW) != 0)
+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap();
+
+ return NewGEPFlags;
+}
+
+static LLVMGEPNoWrapFlags mapToLLVMGEPNoWrapFlags(GEPNoWrapFlags GEPFlags) {
+ LLVMGEPNoWrapFlags NewGEPFlags = 0;
+ if (GEPFlags.isInBounds())
+ NewGEPFlags |= LLVMGEPFlagInBounds;
+ if (GEPFlags.hasNoUnsignedSignedWrap())
+ NewGEPFlags |= LLVMGEPFlagNUSW;
+ if (GEPFlags.hasNoUnsignedWrap())
+ NewGEPFlags |= LLVMGEPFlagNUW;
+
+ return NewGEPFlags;
+}
+
/*--.. Constant expressions ................................................--*/
LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal) {
@@ -1789,6 +1815,17 @@ LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
}
+LLVMValueRef LLVMConstGEPWithWrapFlags(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
+ LLVMValueRef *ConstantIndices,
+ unsigned NumIndices,
+ LLVMGEPNoWrapFlags WrapFlags) {
+ ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
+ NumIndices);
+ Constant *Val = unwrap<Constant>(ConstantVal);
+ return wrap(ConstantExpr::getGetElementPtr(
+ unwrap(Ty), Val, IdxList, mapFromLLVMGEPNoWrapFlags(WrapFlags)));
+}
+
LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType) {
return wrap(ConstantExpr::getTrunc(unwrap<Constant>(ConstantVal),
unwrap(ToType)));
@@ -3090,30 +3127,6 @@ LLVMTypeRef LLVMGetAllocatedType(LLVMValueRef Alloca) {
/*--.. Operations on gep instructions (only) ...............................--*/
-static GEPNoWrapFlags mapFromLLVMGEPNoWrapFlags(LLVMGEPNoWrapFlags GEPFlags) {
- GEPNoWrapFlags NewGEPFlags;
- if ((GEPFlags & LLVMGEPFlagInBounds) != 0)
- NewGEPFlags |= GEPNoWrapFlags::inBounds();
- if ((GEPFlags & LLVMGEPFlagNUSW) != 0)
- NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap();
- if ((GEPFlags & LLVMGEPFlagNUW) != 0)
- NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap();
-
- return NewGEPFlags;
-}
-
-static LLVMGEPNoWrapFlags mapToLLVMGEPNoWrapFlags(GEPNoWrapFlags GEPFlags) {
- LLVMGEPNoWrapFlags NewGEPFlags = 0;
- if (GEPFlags.isInBounds())
- NewGEPFlags |= LLVMGEPFlagInBounds;
- if (GEPFlags.hasNoUnsignedSignedWrap())
- NewGEPFlags |= LLVMGEPFlagNUSW;
- if (GEPFlags.hasNoUnsignedWrap())
- NewGEPFlags |= LLVMGEPFlagNUW;
-
- return NewGEPFlags;
-}
-
LLVMBool LLVMIsInBounds(LLVMValueRef GEP) {
return unwrap<GEPOperator>(GEP)->isInBounds();
}
@@ -3936,6 +3949,16 @@ LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
unwrap(B)->CreateInBoundsGEP(unwrap(Ty), unwrap(Pointer), IdxList, Name));
}
+LLVMValueRef LLVMBuildGEPWithWrapFlags(LLVMBuilderRef B, LLVMTypeRef Ty,
+ LLVMValueRef Pointer,
+ LLVMValueRef *Indices,
+ unsigned NumIndices, const char *Name,
+ LLVMGEPNoWrapFlags WrapFlags) {
+ ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices);
+ return wrap(unwrap(B)->CreateGEP(unwrap(Ty), unwrap(Pointer), IdxList, Name,
+ mapFromLLVMGEPNoWrapFlags(WrapFlags)));
+}
+
LLVMValueRef LLVMBuildStructGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef Pointer, unsigned Idx,
const char *Name) {
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index 5dcaa04f4f72c..06e1c44e0c490 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -25,6 +25,9 @@ module asm "classical GAS"
@const_gep = global ptr getelementptr (i32, ptr @var, i64 2)
@const_inbounds_gep = global ptr getelementptr inbounds (i32, ptr @var, i64 1)
+ at const_gep_nuw = global ptr getelementptr nuw (i32, ptr @var, i64 1)
+ at const_gep_nusw = global ptr getelementptr nusw (i32, ptr @var, i64 1)
+ at const_gep_nuw_inbounds = global ptr getelementptr nuw inbounds (i32, ptr @var, i64 1)
@aliased1 = alias i32, ptr @var
@aliased2 = internal alias i32, ptr @var
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 3c7169efde412..d9ae840762a46 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -412,10 +412,9 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
SmallVector<LLVMValueRef, 8> Idx;
for (int i = 1; i <= NumIdx; i++)
Idx.push_back(clone_constant(LLVMGetOperand(Cst, i), M));
- if (LLVMIsInBounds(Cst))
- return LLVMConstInBoundsGEP2(ElemTy, Ptr, Idx.data(), NumIdx);
- else
- return LLVMConstGEP2(ElemTy, Ptr, Idx.data(), NumIdx);
+
+ return LLVMConstGEPWithWrapFlags(ElemTy, Ptr, Idx.data(), NumIdx,
+ LLVMGEPGetNoWrapFlags(Cst));
}
default:
fprintf(stderr, "%d is not a supported opcode for constant expressions\n",
@@ -768,8 +767,9 @@ struct FunCloner {
for (int i = 1; i <= NumIdx; i++)
Idx.push_back(CloneValue(LLVMGetOperand(Src, i)));
- Dst = LLVMBuildGEP2(Builder, ElemTy, Ptr, Idx.data(), NumIdx, Name);
- LLVMGEPSetNoWrapFlags(Dst, LLVMGEPGetNoWrapFlags(Src));
+ Dst =
+ LLVMBuildGEPWithWrapFlags(Builder, ElemTy, Ptr, Idx.data(), NumIdx,
+ Name, LLVMGEPGetNoWrapFlags(Src));
break;
}
case LLVMAtomicRMW: {
More information about the llvm-commits
mailing list