[llvm] r317879 - [RegAlloc, SystemZ] Increase number of LOCRs by passing "hard" regalloc hints.

Jonas Paulsson via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 10 00:46:26 PST 2017


Author: jonpa
Date: Fri Nov 10 00:46:26 2017
New Revision: 317879

URL: http://llvm.org/viewvc/llvm-project?rev=317879&view=rev
Log:
[RegAlloc, SystemZ] Increase number of LOCRs by passing "hard" regalloc hints.

* The method getRegAllocationHints() is now of bool type instead of void. If
true is returned, regalloc (AllocationOrder) will *only* try to allocate the
hints, as opposed to merely trying them before non-hinted registers.

* TargetRegisterInfo::getRegAllocationHints() is implemented for SystemZ with
an increase in number of LOCRs.

In this case, it is desired to force the hints even though there is a slight
increase in spilling, because if a non-hinted register would be allocated,
the LOCRMux pseudo would have to be expanded with a jump sequence. The LOCR
(Load On Condition) SystemZ instruction must have both operands in either the
low or high part of the 64 bit register.

Reviewers: Quentin Colombet and Ulrich Weigand
https://reviews.llvm.org/D36795

Added:
    llvm/trunk/test/CodeGen/SystemZ/cond-move-04.mir
Modified:
    llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
    llvm/trunk/lib/CodeGen/AllocationOrder.cpp
    llvm/trunk/lib/CodeGen/AllocationOrder.h
    llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
    llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
    llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp
    llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h

Modified: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetRegisterInfo.h?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h Fri Nov 10 00:46:26 2017
@@ -778,7 +778,8 @@ public:
   /// Get a list of 'hint' registers that the register allocator should try
   /// first when allocating a physical register for the virtual register
   /// VirtReg. These registers are effectively moved to the front of the
-  /// allocation order.
+  /// allocation order. If true is returned, regalloc will try to only use
+  /// hints to the greatest extent possible even if it means spilling.
   ///
   /// The Order argument is the allocation order for VirtReg's register class
   /// as returned from RegisterClassInfo::getOrder(). The hint registers must
@@ -789,7 +790,7 @@ public:
   /// HintType == 0. Targets that override this function should defer to the
   /// default implementation if they have no reason to change the allocation
   /// order for VirtReg. There may be target-independent hints.
