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); });
// 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))
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;
}
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
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