[llvm] 3c127e8 - [ConstraintElim] Replace NUWSub decomp with recursive decomp of ops.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 2 14:06:19 PST 2024


Author: Florian Hahn
Date: 2024-01-02T22:05:57Z
New Revision: 3c127e83c07c3791e86413c22a414a030d4302e3

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

LOG: [ConstraintElim] Replace NUWSub decomp with recursive decomp of ops.

The current patterns for NUWSub decompositions do not handle negative
constants correctly at the moment (causing #76713).

Replace the incorrect pattern by more general code that recursively
decomposes the operands and then combines the results. This is already
done in most other places that handle operators like add/mul.

This means we fall back to the general constant handling code (fixes the
mis-compile) while also being able to support reasoning about
decomposable expressions in the SUB operands.

Fixes https://github.com/llvm/llvm-project/issues/76713.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
    llvm/test/Transforms/ConstraintElimination/sub-nuw.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 49ac1e96e2554f..06c87bd6dc374a 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -366,6 +366,13 @@ struct Decomposition {
     append_range(Vars, Other.Vars);
   }
 
+  void sub(const Decomposition &Other) {
+    Decomposition Tmp = Other;
+    Tmp.mul(-1);
+    add(Tmp.Offset);
+    append_range(Vars, Tmp.Vars);
+  }
+
   void mul(int64_t Factor) {
     Offset = multiplyWithOverflow(Offset, Factor);
     for (auto &Var : Vars)
@@ -569,10 +576,12 @@ static Decomposition decompose(Value *V,
     return Result;
   }
 
-  if (match(V, m_NUWSub(m_Value(Op0), m_ConstantInt(CI))) && canUseSExt(CI))
-    return {-1 * CI->getSExtValue(), {{1, Op0}}};
-  if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1))))
-    return {0, {{1, Op0}, {-1, Op1}}};
+  if (match(V, m_NUWSub(m_Value(Op0), m_Value(Op1)))) {
+    auto ResA = decompose(Op0, Preconditions, IsSigned, DL);
+    auto ResB = decompose(Op1, Preconditions, IsSigned, DL);
+    ResA.sub(ResB);
+    return ResA;
+  }
 
   return {V, IsKnownNonNegative};
 }

diff  --git a/llvm/test/Transforms/ConstraintElimination/sub-nuw.ll b/llvm/test/Transforms/ConstraintElimination/sub-nuw.ll
index ba468789af5c63..5ae559dc2b1b6d 100644
--- a/llvm/test/Transforms/ConstraintElimination/sub-nuw.ll
+++ b/llvm/test/Transforms/ConstraintElimination/sub-nuw.ll
@@ -316,12 +316,13 @@ define i1 @sub_nuw_neg_i16(i16 %a) {
 ; CHECK-LABEL: @sub_nuw_neg_i16(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[NEG2:%.*]] = sub nuw i16 [[A:%.*]], -305
-; CHECK-NEXT:    br i1 false, label [[EXIT_1:%.*]], label [[EXIT_2:%.*]]
+; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i16 0, [[NEG2]]
+; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_1:%.*]], label [[EXIT_2:%.*]]
 ; CHECK:       exit.1:
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i16 [[A]], 0
+; CHECK-NEXT:    ret i1 [[C_2]]
 ; CHECK:       exit.2:
-; CHECK-NEXT:    [[C_3:%.*]] = icmp ugt i16 [[A]], 0
-; CHECK-NEXT:    ret i1 [[C_3]]
+; CHECK-NEXT:    ret i1 true
 ;
 entry:
   %neg2 = sub nuw i16 %a, -305
@@ -380,7 +381,6 @@ entry:
   ret i1 %c
 }
 
-; FIXME: currently this incorrectly simplifies %c4 to true.
 define i1 @pr76713(i16 %i1, i16 %i3) {
 ; CHECK-LABEL: @pr76713(
 ; CHECK-NEXT:  entry:
@@ -394,7 +394,8 @@ define i1 @pr76713(i16 %i1, i16 %i3) {
 ; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i16 [[I1]], -3
 ; CHECK-NEXT:    [[ARRAYIDX_IDX:%.*]] = mul nuw nsw i16 [[I3]], 4
 ; CHECK-NEXT:    [[I6:%.*]] = add nuw nsw i16 [[ARRAYIDX_IDX]], [[SUB]]
-; CHECK-NEXT:    ret i1 true
+; CHECK-NEXT:    [[C4:%.*]] = icmp ult i16 12, [[I6]]
+; CHECK-NEXT:    ret i1 [[C4]]
 ; CHECK:       else:
 ; CHECK-NEXT:    ret i1 false
 ;
@@ -417,7 +418,6 @@ else:
   ret i1 0
 }
 
-; FIXME: Currently gets mis-compiled.
 define void @sub_nuw_chained_positive_constants(i16 %a) {
 ; CHECK-LABEL: @sub_nuw_chained_positive_constants(
 ; CHECK-NEXT:  entry:
@@ -426,16 +426,13 @@ define void @sub_nuw_chained_positive_constants(i16 %a) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i16 [[SUB2]], 90
 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_1:%.*]], label [[EXIT_2:%.*]]
 ; CHECK:       exit.1:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i16 [[A]], 120
-; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ugt i16 [[A]], 121
 ; CHECK-NEXT:    call void @use(i1 [[C_3]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit.2:
-; CHECK-NEXT:    [[C_4:%.*]] = icmp ugt i16 [[A]], 120
-; CHECK-NEXT:    call void @use(i1 [[C_4]])
-; CHECK-NEXT:    [[C_5:%.*]] = icmp ugt i16 [[A]], 121
-; CHECK-NEXT:    call void @use(i1 [[C_5]])
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -459,7 +456,6 @@ exit.2:
   ret void
 }
 
-; FIXME: Currently gets mis-compiled.
 define void @sub_nuw_chained_negative_constants(i8 %a) {
 ; CHECK-LABEL: @sub_nuw_chained_negative_constants(
 ; CHECK-NEXT:  entry:
@@ -468,14 +464,13 @@ define void @sub_nuw_chained_negative_constants(i8 %a) {
 ; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[SUB2]], 20
 ; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_1:%.*]], label [[EXIT_2:%.*]]
 ; CHECK:       exit.1:
-; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i8 [[A]], -96
-; CHECK-NEXT:    call void @use(i1 [[C_2]])
+; CHECK-NEXT:    call void @use(i1 true)
 ; CHECK-NEXT:    [[C_3:%.*]] = icmp ugt i8 [[A]], -95
 ; CHECK-NEXT:    call void @use(i1 [[C_3]])
 ; CHECK-NEXT:    ret void
 ; CHECK:       exit.2:
-; CHECK-NEXT:    call void @use(i1 true)
-; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 false)
 ; CHECK-NEXT:    ret void
 ;
 entry:


        


More information about the llvm-commits mailing list