-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstCombine] simplify average of lsb #95684
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: None (c8ef) Changesclose: #94737 In this patch, we combine Full diff: https://github.com/llvm/llvm-project/pull/95684.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 4a014ab6e044e..bb68aa79ca970 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1284,6 +1284,14 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
return NewSub;
}
+ // ((X % 2) + (Y % 2)) / 2 --> (X & Y & 1)
+ if (match(Op0,
+ m_Add(m_And(m_Value(X), m_One()), m_And(m_Value(Y), m_One()))) &&
+ match(Op1, m_One())) {
+ Value *And = Builder.CreateAnd(X, Y);
+ return BinaryOperator::CreateAnd(And, ConstantInt::get(And->getType(), 1));
+ }
+
// (sub nuw X, (Y << nuw Z)) >>u exact Z --> (X >>u exact Z) sub nuw Y
if (I.isExact() &&
match(Op0, m_OneUse(m_NUWSub(m_Value(X),
diff --git a/llvm/test/Transforms/InstCombine/avg-lsb.ll b/llvm/test/Transforms/InstCombine/avg-lsb.ll
new file mode 100644
index 0000000000000..e9fdb5bfe8dc9
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/avg-lsb.ll
@@ -0,0 +1,46 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i8 @avg_lsb(i8 %a, i8 %b) {
+; CHECK-LABEL: define i8 @avg_lsb(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[B]], [[A]]
+; CHECK-NEXT: [[DIV2:%.*]] = and i8 [[TMP1]], 1
+; CHECK-NEXT: ret i8 [[DIV2]]
+;
+ %rem = and i8 %a, 1
+ %rem1 = and i8 %b, 1
+ %add = add nuw nsw i8 %rem1, %rem
+ %div2 = lshr i8 %add, 1
+ ret i8 %div2
+}
+
+define i8 @avg_lsb_mismatch(i8 %a, i8 %b) {
+; CHECK-LABEL: define i8 @avg_lsb_mismatch(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[REM:%.*]] = and i8 [[A]], 1
+; CHECK-NEXT: [[REM1:%.*]] = and i8 [[B]], 3
+; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i8 [[REM1]], [[REM]]
+; CHECK-NEXT: [[DIV2:%.*]] = lshr i8 [[ADD]], 1
+; CHECK-NEXT: ret i8 [[DIV2]]
+;
+ %rem = and i8 %a, 1
+ %rem1 = and i8 %b, 3
+ %add = add nuw nsw i8 %rem1, %rem
+ %div2 = lshr i8 %add, 1
+ ret i8 %div2
+}
+
+define <2 x i8> @avg_lsb_vector(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: define <2 x i8> @avg_lsb_vector(
+; CHECK-SAME: <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[B]], [[A]]
+; CHECK-NEXT: [[DIV2:%.*]] = and <2 x i8> [[TMP1]], <i8 1, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[DIV2]]
+;
+ %rem = and <2 x i8> %a, <i8 1, i8 1>
+ %rem1 = and <2 x i8> %b, <i8 1, i8 1>
+ %add = add nuw nsw <2 x i8> %rem1, %rem
+ %div2 = lshr <2 x i8> %add, <i8 1, i8 1>
+ ret <2 x i8> %div2
+}
|
; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[A]], [[B]] | ||
; CHECK-NEXT: [[LSHR:%.*]] = zext i1 [[TMP1]] to i32 | ||
; CHECK-NEXT: ret i32 [[LSHR]] | ||
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[ZEXT_A]], [[ZEXT_B]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it's a regression.
@@ -1284,6 +1284,13 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) { | |||
return NewSub; | |||
} | |||
|
|||
// Fold (X + Y) / 2 --> (X & Y) iff (X u<= 1) && (Y u<= 1) | |||
if (match(Op0, m_Add(m_Value(X), m_Value(Y))) && match(Op1, m_One()) && | |||
computeKnownBits(X, 0, &I).countMaxActiveBits() <= 1 && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nikic Can you check compile-time impact of this change? If it is high, I suggest to revert the generalization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No compile-time impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you!
@c8ef I was already assigned to this and had still been planning to work on it. Please ask first before you take issues that are already assigned to someone else. |
close: #94737
alive2:
https://alive2.llvm.org/ce/z/TtauVqhttps://alive2.llvm.org/ce/z/WF_7mXIn this patch, we combine
(X + Y) / 2
into(X & Y)
only when both X and Y are less than or equal to 1.