[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