[llvm] 5bc0bd0 - [AArch64][GlobalISel] Fold G_XOR x, -1 into G_SELECT and select CSINV
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 16 14:14:30 PST 2020
Author: Jessica Paquette
Date: 2020-11-16T14:14:14-08:00
New Revision: 5bc0bd05e6a8d788e08cdf3d154f3a33202aee53
URL: https://github.com/llvm/llvm-project/commit/5bc0bd05e6a8d788e08cdf3d154f3a33202aee53
DIFF: https://github.com/llvm/llvm-project/commit/5bc0bd05e6a8d788e08cdf3d154f3a33202aee53.diff
LOG: [AArch64][GlobalISel] Fold G_XOR x, -1 into G_SELECT and select CSINV
When we see
```
xor = G_XOR xor_lhs, -1
select = G_SELECT cc, tval, xor
```
Fold this into
```
select = CSINV tval, xor_lhs, cc
```
Update select-select.mir to reflect the changes.
For now, only handle the case where the G_XOR is the false-value for the
G_SELECT. It may make more sense to handle the true-value case in post-legalizer
lowering.
Differential Revision: https://reviews.llvm.org/D90774
Added:
Modified:
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 5aa2398b5b04..c3bf8737504f 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -1011,7 +1011,7 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
// By default, we'll try and emit a CSEL.
unsigned Opc = Is32Bit ? AArch64::CSELWr : AArch64::CSELXr;
bool Optimized = false;
- auto TryOptNegIntoSelect = [&Opc, &False, Is32Bit, &MRI]() {
+ auto TryFoldBinOpIntoSelect = [&Opc, &False, Is32Bit, &MRI]() {
// Attempt to fold:
//
// sub = G_SUB 0, x
@@ -1019,10 +1019,27 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
//
// Into:
// select = CSNEG true, x, cc
- if (!mi_match(False, MRI, m_Neg(m_Reg(False))))
- return false;
- Opc = Is32Bit ? AArch64::CSNEGWr : AArch64::CSNEGXr;
- return true;
+ Register MatchReg;
+ if (mi_match(False, MRI, m_Neg(m_Reg(MatchReg)))) {
+ Opc = Is32Bit ? AArch64::CSNEGWr : AArch64::CSNEGXr;
+ False = MatchReg;
+ return true;
+ }
+
+ // Attempt to fold:
+ //
+ // xor = G_XOR x, -1
+ // select = G_SELECT cc, true, xor
+ //
+ // Into:
+ // select = CSINV true, x, cc
+ if (mi_match(False, MRI, m_Not(m_Reg(MatchReg)))) {
+ Opc = Is32Bit ? AArch64::CSINVWr : AArch64::CSINVXr;
+ False = MatchReg;
+ return true;
+ }
+
+ return false;
};
// Helper lambda which tries to use CSINC/CSINV for the instruction when its
@@ -1100,7 +1117,7 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
return false;
};
- Optimized |= TryOptNegIntoSelect();
+ Optimized |= TryFoldBinOpIntoSelect();
Optimized |= TryOptSelectCst();
auto SelectInst = MIB.buildInstr(Opc, {Dst}, {True, False}).addImm(CC);
constrainSelectedInstRegOperands(*SelectInst, TII, TRI, RBI);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
index 621229d9a8ca..2d7928f906ed 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
@@ -437,3 +437,98 @@ body: |
%select:gpr(s32) = G_SELECT %cond(s1), %t, %sub
$w0 = COPY %select(s32)
RET_ReallyLR implicit $w0
+...
+---
+name: csinv_s32
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1, $w2
+ ; G_SELECT cc, true, (G_XOR x, -1) -> CSINV true, x, cc
+
+ ; CHECK-LABEL: name: csinv_s32
+ ; CHECK: liveins: $w0, $w1, $w2
+ ; CHECK: %reg0:gpr32 = COPY $w0
+ ; CHECK: %reg1:gpr32 = COPY $w1
+ ; CHECK: %t:gpr32 = COPY $w2
+ ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %reg0, 0, implicit-def $nzcv
+ ; CHECK: %select:gpr32 = CSINVWr %t, %reg1, 1, implicit $nzcv
+ ; CHECK: $w0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $w0
+ %reg0:gpr(s32) = COPY $w0
+ %reg1:gpr(s32) = COPY $w1
+ %cond:gpr(s1) = G_TRUNC %reg0(s32)
+ %t:gpr(s32) = COPY $w2
+ %negative_one:gpr(s32) = G_CONSTANT i32 -1
+ %xor:gpr(s32) = G_XOR %reg1(s32), %negative_one
+ %select:gpr(s32) = G_SELECT %cond(s1), %t, %xor
+ $w0 = COPY %select(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: csinv_s64
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+ ; G_SELECT cc, true, (G_XOR x, -1) -> CSINV true, x, cc
+
+ ; CHECK-LABEL: name: csinv_s64
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK: %reg0:gpr64 = COPY $x0
+ ; CHECK: %reg1:gpr64 = COPY $x1
+ ; CHECK: %cond:gpr32 = COPY %reg0.sub_32
+ ; CHECK: %t:gpr64 = COPY $x2
+ ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %cond, 0, implicit-def $nzcv
+ ; CHECK: %select:gpr64 = CSINVXr %t, %reg1, 1, implicit $nzcv
+ ; CHECK: $x0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $x0
+ %reg0:gpr(s64) = COPY $x0
+ %reg1:gpr(s64) = COPY $x1
+ %cond:gpr(s1) = G_TRUNC %reg0(s64)
+ %t:gpr(s64) = COPY $x2
+ %negative_one:gpr(s64) = G_CONSTANT i64 -1
+ %xor:gpr(s64) = G_XOR %reg1(s64), %negative_one
+ %select:gpr(s64) = G_SELECT %cond(s1), %t, %xor
+ $x0 = COPY %select(s64)
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: xor_not_negative_one
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+ ; zext(s32 -1) != s64 -1, so we can't fold it away.
+
+ ; CHECK-LABEL: name: xor_not_negative_one
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK: %reg0:gpr64 = COPY $x0
+ ; CHECK: %reg1:gpr64 = COPY $x1
+ ; CHECK: %cond:gpr32 = COPY %reg0.sub_32
+ ; CHECK: %t:gpr64 = COPY $x2
+ ; CHECK: %negative_one:gpr32 = MOVi32imm -1
+ ; CHECK: %zext:gpr64 = SUBREG_TO_REG 0, %negative_one, %subreg.sub_32
+ ; CHECK: %xor:gpr64 = EORXrr %reg1, %zext
+ ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %cond, 0, implicit-def $nzcv
+ ; CHECK: %select:gpr64 = CSELXr %t, %xor, 1, implicit $nzcv
+ ; CHECK: $x0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $x0
+ %reg0:gpr(s64) = COPY $x0
+ %reg1:gpr(s64) = COPY $x1
+ %cond:gpr(s1) = G_TRUNC %reg0(s64)
+ %t:gpr(s64) = COPY $x2
+ %negative_one:gpr(s32) = G_CONSTANT i32 -1
+ %zext:gpr(s64) = G_ZEXT %negative_one(s32)
+ %xor:gpr(s64) = G_XOR %reg1(s64), %zext
+ %select:gpr(s64) = G_SELECT %cond(s1), %t, %xor
+ $x0 = COPY %select(s64)
+ RET_ReallyLR implicit $x0
More information about the llvm-commits
mailing list