[llvm] [InstCombine] Fold ((X << nuw Z) binop nuw Y) >>u Z --> X binop nuw (Y >>u Z) (PR #88193)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue May 7 03:33:00 PDT 2024
================
@@ -1259,6 +1259,52 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
match(Op1, m_SpecificIntAllowPoison(BitWidth - 1)))
return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty);
+ Value *Y;
+ if (match(Op0, m_OneUse(m_NUWSub(m_NUWShl(m_Value(X), m_Specific(Op1)),
+ m_Value(Y))))) {
+ Value *NewLshr = Builder.CreateLShr(Y, Op1, "", I.isExact());
+ auto *NewSub = BinaryOperator::CreateNUWSub(NewLshr, X);
+ NewSub->setHasNoSignedWrap(
+ cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap());
+ return NewSub;
+ }
+
+ auto isSuitableBinOpcode = [](Instruction::BinaryOps BinOpcode) {
+ switch (BinOpcode) {
+ default:
+ return false;
+ case Instruction::Add:
+ case Instruction::Or:
+ case Instruction::Xor:
+ // And does not work here, and sub is handled separately.
+ return true;
+ }
+ };
+
+ // If both the add and the shift are nuw, then:
+ // ((X << nuw Z) binop nuw Y) >>u Z --> X binop nuw (Y >>u Z)
+ if (match(Op0, m_OneUse(m_c_BinOp(m_NUWShl(m_Value(X), m_Specific(Op1)),
+ m_Value(Y))))) {
+ BinaryOperator *Op0OB = cast<BinaryOperator>(Op0);
+ bool canFold = false;
+ if (isSuitableBinOpcode(Op0OB->getOpcode())) {
+ if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(Op0)) {
+ if (Inst->hasNoUnsignedWrap())
+ canFold = true;
+ } else
+ canFold = true;
+
+ if (canFold) {
----------------
arsenm wrote:
You can avoid the canFold variable:
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(Op0);
!OBO || OBO->hasNoUnsignedWrap()) {
https://github.com/llvm/llvm-project/pull/88193
More information about the llvm-commits
mailing list