[llvm] 0ce2920 - [InstCombine] try to narrow min/max intrinsics with constant operand

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 1 10:55:20 PST 2021


Author: Sanjay Patel
Date: 2021-02-01T13:44:13-05:00
New Revision: 0ce2920f1707266c0d94dacc8719251b7b6a2c01

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

LOG: [InstCombine] try to narrow min/max intrinsics with constant operand

The constant trunc/ext may not be the optimal pre-condition,
but I think that handles the common cases.

Example of Alive2 proof:
https://alive2.llvm.org/ce/z/sREeLC

This is another step towards canonicalizing to the intrinsics.
Narrowing was identified as source of potential regression for
abs(), so we need to handle this for min/max - see:
https://llvm.org/PR48816

If this is not enough, we could process intrinsics in
the trunc-driven matching in canEvaluateTruncated().

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/test/Transforms/InstCombine/minmax-intrinsics.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 5482b944e347..6c87dcaa2985 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -839,6 +839,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
       return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
     }
+    Constant *C;
+    if (match(I0, m_ZExt(m_Value(X))) && match(I1, m_Constant(C)) &&
+        I0->hasOneUse()) {
+      Constant *NarrowC = ConstantExpr::getTrunc(C, X->getType());
+      if (ConstantExpr::getZExt(NarrowC, II->getType()) == C) {
+        Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC);
+        return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
+      }
+    }
     // If both operands of unsigned min/max are sign-extended, it is still ok
     // to narrow the operation.
     LLVM_FALLTHROUGH;
@@ -852,6 +861,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
       return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType());
     }
