[C API] Add getters and setters for NUW, NSW, and Exact
authorJustin Bogner <mail@justinbogner.com>
Thu, 8 Jun 2023 22:59:38 +0000 (15:59 -0700)
committerJustin Bogner <mail@justinbogner.com>
Thu, 8 Jun 2023 23:11:11 +0000 (16:11 -0700)
This partially addresses Bug 42692; see discussion there.

Adds C API getters and setters for the NUW, NSW, and Exact flags on various
instructions.

Patch by Craig Disselkoen. Thanks!

Differential Revision: https://reviews.llvm.org/D89252

llvm/include/llvm-c/Core.h
llvm/lib/IR/Core.cpp
llvm/test/Bindings/llvm-c/echo.ll
llvm/tools/llvm-c-test/echo.cpp

index 78dff8a..fbba8ca 100644 (file)
@@ -3913,6 +3913,13 @@ LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V,
 LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name);
 LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name);
 
+LLVMBool LLVMGetNUW(LLVMValueRef ArithInst);
+void LLVMSetNUW(LLVMValueRef ArithInst, LLVMBool HasNUW);
+LLVMBool LLVMGetNSW(LLVMValueRef ArithInst);
+void LLVMSetNSW(LLVMValueRef ArithInst, LLVMBool HasNSW);
+LLVMBool LLVMGetExact(LLVMValueRef DivOrShrInst);
+void LLVMSetExact(LLVMValueRef DivOrShrInst, LLVMBool IsExact);
+
 /* Memory */
 LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
 LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty,
index 4aee5ce..964e51e 100644 (file)
@@ -3444,6 +3444,36 @@ LLVMValueRef LLVMBuildNot(LLVMBuilderRef B, LLVMValueRef V, const char *Name) {
   return wrap(unwrap(B)->CreateNot(unwrap(V), Name));
 }
 
+LLVMBool LLVMGetNUW(LLVMValueRef ArithInst) {
+  Value *P = unwrap<Value>(ArithInst);
+  return cast<Instruction>(P)->hasNoUnsignedWrap();
+}
+
+void LLVMSetNUW(LLVMValueRef ArithInst, LLVMBool HasNUW) {
+  Value *P = unwrap<Value>(ArithInst);
+  cast<Instruction>(P)->setHasNoUnsignedWrap(HasNUW);
+}
+
+LLVMBool LLVMGetNSW(LLVMValueRef ArithInst) {
+  Value *P = unwrap<Value>(ArithInst);
+  return cast<Instruction>(P)->hasNoSignedWrap();
+}
+
+void LLVMSetNSW(LLVMValueRef ArithInst, LLVMBool HasNSW) {
+  Value *P = unwrap<Value>(ArithInst);
+  cast<Instruction>(P)->setHasNoSignedWrap(HasNSW);
+}
+
+LLVMBool LLVMGetExact(LLVMValueRef DivOrShrInst) {
+  Value *P = unwrap<Value>(DivOrShrInst);
+  return cast<Instruction>(P)->isExact();
+}
+
+void LLVMSetExact(LLVMValueRef DivOrShrInst, LLVMBool IsExact) {
+  Value *P = unwrap<Value>(DivOrShrInst);
+  cast<Instruction>(P)->setIsExact(IsExact);
+}
+
 /*--.. Memory ..............................................................--*/
 
 LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
index da7a801..438a2be 100644 (file)
@@ -80,7 +80,17 @@ define i32 @iops(i32 %a, i32 %b) {
   %11 = and i32 %9, %10
   %12 = or i32 %2, %11
   %13 = xor i32 %12, %4
-  ret i32 %13
+  %14 = add nuw i32 %13, %a
+  %15 = add nsw i32 %14, %b
+  %16 = add nuw nsw i32 %15, %a
+  %17 = shl nuw i32 %16, %a
+  %18 = shl nsw i32 %17, %b
+  %19 = shl nuw nsw i32 %18, %a
+  %20 = udiv exact i32 %19, %1
+  %21 = sdiv exact i32 %20, %2
+  %22 = lshr exact i32 %21, %4
+  %23 = ashr exact i32 %22, %14
+  ret i32 %23
 }
 
 define i32 @call() {
index ed2999f..b0535c7 100644 (file)
@@ -536,31 +536,47 @@ struct FunCloner {
       case LLVMAdd: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool NUW = LLVMGetNUW(Src);
+        LLVMBool NSW = LLVMGetNSW(Src);
         Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
+        LLVMSetNUW(Dst, NUW);
+        LLVMSetNSW(Dst, NSW);
         break;
       }
       case LLVMSub: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool NUW = LLVMGetNUW(Src);
+        LLVMBool NSW = LLVMGetNSW(Src);
         Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
+        LLVMSetNUW(Dst, NUW);
+        LLVMSetNSW(Dst, NSW);
         break;
       }
       case LLVMMul: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool NUW = LLVMGetNUW(Src);
+        LLVMBool NSW = LLVMGetNSW(Src);
         Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
+        LLVMSetNUW(Dst, NUW);
+        LLVMSetNSW(Dst, NSW);
         break;
       }
       case LLVMUDiv: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool IsExact = LLVMGetExact(Src);
         Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
+        LLVMSetExact(Dst, IsExact);
         break;
       }
       case LLVMSDiv: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool IsExact = LLVMGetExact(Src);
         Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
+        LLVMSetExact(Dst, IsExact);
         break;
       }
       case LLVMURem: {
@@ -578,19 +594,27 @@ struct FunCloner {
       case LLVMShl: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool NUW = LLVMGetNUW(Src);
+        LLVMBool NSW = LLVMGetNSW(Src);
         Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
+        LLVMSetNUW(Dst, NUW);
+        LLVMSetNSW(Dst, NSW);
         break;
       }
       case LLVMLShr: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool IsExact = LLVMGetExact(Src);
         Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
+        LLVMSetExact(Dst, IsExact);
         break;
       }
       case LLVMAShr: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool IsExact = LLVMGetExact(Src);
         Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
+        LLVMSetExact(Dst, IsExact);
         break;
       }
       case LLVMAnd: {