[llvm] [PowerPC][CodeGen] Exploit STMW and LMW in 32-bit big-endian mode. (PR #74415)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 27 19:04:53 PST 2023
https://github.com/EsmeYi updated https://github.com/llvm/llvm-project/pull/74415
>From c46a2f6708f72c279aea92eed68b51205824e823 Mon Sep 17 00:00:00 2001
From: esmeyi <esme.yi at ibm.com>
Date: Tue, 26 Dec 2023 01:01:18 -0500
Subject: [PATCH 1/2] Squash commits.
---
llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 104 +++++++++++++++++-
llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 12 +-
llvm/test/CodeGen/PowerPC/aix-stm-lm-merge.ll | 16 +++
3 files changed, 123 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/CodeGen/PowerPC/aix-stm-lm-merge.ll
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index 245e78641ed654..daedcb643f84b6 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -40,6 +40,12 @@ EnablePEVectorSpills("ppc-enable-pe-vector-spills",
cl::desc("Enable spills in prologue to vector registers."),
cl::init(false), cl::Hidden);
+static cl::opt<bool>
+ EnableLoadStoreMultiple("ppc-enable-load-store-multiple",
+ cl::desc("Enable load/store multiple (only "
+ "support on 32-bit AIX)."),
+ cl::init(false), cl::Hidden);
+
static unsigned computeReturnSaveOffset(const PPCSubtarget &STI) {
if (STI.isAIXABI())
return STI.isPPC64() ? 16 : 8;
@@ -2399,6 +2405,43 @@ bool PPCFrameLowering::assignCalleeSavedSpillSlots(
return AllSpilledToReg;
}
+static void findContinuousLoadStore(const MachineFunction *MF,
+ ArrayRef<CalleeSavedInfo> CSI,
+ Register &MergeFrom) {
+ const MachineFrameInfo &MFI = MF->getFrameInfo();
+ int64_t Offset = MFI.estimateStackSize(*MF);
+ Register LastReg = PPC::R0;
+ for (unsigned I = 0, E = CSI.size(); I + 1 < E; ++I) {
+ Register CurrReg = CSI[I].getReg();
+ Offset += MFI.getObjectOffset(CSI[I].getFrameIdx());
+ if (CurrReg < PPC::R13 || CSI[I].isSpilledToReg() ||
+ CSI[I].getFrameIdx() >= 0 || !isInt<16>(Offset))
+ continue;
+
+ // Check memory operand type.
+ if (MFI.getObjectSize(CSI[I].getFrameIdx()) != 4)
+ continue;
+
+ // Record the first reg that STMW/LMW are going to merge since STMW/LMW save
+ // from rN to r31, where rN >= r13.
+ if (MergeFrom == PPC::R0)
+ MergeFrom = CurrReg;
+
+ // Check continuous store/load.
+ if ((CSI[I].getFrameIdx() - CSI[I + 1].getFrameIdx() != 1) ||
+ (CSI[I + 1].getReg().id() - CurrReg.id() != 1))
+ MergeFrom = PPC::R0;
+
+ LastReg = CSI[I + 1].getReg();
+ if (LastReg >= PPC::R31)
+ break;
+ }
+
+ // Make sure the last register is r31.
+ if (LastReg != PPC::R31)
+ MergeFrom = PPC::R0;
+}
+
bool PPCFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
@@ -2407,6 +2450,7 @@ bool PPCFrameLowering::spillCalleeSavedRegisters(
const PPCInstrInfo &TII = *Subtarget.getInstrInfo();
PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
bool MustSaveTOC = FI->mustSaveTOC();
+ const MachineFrameInfo &MFI = MF->getFrameInfo();
DebugLoc DL;
bool CRSpilled = false;
MachineInstrBuilder CRMIB;
@@ -2429,6 +2473,10 @@ bool PPCFrameLowering::spillCalleeSavedRegisters(
}
}
+ Register MergeFrom = PPC::R0;
+ if (EnableLoadStoreMultiple && Subtarget.isAIXABI() && !Subtarget.isPPC64())
+ findContinuousLoadStore(MF, CSI, MergeFrom);
+
for (const CalleeSavedInfo &I : CSI) {
Register Reg = I.getReg();
@@ -2511,9 +2559,30 @@ bool PPCFrameLowering::spillCalleeSavedRegisters(
// saved vector registers.
if (Subtarget.needsSwapsForVSXMemOps() &&
!MF->getFunction().hasFnAttribute(Attribute::NoUnwind))
- TII.storeRegToStackSlotNoUpd(MBB, MI, Reg, !IsLiveIn,
- I.getFrameIdx(), RC, TRI);
- else
+ TII.storeRegToStackSlotNoUpd(MBB, MI, Reg, !IsLiveIn, I.getFrameIdx(),
+ RC, TRI);
+ else if (MergeFrom >= PPC::R13 && MergeFrom < PPC::R31 &&
+ Reg >= MergeFrom && Reg <= PPC::R31) {
+ if (Reg == MergeFrom) {
+ // Build an STMW instruction.
+ int FrameIdx = I.getFrameIdx();
+ MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(PPC::STMW));
+ MIB.addReg(Reg, getKillRegState(!IsLiveIn));
+ // Add frame reference.
+ MIB.addImm(0).addFrameIndex(FrameIdx);
+ MachineMemOperand *MMO = MF->getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(*MF, FrameIdx),
+ MachineMemOperand::MOStore, MFI.getObjectSize(FrameIdx),
+ MFI.getObjectAlign(FrameIdx));
+ MIB.addMemOperand(MMO);
+ FI->setHasSpills();
+ // Add implicit uses.
+ Register MergeEnd = PPC::R31;
+ for (unsigned I = MergeFrom.id(); I <= MergeEnd.id(); ++I)
+ MIB.addUse(Register(I), RegState::Implicit);
+ } else
+ continue;
+ } else
TII.storeRegToStackSlot(MBB, MI, Reg, !IsLiveIn, I.getFrameIdx(), RC,
TRI, Register());
}
@@ -2600,6 +2669,7 @@ bool PPCFrameLowering::restoreCalleeSavedRegisters(
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII = *Subtarget.getInstrInfo();
PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
+ const MachineFrameInfo &MFI = MF->getFrameInfo();
bool MustSaveTOC = FI->mustSaveTOC();
bool CR2Spilled = false;
bool CR3Spilled = false;
@@ -2607,6 +2677,10 @@ bool PPCFrameLowering::restoreCalleeSavedRegisters(
unsigned CSIIndex = 0;
BitVector Restored(TRI->getNumRegs());
+ Register MergeFrom = PPC::R0;
+ if (EnableLoadStoreMultiple && Subtarget.isAIXABI() && !Subtarget.isPPC64())
+ findContinuousLoadStore(MF, CSI, MergeFrom);
+
// Initialize insertion-point logic; we will be restoring in reverse
// order of spill.
MachineBasicBlock::iterator I = MI, BeforeI = I;
@@ -2686,7 +2760,29 @@ bool PPCFrameLowering::restoreCalleeSavedRegisters(
!MF->getFunction().hasFnAttribute(Attribute::NoUnwind))
TII.loadRegFromStackSlotNoUpd(MBB, I, Reg, CSI[i].getFrameIdx(), RC,
TRI);
- else
+ else if (MergeFrom >= PPC::R13 && MergeFrom < PPC::R31 &&
+ Reg >= MergeFrom && Reg <= PPC::R31) {
+ if (Reg == MergeFrom) {
+ // Build an LMW instruction.
+ int FrameIdx = CSI[i].getFrameIdx();
+ DebugLoc DL;
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, I, DL, TII.get(PPC::LMW), MergeFrom);
+ // Add frame reference.
+ MIB.addImm(0).addFrameIndex(FrameIdx);
+ MachineMemOperand *MMO = MF->getMachineMemOperand(
+ MachinePointerInfo::getFixedStack(*MF, FrameIdx),
+ MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIdx),
+ MFI.getObjectAlign(FrameIdx));
+ MIB.addMemOperand(MMO);
+ FI->setHasSpills();
+ // Add implicit defs.
+ Register MergeEnd = PPC::R31;
+ for (unsigned I = MergeFrom.id(); I <= MergeEnd.id(); ++I)
+ MIB.addDef(Register(I), RegState::Implicit);
+ } else
+ continue;
+ } else
TII.loadRegFromStackSlot(MBB, I, Reg, CSI[i].getFrameIdx(), RC, TRI,
Register());
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index 7d913a77cc7155..21ec25b2e93dd9 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -1673,8 +1673,10 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
// If the instruction is not present in ImmToIdxMap, then it has no immediate
// form (and must be r+r).
+ // STMW and LMW only have immediate form.
bool noImmForm = !MI.isInlineAsm() && OpC != TargetOpcode::STACKMAP &&
- OpC != TargetOpcode::PATCHPOINT && !ImmToIdxMap.count(OpC);
+ OpC != TargetOpcode::PATCHPOINT && !ImmToIdxMap.count(OpC) &&
+ OpC != PPC::STMW && OpC != PPC::LMW;
// Now add the frame object offset to the offset from r1.
int64_t Offset = MFI.getObjectOffset(FrameIndex);
@@ -1716,10 +1718,10 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
isInt<16>(Offset);
if (TII.isPrefixed(MI.getOpcode()))
OffsetFitsMnemonic = isInt<34>(Offset);
- if (!noImmForm && ((OffsetFitsMnemonic &&
- ((Offset % offsetMinAlign(MI)) == 0)) ||
- OpC == TargetOpcode::STACKMAP ||
- OpC == TargetOpcode::PATCHPOINT)) {
+ if (!noImmForm &&
+ ((OffsetFitsMnemonic && ((Offset % offsetMinAlign(MI)) == 0)) ||
+ OpC == TargetOpcode::STACKMAP || OpC == TargetOpcode::PATCHPOINT ||
+ OpC == PPC::STMW || OpC == PPC::LMW)) {
MI.getOperand(OffsetOperandNo).ChangeToImmediate(Offset);
return false;
}
diff --git a/llvm/test/CodeGen/PowerPC/aix-stm-lm-merge.ll b/llvm/test/CodeGen/PowerPC/aix-stm-lm-merge.ll
new file mode 100644
index 00000000000000..9a5d9466ae4596
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-stm-lm-merge.ll
@@ -0,0 +1,16 @@
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mattr=-altivec \
+; RUN: -mcpu=pwr4 --ppc-enable-load-store-multiple < %s | FileCheck %s
+
+target triple = "powerpc-ibm-aix7.2.0.0"
+
+define dso_local void @test_simple() #0 {
+entry:
+ call void asm sideeffect "nop", "~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"()
+ ret void
+}
+
+; CHECK: stmw 16, -64(1) # 4-byte Folded Spill
+; CHECK-NEXT: #APP
+; CHECK-NEXT: nop
+; CHECK-NEXT: #NO_APP
+; CHECK-NEXT: lmw 16, -64(1) # 4-byte Folded Reload
>From 89e70853cfd924f6ca1728b73f29b37f19a219b7 Mon Sep 17 00:00:00 2001
From: esmeyi <esme.yi at ibm.com>
Date: Wed, 27 Dec 2023 22:03:39 -0500
Subject: [PATCH 2/2] Spec and bootstrap are clean.
---
llvm/lib/Target/PowerPC/PPCFrameLowering.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index daedcb643f84b6..7ff6272e0b8450 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -2419,8 +2419,8 @@ static void findContinuousLoadStore(const MachineFunction *MF,
continue;
// Check memory operand type.
- if (MFI.getObjectSize(CSI[I].getFrameIdx()) != 4)
- continue;
+ assert(MFI.getObjectSize(CSI[I].getFrameIdx()) == 4 &&
+ "memory operand type is incorrect.");
// Record the first reg that STMW/LMW are going to merge since STMW/LMW save
// from rN to r31, where rN >= r13.
More information about the llvm-commits
mailing list