-
Notifications
You must be signed in to change notification settings - Fork 15k
[InstComb] Fold shr ([x]or x, y), x -> shr y, x #165866
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: Ramkumar Ramachandra (artagnon) ChangesProof: https://alive2.llvm.org/ce/z/yWCmMd Full diff: https://github.com/llvm/llvm-project/pull/165866.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 899a3c16554c9..6410a509a48af 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1836,6 +1836,11 @@ Instruction *InstCombinerImpl::visitAShr(BinaryOperator &I) {
return Lshr;
}
+ // ashr (xor %x, %y), %x --> ashr %y, %x
+ Value *Y;
+ if (match(Op0, m_Xor(m_Value(X), m_Value(Y))) && Op1 == X)
+ return BinaryOperator::CreateAShr(Y, X);
+
// ashr (xor %x, -1), %y --> xor (ashr %x, %y), -1
if (match(Op0, m_OneUse(m_Not(m_Value(X))))) {
// Note that we must drop 'exact'-ness of the shift!
diff --git a/llvm/test/Transforms/InstCombine/shift-logic.ll b/llvm/test/Transforms/InstCombine/shift-logic.ll
index ab8d98a9523ba..2de2073a183b7 100644
--- a/llvm/test/Transforms/InstCombine/shift-logic.ll
+++ b/llvm/test/Transforms/InstCombine/shift-logic.ll
@@ -186,6 +186,7 @@ define i32 @ashr_xor(i32 %x, i32 %py) {
ret i32 %sh1
}
+
define i32 @shr_mismatch_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @shr_mismatch_xor(
; CHECK-NEXT: [[SH0:%.*]] = ashr i32 [[X:%.*]], 5
@@ -225,6 +226,27 @@ define <2 x i32> @ashr_poison_poison_xor(<2 x i32> %x, <2 x i32> %y) {
ret <2 x i32> %sh1
}
+define i32 @ashr_xor_operand_match(i32 %x, i32 %y) {
+; CHECK-LABEL: @ashr_xor_operand_match(
+; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[SH1:%.*]], [[TMP1:%.*]]
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %r = xor i32 %x, %y
+ %ret = ashr i32 %r, %x
+ ret i32 %ret
+}
+
+define i32 @ashr_xor_operand_mismtach(i32 %x, i32 %y) {
+; CHECK-LABEL: @ashr_xor_operand_mismtach(
+; CHECK-NEXT: [[R:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[RET:%.*]] = ashr i32 [[R]], [[Y]]
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %r = xor i32 %x, %y
+ %ret = ashr i32 %r, %y
+ ret i32 %ret
+}
+
define i32 @lshr_or_extra_use(i32 %x, i32 %y, ptr %p) {
; CHECK-LABEL: @lshr_or_extra_use(
; CHECK-NEXT: [[SH0:%.*]] = lshr i32 [[X:%.*]], 5
|
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.
I don't like to special handle this case. It works because the number of active bits of x is never greater than x itself: https://alive2.llvm.org/ce/z/sYnoVM
All the patterns like [la]shr (bitop x, y), x can be simplified.
Proof: https://alive2.llvm.org/ce/z/yWCmMd Co-authored-by: John Regehr <regehr@cs.utah.edu>
Thanks, this is a good generalization! However, it doesn't work for and: https://alive2.llvm.org/ce/z/vE3MEi |
|
Looks like this pattern doesn't appear in the wild? Zero diff on llvm-opt-benchmark? Can someone confirm that there wasn't some error so we can close this? |
Confirmed. Does this pattern come from a real-world issue? |
No, unfortunately it comes from a SuperOptimizer. |
Proof: https://alive2.llvm.org/ce/z/vE3MEi