[llvm] 153da08 - [InstCombine] hoist min/max intrinsics above select with constant op

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 27 07:09:06 PDT 2021


Author: Sanjay Patel
Date: 2021-06-27T10:02:23-04:00
New Revision: 153da08a6cd7feea6644b3191019573d70a5bbd3

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

LOG: [InstCombine] hoist min/max intrinsics above select with constant op

This is an extension of the handling for unary intrinsics and
follows the logic that we use for binary ops.

We don't canonicalize to min/max intrinsics yet, but this might
help unlock other folds seen in D98152.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/test/Transforms/InstCombine/select-min-max.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 256c79dbdf1dd..fb3dfd89895be 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1041,6 +1041,11 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     if (Instruction *Sel = foldClampRangeOfTwo(II, Builder))
       return Sel;
 
+    if (match(I1, m_ImmConstant()))
+      if (auto *Sel = dyn_cast<SelectInst>(I0))
+        if (Instruction *R = FoldOpIntoSelect(*II, Sel))
+          return R;
+
     break;
   }
   case Intrinsic::bswap: {

diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 2dee94392c218..25b740503fbe2 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -942,13 +942,16 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, Value *SO,
     assert(canConstantFoldCallTo(II, cast<Function>(II->getCalledOperand())) &&
            "Expected constant-foldable intrinsic");
     Intrinsic::ID IID = II->getIntrinsicID();
-    SmallVector<Value *, 2> Args = {SO};
-
-    // Propagate the zero-is-undef argument to the new instruction.
-    if (IID == Intrinsic::ctlz || IID == Intrinsic::cttz)
-      Args.push_back(II->getArgOperand(1));
-
-    return Builder.CreateIntrinsic(IID, I.getType(), Args);
+    if (II->getNumArgOperands() == 1)
+      return Builder.CreateUnaryIntrinsic(IID, SO);
+
+    // This works for real binary ops like min/max (where we always expect the
+    // constant operand to be canonicalized as op1) and unary ops with a bonus
+    // constant argument like ctlz/cttz.
+    // TODO: Handle non-commutative binary intrinsics as below for binops.
+    assert(II->getNumArgOperands() == 2 && "Expected binary intrinsic");
+    assert(isa<Constant>(II->getArgOperand(1)) && "Expected constant operand");
+    return Builder.CreateBinaryIntrinsic(IID, SO, II->getArgOperand(1));
   }
 
   assert(I.isBinaryOp() && "Unexpected opcode for select folding");

