Skip to content

[InstCombine] Add reverse of ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z) #91386

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2024

Conversation

AZero13
Copy link
Contributor

@AZero13 AZero13 commented May 7, 2024

This is the same fold as ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z), which we already have, but with the sub operands swapped.

Proof: https://alive2.llvm.org/ce/z/2cRcdx

@llvmbot
Copy link
Member

llvmbot commented May 7, 2024

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

Changes

I just swapped lshr and x around.

Proof: https://alive2.llvm.org/ce/z/2cRcdx


Full diff: https://github.com/llvm/llvm-project/pull/91386.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp (+12-1)
  • (modified) llvm/test/Transforms/InstCombine/lshr.ll (+27)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 8847de366713..4378c4155ed7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1259,7 +1259,7 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
       match(Op1, m_SpecificIntAllowPoison(BitWidth - 1)))
     return new ZExtInst(Builder.CreateIsNotNeg(X, "isnotneg"), Ty);
 
-  // ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z),
+  // ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z)
   Value *Y;
   if (I.isExact() &&
       match(Op0, m_OneUse(m_NUWSub(m_NUWShl(m_Value(X), m_Specific(Op1)),
@@ -1271,6 +1271,17 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
     return NewSub;
   }
 
+  // (sub nuw Y, (X << nuw Z)) >>u exact Z --> (Y >>u exact Z) sub nuw X
+  if (I.isExact() &&
+      match(Op0, m_OneUse(m_NUWSub(m_Value(Y),
+                                   m_NUWShl(m_Value(X), m_Specific(Op1)))))) {
+    Value *NewLshr = Builder.CreateLShr(Y, Op1, "", /*isExact=*/true);
+    auto *NewSub = BinaryOperator::CreateNUWSub(NewLshr, X);
+    NewSub->setHasNoSignedWrap(
+        cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap());
+    return NewSub;
+  }
+
   auto isSuitableBinOpcode = [](Instruction::BinaryOps BinOpcode) {
     switch (BinOpcode) {
     default:
diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index 563e669f9035..9c22023d9a3d 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -464,6 +464,33 @@ define i32 @shl_sub_lshr(i32 %x, i32 %c, i32 %y) {
   ret i32 %lshr
 }
 
+define i32 @shl_sub_lshr_reverse(i32 %x, i32 %c, i32 %y) {
+; CHECK-LABEL: @shl_sub_lshr_reverse(
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[Y:%.*]], [[C:%.*]]
+; CHECK-NEXT:    [[LSHR:%.*]] = sub nuw nsw i32 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT:    ret i32 [[LSHR]]
+;
+  %shl = shl nuw i32 %x, %c
+  %sub = sub nuw nsw i32 %y, %shl
+  %lshr = lshr exact i32 %sub, %c
+  ret i32 %lshr
+}
+
+; Negative Test
+
+define i32 @shl_sub_lshr_reverse_no_exact(i32 %x, i32 %c, i32 %y) {
+; CHECK-LABEL: @shl_sub_lshr_reverse_no_exact(
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[C:%.*]]
+; CHECK-NEXT:    [[SUB:%.*]] = sub nuw nsw i32 [[Y:%.*]], [[SHL]]
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[SUB]], [[C]]
+; CHECK-NEXT:    ret i32 [[LSHR]]
+;
+  %shl = shl nuw i32 %x, %c
+  %sub = sub nuw nsw i32 %y, %shl
+  %lshr = lshr i32 %sub, %c
+  ret i32 %lshr
+}
+
 define i32 @shl_or_lshr(i32 %x, i32 %c, i32 %y) {
 ; CHECK-LABEL: @shl_or_lshr(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[Y:%.*]], [[C:%.*]]

@AZero13 AZero13 changed the title Add reverse of ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z) [InstCombine] Add reverse of ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z) May 8, 2024
@AZero13 AZero13 force-pushed the binop-2 branch 4 times, most recently from d20c211 to f7e13cd Compare May 8, 2024 02:54
AZero13 added 2 commits May 12, 2024 16:27
…xact Z) sub nuw Y

This is the same fold as ((X << nuw Z) sub nuw Y) >>u exact Z --> X sub nuw (Y >>u exact Z), but with the sub operands swapped.

Proof: https://alive2.llvm.org/ce/z/2cRcdx
@AZero13 AZero13 merged commit c42c320 into llvm:main May 27, 2024
4 checks passed
@dtcxzyw
Copy link
Member

dtcxzyw commented May 27, 2024

Has this patch been reviewed before?

nikic added a commit that referenced this pull request May 27, 2024
…ct Z --> X sub nuw (Y >>u exact Z) (#91386)"

This reverts commit c42c320.

PR merged without review.
@goldsteinn
Copy link
Contributor

LGTM. Wait for an additional approval.

@dtcxzyw
Copy link
Member

dtcxzyw commented May 27, 2024

@AtariDreams The implementation looks OK to me. Please file another PR to reland this.

BTW, one of my friends from ms-stl told me you always use force-pushing to update your PR: microsoft/STL#4140 (comment). It is not a good practice :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants