[llvm] [SystemZ] Improve shouldCoalesce() for i128. (PR #74942)

Jonas Paulsson via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 12 12:40:39 PST 2023


https://github.com/JonPsson1 updated https://github.com/llvm/llvm-project/pull/74942

>From a15e99f858bd06c8ec1eaacbd71338205f95da3d Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Sat, 9 Dec 2023 10:25:10 -0600
Subject: [PATCH 1/2] Improve for PAIR128

---
 llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp | 11 ++++++++++-
 llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll |  4 +---
 llvm/test/CodeGen/SystemZ/atomicrmw-xchg-07.ll  |  3 +--
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 4d6b94da3a2754..e822dbf586ab73 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -384,6 +384,7 @@ bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
                                   const TargetRegisterClass *NewRC,
                                   LiveIntervals &LIS) const {
   assert (MI->isCopy() && "Only expecting COPY instructions");
+  const MachineRegisterInfo *MRI = &MI->getMF()->getRegInfo();
 
   // Coalesce anything which is not a COPY involving a subreg to/from GR128.
   if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&
@@ -400,7 +401,6 @@ bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
   LiveInterval &IntGR128 = LIS.getInterval(GR128Reg);
   LiveInterval &IntGRNar = LIS.getInterval(GRNarReg);
 
-  // Check that the two virtual registers are local to MBB.
   MachineBasicBlock *MBB = MI->getParent();
   MachineInstr *FirstMI_GR128 =
     LIS.getInstructionFromIndex(IntGR128.beginIndex());
@@ -408,6 +408,15 @@ bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
     LIS.getInstructionFromIndex(IntGRNar.beginIndex());
   MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex());
   MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex());
+
+  // Allow cases (like PAIR128) where there is just one use of the narrow
+  // source reg defined close to MI.
+  if (WideOpNo == 0 && MRI->hasOneUse(GRNarReg) &&
+      FirstMI_GRNar && FirstMI_GRNar->getParent() == MBB &&
+      std::distance(FirstMI_GRNar->getIterator(), MI->getIterator()) < 5)
+    return true;
+
+  // Check that the two virtual registers are local to MBB.
   if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) ||
       (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
       (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) ||
diff --git a/llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll b/llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll
index 0e8f0446802220..41b0964be05e56 100644
--- a/llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll
+++ b/llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll
@@ -14,13 +14,11 @@ define i128 @atomicrmw_xchg(ptr %src, i128 %b) {
 ; CHECK-NEXT:    stmg %r12, %r15, 96(%r15)
 ; CHECK-NEXT:    .cfi_offset %r12, -64
 ; CHECK-NEXT:    .cfi_offset %r13, -56
-; CHECK-NEXT:    .cfi_offset %r14, -48
 ; CHECK-NEXT:    .cfi_offset %r15, -40
-; CHECK-NEXT:    lg %r14, 8(%r4)
+; CHECK-NEXT:    lg %r1, 8(%r4)
 ; CHECK-NEXT:    lg %r0, 0(%r4)
 ; CHECK-NEXT:    lg %r4, 8(%r3)
 ; CHECK-NEXT:    lg %r5, 0(%r3)
-; CHECK-NEXT:    lgr %r1, %r14
 ; CHECK-NEXT:  .LBB0_1: # %atomicrmw.start
 ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    lgr %r12, %r5
diff --git a/llvm/test/CodeGen/SystemZ/atomicrmw-xchg-07.ll b/llvm/test/CodeGen/SystemZ/atomicrmw-xchg-07.ll
index b9e29599af7ee7..18fa89e6ca6cb8 100644
--- a/llvm/test/CodeGen/SystemZ/atomicrmw-xchg-07.ll
+++ b/llvm/test/CodeGen/SystemZ/atomicrmw-xchg-07.ll
@@ -4,11 +4,10 @@
 
 define void @f1(ptr align 16 %ret, ptr align 16 %src, ptr align 16 %b) {
 ; CHECK-LABEL: f1:
-; CHECK:       lg      %r14, 8(%r4)
+; CHECK:       lg      %r1, 8(%r4)
 ; CHECK-NEXT:  lg      %r0, 0(%r4)
 ; CHECK-NEXT:  lg      %r4, 8(%r3)
 ; CHECK-NEXT:  lg      %r5, 0(%r3)
-; CHECK-NEXT:  lgr     %r1, %r14
 ; CHECK-NEXT:.LBB0_1:                          # %atomicrmw.start
 ; CHECK-NEXT:                                  # =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:  lgr     %r12, %r5

>From fa8c8bf5b4f2476e194294c77107412cffb74bb1 Mon Sep 17 00:00:00 2001
From: Jonas Paulsson <paulson1 at linux.ibm.com>
Date: Tue, 12 Dec 2023 14:39:05 -0600
Subject: [PATCH 2/2] Change heuristics to allow global i128 interval

---
 .../Target/SystemZ/SystemZRegisterInfo.cpp    | 53 +++++++++----------
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index e822dbf586ab73..97ae352a60870b 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -384,58 +384,55 @@ bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,
                                   const TargetRegisterClass *NewRC,
                                   LiveIntervals &LIS) const {
   assert (MI->isCopy() && "Only expecting COPY instructions");
-  const MachineRegisterInfo *MRI = &MI->getMF()->getRegInfo();
 
   // Coalesce anything which is not a COPY involving a subreg to/from GR128.
   if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&
-        (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64)))
+        (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64)) ||
+      MI->getOperand(1).isUndef())
     return true;
 