diff  --git a/llvm/test/Transforms/InstCombine/select-min-max.ll b/llvm/test/Transforms/InstCombine/select-min-max.ll
index f14016eb4d136..ae6ee31705918 100644
--- a/llvm/test/Transforms/InstCombine/select-min-max.ll
+++ b/llvm/test/Transforms/InstCombine/select-min-max.ll
@@ -111,8 +111,7 @@ define i5 @umin_umin_common_op_10_uses(i1 %cond, i5 %x, i5 %y, i5 %z, i5* %p1, i
 
 define i5 @smin_select_const_const(i1 %b) {
 ; CHECK-LABEL: @smin_select_const_const(
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i5 -3, i5 8
-; CHECK-NEXT:    [[C:%.*]] = call i5 @llvm.smin.i5(i5 [[S]], i5 5)
+; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 5
 ; CHECK-NEXT:    ret i5 [[C]]
 ;
   %s = select i1 %b, i5 -3, i5 8
@@ -122,8 +121,7 @@ define i5 @smin_select_const_const(i1 %b) {
 
 define <2 x i8> @smax_select_const_const(<2 x i1> %b) {
 ; CHECK-LABEL: @smax_select_const_const(
-; CHECK-NEXT:    [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> <i8 1, i8 3>, <2 x i8> <i8 5, i8 43>
-; CHECK-NEXT:    [[C:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[S]], <2 x i8> <i8 0, i8 42>)
+; CHECK-NEXT:    [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> <i8 1, i8 42>, <2 x i8> <i8 5, i8 43>
 ; CHECK-NEXT:    ret <2 x i8> [[C]]
 ;
   %s = select <2 x i1> %b, <2 x i8> <i8 1, i8 3>, <2 x i8> <i8 5, i8 43>
@@ -133,8 +131,7 @@ define <2 x i8> @smax_select_const_const(<2 x i1> %b) {
 
 define i5 @umin_select_const_const(i1 %b) {
 ; CHECK-LABEL: @umin_select_const_const(
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i5 8, i5 3
-; CHECK-NEXT:    [[C:%.*]] = call i5 @llvm.umin.i5(i5 [[S]], i5 4)
+; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i5 4, i5 3
 ; CHECK-NEXT:    ret i5 [[C]]
 ;
   %s = select i1 %b, i5 8, i5 3
@@ -144,8 +141,7 @@ define i5 @umin_select_const_const(i1 %b) {
 
 define <3 x i5> @umax_select_const_const(<3 x i1> %b) {
 ; CHECK-LABEL: @umax_select_const_const(
-; CHECK-NEXT:    [[S:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> <i5 7, i5 8, i5 9>
-; CHECK-NEXT:    [[C:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[S]], <3 x i5> <i5 5, i5 8, i5 -16>)
+; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 -16>, <3 x i5> <i5 7, i5 8, i5 -16>
 ; CHECK-NEXT:    ret <3 x i5> [[C]]
 ;
   %s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> <i5 7, i5 8, i5 9>
@@ -155,8 +151,8 @@ define <3 x i5> @umax_select_const_const(<3 x i1> %b) {
 
 define i5 @smin_select_const(i1 %b, i5 %x) {
 ; CHECK-LABEL: @smin_select_const(
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i5 -3, i5 [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = call i5 @llvm.smin.i5(i5 [[S]], i5 5)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 5)
+; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 [[TMP1]]
 ; CHECK-NEXT:    ret i5 [[C]]
 ;
   %s = select i1 %b, i5 -3, i5 %x
@@ -166,8 +162,8 @@ define i5 @smin_select_const(i1 %b, i5 %x) {
 
 define <2 x i8> @smax_select_const(<2 x i1> %b, <2 x i8> %x) {
 ; CHECK-LABEL: @smax_select_const(
-; CHECK-NEXT:    [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> [[X:%.*]], <2 x i8> <i8 5, i8 43>
-; CHECK-NEXT:    [[C:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[S]], <2 x i8> <i8 0, i8 42>)
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> <i8 0, i8 42>)
+; CHECK-NEXT:    [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> [[TMP1]], <2 x i8> <i8 5, i8 43>
 ; CHECK-NEXT:    ret <2 x i8> [[C]]
 ;
   %s = select <2 x i1> %b, <2 x i8> %x, <2 x i8> <i8 5, i8 43>
@@ -177,8 +173,8 @@ define <2 x i8> @smax_select_const(<2 x i1> %b, <2 x i8> %x) {
 
 define i5 @umin_select_const(i1 %b, i5 %x) {
 ; CHECK-LABEL: @umin_select_const(
-; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i5 [[X:%.*]], i5 3
-; CHECK-NEXT:    [[C:%.*]] = call i5 @llvm.umin.i5(i5 [[S]], i5 4)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 4)
+; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i5 [[TMP1]], i5 3
 ; CHECK-NEXT:    ret i5 [[C]]
 ;
   %s = select i1 %b, i5 %x, i5 3
@@ -188,8 +184,8 @@ define i5 @umin_select_const(i1 %b, i5 %x) {
 
 define <3 x i5> @umax_select_const(<3 x i1> %b, <3 x i5> %x) {
 ; CHECK-LABEL: @umax_select_const(
-; CHECK-NEXT:    [[S:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> [[X:%.*]]
-; CHECK-NEXT:    [[C:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[S]], <3 x i5> <i5 5, i5 8, i5 1>)
+; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 5, i5 8, i5 1>)
+; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 4>, <3 x i5> [[TMP1]]
 ; CHECK-NEXT:    ret <3 x i5> [[C]]
 ;
   %s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> %x


        


More information about the llvm-commits mailing list