[llvm] 9a8bfe3 - [AArch64][GlobalISel] Select G_SELECT cc, t, (G_SUB 0, x) -> CSNEG t, x, cc
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 13 10:16:47 PST 2020
Author: Jessica Paquette
Date: 2020-11-13T10:12:51-08:00
New Revision: 9a8bfe38350d85879474b365e035bae15566ae2c
URL: https://github.com/llvm/llvm-project/commit/9a8bfe38350d85879474b365e035bae15566ae2c
DIFF: https://github.com/llvm/llvm-project/commit/9a8bfe38350d85879474b365e035bae15566ae2c.diff
LOG: [AArch64][GlobalISel] Select G_SELECT cc, t, (G_SUB 0, x) -> CSNEG t, x, cc
When we see
```
%sub = G_SUB 0, %x
%select = G_SELECT %cc, %t, %sub
```
Fold away the G_SUB by producing
```
%select = CSNEG %t, %x, cc
```
Simple IR example: https://godbolt.org/z/K8TEnh
This is valid on both sides of the select, but for now, just handle one side.
It may make more sense to handle swapping sides during post-legalizer lowering.
Differential Revision: https://reviews.llvm.org/D90723
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 f7d3bcf80bd7..1d5791399014 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -1010,12 +1010,29 @@ 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]() {
+ // Attempt to fold:
+ //
+ // sub = G_SUB 0, x
+ // select = G_SELECT cc, true, sub
+ //
+ // 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;
+ };
// Helper lambda which tries to use CSINC/CSINV for the instruction when its
// true/false values are constants.
// FIXME: All of these patterns already exist in tablegen. We should be
// able to import these.
- auto TryOptSelectCst = [&Opc, &True, &False, &CC, Is32Bit, &MRI]() {
+ auto TryOptSelectCst = [&Opc, &True, &False, &CC, Is32Bit, &MRI,
+ &Optimized]() {
+ if (Optimized)
+ return false;
auto TrueCst = getConstantVRegValWithLookThrough(True, MRI);
auto FalseCst = getConstantVRegValWithLookThrough(False, MRI);
if (!TrueCst && !FalseCst)
@@ -1083,7 +1100,8 @@ AArch64InstructionSelector::emitSelect(Register Dst, Register True,
return false;
};
- TryOptSelectCst();
+ Optimized |= TryOptNegIntoSelect();
+ Optimized |= TryOptSelectCst();
auto SelectInst = MIB.buildInstr(Opc, {Dst}, {True, False}).addImm(CC);
constrainSelectedInstRegOperands(*SelectInst, TII, TRI, RBI);
return &*SelectInst;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
index fd7620e317ce..621229d9a8ca 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-select.mir
@@ -345,3 +345,95 @@ body: |
%select:gpr(s64) = G_SELECT %cond(s1), %t, %f
$x0 = COPY %select(s64)
RET_ReallyLR implicit $x0
+
+...
+---
+name: csneg_s32
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1, $w2
+ ; G_SELECT cc, true, (G_SUB 0, x) -> CSNEG true, x, cc
+
+ ; CHECK-LABEL: name: csneg_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 = CSNEGWr %t, %reg1, 1, implicit $nzcv
+ ; CHECK: $w0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $w0
+ %reg0:gpr(s32) = COPY $w0
+ %cond:gpr(s1) = G_TRUNC %reg0(s32)
+ %reg1:gpr(s32) = COPY $w1
+ %t:gpr(s32) = COPY $w2
+ %zero:gpr(s32) = G_CONSTANT i32 0
+ %sub:gpr(s32) = G_SUB %zero(s32), %reg1
+ %select:gpr(s32) = G_SELECT %cond(s1), %t, %sub
+ $w0 = COPY %select(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: csneg_s64
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0, $x1, $x2
+ ; G_SELECT cc, true, (G_SUB 0, x) -> CSNEG true, x, cc
+
+ ; CHECK-LABEL: name: csneg_s64
+ ; CHECK: liveins: $x0, $x1, $x2
+ ; CHECK: %reg0:gpr64 = COPY $x0
+ ; CHECK: %cond:gpr32 = COPY %reg0.sub_32
+ ; CHECK: %reg1:gpr64 = COPY $x1
+ ; CHECK: %t:gpr64 = COPY $x2
+ ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %cond, 0, implicit-def $nzcv
+ ; CHECK: %select:gpr64 = CSNEGXr %t, %reg1, 1, implicit $nzcv
+ ; CHECK: $x0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $x0
+ %reg0:gpr(s64) = COPY $x0
+ %cond:gpr(s1) = G_TRUNC %reg0(s64)
+ %reg1:gpr(s64) = COPY $x1
+ %t:gpr(s64) = COPY $x2
+ %zero:gpr(s64) = G_CONSTANT i64 0
+ %sub:gpr(s64) = G_SUB %zero(s64), %reg1
+ %select:gpr(s64) = G_SELECT %cond(s1), %t, %sub
+ $x0 = COPY %select(s64)
+ RET_ReallyLR implicit $x0
+...
+---
+name: csneg_with_true_cst
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1, $w2
+ ; We should prefer eliminating the G_SUB over eliminating the constant true
+ ; value.
+
+ ; CHECK-LABEL: name: csneg_with_true_cst
+ ; CHECK: liveins: $w0, $w1, $w2
+ ; CHECK: %reg0:gpr32 = COPY $w0
+ ; CHECK: %t:gpr32 = MOVi32imm 1
+ ; CHECK: %reg2:gpr32 = COPY $w2
+ ; CHECK: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri %reg0, 0, implicit-def $nzcv
+ ; CHECK: %select:gpr32 = CSNEGWr %t, %reg2, 1, implicit $nzcv
+ ; CHECK: $w0 = COPY %select
+ ; CHECK: RET_ReallyLR implicit $w0
+ %reg0:gpr(s32) = COPY $w0
+ %cond:gpr(s1) = G_TRUNC %reg0(s32)
+ %reg1:gpr(s32) = COPY $w1
+ %t:gpr(s32) = G_CONSTANT i32 1
+ %zero:gpr(s32) = G_CONSTANT i32 0
+ %reg2:gpr(s32) = COPY $w2
+ %sub:gpr(s32) = G_SUB %zero(s32), %reg2
+ %select:gpr(s32) = G_SELECT %cond(s1), %t, %sub
+ $w0 = COPY %select(s32)
+ RET_ReallyLR implicit $w0
More information about the llvm-commits
mailing list