Recommit "[SCCP] Support NUW/NSW inference for all overflowing binary operators."
authorFlorian Hahn <flo@fhahn.com>
Mon, 30 Jan 2023 20:15:28 +0000 (20:15 +0000)
committerFlorian Hahn <flo@fhahn.com>
Mon, 30 Jan 2023 20:15:28 +0000 (20:15 +0000)
This reverts commit 43acb61a08fffada31fb2e20e45fcc8492ef76b9.

Recommit the patch after fixing the issue causing the revert in 4e607ec4987.
Extra tests have been added in 5c6cb61ad416a544.

Original commit message:

   Extend the NUW/NSW inference logic add in 72121a20cd and cdeaf5f28c3dc
    to all overflowing binary operators.

    Reviewed By: nikic

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

llvm/lib/Transforms/Utils/SCCPSolver.cpp
llvm/test/Transforms/SCCP/ip-constant-ranges.ll
llvm/test/Transforms/SCCP/ip-ranges-binaryops.ll
llvm/test/Transforms/SCCP/sub-nuw-nsw-flags.ll
llvm/test/Transforms/SCCP/ub-shift.ll
llvm/test/Transforms/SCCP/widening.ll

index 80f11268ba139ebd6215034fe21b0cfefada80f8..3dd155ba3c9b2f6f14879a08963c24cd97375ab8 100644 (file)
@@ -127,7 +127,7 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
 static bool refineInstruction(SCCPSolver &Solver,
                               const SmallPtrSetImpl<Value *> &InsertedValues,
                               Instruction &Inst) {
-  if (Inst.getOpcode() != Instruction::Add)
+  if (!isa<OverflowingBinaryOperator>(Inst))
     return false;
 
   auto GetRange = [&Solver, &InsertedValues](Value *Op) {
@@ -145,7 +145,8 @@ static bool refineInstruction(SCCPSolver &Solver,
   bool Changed = false;
   if (!Inst.hasNoUnsignedWrap()) {
     auto NUWRange = ConstantRange::makeGuaranteedNoWrapRegion(
-        Instruction::Add, RangeB, OverflowingBinaryOperator::NoUnsignedWrap);
+        Instruction::BinaryOps(Inst.getOpcode()), RangeB,
+        OverflowingBinaryOperator::NoUnsignedWrap);
     if (NUWRange.contains(RangeA)) {
       Inst.setHasNoUnsignedWrap();
       Changed = true;
@@ -153,7 +154,7 @@ static bool refineInstruction(SCCPSolver &Solver,
   }
   if (!Inst.hasNoSignedWrap()) {
     auto NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(
-        Instruction::Add, RangeB, OverflowingBinaryOperator::NoSignedWrap);
+        Instruction::BinaryOps(Inst.getOpcode()), RangeB, OverflowingBinaryOperator::NoSignedWrap);
     if (NSWRange.contains(RangeA)) {
       Inst.setHasNoSignedWrap();
       Changed = true;
index ff5f15ef41dc08ae144a427e7233e0b279f56520..07068441ae4f4e81a1fa778f3d67d68b6fd44957 100644 (file)
@@ -243,7 +243,7 @@ define internal i32 @recursive_f(i32 %i) {
 ; CHECK:       if.then:
 ; CHECK-NEXT:    br label [[RETURN:%.*]]
 ; CHECK:       if.else:
-; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[I]], 1
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[I]], 1
 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @recursive_f(i32 [[SUB]])
 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[I]], [[CALL]]
 ; CHECK-NEXT:    br label [[RETURN]]
index d10a4dea73e0e728fcd66f63cfa1068a9f143f85..b9d5313dc215f92d89d76567968a06e53ee827ef 100644 (file)
@@ -50,7 +50,7 @@ define i1 @caller.add() {
 ; x - y = [-190, -79)
 define internal i1 @f.sub(i32 %x, i32 %y) {
 ; CHECK-LABEL: @f.sub(
-; CHECK-NEXT:    [[A_1:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A_1:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i32 [[A_1]], -81
 ; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i32 [[A_1]], -189
 ; CHECK-NEXT:    [[C_5:%.*]] = icmp eq i32 [[A_1]], -150
@@ -94,7 +94,7 @@ define i1 @caller.sub() {
 ; x * y = [1000, 4001)
 define internal i1 @f.mul(i32 %x, i32 %y) {
 ; CHECK-LABEL: @f.mul(
-; CHECK-NEXT:    [[A_1:%.*]] = mul i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[A_1:%.*]] = mul nuw nsw i32 [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[C_2:%.*]] = icmp sgt i32 [[A_1]], 3999
 ; CHECK-NEXT:    [[C_4:%.*]] = icmp slt i32 [[A_1]], 1001
 ; CHECK-NEXT:    [[C_5:%.*]] = icmp eq i32 [[A_1]], 1500
index 3b3cd663bc5425a42a5346a465c58ba2b2468392..31c5575e14a4af26235e274b20547f32608aa5b8 100644 (file)
@@ -5,7 +5,7 @@ define i8 @range_from_lshr(i8 %a) {
 ; CHECK-LABEL: @range_from_lshr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[A_SHR:%.*]] = lshr i8 [[A:%.*]], 1
-; CHECK-NEXT:    [[SUB_1:%.*]] = sub i8 [[A_SHR]], 1
+; CHECK-NEXT:    [[SUB_1:%.*]] = sub nsw i8 [[A_SHR]], 1
 ; CHECK-NEXT:    [[SUB_2:%.*]] = sub i8 [[A_SHR]], -128
 ; CHECK-NEXT:    [[SUB_3:%.*]] = sub i8 [[A_SHR]], -127
 ; CHECK-NEXT:    [[SUB_4:%.*]] = sub i8 [[A_SHR]], -1
@@ -31,7 +31,7 @@ define i8 @sub_zero(i8 %a) {
 ; CHECK-LABEL: @sub_zero(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[SUB_1:%.*]] = sub i8 0, [[A:%.*]]
-; CHECK-NEXT:    [[SUB_2:%.*]] = sub i8 -1, [[A]]
+; CHECK-NEXT:    [[SUB_2:%.*]] = sub nuw nsw i8 -1, [[A]]
 ; CHECK-NEXT:    [[SUB_3:%.*]] = sub i8 1, [[A]]
 ; CHECK-NEXT:    [[SUB_4:%.*]] = sub i8 [[A]], -1
 ; CHECK-NEXT:    [[RES_1:%.*]] = xor i8 [[SUB_1]], [[SUB_2]]
index e3a483ecce3bae85f033c775e69cbd7a6f443f62..ae2739d0445d0e940d64edb0364f4becc9bda039 100644 (file)
@@ -5,7 +5,7 @@ define void @shift_undef_64(ptr %p) {
 ; CHECK-LABEL: @shift_undef_64(
 ; CHECK-NEXT:    store i64 0, ptr [[P:%.*]], align 4
 ; CHECK-NEXT:    store i64 -1, ptr [[P]], align 4
-; CHECK-NEXT:    [[R3:%.*]] = shl i64 -1, 4294967298
+; CHECK-NEXT:    [[R3:%.*]] = shl nuw nsw i64 -1, 4294967298
 ; CHECK-NEXT:    store i64 [[R3]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
@@ -25,7 +25,7 @@ define void @shift_undef_65(ptr %p) {
 ; CHECK-LABEL: @shift_undef_65(
 ; CHECK-NEXT:    store i65 0, ptr [[P:%.*]], align 4
 ; CHECK-NEXT:    store i65 0, ptr [[P]], align 4
-; CHECK-NEXT:    [[R3:%.*]] = shl i65 1, -18446744073709551615
+; CHECK-NEXT:    [[R3:%.*]] = shl nuw nsw i65 1, -18446744073709551615
 ; CHECK-NEXT:    store i65 [[R3]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
@@ -45,7 +45,7 @@ define void @shift_undef_256(ptr %p) {
 ; CHECK-LABEL: @shift_undef_256(
 ; CHECK-NEXT:    store i256 0, ptr [[P:%.*]], align 4
 ; CHECK-NEXT:    store i256 0, ptr [[P]], align 4
-; CHECK-NEXT:    [[R3:%.*]] = shl i256 1, 18446744073709551619
+; CHECK-NEXT:    [[R3:%.*]] = shl nuw nsw i256 1, 18446744073709551619
 ; CHECK-NEXT:    store i256 [[R3]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
@@ -65,7 +65,7 @@ define void @shift_undef_511(ptr %p) {
 ; CHECK-LABEL: @shift_undef_511(
 ; CHECK-NEXT:    store i511 0, ptr [[P:%.*]], align 4
 ; CHECK-NEXT:    store i511 -1, ptr [[P]], align 4
-; CHECK-NEXT:    [[R3:%.*]] = shl i511 -3, 1208925819614629174706180
+; CHECK-NEXT:    [[R3:%.*]] = shl nuw nsw i511 -3, 1208925819614629174706180
 ; CHECK-NEXT:    store i511 [[R3]], ptr [[P]], align 4
 ; CHECK-NEXT:    ret void
 ;
index 4485fb42fb4fbc2d5473e308b490b5c1f5bbf0b1..f482ed3a4e7f655d25596c632e89f59d43f38933 100644 (file)
@@ -447,8 +447,8 @@ define void @foo(ptr %arg) {
 ; SCCP:       bb4:
 ; SCCP-NEXT:    [[TMP5:%.*]] = add i64 [[TMP2]], 3
 ; SCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
-; SCCP-NEXT:    [[TMP7:%.*]] = sub i64 3, [[TMP6]]
-; SCCP-NEXT:    [[TMP8:%.*]] = shl i64 [[TMP7]], 1
+; SCCP-NEXT:    [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
+; SCCP-NEXT:    [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
 ; SCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
 ; SCCP-NEXT:    [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
 ; SCCP-NEXT:    br label [[BB11:%.*]]
@@ -484,8 +484,8 @@ define void @foo(ptr %arg) {
 ; IPSCCP:       bb4:
 ; IPSCCP-NEXT:    [[TMP5:%.*]] = add i64 [[TMP2]], 3
 ; IPSCCP-NEXT:    [[TMP6:%.*]] = and i64 [[TMP5]], 3
-; IPSCCP-NEXT:    [[TMP7:%.*]] = sub i64 3, [[TMP6]]
-; IPSCCP-NEXT:    [[TMP8:%.*]] = shl i64 [[TMP7]], 1
+; IPSCCP-NEXT:    [[TMP7:%.*]] = sub nuw nsw i64 3, [[TMP6]]
+; IPSCCP-NEXT:    [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 1
 ; IPSCCP-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32
 ; IPSCCP-NEXT:    [[TMP10:%.*]] = zext i32 [[TMP9]] to i64
 ; IPSCCP-NEXT:    br label [[BB11:%.*]]