[PATCH] D92717: [IC] Fix invalid creation of uadd.sat

Dave Green via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 5 03:41:42 PST 2020


dmgreen created this revision.
dmgreen added reviewers: spatel, nikic, meheff, RKSimon.
Herald added a subscriber: hiraditya.
dmgreen requested review of this revision.
Herald added a project: LLVM.

We could create uadd.sat under incorrect circumstances if a select with -1 as the false value was canonicalized by swapping the T/F values. Unlike the other transforms in the same function, it is not invariant to equality.

Some alive proofs: https://alive2.llvm.org/ce/z/emmKKL
Fixes PR48390


https://reviews.llvm.org/D92717

Files:
  llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
  llvm/test/Transforms/InstCombine/saturating-add-sub.ll


Index: llvm/test/Transforms/InstCombine/saturating-add-sub.ll
===================================================================
--- llvm/test/Transforms/InstCombine/saturating-add-sub.ll
+++ llvm/test/Transforms/InstCombine/saturating-add-sub.ll
@@ -1722,8 +1722,10 @@
 
 define i32 @swapped_select(i32 %x1, i32 %x2) {
 ; CHECK-LABEL: @swapped_select(
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X2:%.*]], i32 [[X1:%.*]])
-; CHECK-NEXT:    ret i32 [[TMP1]]
+; CHECK-NEXT:    [[X14:%.*]] = add i32 [[X1:%.*]], [[X2:%.*]]
+; CHECK-NEXT:    [[X6:%.*]] = icmp ugt i32 [[X14]], [[X2]]
+; CHECK-NEXT:    [[X9:%.*]] = select i1 [[X6]], i32 [[X14]], i32 -1
+; CHECK-NEXT:    ret i32 [[X9]]
 ;
   %x14 = add i32 %x1, %x2
   %x6 = icmp ult i32 %x2, %x14
@@ -1733,8 +1735,10 @@
 
 define i32 @swapped_both(i32 %x1, i32 %x2) {
 ; CHECK-LABEL: @swapped_both(
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X2:%.*]], i32 [[X1:%.*]])
-; CHECK-NEXT:    ret i32 [[TMP1]]
+; CHECK-NEXT:    [[X14:%.*]] = add i32 [[X1:%.*]], [[X2:%.*]]
+; CHECK-NEXT:    [[X6:%.*]] = icmp ugt i32 [[X14]], [[X2]]
+; CHECK-NEXT:    [[X9:%.*]] = select i1 [[X6]], i32 [[X14]], i32 -1
+; CHECK-NEXT:    ret i32 [[X9]]
 ;
   %x14 = add i32 %x1, %x2
   %x6 = icmp ugt i32 %x14, %x2
Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -768,9 +768,11 @@
   // Canonicalize -1 (saturated result) to true value of the select. Just
   // swapping the compare operands is legal, because the selected value is the
   // same in case of equality, so we can interchange u< and u<=.
+  bool Swapped = false;
   if (match(FVal, m_AllOnes())) {
     std::swap(TVal, FVal);
     std::swap(Cmp0, Cmp1);
+    Swapped = true;
   }
   if (!match(TVal, m_AllOnes()))
     return nullptr;
@@ -801,8 +803,9 @@
     return Builder.CreateBinaryIntrinsic(
         Intrinsic::uadd_sat, BO->getOperand(0), BO->getOperand(1));
   }
-  // The overflow may be detected via the add wrapping round.
-  if (match(Cmp0, m_c_Add(m_Specific(Cmp1), m_Value(Y))) &&
+  // The overflow may be detected via the add wrapping round. Which is only
+  // valid if we did not swap the true and false values.
+  if (!Swapped && match(Cmp0, m_c_Add(m_Specific(Cmp1), m_Value(Y))) &&
       match(FVal, m_c_Add(m_Specific(Cmp1), m_Specific(Y)))) {
     // ((X + Y) u< X) ? -1 : (X + Y) --> uadd.sat(X, Y)
     // ((X + Y) u< Y) ? -1 : (X + Y) --> uadd.sat(X, Y)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D92717.309728.patch
Type: text/x-patch
Size: 2617 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201205/2708f4d2/attachment.bin>


More information about the llvm-commits mailing list