+    Constant *C;
+    if (match(I0, m_SExt(m_Value(X))) && match(I1, m_Constant(C)) &&
+        I0->hasOneUse()) {
+      Constant *NarrowC = ConstantExpr::getTrunc(C, X->getType());
+      if (ConstantExpr::getSExt(NarrowC, II->getType()) == C) {
+        Value *NarrowMaxMin = Builder.CreateBinaryIntrinsic(IID, X, NarrowC);
+        return CastInst::Create(Instruction::SExt, NarrowMaxMin, II->getType());
+      }
+    }
     break;
   }
   case Intrinsic::bswap: {

diff  --git a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
index ecfcd0f267c1..4e3987f4640c 100644
--- a/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-intrinsics.ll
@@ -213,8 +213,8 @@ define i8 @umin_zext_uses(i5 %x, i5 %y) {
 
 define i8 @smax_sext_constant(i5 %x) {
 ; CHECK-LABEL: @smax_sext_constant(
-; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[E]], i8 7)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.smax.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
 ; CHECK-NEXT:    ret i8 [[M]]
 ;
   %e = sext i5 %x to i8
@@ -222,6 +222,8 @@ define i8 @smax_sext_constant(i5 %x) {
   ret i8 %m
 }
 
+; simplifies
+
 define i8 @smax_sext_constant_big(i5 %x) {
 ; CHECK-LABEL: @smax_sext_constant_big(
 ; CHECK-NEXT:    ret i8 16
@@ -231,6 +233,8 @@ define i8 @smax_sext_constant_big(i5 %x) {
   ret i8 %m
 }
 
+; negative test
+
 define i8 @smax_zext_constant(i5 %x) {
 ; CHECK-LABEL: @smax_zext_constant(
 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -244,8 +248,8 @@ define i8 @smax_zext_constant(i5 %x) {
 
 define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
 ; CHECK-LABEL: @smin_sext_constant(
-; CHECK-NEXT:    [[E:%.*]] = sext <3 x i5> [[X:%.*]] to <3 x i8>
-; CHECK-NEXT:    [[M:%.*]] = call <3 x i8> @llvm.smin.v3i8(<3 x i8> [[E]], <3 x i8> <i8 7, i8 15, i8 -16>)
+; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.smin.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -16>)
+; CHECK-NEXT:    [[M:%.*]] = sext <3 x i5> [[TMP1]] to <3 x i8>
 ; CHECK-NEXT:    ret <3 x i8> [[M]]
 ;
   %e = sext <3 x i5> %x to <3 x i8>
@@ -253,6 +257,8 @@ define <3 x i8> @smin_sext_constant(<3 x i5> %x) {
   ret <3 x i8> %m
 }
 
+; negative test
+
 define i8 @smin_zext_constant(i5 %x) {
 ; CHECK-LABEL: @smin_zext_constant(
 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -266,8 +272,8 @@ define i8 @smin_zext_constant(i5 %x) {
 
 define i8 @umax_sext_constant(i5 %x) {
 ; CHECK-LABEL: @umax_sext_constant(
-; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[E]], i8 7)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umax.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT:    [[M:%.*]] = sext i5 [[TMP1]] to i8
 ; CHECK-NEXT:    ret i8 [[M]]
 ;
   %e = sext i5 %x to i8
@@ -275,6 +281,8 @@ define i8 @umax_sext_constant(i5 %x) {
   ret i8 %m
 }
 
+; negative test
+
 define i8 @umax_sext_constant_big(i5 %x) {
 ; CHECK-LABEL: @umax_sext_constant_big(
 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
@@ -288,8 +296,8 @@ define i8 @umax_sext_constant_big(i5 %x) {
 
 define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
 ; CHECK-LABEL: @umax_zext_constant(
-; CHECK-NEXT:    [[E:%.*]] = zext <3 x i5> [[X:%.*]] to <3 x i8>
-; CHECK-NEXT:    [[M:%.*]] = call <3 x i8> @llvm.umax.v3i8(<3 x i8> [[E]], <3 x i8> <i8 7, i8 15, i8 31>)
+; CHECK-NEXT:    [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 7, i5 15, i5 -1>)
+; CHECK-NEXT:    [[M:%.*]] = zext <3 x i5> [[TMP1]] to <3 x i8>
 ; CHECK-NEXT:    ret <3 x i8> [[M]]
 ;
   %e = zext <3 x i5> %x to <3 x i8>
@@ -297,6 +305,8 @@ define <3 x i8> @umax_zext_constant(<3 x i5> %x) {
   ret <3 x i8> %m
 }
 
+; simplifies
+
 define i8 @umax_zext_constant_big(i5 %x) {
 ; CHECK-LABEL: @umax_zext_constant_big(
 ; CHECK-NEXT:    ret i8 126
@@ -308,8 +318,8 @@ define i8 @umax_zext_constant_big(i5 %x) {
 
 define i8 @umin_sext_constant(i5 %x) {
 ; CHECK-LABEL: @umin_sext_constant(
-; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
 ; CHECK-NEXT:    ret i8 [[M]]
 ;
   %e = sext i5 %x to i8
@@ -317,6 +327,8 @@ define i8 @umin_sext_constant(i5 %x) {
   ret i8 %m
 }
 
+; negative test
+
 define i8 @umin_sext_constant_big(i5 %x) {
 ; CHECK-LABEL: @umin_sext_constant_big(
 ; CHECK-NEXT:    [[E:%.*]] = sext i5 [[X:%.*]] to i8
@@ -330,8 +342,8 @@ define i8 @umin_sext_constant_big(i5 %x) {
 
 define i8 @umin_zext_constant(i5 %x) {
 ; CHECK-LABEL: @umin_zext_constant(
-; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[E]], i8 7)
+; CHECK-NEXT:    [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 7)
+; CHECK-NEXT:    [[M:%.*]] = zext i5 [[TMP1]] to i8
 ; CHECK-NEXT:    ret i8 [[M]]
 ;
   %e = zext i5 %x to i8
@@ -339,6 +351,8 @@ define i8 @umin_zext_constant(i5 %x) {
   ret i8 %m
 }
 
+; simplifies
+
 define i8 @umin_zext_constant_big(i5 %x) {
 ; CHECK-LABEL: @umin_zext_constant_big(
 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8
@@ -349,6 +363,8 @@ define i8 @umin_zext_constant_big(i5 %x) {
   ret i8 %m
 }
 
+; negative test
+
 define i8 @umin_zext_constanti_uses(i5 %x) {
 ; CHECK-LABEL: @umin_zext_constanti_uses(
 ; CHECK-NEXT:    [[E:%.*]] = zext i5 [[X:%.*]] to i8


        


More information about the llvm-commits mailing list