[llvm] 37ca6fa - [ValueTracking] Add support for overflow detection functions is `isKnownNonZero`

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 08:41:10 PDT 2024


Author: Noah Goldstein
Date: 2024-04-10T10:40:48-05:00
New Revision: 37ca6fa1e26e86c85c544023b18695be420e80dd

URL: https://github.com/llvm/llvm-project/commit/37ca6fa1e26e86c85c544023b18695be420e80dd
DIFF: https://github.com/llvm/llvm-project/commit/37ca6fa1e26e86c85c544023b18695be420e80dd.diff

LOG: [ValueTracking] Add support for overflow detection functions is `isKnownNonZero`

Adds support for: `{s,u}{add,sub,mul}.with.overflow`

The logic is identical to the the non-overflow binops, we where just
missing the cases.

Closes #87701

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstCombine/known-bits.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2c9ea8aa38512d..b32dc493ace919 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2798,6 +2798,29 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
     // handled in isKnownNonZero.
     return false;
   }
+  case Instruction::ExtractValue: {
+    const WithOverflowInst *WO;
+    if (match(I, m_ExtractValue<0>(m_WithOverflowInst(WO)))) {
+      switch (WO->getBinaryOp()) {
+      default:
+        break;
+      case Instruction::Add:
+        return isNonZeroAdd(DemandedElts, Depth, Q, BitWidth,
+                            WO->getArgOperand(0), WO->getArgOperand(1),
+                            /*NSW=*/false,
+                            /*NUW=*/false);
+      case Instruction::Sub:
+        return isNonZeroSub(DemandedElts, Depth, Q, BitWidth,
+                            WO->getArgOperand(0), WO->getArgOperand(1));
+      case Instruction::Mul:
+        return isNonZeroMul(DemandedElts, Depth, Q, BitWidth,
+                            WO->getArgOperand(0), WO->getArgOperand(1),
+                            /*NSW=*/false, /*NUW=*/false);
+        break;
+      }
+    }
+    break;
+  }
   case Instruction::Call:
   case Instruction::Invoke: {
     const auto *Call = cast<CallBase>(I);

diff  --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index ddd5970ccabdb8..e27e4a3eddfbb1 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -642,12 +642,9 @@ define i1 @extract_value_uadd(<2 x i8> %xx, <2 x i8> %yy) {
 ; CHECK-NEXT:    [[X:%.*]] = add nuw <2 x i8> [[X0]], <i8 1, i8 0>
 ; CHECK-NEXT:    [[Y:%.*]] = add nuw <2 x i8> [[Y0]], <i8 1, i8 0>
 ; CHECK-NEXT:    [[ADD_UOV:%.*]] = call { <2 x i8>, <2 x i1> } @llvm.uadd.with.overflow.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
-; CHECK-NEXT:    [[ADD:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[ADD_UOV]], 0
 ; CHECK-NEXT:    [[UOV:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[ADD_UOV]], 1
 ; CHECK-NEXT:    call void @use.2xi1(<2 x i1> [[UOV]])
-; CHECK-NEXT:    [[ADD_ELE:%.*]] = extractelement <2 x i8> [[ADD]], i64 0
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[ADD_ELE]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %x0 = and <2 x i8> %xx, <i8 63, i8 255>
   %y0 = and <2 x i8> %yy, <i8 63, i8 255>
@@ -670,12 +667,9 @@ define i1 @extract_value_uadd2(<2 x i8> %xx, <2 x i8> %yy) {
 ; CHECK-NEXT:    [[X:%.*]] = add nuw <2 x i8> [[X0]], <i8 0, i8 1>
 ; CHECK-NEXT:    [[Y:%.*]] = add nuw <2 x i8> [[Y0]], <i8 0, i8 1>
 ; CHECK-NEXT:    [[ADD_UOV:%.*]] = call { <2 x i8>, <2 x i1> } @llvm.uadd.with.overflow.v2i8(<2 x i8> [[X]], <2 x i8> [[Y]])
-; CHECK-NEXT:    [[ADD:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[ADD_UOV]], 0
 ; CHECK-NEXT:    [[UOV:%.*]] = extractvalue { <2 x i8>, <2 x i1> } [[ADD_UOV]], 1
 ; CHECK-NEXT:    call void @use.2xi1(<2 x i1> [[UOV]])
-; CHECK-NEXT:    [[ADD_ELE:%.*]] = extractelement <2 x i8> [[ADD]], i64 1
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[ADD_ELE]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %x0 = and <2 x i8> %xx, <i8 255, i8 63>
   %y0 = and <2 x i8> %yy, <i8 255, i8 63>
@@ -784,11 +778,9 @@ define i1 @extract_value_sadd(i8 %xx, i8 %yy) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[X_LEMMA]])
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[Y_LEMMA]])
 ; CHECK-NEXT:    [[ADD_SOV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X]], i8 [[Y]])
-; CHECK-NEXT:    [[ADD:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 0
 ; CHECK-NEXT:    [[SOV:%.*]] = extractvalue { i8, i1 } [[ADD_SOV]], 1
 ; CHECK-NEXT:    call void @use.i1(i1 [[SOV]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[ADD]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %x = add nuw i8 %xx, 1
   %y = add nuw i8 %yy, 1
@@ -836,8 +828,7 @@ define i1 @extract_value_usub(i8 %x, i8 %zz) {
 ; CHECK-NEXT:    [[UOV:%.*]] = extractvalue { i8, i1 } [[SUB_UOV]], 1
 ; CHECK-NEXT:    call void @use.i1(i1 [[UOV]])
 ; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[SUB]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %z = add nuw i8 %zz, 1
   %y = add i8 %x, %z
@@ -881,8 +872,7 @@ define i1 @extract_value_ssub(i8 %x, i8 %zz) {
 ; CHECK-NEXT:    [[SOV:%.*]] = extractvalue { i8, i1 } [[SUB_SOV]], 1
 ; CHECK-NEXT:    call void @use.i1(i1 [[SOV]])
 ; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[SUB]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %z = add nuw i8 %zz, 1
   %y = add i8 %x, %z
@@ -924,8 +914,7 @@ define i1 @extract_value_umul(i8 %xx, i8 %yy) {
 ; CHECK-NEXT:    [[UOV:%.*]] = extractvalue { i8, i1 } [[MUL_UOV]], 1
 ; CHECK-NEXT:    call void @use.i1(i1 [[UOV]])
 ; CHECK-NEXT:    call void @use.i8(i8 [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[MUL]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %x = or i8 %xx, 1
   %y = add nuw i8 %yy, 1
@@ -972,8 +961,7 @@ define i1 @extract_value_smul(i8 %xx, i8 %yy) {
 ; CHECK-NEXT:    [[SOV:%.*]] = extractvalue { i8, i1 } [[MUL_SOV]], 1
 ; CHECK-NEXT:    call void @use.i1(i1 [[SOV]])
 ; CHECK-NEXT:    call void @use.i8(i8 [[MUL]])
-; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[MUL]], 0
-; CHECK-NEXT:    ret i1 [[R]]
+; CHECK-NEXT:    ret i1 false
 ;
   %x = or i8 %xx, 1
   %y = add nuw i8 %yy, 1


        


More information about the llvm-commits mailing list