[llvm] r366625 - [GlobalISel][AArch64] Contract trivial same-size cross-bank copies into G_STOREs

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 19 18:55:35 PDT 2019


Author: paquette
Date: Fri Jul 19 18:55:35 2019
New Revision: 366625

URL: http://llvm.org/viewvc/llvm-project?rev=366625&view=rev
Log:
[GlobalISel][AArch64] Contract trivial same-size cross-bank copies into G_STOREs

Sometimes, you can end up with cross-bank copies between same-sized GPRs and
FPRs, which feed into G_STOREs. When these copies feed only into stores, they
aren't necessary; we can just store using the original register bank.

This provides some minor code size savings for some floating point SPEC
benchmarks. (Around 0.2% for 453.povray and 450.soplex)

This issue doesn't seem to show up due to regbankselect or anything similar. So,
this patch introduces an early select function, `contractCrossBankCopyIntoStore`
which performs the contraction when possible. The selector then continues
normally and selects the correct store opcode, eliminating needless copies
along the way.

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

Added:
    llvm/trunk/test/CodeGen/AArch64/GlobalISel/contract-store.mir
Modified:
    llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp

Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=366625&r1=366624&r2=366625&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Fri Jul 19 18:55:35 2019
@@ -69,6 +69,10 @@ private:
   bool earlySelectSHL(MachineInstr &I, MachineRegisterInfo &MRI) const;
   bool earlySelectLoad(MachineInstr &I, MachineRegisterInfo &MRI) const;
 
+  /// Eliminate same-sized cross-bank copies into stores before selectImpl().
+  void contractCrossBankCopyIntoStore(MachineInstr &I,
+                                      MachineRegisterInfo &MRI) const;
+
   bool selectVaStartAAPCS(MachineInstr &I, MachineFunction &MF,
                           MachineRegisterInfo &MRI) const;
   bool selectVaStartDarwin(MachineInstr &I, MachineFunction &MF,
@@ -1120,6 +1124,9 @@ void AArch64InstructionSelector::preISel
     }
     return;
   }
+  case TargetOpcode::G_STORE:
+    contractCrossBankCopyIntoStore(I, MRI);
+    return;
   default:
     return;
   }
@@ -1160,6 +1167,48 @@ bool AArch64InstructionSelector::earlySe
   return constrainSelectedInstRegOperands(*NewI, TII, TRI, RBI);
 }
 
