[llvm] [InstCombine] Fold (X << Y) / (X << Z) -> 1 << Y >> Z (PR #68863)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 12 07:23:16 PDT 2023
================
@@ -980,6 +980,27 @@ static Instruction *foldIDivShl(BinaryOperator &I,
Ret = BinaryOperator::CreateSDiv(X, Y);
}
+ // If X << Y and X << Z does not overflow, then:
+ // (X << Y) / (X << Z) -> (1 << Y) / (1 << Z) -> 1 << Y >> Z
+ // Only when both Op0 and Op1 have uses, this fold produces one extra
+ // instruction.
+ if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
+ match(Op1, m_Shl(m_Specific(X), m_Value(Z))) &&
+ (Op0->hasOneUse() || Op1->hasOneUse())) {
+ auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
+ auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
+
+ Constant *One = ConstantInt::get(X->getType(), 1);
+
+ if ((!IsSigned && Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap()) ||
+ (IsSigned && Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() &&
+ Shl1->hasNoUnsignedWrap())) {
+ Value *Dividend = Builder.CreateShl(One, Y, "shl.dividend",
+ /*HasNUW*/ true, /*HasNSW*/ IsSigned);
+ Ret = BinaryOperator::CreateLShr(Dividend, Z, "lshr.divisor");
----------------
nikic wrote:
This name is pointless and will be ignored.
https://github.com/llvm/llvm-project/pull/68863
More information about the llvm-commits
mailing list