[llvm] f55a518 - [AArch64][GlobalISel] Support shifted register form in emitTST

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 28 10:14:21 PDT 2020


Author: Jessica Paquette
Date: 2020-09-28T10:13:47-07:00
New Revision: f55a5186c6c005fe171a35a832000829cd00cd2a

URL: https://github.com/llvm/llvm-project/commit/f55a5186c6c005fe171a35a832000829cd00cd2a
DIFF: https://github.com/llvm/llvm-project/commit/f55a5186c6c005fe171a35a832000829cd00cd2a.diff

LOG: [AArch64][GlobalISel] Support shifted register form in emitTST

Support emitting ANDSXrs and ANDSWrs in `emitTST`. Update opt-fold-compare.mir
to show that it works.

Differential Revision: https://reviews.llvm.org/D87530

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
    llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-compare.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index fc12d1bcbef6..53875db57c0d 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -225,7 +225,7 @@ class AArch64InstructionSelector : public InstructionSelector {
                          MachineIRBuilder &MIRBuilder) const;
   MachineInstr *emitCMN(MachineOperand &LHS, MachineOperand &RHS,
                         MachineIRBuilder &MIRBuilder) const;
-  MachineInstr *emitTST(const Register &LHS, const Register &RHS,
+  MachineInstr *emitTST(MachineOperand &LHS, MachineOperand &RHS,
                         MachineIRBuilder &MIRBuilder) const;
   MachineInstr *emitExtractVectorElt(Optional<Register> DstReg,
                                      const RegisterBank &DstRB, LLT ScalarTy,
@@ -3905,31 +3905,31 @@ AArch64InstructionSelector::emitCMN(MachineOperand &LHS, MachineOperand &RHS,
 }
 
 MachineInstr *
-AArch64InstructionSelector::emitTST(const Register &LHS, const Register &RHS,
+AArch64InstructionSelector::emitTST(MachineOperand &LHS, MachineOperand &RHS,
                                     MachineIRBuilder &MIRBuilder) const {
+  assert(LHS.isReg() && RHS.isReg() && "Expected register operands?");
   MachineRegisterInfo &MRI = MIRBuilder.getMF().getRegInfo();
-  unsigned RegSize = MRI.getType(LHS).getSizeInBits();
+  unsigned RegSize = MRI.getType(LHS.getReg()).getSizeInBits();
   bool Is32Bit = (RegSize == 32);
-  static const unsigned OpcTable[2][2]{{AArch64::ANDSXrr, AArch64::ANDSXri},
-                                       {AArch64::ANDSWrr, AArch64::ANDSWri}};
+  const unsigned OpcTable[3][2] = {{AArch64::ANDSXri, AArch64::ANDSWri},
+                                   {AArch64::ANDSXrs, AArch64::ANDSWrs},
+                                   {AArch64::ANDSXrr, AArch64::ANDSWrr}};
   Register ZReg = Is32Bit ? AArch64::WZR : AArch64::XZR;
+  // ANDS needs a logical immediate for its immediate form. Check if we can
+  // fold one in.
+  if (auto ValAndVReg = getConstantVRegValWithLookThrough(RHS.getReg(), MRI)) {
+    if (AArch64_AM::isLogicalImmediate(ValAndVReg->Value, RegSize)) {
+      auto TstMI = MIRBuilder.buildInstr(OpcTable[0][Is32Bit], {ZReg}, {LHS});
+      TstMI.addImm(
+          AArch64_AM::encodeLogicalImmediate(ValAndVReg->Value, RegSize));
+      constrainSelectedInstRegOperands(*TstMI, TII, TRI, RBI);
+      return &*TstMI;
+    }
+  }
 
-  // We might be able to fold in an immediate into the TST. We need to make sure
-  // it's a logical immediate though, since ANDS requires that.
-  auto ValAndVReg = getConstantVRegValWithLookThrough(RHS, MRI);
-  bool IsImmForm = ValAndVReg.hasValue() &&
-                   AArch64_AM::isLogicalImmediate(ValAndVReg->Value, RegSize);
-  unsigned Opc = OpcTable[Is32Bit][IsImmForm];
-  auto TstMI = MIRBuilder.buildInstr(Opc, {ZReg}, {LHS});
-
-  if (IsImmForm)
-    TstMI.addImm(
-        AArch64_AM::encodeLogicalImmediate(ValAndVReg->Value, RegSize));
-  else
-    TstMI.addUse(RHS);
-
-  constrainSelectedInstRegOperands(*TstMI, TII, TRI, RBI);
-  return &*TstMI;
+  if (auto Fns = selectLogicalShiftedRegister(RHS))
+    return emitInstr(OpcTable[1][Is32Bit], {ZReg}, {LHS}, MIRBuilder, Fns);
+  return emitInstr(OpcTable[2][Is32Bit], {ZReg}, {LHS, RHS}, MIRBuilder);
 }
 
 std::pair<MachineInstr *, CmpInst::Predicate>
@@ -4289,8 +4289,8 @@ MachineInstr *AArch64InstructionSelector::tryFoldIntegerCompare(
     if (!ValAndVReg || ValAndVReg->Value != 0)
       return nullptr;
 
-    return emitTST(LHSDef->getOperand(1).getReg(),
-                   LHSDef->getOperand(2).getReg(), MIRBuilder);
+    return emitTST(LHSDef->getOperand(1),
+                   LHSDef->getOperand(2), MIRBuilder);
   }
 
   return nullptr;

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-compare.mir b/llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-compare.mir
index 26e4e8c7a8a6..e58d97304d2b 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-compare.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/opt-fold-compare.mir
@@ -510,3 +510,70 @@ body:             |
     %7:gpr(s32) = G_ICMP intpred(eq), %0, %1
     $w0 = COPY %7(s32)
     RET_ReallyLR implicit $x0
+
+...
+---
+name:            tst_fold_shift_s64
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $x0, $x1
+    ; We should fold the G_SHL into the ANDS to get ANDSXrs.
+    ;
+    ; CHECK-LABEL: name: tst_fold_shift_s64
+    ; CHECK: liveins: $x0, $x1
+    ; CHECK: %copy:gpr64 = COPY $x1
+    ; CHECK: %zero:gpr64 = COPY $xzr
+    ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 1
+    ; CHECK: %one:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32
+    ; CHECK: $xzr = ANDSXrs %zero, %copy, 16, implicit-def $nzcv
+    ; CHECK: %select:gpr64 = CSELXr %one, %zero, 0, implicit $nzcv
+    ; CHECK: $x0 = COPY %select
+    ; CHECK: RET_ReallyLR implicit $x0
+    %copy:gpr(s64) = COPY $x1
+    %zero:gpr(s64) = G_CONSTANT i64 0
+    %one:gpr(s64) = G_CONSTANT i64 1
+    %cst:gpr(s64) = G_CONSTANT i64 16
+    %shift:gpr(s64) = G_SHL %copy(s64), %cst(s64)
+    %and:gpr(s64) = G_AND %zero, %shift
+    %cmp:gpr(s32) = G_ICMP intpred(eq), %and(s64), %zero
+    %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
+    %select:gpr(s64) = G_SELECT %cmp_trunc(s1), %one, %zero
+    $x0 = COPY %select(s64)
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:            tst_fold_shift_s32
+alignment:       4
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $w0, $w1
+    ; We should fold the G_SHL into the ANDS to get ANDSWrs.
+    ;
+    ; CHECK-LABEL: name: tst_fold_shift_s32
+    ; CHECK: liveins: $w0, $w1
+    ; CHECK: %copy:gpr32 = COPY $w1
+    ; CHECK: %zero:gpr32 = COPY $wzr
+    ; CHECK: %one:gpr32 = MOVi32imm 1
+    ; CHECK: $wzr = ANDSWrs %zero, %copy, 16, implicit-def $nzcv
+    ; CHECK: %select:gpr32 = CSELWr %one, %zero, 0, implicit $nzcv
+    ; CHECK: $w0 = COPY %select
+    ; CHECK: RET_ReallyLR implicit $w0
+    %copy:gpr(s32) = COPY $w1
+    %zero:gpr(s32) = G_CONSTANT i32 0
+    %one:gpr(s32) = G_CONSTANT i32 1
+    %cst:gpr(s32) = G_CONSTANT i32 16
+    %shift:gpr(s32) = G_SHL %copy(s32), %cst(s32)
+    %and:gpr(s32) = G_AND %zero, %shift
+    %cmp:gpr(s32) = G_ICMP intpred(eq), %and(s32), %zero
+    %cmp_trunc:gpr(s1) = G_TRUNC %cmp(s32)
+    %select:gpr(s32) = G_SELECT %cmp_trunc(s1), %one, %zero
+    $w0 = COPY %select(s32)
+    RET_ReallyLR implicit $w0


        


More information about the llvm-commits mailing list