+void AArch64InstructionSelector::contractCrossBankCopyIntoStore(
+    MachineInstr &I, MachineRegisterInfo &MRI) const {
+  assert(I.getOpcode() == TargetOpcode::G_STORE && "Expected G_STORE");
+  // If we're storing a scalar, it doesn't matter what register bank that
+  // scalar is on. All that matters is the size.
+  //
+  // So, if we see something like this (with a 32-bit scalar as an example):
+  //
+  // %x:gpr(s32) = ... something ...
+  // %y:fpr(s32) = COPY %x:gpr(s32)
+  // G_STORE %y:fpr(s32)
+  //
+  // We can fix this up into something like this:
+  //
+  // G_STORE %x:gpr(s32)
+  //
+  // And then continue the selection process normally.
+  MachineInstr *Def = getDefIgnoringCopies(I.getOperand(0).getReg(), MRI);
+  if (!Def)
+    return;
+  Register DefDstReg = Def->getOperand(0).getReg();
+  LLT DefDstTy = MRI.getType(DefDstReg);
+  Register StoreSrcReg = I.getOperand(0).getReg();
+  LLT StoreSrcTy = MRI.getType(StoreSrcReg);
+
+  // If we get something strange like a physical register, then we shouldn't
+  // go any further.
+  if (!DefDstTy.isValid())
+    return;
+
+  // Are the source and dst types the same size?
+  if (DefDstTy.getSizeInBits() != StoreSrcTy.getSizeInBits())
+    return;
+
+  if (RBI.getRegBank(StoreSrcReg, MRI, TRI) ==
+      RBI.getRegBank(DefDstReg, MRI, TRI))
+    return;
+
+  // We have a cross-bank copy, which is entering a store. Let's fold it.
+  I.getOperand(0).setReg(DefDstReg);
+}
+
 bool AArch64InstructionSelector::earlySelectLoad(
     MachineInstr &I, MachineRegisterInfo &MRI) const {
   // Try to fold in shifts, etc into the addressing mode of a load.

Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/contract-store.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/contract-store.mir?rev=366625&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/contract-store.mir (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/contract-store.mir Fri Jul 19 18:55:35 2019
@@ -0,0 +1,89 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+
+--- |
+  define void @contract_s64_gpr(i64* %addr) { ret void }
+  define void @contract_s32_gpr(i32* %addr) { ret void }
+  define void @contract_s64_fpr(i64* %addr) { ret void }
+  define void @contract_s32_fpr(i32* %addr) { ret void }
+  define void @contract_s16_fpr(i16* %addr) { ret void }
+...
+---
+name:            contract_s64_gpr
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.0:
+    liveins: $x0, $x1
+    ; CHECK-LABEL: name: contract_s64_gpr
+    ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+    ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
+    ; CHECK: STRXui [[COPY1]], [[COPY]], 0 :: (store 8 into %ir.addr)
+    %0:gpr(p0) = COPY $x0
+    %1:gpr(s64) = COPY $x1
+    %2:fpr(s64) = COPY %1
+    G_STORE  %2:fpr(s64), %0 :: (store 8 into %ir.addr)
+...
+---
+name:            contract_s32_gpr
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.0:
+    liveins: $x0, $w1
+    ; CHECK-LABEL: name: contract_s32_gpr
+    ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+    ; CHECK: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1
+    ; CHECK: STRWui [[COPY1]], [[COPY]], 0 :: (store 4 into %ir.addr)
+    %0:gpr(p0) = COPY $x0
+    %1:gpr(s32) = COPY $w1
+    %2:fpr(s32) = COPY %1
+    G_STORE  %2:fpr(s32), %0 :: (store 4 into %ir.addr)
+...
+---
+name:            contract_s64_fpr
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.0:
+    liveins: $x0, $d1
+    ; CHECK-LABEL: name: contract_s64_fpr
+    ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+    ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1
+    ; CHECK: STRDui [[COPY1]], [[COPY]], 0 :: (store 8 into %ir.addr)
+    %0:gpr(p0) = COPY $x0
+    %1:fpr(s64) = COPY $d1
+    %2:gpr(s64) = COPY %1
+    G_STORE %2:gpr(s64), %0 :: (store 8 into %ir.addr)
+...
+---
+name:            contract_s32_fpr
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.0:
+    liveins: $x0, $s1
+    ; CHECK-LABEL: name: contract_s32_fpr
+    ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+    ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
+    ; CHECK: STRSui [[COPY1]], [[COPY]], 0 :: (store 4 into %ir.addr)
+    %0:gpr(p0) = COPY $x0
+    %1:fpr(s32) = COPY $s1
+    %2:gpr(s32) = COPY %1
+    G_STORE %2:gpr(s32), %0 :: (store 4 into %ir.addr)
+...
+---
+name:            contract_s16_fpr
+legalized:       true
+regBankSelected: true
+body:             |
+  bb.0:
+    liveins: $x0, $h1
+    ; CHECK-LABEL: name: contract_s16_fpr
+    ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+    ; CHECK: [[COPY1:%[0-9]+]]:fpr16 = COPY $h1
+    ; CHECK: STRHui [[COPY1]], [[COPY]], 0 :: (store 2 into %ir.addr)
+    %0:gpr(p0) = COPY $x0
+    %1:fpr(s16) = COPY $h1
+    %2:gpr(s16) = COPY %1
+    G_STORE  %2:gpr(s16), %0 :: (store 2 into %ir.addr)




More information about the llvm-commits mailing list