diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -3913,6 +3913,13 @@ 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, diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -3444,6 +3444,36 @@ return wrap(unwrap(B)->CreateNot(unwrap(V), Name)); } +LLVMBool LLVMGetNUW(LLVMValueRef ArithInst) { + Value *P = unwrap(ArithInst); + return cast(P)->hasNoUnsignedWrap(); +} + +void LLVMSetNUW(LLVMValueRef ArithInst, LLVMBool HasNUW) { + Value *P = unwrap(ArithInst); + cast(P)->setHasNoUnsignedWrap(HasNUW); +} + +LLVMBool LLVMGetNSW(LLVMValueRef ArithInst) { + Value *P = unwrap(ArithInst); + return cast(P)->hasNoSignedWrap(); +} + +void LLVMSetNSW(LLVMValueRef ArithInst, LLVMBool HasNSW) { + Value *P = unwrap(ArithInst); + cast(P)->setHasNoSignedWrap(HasNSW); +} + +LLVMBool LLVMGetExact(LLVMValueRef DivOrShrInst) { + Value *P = unwrap(DivOrShrInst); + return cast(P)->isExact(); +} + +void LLVMSetExact(LLVMValueRef DivOrShrInst, LLVMBool IsExact) { + Value *P = unwrap(DivOrShrInst); + cast(P)->setIsExact(IsExact); +} + /*--.. Memory ..............................................................--*/ LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty, diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -80,7 +80,17 @@ %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() { diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -536,31 +536,47 @@ 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 @@ 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: {