-  virtual void getRegAllocationHints(unsigned VirtReg,
+  virtual bool getRegAllocationHints(unsigned VirtReg,
                                      ArrayRef<MCPhysReg> Order,
                                      SmallVectorImpl<MCPhysReg> &Hints,
                                      const MachineFunction &MF,

Modified: llvm/trunk/lib/CodeGen/AllocationOrder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AllocationOrder.cpp?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AllocationOrder.cpp (original)
+++ llvm/trunk/lib/CodeGen/AllocationOrder.cpp Fri Nov 10 00:46:26 2017
@@ -31,11 +31,12 @@ AllocationOrder::AllocationOrder(unsigne
                                  const VirtRegMap &VRM,
                                  const RegisterClassInfo &RegClassInfo,
                                  const LiveRegMatrix *Matrix)
-  : Pos(0) {
+  : Pos(0), HardHints(false) {
   const MachineFunction &MF = VRM.getMachineFunction();
   const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
   Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
-  TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix);
+  if (TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix))
+    HardHints = true;
   rewind();
 
   DEBUG({

Modified: llvm/trunk/lib/CodeGen/AllocationOrder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AllocationOrder.h?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AllocationOrder.h (original)
+++ llvm/trunk/lib/CodeGen/AllocationOrder.h Fri Nov 10 00:46:26 2017
@@ -32,7 +32,11 @@ class LLVM_LIBRARY_VISIBILITY Allocation
   ArrayRef<MCPhysReg> Order;
   int Pos;
 
+  // If HardHints is true, *only* Hints will be returned.
+  bool HardHints;
+
 public:
+
   /// Create a new AllocationOrder for VirtReg.
   /// @param VirtReg      Virtual register to allocate for.
   /// @param VRM          Virtual register map for function.
@@ -51,6 +55,8 @@ public:
   unsigned next(unsigned Limit = 0) {
     if (Pos < 0)
       return Hints.end()[Pos++];
+    if (HardHints)
+      return 0;
     if (!Limit)
       Limit = Order.size();
     while (Pos < int(Limit)) {
@@ -68,6 +74,8 @@ public:
   unsigned nextWithDups(unsigned Limit) {
     if (Pos < 0)
       return Hints.end()[Pos++];
+    if (HardHints)
+      return 0;
     if (Pos < int(Limit))
       return Order[Pos++];
     return 0;

Modified: llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetRegisterInfo.cpp Fri Nov 10 00:46:26 2017
@@ -360,7 +360,7 @@ bool TargetRegisterInfo::shouldRewriteCo
 }
 
 // Compute target-independent register allocator hints to help eliminate copies.
-void
+bool
 TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg,
                                           ArrayRef<MCPhysReg> Order,
                                           SmallVectorImpl<MCPhysReg> &Hints,
@@ -382,17 +382,18 @@ TargetRegisterInfo::getRegAllocationHint
 
   // Check that Phys is a valid hint in VirtReg's register class.
   if (!isPhysicalRegister(Phys))
-    return;
+    return false;
   if (MRI.isReserved(Phys))
-    return;
+    return false;
   // Check that Phys is in the allocation order. We shouldn't heed hints
   // from VirtReg's register class if they aren't in the allocation order. The
   // target probably has a reason for removing the register.
   if (!is_contained(Order, Phys))
-    return;
+    return false;
 
   // All clear, tell the register allocator to prefer this register.
   Hints.push_back(Phys);
+  return false;
 }
 
 bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const {

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Fri Nov 10 00:46:26 2017
@@ -280,7 +280,7 @@ static unsigned getPairedGPR(unsigned Re
 }
 
 // Resolve the RegPairEven / RegPairOdd register allocator hints.
-void
+bool
 ARMBaseRegisterInfo::getRegAllocationHints(unsigned VirtReg,
                                            ArrayRef<MCPhysReg> Order,
                                            SmallVectorImpl<MCPhysReg> &Hints,
@@ -300,7 +300,7 @@ ARMBaseRegisterInfo::getRegAllocationHin
     break;
   default:
     TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF, VRM);
-    return;
+    return false;
   }
 
   // This register should preferably be even (Odd == 0) or odd (Odd == 1).
@@ -308,7 +308,7 @@ ARMBaseRegisterInfo::getRegAllocationHin
   // the paired register as the first hint.
   unsigned Paired = Hint.second;
   if (Paired == 0)
-    return;
+    return false;
 
   unsigned PairedPhys = 0;
   if (TargetRegisterInfo::isPhysicalRegister(Paired)) {
@@ -331,6 +331,7 @@ ARMBaseRegisterInfo::getRegAllocationHin
       continue;
     Hints.push_back(Reg);
   }
+  return false;
 }
 
 void

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Fri Nov 10 00:46:26 2017
@@ -145,7 +145,7 @@ public:
   unsigned getRegPressureLimit(const TargetRegisterClass *RC,
                                MachineFunction &MF) const override;
 
-  void getRegAllocationHints(unsigned VirtReg,
+  bool getRegAllocationHints(unsigned VirtReg,
                              ArrayRef<MCPhysReg> Order,
                              SmallVectorImpl<MCPhysReg> &Hints,
                              const MachineFunction &MF,

Modified: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.cpp Fri Nov 10 00:46:26 2017
@@ -16,6 +16,7 @@
 #include "SystemZ.h"
 #include "SystemZInstrBuilder.h"
 #include "SystemZSubtarget.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/CodeGen/LiveInterval.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
 #include "llvm/CodeGen/LiveVariables.h"
@@ -45,6 +46,9 @@ using namespace llvm;
 #define GET_INSTRMAP_INFO
 #include "SystemZGenInstrInfo.inc"
 
+#define DEBUG_TYPE "systemz-II"
+STATISTIC(LOCRMuxJumps, "Number of LOCRMux jump-sequences (lower is better)");
+
 // Return a mask with Count low bits set.
 static uint64_t allOnes(unsigned int Count) {
   return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;
@@ -209,6 +213,8 @@ void SystemZInstrInfo::expandLOCRPseudo(
     MI.setDesc(get(LowOpcode));
   else if (DestIsHigh && SrcIsHigh)
     MI.setDesc(get(HighOpcode));
+  else
+    LOCRMuxJumps++;
 
   // If we were unable to implement the pseudo with a single instruction, we
   // need to convert it back into a branch sequence.  This cannot be done here

Modified: llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.cpp Fri Nov 10 00:46:26 2017
@@ -11,9 +11,11 @@
 #include "SystemZInstrInfo.h"
 #include "SystemZSubtarget.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/VirtRegMap.h"
 
 using namespace llvm;
 
@@ -23,6 +25,85 @@ using namespace llvm;
 SystemZRegisterInfo::SystemZRegisterInfo()
     : SystemZGenRegisterInfo(SystemZ::R14D) {}
 
+// Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO
+// somehow belongs in it. Otherwise, return GRX32.
+static const TargetRegisterClass *getRC32(MachineOperand &MO,
+                                          const VirtRegMap *VRM,
+                                          const MachineRegisterInfo *MRI) {
+  const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());
+
+  if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
+      MO.getSubReg() == SystemZ::subreg_l32)
+    return &SystemZ::GR32BitRegClass;
+  if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||
+      MO.getSubReg() == SystemZ::subreg_h32)
+    return &SystemZ::GRH32BitRegClass;
+
+  if (VRM && VRM->hasPhys(MO.getReg())) {
+    unsigned PhysReg = VRM->getPhys(MO.getReg());
+    if (SystemZ::GR32BitRegClass.contains(PhysReg))
+      return &SystemZ::GR32BitRegClass;
+    assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&
+            "Phys reg not in GR32 or GRH32?");
+    return &SystemZ::GRH32BitRegClass;
+  }
+
+  assert (RC == &SystemZ::GRX32BitRegClass);
+  return RC;
+}
+
+bool
+SystemZRegisterInfo::getRegAllocationHints(unsigned VirtReg,
+                                           ArrayRef<MCPhysReg> Order,
+                                           SmallVectorImpl<MCPhysReg> &Hints,
+                                           const MachineFunction &MF,
+                                           const VirtRegMap *VRM,
+                                           const LiveRegMatrix *Matrix) const {
+  const MachineRegisterInfo *MRI = &MF.getRegInfo();
+  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+  if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {
+    SmallVector<unsigned, 8> Worklist;
+    SmallSet<unsigned, 4> DoneRegs;
+    Worklist.push_back(VirtReg);
+    while (Worklist.size()) {
+      unsigned Reg = Worklist.pop_back_val();
+      if (!DoneRegs.insert(Reg).second)
+        continue;
+
+      for (auto &Use : MRI->use_instructions(Reg))
+        // For LOCRMux, see if the other operand is already a high or low
+        // register, and in that case give the correpsonding hints for
+        // VirtReg. LOCR instructions need both operands in either high or
+        // low parts.
+        if (Use.getOpcode() == SystemZ::LOCRMux) {
+          MachineOperand &TrueMO = Use.getOperand(1);
+          MachineOperand &FalseMO = Use.getOperand(2);
+          const TargetRegisterClass *RC =
+            TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),
+                                   getRC32(TrueMO, VRM, MRI));
+          if (RC && RC != &SystemZ::GRX32BitRegClass) {
+            for (MCPhysReg Reg : Order)
+              if (RC->contains(Reg) && !MRI->isReserved(Reg))
+                Hints.push_back(Reg);
+            // Return true to make these hints the only regs available to
+            // RA. This may mean extra spilling but since the alternative is
+            // a jump sequence expansion of the LOCRMux, it is preferred.
+            return true;
+          }
+
+          // Add the other operand of the LOCRMux to the worklist.
+          unsigned OtherReg =
+            (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());
+          if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)
+            Worklist.push_back(OtherReg);
+        }
+    }
+  }
+
+  return TargetRegisterInfo::getRegAllocationHints(VirtReg, Order, Hints, MF,
+                                                   VRM, Matrix);
+}
+
 const MCPhysReg *
 SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&

Modified: llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h?rev=317879&r1=317878&r2=317879&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZRegisterInfo.h Fri Nov 10 00:46:26 2017
@@ -44,6 +44,13 @@ public:
     return &SystemZ::ADDR64BitRegClass;
   }
 
