-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
Conversation
@llvm/pr-subscribers-llvm-transforms Author: AtariDreams (AtariDreams) ChangesI 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:
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:%.*]]
|
d20c211
to
f7e13cd
Compare
…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
Has this patch been reviewed before? |
LGTM. Wait for an additional approval. |
@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 :( |
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