Skip to content

Commit 0d9c027

Browse files
committed
[InstCombine] Make takeLog2 visible in all of InstCombine; NFC
Also add `tryGetLog2` helper that encapsulates the common pattern: ``` if (takeLog2(..., /*DoFold=*/false)) { Value * Log2 = takeLog2(..., /*DoFold=*/true); ... } ``` Closes #122498
1 parent fb1d6f0 commit 0d9c027

File tree

2 files changed

+29
-36
lines changed

2 files changed

+29
-36
lines changed

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,18 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
785785
void handlePotentiallyDeadBlocks(SmallVectorImpl<BasicBlock *> &Worklist);
786786
void handlePotentiallyDeadSuccessors(BasicBlock *BB, BasicBlock *LiveSucc);
787787
void freelyInvertAllUsersOf(Value *V, Value *IgnoredUser = nullptr);
788+
789+
/// Take the exact integer log2 of the value. If DoFold is true, create the
790+
/// actual instructions, otherwise return a non-null dummy value. Return
791+
/// nullptr on failure. Note, if DoFold is true the caller must ensure that
792+
/// takeLog2 will succeed, otherwise it may create stray instructions.
793+
Value *takeLog2(Value *Op, unsigned Depth, bool AssumeNonZero, bool DoFold);
794+
795+
Value *tryGetLog2(Value *Op, bool AssumeNonZero) {
796+
if (takeLog2(Op, /*Depth=*/0, AssumeNonZero, /*DoFold=*/false))
797+
return takeLog2(Op, /*Depth=*/0, AssumeNonZero, /*DoFold=*/true);
798+
return nullptr;
799+
}
788800
};
789801

790802
class Negator final {

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 17 additions & 36 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,19 +528,13 @@ 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,
535-
/*DoFold*/ false)) {
536-
Value *Res = takeLog2(Builder, Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
537-
/*DoFold*/ true);
531+
if (Value *Res = tryGetLog2(Op0, /*AssumeNonZero=*/false)) {
538532
BinaryOperator *Shl = BinaryOperator::CreateShl(Op1, Res);
539533
// We can only propegate nuw flag.
540534
Shl->setHasNoUnsignedWrap(HasNUW);
541535
return Shl;
542536
}
543-
if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
544-
/*DoFold*/ false)) {
545-
Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
546-
/*DoFold*/ true);
537+
if (Value *Res = tryGetLog2(Op1, /*AssumeNonZero=*/false)) {
547538
BinaryOperator *Shl = BinaryOperator::CreateShl(Op0, Res);
548539
// We can only propegate nuw flag.
549540
Shl->setHasNoUnsignedWrap(HasNUW);
@@ -1407,13 +1398,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
14071398
return nullptr;
14081399
}
14091400

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) {
1401+
Value *InstCombinerImpl::takeLog2(Value *Op, unsigned Depth, bool AssumeNonZero,
1402+
bool DoFold) {
14171403
auto IfFold = [DoFold](function_ref<Value *()> Fn) {
14181404
if (!DoFold)
14191405
return reinterpret_cast<Value *>(-1);
@@ -1432,22 +1418,22 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
14321418
});
14331419

14341420
// The remaining tests are all recursive, so bail out if we hit the limit.
1435-
if (Depth++ == MaxDepth)
1421+
if (Depth++ == MaxAnalysisRecursionDepth)
14361422
return nullptr;
14371423

14381424
// log2(zext X) -> zext log2(X)
14391425
// FIXME: Require one use?
14401426
Value *X, *Y;
14411427
if (match(Op, m_ZExt(m_Value(X))))
1442-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1428+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
14431429
return IfFold([&]() { return Builder.CreateZExt(LogX, Op->getType()); });
14441430

14451431
// log2(trunc x) -> trunc log2(X)
14461432
// FIXME: Require one use?
14471433
if (match(Op, m_Trunc(m_Value(X)))) {
14481434
auto *TI = cast<TruncInst>(Op);
14491435
if (AssumeNonZero || TI->hasNoUnsignedWrap())
1450-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1436+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
14511437
return IfFold([&]() {
14521438
return Builder.CreateTrunc(LogX, Op->getType(), "",
14531439
/*IsNUW=*/TI->hasNoUnsignedWrap());
@@ -1460,7 +1446,7 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
14601446
auto *BO = cast<OverflowingBinaryOperator>(Op);
14611447
// nuw will be set if the `shl` is trivially non-zero.
14621448
if (AssumeNonZero || BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap())
1463-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1449+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
14641450
return IfFold([&]() { return Builder.CreateAdd(LogX, Y); });
14651451
}
14661452

@@ -1469,26 +1455,25 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
14691455
if (match(Op, m_LShr(m_Value(X), m_Value(Y)))) {
14701456
auto *PEO = cast<PossiblyExactOperator>(Op);
14711457
if (AssumeNonZero || PEO->isExact())
1472-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1458+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
14731459
return IfFold([&]() { return Builder.CreateSub(LogX, Y); });
14741460
}
14751461

14761462
// log2(X & Y) -> either log2(X) or log2(Y)
14771463
// This requires `AssumeNonZero` as `X & Y` may be zero when X != Y.
14781464
if (AssumeNonZero && match(Op, m_And(m_Value(X), m_Value(Y)))) {
1479-
if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
1465+
if (Value *LogX = takeLog2(X, Depth, AssumeNonZero, DoFold))
14801466
return IfFold([&]() { return LogX; });
1481-
if (Value *LogY = takeLog2(Builder, Y, Depth, AssumeNonZero, DoFold))
1467+
if (Value *LogY = takeLog2(Y, Depth, AssumeNonZero, DoFold))
14821468
return IfFold([&]() { return LogY; });
14831469
}
14841470

14851471
// log2(Cond ? X : Y) -> Cond ? log2(X) : log2(Y)
14861472
// FIXME: Require one use?
14871473
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))
1474+
if (Value *LogX = takeLog2(SI->getOperand(1), Depth, AssumeNonZero, DoFold))
1475+
if (Value *LogY =
1476+
takeLog2(SI->getOperand(2), Depth, AssumeNonZero, DoFold))
14921477
return IfFold([&]() {
14931478
return Builder.CreateSelect(SI->getOperand(0), LogX, LogY);
14941479
});
@@ -1499,9 +1484,9 @@ static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
14991484
if (MinMax && MinMax->hasOneUse() && !MinMax->isSigned()) {
15001485
// Use AssumeNonZero as false here. Otherwise we can hit case where
15011486
// log2(umax(X, Y)) != umax(log2(X), log2(Y)) (because overflow).
1502-
if (Value *LogX = takeLog2(Builder, MinMax->getLHS(), Depth,
1487+
if (Value *LogX = takeLog2(MinMax->getLHS(), Depth,
15031488
/*AssumeNonZero*/ false, DoFold))
1504-
if (Value *LogY = takeLog2(Builder, MinMax->getRHS(), Depth,
1489+
if (Value *LogY = takeLog2(MinMax->getRHS(), Depth,
15051490
/*AssumeNonZero*/ false, DoFold))
15061491
return IfFold([&]() {
15071492
return Builder.CreateBinaryIntrinsic(MinMax->getIntrinsicID(), LogX,
@@ -1614,13 +1599,9 @@ Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
16141599
}
16151600

16161601
// Op1 udiv Op2 -> Op1 lshr log2(Op2), if log2() folds away.
1617-
if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ true,
1618-
/*DoFold*/ false)) {
1619-
Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0,
1620-
/*AssumeNonZero*/ true, /*DoFold*/ true);
1602+
if (Value *Res = tryGetLog2(Op1, /*AssumeNonZero=*/true))
16211603
return replaceInstUsesWith(
16221604
I, Builder.CreateLShr(Op0, Res, I.getName(), I.isExact()));
1623-
}
16241605

16251606
return nullptr;
16261607
}

0 commit comments

Comments
 (0)