[llvm] [PowerPC] Spill non-volatile registers required for traceback table (PR #71115)

Stefan Pintilie via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 22 12:25:46 PST 2024


================
@@ -2733,6 +2735,65 @@ bool PPCFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const {
   return !MF.getSubtarget<PPCSubtarget>().is32BitELFABI();
 }
 
+void PPCFrameLowering::updateCalleeSaves(const MachineFunction &MF,
+                                         BitVector &SavedRegs) const {
+  // The AIX ABI uses traceback tables for EH which require that if callee-saved
+  // register N is used, all registers N-31 must be saved/restored.
+  // NOTE: The check for AIX is not actually what is relevant. Traceback tables
+  // on Linux have the same requirements. It is just that AIX is the only ABI
+  // for which we actually use traceback tables. If another ABI needs to be
+  // supported that also uses them, we can add a check such as
+  // Subtarget.usesTraceBackTables().
+  assert(Subtarget.isAIXABI() && "function only called for AIX");
+
+  // If there are no callee saves then there is nothing to do.
+  if (SavedRegs.none())
+    return;
+
+  const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
+  const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&MF);
+  MCPhysReg LowestGPR = PPC::R31;
+  MCPhysReg LowestG8R = PPC::X31;
+  MCPhysReg LowestFPR = PPC::F31;
+  MCPhysReg LowestVR = PPC::V31;
+
+  // Traverse the CSR's twice so as not to rely on ascending ordering of
+  // registers in the array. The first pass finds the lowest numbered
+  // register and the second pass marks all higher numbered registers
+  // for spilling.
+  for (int i = 0; CSRegs[i]; i++) {
+    // Get the lowest numbered register for each class that actually needs
+    // to be saved.
+    MCPhysReg Cand = CSRegs[i];
+    if (!SavedRegs.test(Cand))
+      continue;
+    if (PPC::GPRCRegClass.contains(Cand) && Cand < LowestGPR)
+      LowestGPR = Cand;
+    else if (PPC::G8RCRegClass.contains(Cand) && Cand < LowestG8R)
+      LowestG8R = Cand;
+    else if ((PPC::F4RCRegClass.contains(Cand) ||
+              PPC::F8RCRegClass.contains(Cand)) &&
+             Cand < LowestFPR)
+      LowestFPR = Cand;
+    else if (PPC::VRRCRegClass.contains(Cand) && Cand < LowestVR)
+      LowestVR = Cand;
+  }
+
+  for (int i = 0; CSRegs[i]; i++) {
+    MCPhysReg Cand = CSRegs[i];
+    if (PPC::GPRCRegClass.contains(Cand) && Cand > LowestGPR)
+      SavedRegs.set(Cand);
+    else if (PPC::G8RCRegClass.contains(Cand) && Cand > LowestG8R)
+      SavedRegs.set(Cand);
+    else if ((PPC::F4RCRegClass.contains(Cand) ||
+              PPC::F8RCRegClass.contains(Cand)) &&
+             Cand > LowestFPR)
+      SavedRegs.set(Cand);
+    else if (PPC::VRRCRegClass.contains(Cand) && Cand > LowestVR)
+      SavedRegs.set(Cand);
----------------
stefanp-ibm wrote:

All of these conditions seem to end up doing the same thing. You can probably just common them up.
```
if ( (PPC::GPRCRegClass.contains(Cand) && Cand > LowestGPR)) ||
     (PPC::G8RCRegClass.contains(Cand) && Cand > LowestG8R)) ||
     (PPC::F4RCRegClass.contains(Cand) ||
              PPC::F8RCRegClass.contains(Cand)) &&
             Cand > LowestFPR) ||
     (PPC::VRRCRegClass.contains(Cand) && Cand > LowestVR) )
       SavedRegs.set(Cand);
```

https://github.com/llvm/llvm-project/pull/71115


More information about the llvm-commits mailing list