[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