[PATCH] D145457: [InstSimplify] Add simplifications for `umin/umax(uadd/usub.sat(X, Y), X)`

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 6 18:07:03 PST 2023


goldstein.w.n created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

`umax(uadd.sat(X, Y), X) --> uadd.sat(X, Y)`

- https://alive2.llvm.org/ce/z/mEJk_t

`umin(uadd.sat(X, Y), X) --> X`

- https://alive2.llvm.org/ce/z/ZfVrjD

`umax(usub.sat(X, Y), X) --> X`

- https://alive2.llvm.org/ce/z/ec8xDQ

`umin(usub.sat(X, Y), X) --> usub.sat(X, Y)`

- https://alive2.llvm.org/ce/z/FLkAcA


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145457

Files:
  llvm/lib/Analysis/InstructionSimplify.cpp
  llvm/test/Transforms/InstSimplify/minmax-intrin.ll


Index: llvm/test/Transforms/InstSimplify/minmax-intrin.ll
===================================================================
--- llvm/test/Transforms/InstSimplify/minmax-intrin.ll
+++ llvm/test/Transforms/InstSimplify/minmax-intrin.ll
@@ -21,8 +21,7 @@
 define <2 x i8> @umax_uadd_sat(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @umax_uadd_sat(
 ; CHECK-NEXT:    [[XX:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = call <2 x i8> @llvm.umax.v2i8(<2 x i8> [[X]], <2 x i8> [[XX]])
-; CHECK-NEXT:    ret <2 x i8> [[RET]]
+; CHECK-NEXT:    ret <2 x i8> [[XX]]
 ;
   %xx = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %x, <2 x i8> %y)
   %ret = call <2 x i8> @llvm.umax.v2i8(<2 x i8> %x, <2 x i8> %xx)
@@ -31,9 +30,7 @@
 
 define i8 @umin_uadd_sat(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umin_uadd_sat(
-; CHECK-NEXT:    [[XX:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = call i8 @llvm.umin.i8(i8 [[XX]], i8 [[X]])
-; CHECK-NEXT:    ret i8 [[RET]]
+; CHECK-NEXT:    ret i8 [[X:%.*]]
 ;
   %xx = call i8 @llvm.uadd.sat.i8(i8 %x, i8 %y)
   %ret = call i8 @llvm.umin.i8(i8 %xx, i8 %x)
@@ -42,9 +39,7 @@
 
 define i8 @umax_usub_sat(i8 %x, i8 %y) {
 ; CHECK-LABEL: @umax_usub_sat(
-; CHECK-NEXT:    [[XX:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[XX]])
-; CHECK-NEXT:    ret i8 [[RET]]
+; CHECK-NEXT:    ret i8 [[X:%.*]]
 ;
   %xx = call i8 @llvm.usub.sat.i8(i8 %x, i8 %y)
   %ret = call i8 @llvm.umax.i8(i8 %x, i8 %xx)
@@ -54,8 +49,7 @@
 define <2 x i8> @umin_usub_sat(<2 x i8> %x, <2 x i8> %y) {
 ; CHECK-LABEL: @umin_usub_sat(
 ; CHECK-NEXT:    [[XX:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]])
-; CHECK-NEXT:    [[RET:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[X]], <2 x i8> [[XX]])
-; CHECK-NEXT:    ret <2 x i8> [[RET]]
+; CHECK-NEXT:    ret <2 x i8> [[XX]]
 ;
   %xx = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %x, <2 x i8> %y)
   %ret = call <2 x i8> @llvm.umin.v2i8(<2 x i8> %x, <2 x i8> %xx)
Index: llvm/lib/Analysis/InstructionSimplify.cpp
===================================================================
--- llvm/lib/Analysis/InstructionSimplify.cpp
+++ llvm/lib/Analysis/InstructionSimplify.cpp
@@ -6105,6 +6105,27 @@
   return nullptr;
 }
 
+static Value *foldMinMaxOfIntrin(Intrinsic::ID IID, Value *Op0, Value *Op1) {
+  if (IID == Intrinsic::umax || IID == Intrinsic::umin) {
+    // umax(uadd.sat(X, Y), X) --> uadd.sat(X, Y)
+    // umin(uadd.sat(X, Y), X) --> X
+    if (match(Op0,
+              m_Intrinsic<Intrinsic::uadd_sat>(m_Specific(Op1), m_Value())) ||
+        match(Op0,
+              m_Intrinsic<Intrinsic::uadd_sat>(m_Value(), m_Specific(Op1))))
+      return IID == Intrinsic::umax ? Op0 : Op1;
+    // umax(usub.sat(X, Y), X) --> X
+    // umin(usub.sat(X, Y), X) --> usub.sat(X, Y)
+    if (match(Op0,
+              m_Intrinsic<Intrinsic::usub_sat>(m_Specific(Op1), m_Value())) ||
+        match(Op0,
+              m_Intrinsic<Intrinsic::usub_sat>(m_Value(), m_Specific(Op1))))
+      return IID == Intrinsic::umin ? Op0 : Op1;
+  }
+
+  return nullptr;
+}
+
 static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1,
                                       const SimplifyQuery &Q) {
   Intrinsic::ID IID = F->getIntrinsicID();
@@ -6184,6 +6205,11 @@
     if (Value *V = foldMinMaxSharedOp(IID, Op1, Op0))
       return V;
 
+    if (Value *V = foldMinMaxOfIntrin(IID, Op0, Op1))
+      return V;
+    if (Value *V = foldMinMaxOfIntrin(IID, Op1, Op0))
+      return V;
+
     ICmpInst::Predicate Pred =
         ICmpInst::getNonStrictPredicate(MinMaxIntrinsic::getPredicate(IID));
     if (isICmpTrue(Pred, Op0, Op1, Q.getWithoutUndef(), RecursionLimit))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D145457.502883.patch
Type: text/x-patch
Size: 3841 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230307/c59738a8/attachment.bin>


More information about the llvm-commits mailing list