Skip to content

Commit b21edc4

Browse files
committed
[InstCombine] Move takeLog2 to InstructionCombiner; NFC
1 parent 372044e commit b21edc4

File tree

3 files changed

+111
-114
lines changed

3 files changed

+111
-114
lines changed

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
195195
PatternMatch::m_Value()));
196196
}
197197

198+
// Take the exact integer log2 of the value. If DoFold is true, create the
199+
// actual instructions, otherwise return a non-null dummy value. Return
200+
// nullptr on failure. Note, if DoFold is true the caller must ensure that
201+
// takeLog2 will succeed, otherwise it may create stray instructions.
202+
Value *takeLog2(Value *Op, unsigned Depth, bool AssumeNonZero, bool DoFold);
203+
198204
/// Return nonnull value if V is free to invert under the condition of
199205
/// WillInvertAllUses.
200206
/// If Builder is nonnull, it will return a simplified ~V.

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 6 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,6 @@ static Value *foldMulShl1(BinaryOperator &Mul, bool CommuteOperands,
185185
return nullptr;
186186
}
187187

188-
static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
189-
bool AssumeNonZero, bool DoFold);
190-
191188
Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
192189
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
193190
if (Value *V =
@@ -531,18 +528,18 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
531528
// (shl Op1, Log2(Op0))
532529
// if Log2(Op1) folds away ->
533530
// (shl Op0, Log2(Op1))
534-
if (takeLog2(Builder, Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
531+
if (takeLog2(Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
535532
/*DoFold*/ false)) {
536-
Value *Res = takeLog2(Builder, Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
533+
Value *Res = takeLog2(Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
537534
/*DoFold*/ true);
538535
BinaryOperator *Shl = BinaryOperator::CreateShl(Op1, Res);
539536
// We can only propegate nuw flag.
540537
Shl->setHasNoUnsignedWrap(HasNUW);
541538
return Shl;
542539
}
543-
if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
540+
if (takeLog2(Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
544541
/*DoFold*/ false)) {
545-
Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
542+
Value *Res = takeLog2(Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
546543
/*DoFold*/ true);
547544
BinaryOperator *Shl = BinaryOperator::CreateShl(Op0, Res);
548545
// We can only propegate nuw flag.
@@ -1407,111 +1404,6 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
14071404
return nullptr;
14081405
}
14091406

1410-
static const unsigned MaxDepth = 6;
1411-
1412-
// Take the exact integer log2 of the value. If DoFold is true, create the
1413-
// actual instructions, otherwise return a non-null dummy value. Return nullptr
1414-
// on failure.
1415-
static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
1416-
bool AssumeNonZero, bool DoFold) {
1417-
auto IfFold = [DoFold](function_ref<Value *()> Fn) {
1418-
if (!DoFold)
1419-
return reinterpret_cast<Value *>(-1);
1420-
return Fn();
1421-
};
1422-
1423-
// FIXME: assert that Op1 isn't/doesn't contain undef.
1424-
1425-
// log2(2^C) -> C
1426-
if (match(Op, m_Power2()))
1427-
return IfFold([&]() {
1428-
Constant *C = ConstantExpr::getExactLogBase2(cast<Constant>(Op));
1429-
if (!C)
1430-
llvm_unreachable("Failed to constant fold udiv -> logbase2");
1431-
return C;
1432-
});
1433-
1434-
// The remaining tests are all recursive, so bail out if we hit the limit.
1435-
if (Depth++ == MaxDepth)
1436-
return nullptr;
1437-
1438-
// log2(zext X) -> zext log2(X)
1439-
// FIXME: Require one use?
1440-
Value *X, *Y;
1441-
if (match(Op, m_ZExt(m_Value(X))))
1442-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1443-
return IfFold([&]() { return Builder.CreateZExt(LogX, Op->getType()); });
1444-
1445-
// log2(trunc x) -> trunc log2(X)
1446-
// FIXME: Require one use?
1447-
if (match(Op, m_Trunc(m_Value(X)))) {
1448-
auto *TI = cast<TruncInst>(Op);
1449-
if (AssumeNonZero || TI->hasNoUnsignedWrap())
1450-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1451-
return IfFold([&]() {
1452-
return Builder.CreateTrunc(LogX, Op->getType(), "",
1453-
/*IsNUW=*/TI->hasNoUnsignedWrap());
1454-
});
1455-
}
1456-
1457-
// log2(X << Y) -> log2(X) + Y
1458-
// FIXME: Require one use unless X is 1?
1459-
if (match(Op, m_Shl(m_Value(X), m_Value(Y)))) {
1460-
auto *BO = cast<OverflowingBinaryOperator>(Op);
1461-
// nuw will be set if the `shl` is trivially non-zero.
1462-
if (AssumeNonZero || BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap())
1463-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1464-
return IfFold([&]() { return Builder.CreateAdd(LogX, Y); });
1465-
}
1466-
1467-
// log2(X >>u Y) -> log2(X) - Y
1468-
// FIXME: Require one use?
1469-
if (match(Op, m_LShr(m_Value(X), m_Value(Y)))) {
1470-
auto *PEO = cast<PossiblyExactOperator>(Op);
1471-
if (AssumeNonZero || PEO->isExact())
1472-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1473-
return IfFold([&]() { return Builder.CreateSub(LogX, Y); });
1474-
}
1475-
1476-
// log2(X & Y) -> either log2(X) or log2(Y)
1477-
// This requires `AssumeNonZero` as `X & Y` may be zero when X != Y.
1478-
if (AssumeNonZero && match(Op, m_And(m_Value(X), m_Value(Y)))) {
1479-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1480-
return IfFold([&]() { return LogX; });
1481-
if (Value *LogY = takeLog2(Builder, Y, Depth, AssumeNonZero, DoFold))
1482-
return IfFold([&]() { return LogY; });
1483-
}
1484-
1485-
// log2(Cond ? X : Y) -> Cond ? log2(X) : log2(Y)
1486-
// FIXME: Require one use?
1487-
if (SelectInst *SI = dyn_cast<SelectInst>(Op))
1488-
if (Value *LogX = takeLog2(Builder, SI->getOperand(1), Depth,
1489-
AssumeNonZero, DoFold))
1490-
if (Value *LogY = takeLog2(Builder, SI->getOperand(2), Depth,
1491-
AssumeNonZero, DoFold))
1492-
return IfFold([&]() {
1493-
return Builder.CreateSelect(SI->getOperand(0), LogX, LogY);
1494-
});
1495-
1496-
// log2(umin(X, Y)) -> umin(log2(X), log2(Y))
1497-
// log2(umax(X, Y)) -> umax(log2(X), log2(Y))
1498-
auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op);
1499-
if (MinMax && MinMax->hasOneUse() && !MinMax->isSigned()) {
1500-
// Use AssumeNonZero as false here. Otherwise we can hit case where
1501-
// log2(umax(X, Y)) != umax(log2(X), log2(Y)) (because overflow).
1502-
if (Value *LogX = takeLog2(Builder, MinMax->getLHS(), Depth,
1503-
/*AssumeNonZero*/ false, DoFold))
1504-
if (Value *LogY = takeLog2(Builder, MinMax->getRHS(), Depth,
1505-
/*AssumeNonZero*/ false, DoFold))
1506-
return IfFold([&]() {
1507-
return Builder.CreateBinaryIntrinsic(MinMax->getIntrinsicID(), LogX,
1508-
LogY);
1509-
});
1510-
}
1511-
1512-
return nullptr;
1513-
}
1514-
15151407
/// If we have zero-extended operands of an unsigned div or rem, we may be able
15161408
/// to narrow the operation (sink the zext below the math).
15171409
static Instruction *narrowUDivURem(BinaryOperator &I,
@@ -1614,9 +1506,9 @@ Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
16141506
}
16151507

16161508
// Op1 udiv Op2 -> Op1 lshr log2(Op2), if log2() folds away.
1617-
if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ true,
1509+
if (takeLog2(Op1, /*Depth*/ 0, /*AssumeNonZero*/ true,
16181510
/*DoFold*/ false)) {
1619-
Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0,
1511+
Value *Res = takeLog2(Op1, /*Depth*/ 0,
16201512
/*AssumeNonZero*/ true, /*DoFold*/ true);
16211513
return replaceInstUsesWith(
16221514
I, Builder.CreateLShr(Op0, Res, I.getName(), I.isExact()));

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,105 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
25652565
return nullptr;
25662566
}
25672567

2568+
Value *InstCombiner::takeLog2(Value *Op, unsigned Depth, bool AssumeNonZero,
2569+
bool DoFold) {
2570+
auto IfFold = [DoFold](function_ref<Value *()> Fn) {
2571+
if (!DoFold)
2572+
return reinterpret_cast<Value *>(-1);
2573+
return Fn();
2574+
};
2575+
2576+
// FIXME: assert that Op1 isn't/doesn't contain undef.
2577+
2578+
// log2(2^C) -> C
2579+
if (match(Op, m_Power2()))
2580+
return IfFold([&]() {
2581+
Constant *C = ConstantExpr::getExactLogBase2(cast<Constant>(Op));
2582+
if (!C)
2583+
llvm_unreachable("Failed to constant fold udiv -> logbase2");
2584+
return C;
2585+
});
2586+
2587+
// The remaining tests are all recursive, so bail out if we hit the limit.
2588+
if (Depth++ == MaxAnalysisRecursionDepth)
2589+
return nullptr;
2590+
2591+
// log2(zext X) -> zext log2(X)
2592+
// FIXME: Require one use?
2593+
Value *X, *Y;
2594+
if (match(Op, m_ZExt(m_Value(X))))
2595+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
2596+
return IfFold([&]() { return Builder.CreateZExt(LogX, Op->getType()); });
2597+
2598+
// log2(trunc x) -> trunc log2(X)
2599+
// FIXME: Require one use?
2600+
if (match(Op, m_Trunc(m_Value(X)))) {
2601+
auto *TI = cast<TruncInst>(Op);
2602+
if (AssumeNonZero || TI->hasNoUnsignedWrap())
2603+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
2604+
return IfFold([&]() {
2605+
return Builder.CreateTrunc(LogX, Op->getType(), "",
2606+
/*IsNUW=*/TI->hasNoUnsignedWrap());
2607+
});
2608+
}
2609+
2610+
// log2(X << Y) -> log2(X) + Y
2611+
// FIXME: Require one use unless X is 1?
2612+
if (match(Op, m_Shl(m_Value(X), m_Value(Y)))) {
2613+
auto *BO = cast<OverflowingBinaryOperator>(Op);
2614+
// nuw will be set if the `shl` is trivially non-zero.
2615+
if (AssumeNonZero || BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap())
2616+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
2617+
return IfFold([&]() { return Builder.CreateAdd(LogX, Y); });
2618+
}
2619+
2620+
// log2(X >>u Y) -> log2(X) - Y
2621+
// FIXME: Require one use?
2622+
if (match(Op, m_LShr(m_Value(X), m_Value(Y)))) {
2623+
auto *PEO = cast<PossiblyExactOperator>(Op);
2624+
if (AssumeNonZero || PEO->isExact())
2625+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
2626+
return IfFold([&]() { return Builder.CreateSub(LogX, Y); });
2627+
}
2628+
2629+
// log2(X & Y) -> either log2(X) or log2(Y)
2630+
// This requires `AssumeNonZero` as `X & Y` may be zero when X != Y.
2631+
if (AssumeNonZero && match(Op, m_And(m_Value(X), m_Value(Y)))) {
2632+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
2633+
return IfFold([&]() { return LogX; });
2634+
if (Value *LogY = takeLog2(Y, Depth, AssumeNonZero, DoFold))
2635+
return IfFold([&]() { return LogY; });
2636+
}
2637+
2638+
// log2(Cond ? X : Y) -> Cond ? log2(X) : log2(Y)
2639+
// FIXME: Require one use?
2640+
if (SelectInst *SI = dyn_cast<SelectInst>(Op))
2641+
if (Value *LogX = takeLog2(SI->getOperand(1), Depth, AssumeNonZero, DoFold))
2642+
if (Value *LogY =
2643+
takeLog2(SI->getOperand(2), Depth, AssumeNonZero, DoFold))
2644+
return IfFold([&]() {
2645+
return Builder.CreateSelect(SI->getOperand(0), LogX, LogY);
2646+
});
2647+
2648+
// log2(umin(X, Y)) -> umin(log2(X), log2(Y))
2649+
// log2(umax(X, Y)) -> umax(log2(X), log2(Y))
2650+
auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op);
2651+
if (MinMax && MinMax->hasOneUse() && !MinMax->isSigned()) {
2652+
// Use AssumeNonZero as false here. Otherwise we can hit case where
2653+
// log2(umax(X, Y)) != umax(log2(X), log2(Y)) (because overflow).
2654+
if (Value *LogX = takeLog2(MinMax->getLHS(), Depth,
2655+
/*AssumeNonZero*/ false, DoFold))
2656+
if (Value *LogY = takeLog2(MinMax->getRHS(), Depth,
2657+
/*AssumeNonZero*/ false, DoFold))
2658+
return IfFold([&]() {
2659+
return Builder.CreateBinaryIntrinsic(MinMax->getIntrinsicID(), LogX,
2660+
LogY);
2661+
});
2662+
}
2663+
2664+
return nullptr;
2665+
}
2666+
25682667
Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
25692668
BuilderTy *Builder,
25702669
bool &DoesConsume, unsigned Depth) {

0 commit comments

Comments
 (0)