[llvm] a4635ec - [ConstraintElim] Support `add nsw` for unsigned preds with positive ops.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 16 12:25:33 PDT 2022


Author: Florian Hahn
Date: 2022-10-16T20:25:14+01:00
New Revision: a4635ec7108c57adc248d203a39e809918a9d028

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

LOG: [ConstraintElim] Support `add nsw` for unsigned preds with positive ops.

If both operands of an `add nsw` are known positive, it can be treated
the same as `add nuw` and added to the unsigned system.

https://alive2.llvm.org/ce/z/6gprff

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
    llvm/test/Transforms/ConstraintElimination/add-nsw.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index e1290e9443f93..db1da1fd8e70f 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -373,6 +373,17 @@ decompose(Value *V, SmallVector<PreconditionTy, 4> &Preconditions,
   if (match(V, m_NUWAdd(m_Value(Op0), m_Value(Op1)))) {
     return MergeResults(Op0, Op1, IsSigned);
   }
+  if (match(V, m_NSWAdd(m_Value(Op0), m_Value(Op1)))) {
+    if (!isKnownNonNegative(Op0, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
+      Preconditions.emplace_back(CmpInst::ICMP_SGE, Op0,
+                                 ConstantInt::get(Op0->getType(), 0));
+    if (!isKnownNonNegative(Op1, DL, /*Depth=*/MaxAnalysisRecursionDepth - 1))
+      Preconditions.emplace_back(CmpInst::ICMP_SGE, Op1,
+                                 ConstantInt::get(Op1->getType(), 0));
+
+    return MergeResults(Op0, Op1, IsSigned);
+  }
+
   if (match(V, m_Add(m_Value(Op0), m_ConstantInt(CI))) && CI->isNegative() &&
       canUseSExt(CI)) {
     Preconditions.emplace_back(

diff  --git a/llvm/test/Transforms/ConstraintElimination/add-nsw.ll b/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
index c7f85719fa478..816c7ae912a18 100644
--- a/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
+++ b/llvm/test/Transforms/ConstraintElimination/add-nsw.ll
@@ -255,7 +255,7 @@ define i1 @test_ult_add_nsw_pos_1(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[T:%.*]] = icmp ult i16 [[START_EXT]], [[HIGH_EXT]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %high.ext = zext i8 %high to i16
@@ -277,7 +277,7 @@ define i1 @test_ult_add_nsw_pos_1_assume_pos(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[T:%.*]] = icmp ult i8 [[START]], [[HIGH]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %start.pos = icmp sge i8 %start, 0
@@ -317,7 +317,7 @@ define i1 @test_ult_add_nsw_pos_1_cmp_no_ext(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[T:%.*]] = icmp ult i8 [[START]], [[HIGH]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %high.ext = zext i8 %high to i16
@@ -339,7 +339,7 @@ define i1 @test_ult_add_nsw_pos_2(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[F:%.*]] = icmp uge i16 [[START_EXT]], [[HIGH_EXT]]
-; CHECK-NEXT:    ret i1 [[F]]
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %high.ext = zext i8 %high to i16
@@ -361,7 +361,7 @@ define i1 @test_ult_add_nsw_pos_2_assume_pos(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[F:%.*]] = icmp uge i8 [[START]], [[HIGH]]
-; CHECK-NEXT:    ret i1 [[F]]
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %start.pos = icmp sge i8 %start, 0
@@ -383,7 +383,7 @@ define i1 @test_ult_add_nsw_pos_2_cmp_no_ext(i8 %start, i8 %high) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i16 [[ADD_EXT]], [[HIGH_EXT]]
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[C:%.*]] = icmp uge i8 [[START]], [[HIGH]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 false
 ;
 entry:
   %high.ext = zext i8 %high to i16
@@ -454,7 +454,7 @@ define i1 @test_ult_add_nsw_pos_4(i8 %start, i8 %high) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i16 [[START_EXT]], 2
 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i16 [[ADD_2]], [[HIGH_EXT]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %high.ext = zext i8 %high to i16
@@ -478,7 +478,7 @@ define i1 @test_ult_add_nsw_pos_4_assume_pos(i8 %start, i8 %high) {
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
 ; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i8 [[START]], 2
 ; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_2]], [[HIGH]]
-; CHECK-NEXT:    ret i1 [[C]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %start.pos = icmp sge i8 %start, 0
@@ -663,3 +663,107 @@ entry:
   %c = icmp ult i8 %add.off.2, %high
   ret i1 %c
 }
+
+define i1 @test_ult_add_nsw_var_8_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
+; CHECK-LABEL: @test_ult_add_nsw_var_8_all_pos(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], [[OFF_2:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
+; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
+; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
+; CHECK-NEXT:    [[OFF_1_ULT:%.*]] = icmp ult i8 [[OFF_1]], [[OFF_2]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_ULT]])
+; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
+; CHECK-NEXT:    ret i1 true
+;
+entry:
+  %start.pos = icmp sge i8 %start, 0
+  call void @llvm.assume(i1 %start.pos)
+  %add = add nsw i8 %start, %off.2
+  %c.1 = icmp ult i8 %add, %high
+  call void @llvm.assume(i1 %c.1)
+  %off.1.pos = icmp sge i8 %off.1, 0
+  call void @llvm.assume(i1 %off.1.pos)
+  %off.2.pos = icmp sge i8 %off.2, 0
+  call void @llvm.assume(i1 %off.2.pos)
+  %off.1.ult = icmp ult i8 %off.1, %off.2
+  call void @llvm.assume(i1 %off.1.ult)
+
+  %add.off.2 = add nsw i8 %start, %off.1
+  %c = icmp ult i8 %add.off.2, %high
+  ret i1 %c
+}
+
+define i1 @test_ult_add_no_nsw_var_8_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
+; CHECK-LABEL: @test_ult_add_no_nsw_var_8_all_pos(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
+; CHECK-NEXT:    [[ADD:%.*]] = add i8 [[START]], [[OFF_2:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
+; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
+; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
+; CHECK-NEXT:    [[OFF_1_ULT:%.*]] = icmp ult i8 [[OFF_1]], [[OFF_2]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_ULT]])
+; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+entry:
+  %start.pos = icmp sge i8 %start, 0
+  call void @llvm.assume(i1 %start.pos)
+  %add = add i8 %start, %off.2
+  %c.1 = icmp ult i8 %add, %high
+  call void @llvm.assume(i1 %c.1)
+  %off.1.pos = icmp sge i8 %off.1, 0
+  call void @llvm.assume(i1 %off.1.pos)
+  %off.2.pos = icmp sge i8 %off.2, 0
+  call void @llvm.assume(i1 %off.2.pos)
+  %off.1.ult = icmp ult i8 %off.1, %off.2
+  call void @llvm.assume(i1 %off.1.ult)
+
+  %add.off.2 = add nsw i8 %start, %off.1
+  %c = icmp ult i8 %add.off.2, %high
+  ret i1 %c
+}
+
+define i1 @test_ult_add_nsw_var_9_all_pos(i8 %start, i8 %off.1, i8 %off.2, i8 %high) {
+; CHECK-LABEL: @test_ult_add_nsw_var_9_all_pos(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[START_POS:%.*]] = icmp sge i8 [[START:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[START_POS]])
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[START]], [[OFF_2:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i8 [[ADD]], [[HIGH:%.*]]
+; CHECK-NEXT:    call void @llvm.assume(i1 [[C_1]])
+; CHECK-NEXT:    [[OFF_1_POS:%.*]] = icmp sge i8 [[OFF_1:%.*]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_1_POS]])
+; CHECK-NEXT:    [[OFF_2_POS:%.*]] = icmp sge i8 [[OFF_2]], 0
+; CHECK-NEXT:    call void @llvm.assume(i1 [[OFF_2_POS]])
+; CHECK-NEXT:    [[ADD_OFF_2:%.*]] = add nsw i8 [[START]], [[OFF_1]]
+; CHECK-NEXT:    [[C:%.*]] = icmp ult i8 [[ADD_OFF_2]], [[HIGH]]
+; CHECK-NEXT:    ret i1 [[C]]
+;
+entry:
+  %start.pos = icmp sge i8 %start, 0
+  call void @llvm.assume(i1 %start.pos)
+  %add = add nsw i8 %start, %off.2
+  %c.1 = icmp ult i8 %add, %high
+  call void @llvm.assume(i1 %c.1)
+  %off.1.pos = icmp sge i8 %off.1, 0
+  call void @llvm.assume(i1 %off.1.pos)
+  %off.2.pos = icmp sge i8 %off.2, 0
+  call void @llvm.assume(i1 %off.2.pos)
+
+  %add.off.2 = add nsw i8 %start, %off.1
+  %c = icmp ult i8 %add.off.2, %high
+  ret i1 %c
+}


        


More information about the llvm-commits mailing list