-  // Allow coalescing of a GR128 subreg COPY only if the live ranges are small
-  // and local to one MBB with not too much interferring registers. Otherwise
+  // Allow coalescing of a GR128 subreg COPY only if the subreg is local to
+  // one MBB and there are not too much interferring physregs. Otherwise
   // regalloc may run out of registers.
 
+  // Check that the subreg is local to MBB.
+  MachineBasicBlock *MBB = MI->getParent();
   unsigned WideOpNo = (getRegSizeInBits(*SrcRC) == 128 ? 1 : 0);
-  Register GR128Reg = MI->getOperand(WideOpNo).getReg();
   Register GRNarReg = MI->getOperand((WideOpNo == 1) ? 0 : 1).getReg();
-  LiveInterval &IntGR128 = LIS.getInterval(GR128Reg);
   LiveInterval &IntGRNar = LIS.getInterval(GRNarReg);
-
-  MachineBasicBlock *MBB = MI->getParent();
-  MachineInstr *FirstMI_GR128 =
-    LIS.getInstructionFromIndex(IntGR128.beginIndex());
   MachineInstr *FirstMI_GRNar =
     LIS.getInstructionFromIndex(IntGRNar.beginIndex());
-  MachineInstr *LastMI_GR128 = LIS.getInstructionFromIndex(IntGR128.endIndex());
   MachineInstr *LastMI_GRNar = LIS.getInstructionFromIndex(IntGRNar.endIndex());
-
-  // Allow cases (like PAIR128) where there is just one use of the narrow
-  // source reg defined close to MI.
-  if (WideOpNo == 0 && MRI->hasOneUse(GRNarReg) &&
-      FirstMI_GRNar && FirstMI_GRNar->getParent() == MBB &&
-      std::distance(FirstMI_GRNar->getIterator(), MI->getIterator()) < 5)
-    return true;
-
-  // Check that the two virtual registers are local to MBB.
-  if ((!FirstMI_GR128 || FirstMI_GR128->getParent() != MBB) ||
-      (!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
-      (!LastMI_GR128 || LastMI_GR128->getParent() != MBB) ||
+  if ((!FirstMI_GRNar || FirstMI_GRNar->getParent() != MBB) ||
       (!LastMI_GRNar || LastMI_GRNar->getParent() != MBB))
     return false;
 
-  MachineBasicBlock::iterator MII = nullptr, MEE = nullptr;
+  Register GR128Reg = MI->getOperand(WideOpNo).getReg();
+  LiveInterval &IntGR128 = LIS.getInterval(GR128Reg);
+  MachineBasicBlock::iterator MII, MEE = nullptr;
   if (WideOpNo == 1) {
-    MII = FirstMI_GR128;
-    MEE = LastMI_GRNar;
+    // Find the local starting point of IntGR128 (we trust that regalloc
+    // should be able to split the interval at CFG edges if necessary).
+    LiveInterval::const_iterator SI = IntGR128.find(LIS.getMBBStartIdx(MBB));
+    assert(SI != IntGR128.end() && "Live segment not found.");
+    MII = LIS.getInstructionFromIndex(SI->start);
+    if (MII == nullptr || MII->getParent() != MBB)
+      MII = MBB->begin();
+    MEE = std::next(LastMI_GRNar->getIterator());
   } else {
     MII = FirstMI_GRNar;
-    MEE = LastMI_GR128;
+    // Similarly, find the local end point of IntGR128.
+    LiveInterval::const_iterator SI = IntGR128.find(LIS.getInstructionIndex(*MI));
+    MEE = LIS.getInstructionFromIndex(SI->end);
+    while (MEE != nullptr && MEE->getParent() == MBB && IntGR128.liveAt(SI->end))
+      MEE = LIS.getInstructionFromIndex((++SI)->end);
+    if (MEE == nullptr || MEE->getParent() != MBB)
+      MEE = MBB->end();
   }
 
   // Check if coalescing seems safe by finding the set of clobbered physreg
   // pairs in the region.
   BitVector PhysClobbered(getNumRegs());
-  MEE++;
   for (; MII != MEE; ++MII) {
     for (const MachineOperand &MO : MII->operands())
       if (MO.isReg() && MO.getReg().isPhysical()) {



More information about the llvm-commits mailing list