[llvm] 587c7ff - [InstCombine] Support min/max intrinsics in udiv->lshr fold

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 23 06:51:50 PST 2022


Author: Nikita Popov
Date: 2022-02-23T15:51:36+01:00
New Revision: 587c7ff15c26d3a751fb6a10b2af60d4a25640c9

URL: https://github.com/llvm/llvm-project/commit/587c7ff15c26d3a751fb6a10b2af60d4a25640c9
DIFF: https://github.com/llvm/llvm-project/commit/587c7ff15c26d3a751fb6a10b2af60d4a25640c9.diff

LOG: [InstCombine] Support min/max intrinsics in udiv->lshr fold

This complements the existing fold for selects. This fold is a bit
more conservative, requiring one-use. The other folds here should
probably also be subjected to a one-use restriction.

https://alive2.llvm.org/ce/z/Q9eCDU
https://alive2.llvm.org/ce/z/8YK2CJ

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/test/Transforms/InstCombine/div-shift.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index aeae25476db61..dd866eaa07bb6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -927,12 +927,14 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
     return nullptr;
 
   // log2(zext X) -> zext log2(X)
+  // FIXME: Require one use?
   Value *X, *Y;
   if (match(Op, m_ZExt(m_Value(X))))
     if (Value *LogX = takeLog2(Builder, X, Depth, DoFold))
       return IfFold([&]() { return Builder.CreateZExt(LogX, Op->getType()); });
 
   // log2(X << Y) -> log2(X) + Y
+  // FIXME: Require one use unless X is 1?
   if (match(Op, m_Shl(m_Value(X), m_Value(Y))))
     if (Value *LogX = takeLog2(Builder, X, Depth, DoFold))
       return IfFold([&]() { return Builder.CreateAdd(LogX, Y); });
@@ -941,6 +943,7 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
   // FIXME: missed optimization: if one of the hands of select is/contains
   //        undef, just directly pick the other one.
   // FIXME: can both hands contain undef?
+  // FIXME: Require one use?
   if (SelectInst *SI = dyn_cast<SelectInst>(Op))
     if (Value *LogX = takeLog2(Builder, SI->getOperand(1), Depth, DoFold))
       if (Value *LogY = takeLog2(Builder, SI->getOperand(2), Depth, DoFold))
@@ -948,6 +951,17 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
           return Builder.CreateSelect(SI->getOperand(0), LogX, LogY);
         });
 
+  // log2(umin(X, Y)) -> umin(log2(X), log2(Y))
+  // log2(umax(X, Y)) -> umax(log2(X), log2(Y))
+  auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op);
+  if (MinMax && MinMax->hasOneUse() && !MinMax->isSigned())
+    if (Value *LogX = takeLog2(Builder, MinMax->getLHS(), Depth, DoFold))
+      if (Value *LogY = takeLog2(Builder, MinMax->getRHS(), Depth, DoFold))
+        return IfFold([&]() {
+          return Builder.CreateBinaryIntrinsic(
+              MinMax->getIntrinsicID(), LogX, LogY);
+        });
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index a2399df69d9bd..ec7ee56d7f5a7 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -108,11 +108,9 @@ define i32 @t6(i32 %x, i32 %z) {
 
 define i8 @udiv_umin(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @udiv_umin(
-; CHECK-NEXT:    [[Y2:%.*]] = shl i8 1, [[Y:%.*]]
-; CHECK-NEXT:    [[Z2:%.*]] = shl i8 1, [[Z:%.*]]
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y2]], i8 [[Z2]])
-; CHECK-NEXT:    [[D:%.*]] = udiv i8 [[X:%.*]], [[M]]
-; CHECK-NEXT:    ret i8 [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[Z:%.*]])
+; CHECK-NEXT:    [[D1:%.*]] = lshr i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[D1]]
 ;
   %y2 = shl i8 1, %y
   %z2 = shl i8 1, %z
@@ -123,11 +121,9 @@ define i8 @udiv_umin(i8 %x, i8 %y, i8 %z) {
 
 define i8 @udiv_umax(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @udiv_umax(
-; CHECK-NEXT:    [[Y2:%.*]] = shl i8 1, [[Y:%.*]]
-; CHECK-NEXT:    [[Z2:%.*]] = shl i8 1, [[Z:%.*]]
-; CHECK-NEXT:    [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[Y2]], i8 [[Z2]])
-; CHECK-NEXT:    [[D:%.*]] = udiv i8 [[X:%.*]], [[M]]
-; CHECK-NEXT:    ret i8 [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[Y:%.*]], i8 [[Z:%.*]])
+; CHECK-NEXT:    [[D1:%.*]] = lshr i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[D1]]
 ;
   %y2 = shl i8 1, %y
   %z2 = shl i8 1, %z


        


More information about the llvm-commits mailing list