[llvm] [InstCombine] Treat `lshr nneg` as `ashr` in `getBinOpsForFactorization` (PR #75521)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 14 22:17:23 PST 2023
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/75521
>From ba5aaf3086f27068099a001501f7ac4ef2850066 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 15 Dec 2023 03:27:28 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests for PR70582. NFC.
---
llvm/test/Transforms/InstCombine/xor.ll | 49 +++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index 7c61401fca07c7..ee282bb2519a43 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -1395,3 +1395,52 @@ define i32 @ctlz_pow2_wrong_const(i32 %x) {
%r = xor i32 %z, 30
ret i32 %r
}
+
+; Tests from PR70582
+define i32 @tryFactorization_xor_ashr_lshr(i32 %a) {
+; CHECK-LABEL: @tryFactorization_xor_ashr_lshr(
+; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
+; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 5, [[A]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NOT]], [[SHR1]]
+; CHECK-NEXT: ret i32 [[XOR]]
+;
+ %not = ashr i32 -3, %a
+ %shr1 = lshr i32 5, %a
+ %xor = xor i32 %not, %shr1
+ ret i32 %xor
+}
+
+define i32 @tryFactorization_xor_lshr_ashr(i32 %a) {
+; CHECK-LABEL: @tryFactorization_xor_lshr_ashr(
+; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
+; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 5, [[A]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHR1]], [[NOT]]
+; CHECK-NEXT: ret i32 [[XOR]]
+;
+ %not = ashr i32 -3, %a
+ %shr1 = lshr i32 5, %a
+ %xor = xor i32 %shr1, %not
+ ret i32 %xor
+}
+
+define i32 @tryFactorization_xor_lshr_lshr(i32 %a) {
+; CHECK-LABEL: @tryFactorization_xor_lshr_lshr(
+; CHECK-NEXT: [[XOR:%.*]] = lshr i32 -8, [[A:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
+;
+ %not = lshr i32 -3, %a
+ %shr1 = lshr i32 5, %a
+ %xor = xor i32 %not, %shr1
+ ret i32 %xor
+}
+
+define i32 @tryFactorization_xor_ashr_ashr(i32 %a) {
+; CHECK-LABEL: @tryFactorization_xor_ashr_ashr(
+; CHECK-NEXT: [[XOR:%.*]] = lshr i32 6, [[A:%.*]]
+; CHECK-NEXT: ret i32 [[XOR]]
+;
+ %not = ashr i32 -3, %a
+ %shr1 = ashr i32 -5, %a
+ %xor = xor i32 %not, %shr1
+ ret i32 %xor
+}
>From d81531a6e73477a768c70bbf4be9fdc4561bdc91 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 15 Dec 2023 03:28:47 +0800
Subject: [PATCH 2/3] [InstCombine] Treat `lshr nneg` as `ashr` in
`getBinOpsForFactorization`
---
.../Transforms/InstCombine/InstructionCombining.cpp | 13 ++++++++++---
llvm/test/Transforms/InstCombine/xor.ll | 8 ++------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 6ac1fdb9252bff..a7ddadc25de43c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -610,7 +610,7 @@ static Value *getIdentityValue(Instruction::BinaryOps Opcode, Value *V) {
/// allow more factorization opportunities.
static Instruction::BinaryOps
getBinOpsForFactorization(Instruction::BinaryOps TopOpcode, BinaryOperator *Op,
- Value *&LHS, Value *&RHS) {
+ Value *&LHS, Value *&RHS, BinaryOperator *OtherOp) {
assert(Op && "Expected a binary operator");
LHS = Op->getOperand(0);
RHS = Op->getOperand(1);
@@ -623,6 +623,13 @@ getBinOpsForFactorization(Instruction::BinaryOps TopOpcode, BinaryOperator *Op,
}
// TODO: We can add other conversions e.g. shr => div etc.
}
+ if (Instruction::isBitwiseLogicOp(TopOpcode)) {
+ if (OtherOp && OtherOp->getOpcode() == Instruction::AShr &&
+ match(Op, m_LShr(m_NonNegative(), m_Value()))) {
+ // lshr nneg C, X --> ashr nneg C, X
+ return Instruction::AShr;
+ }
+ }
return Op->getOpcode();
}
@@ -963,9 +970,9 @@ Value *InstCombinerImpl::tryFactorizationFolds(BinaryOperator &I) {
Instruction::BinaryOps LHSOpcode, RHSOpcode;
if (Op0)
- LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B);
+ LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B, Op1);
if (Op1)
- RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D);
+ RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D, Op0);
// The instruction has the form "(A op' B) op (C op' D)". Try to factorize
// a common term.
diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index ee282bb2519a43..388755b832096c 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -1399,9 +1399,7 @@ define i32 @ctlz_pow2_wrong_const(i32 %x) {
; Tests from PR70582
define i32 @tryFactorization_xor_ashr_lshr(i32 %a) {
; CHECK-LABEL: @tryFactorization_xor_ashr_lshr(
-; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
-; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 5, [[A]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NOT]], [[SHR1]]
+; CHECK-NEXT: [[XOR:%.*]] = ashr i32 -8, [[A:%.*]]
; CHECK-NEXT: ret i32 [[XOR]]
;
%not = ashr i32 -3, %a
@@ -1412,9 +1410,7 @@ define i32 @tryFactorization_xor_ashr_lshr(i32 %a) {
define i32 @tryFactorization_xor_lshr_ashr(i32 %a) {
; CHECK-LABEL: @tryFactorization_xor_lshr_ashr(
-; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
-; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 5, [[A]]
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHR1]], [[NOT]]
+; CHECK-NEXT: [[XOR:%.*]] = ashr i32 -8, [[A:%.*]]
; CHECK-NEXT: ret i32 [[XOR]]
;
%not = ashr i32 -3, %a
>From ba3aad5b2c224150d810af8647ec29c2bfa94faf Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 15 Dec 2023 14:16:55 +0800
Subject: [PATCH 3/3] [InstCombine] Add a negative test with negative LHS on
lshr. NFC.
---
llvm/test/Transforms/InstCombine/xor.ll | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/xor.ll b/llvm/test/Transforms/InstCombine/xor.ll
index 388755b832096c..ba9e992a9443c9 100644
--- a/llvm/test/Transforms/InstCombine/xor.ll
+++ b/llvm/test/Transforms/InstCombine/xor.ll
@@ -1419,6 +1419,19 @@ define i32 @tryFactorization_xor_lshr_ashr(i32 %a) {
ret i32 %xor
}
+define i32 @tryFactorization_xor_ashr_lshr_negative_lhs(i32 %a) {
+; CHECK-LABEL: @tryFactorization_xor_ashr_lshr_negative_lhs(
+; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
+; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 -5, [[A]]
+; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NOT]], [[SHR1]]
+; CHECK-NEXT: ret i32 [[XOR]]
+;
+ %not = ashr i32 -3, %a
+ %shr1 = lshr i32 -5, %a
+ %xor = xor i32 %not, %shr1
+ ret i32 %xor
+}
+
define i32 @tryFactorization_xor_lshr_lshr(i32 %a) {
; CHECK-LABEL: @tryFactorization_xor_lshr_lshr(
; CHECK-NEXT: [[XOR:%.*]] = lshr i32 -8, [[A:%.*]]
More information about the llvm-commits
mailing list