[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
Sun Jul 7 12:19:08 PDT 2024


https://github.com/Benjins created https://github.com/llvm/llvm-project/pull/97970

Previously, only the inbounds flag was accessible via the C API. This adds support for any no-wrap related flags (currently nuw and nusw)

>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] [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: {



More information about the llvm-commits mailing list