+  bool getRegAllocationHints(unsigned VirtReg,
+                             ArrayRef<MCPhysReg> Order,
+                             SmallVectorImpl<MCPhysReg> &Hints,
+                             const MachineFunction &MF,
+                             const VirtRegMap *VRM,
+                             const LiveRegMatrix *Matrix) const override;
+
   // Override TargetRegisterInfo.h.
   bool requiresRegisterScavenging(const MachineFunction &MF) const override {
     return true;

Added: llvm/trunk/test/CodeGen/SystemZ/cond-move-04.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/cond-move-04.mir?rev=317879&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/cond-move-04.mir (added)
+++ llvm/trunk/test/CodeGen/SystemZ/cond-move-04.mir Fri Nov 10 00:46:26 2017
@@ -0,0 +1,75 @@
+# RUN: llc -mtriple=s390x-linux-gnu -mcpu=z13 -start-before=greedy %s -o - \
+# RUN:   | FileCheck %s
+#
+# Test that regalloc manages (via regalloc hints) to avoid a LOCRMux jump
+# sequence expansion.
+
+--- |
+  
+  declare i8* @foo(i8*, i32 signext, i32 signext) local_unnamed_addr
+  
+  define i8* @fun(i8* returned) {
+    br label %2
+  
+  ; <label>:2:                                      ; preds = %6, %1
+    %3 = zext i16 undef to i32
+    switch i32 %3, label %4 [
+      i32 15, label %6
+      i32 125, label %5
+    ]
+  
+  ; <label>:4:                                      ; preds = %2
+    br label %6
+  
+  ; <label>:5:                                      ; preds = %2
+    br label %6
+  
+  ; <label>:6:                                      ; preds = %5, %4, %2
+    %7 = phi i32 [ 4, %2 ], [ undef, %4 ], [ 10, %5 ]
+    %8 = call i8* @foo(i8* undef, i32 signext undef, i32 signext %7)
+    br label %2
+  }
+
+...
+
+# CHECK: locr
+# CHECK-NOT: risblg
+
+---
+name:            fun
+alignment:       2
+tracksRegLiveness: true
+registers:       
+  - { id: 0, class: gr32bit }
+  - { id: 1, class: gr64bit }
+  - { id: 2, class: grx32bit }
+  - { id: 3, class: grx32bit }
+  - { id: 4, class: grx32bit }
+  - { id: 5, class: grx32bit }
+  - { id: 6, class: grx32bit }
+  - { id: 7, class: gr64bit }
+  - { id: 8, class: gr64bit }
+  - { id: 9, class: gr64bit }
+  - { id: 10, class: gr64bit }
+  - { id: 11, class: gr32bit }
+frameInfo:       
+  hasCalls:        true
+body:             |
+  bb.0 (%ir-block.1):
+    %3 = LHIMux 0
+    %2 = LHIMux 4
+    %5 = LHIMux 10
+  
+  bb.1 (%ir-block.2):
+    CHIMux %3, 0, implicit-def %cc
+    %0 = LOCRMux undef %0, %5, 14, 6, implicit %cc
+    %0 = LOCRMux %0, %2, 14, 6, implicit killed %cc
+    ADJCALLSTACKDOWN 0, 0
+    %7 = LGFR %0
+    %r3d = LGHI 0
+    %r4d = COPY %7
+    CallBRASL @foo, undef %r2d, killed %r3d, killed %r4d, csr_systemz, implicit-def dead %r14d, implicit-def dead %cc, implicit-def dead %r2d
+    ADJCALLSTACKUP 0, 0
+    J %bb.1
+
+...




More information about the llvm-commits mailing list