[llvm] 8efc2f5 - [PowerPC][AIX] Spill/restore the callee-saved condition register bits.
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 24 08:26:01 PST 2020
Author: Sean Fertile
Date: 2020-02-24T11:24:46-05:00
New Revision: 8efc2f5723b0892d0518bdac441c674b7d850ac6
URL: https://github.com/llvm/llvm-project/commit/8efc2f5723b0892d0518bdac441c674b7d850ac6
DIFF: https://github.com/llvm/llvm-project/commit/8efc2f5723b0892d0518bdac441c674b7d850ac6.diff
LOG: [PowerPC][AIX] Spill/restore the callee-saved condition register bits.
Extends the existing support for spilling and restoring the condition
register to the linkage area for 32-bit targets, and enables for AIX.
Differential Revision: https://reviews.llvm.org/D74349
Added:
llvm/test/CodeGen/PowerPC/aix-crspill.ll
llvm/test/CodeGen/PowerPC/aix32-crsave.mir
llvm/test/CodeGen/PowerPC/alloca-crspill.ll
Modified:
llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
llvm/lib/Target/PowerPC/PPCFrameLowering.h
llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
Removed:
llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
################################################################################
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
index de79752541dd..02503faaafad 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp
@@ -79,9 +79,8 @@ static unsigned computeBasePointerSaveOffset(const PPCSubtarget &STI) {
: STI.getTargetMachine().isPositionIndependent() ? -12U : -8U;
}
-static unsigned computeCRSaveOffset() {
- // The condition register save offset needs to be updated for AIX PPC32.
- return 8;
+static unsigned computeCRSaveOffset(const PPCSubtarget &STI) {
+ return (STI.isAIXABI() && !STI.isPPC64()) ? 4 : 8;
}
PPCFrameLowering::PPCFrameLowering(const PPCSubtarget &STI)
@@ -92,7 +91,7 @@ PPCFrameLowering::PPCFrameLowering(const PPCSubtarget &STI)
FramePointerSaveOffset(computeFramePointerSaveOffset(Subtarget)),
LinkageSize(computeLinkageSize(Subtarget)),
BasePointerSaveOffset(computeBasePointerSaveOffset(Subtarget)),
- CRSaveOffset(computeCRSaveOffset()) {}
+ CRSaveOffset(computeCRSaveOffset(Subtarget)) {}
// With the SVR4 ABI, callee-saved registers have fixed offsets on the stack.
const PPCFrameLowering::SpillSlot *PPCFrameLowering::getCalleeSavedSpillSlots(
@@ -741,7 +740,8 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
MachineModuleInfo &MMI = MF.getMMI();
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
DebugLoc dl;
- bool needsCFI = MF.needsFrameMoves();
+ // AIX assembler does not support cfi directives.
+ const bool needsCFI = MF.needsFrameMoves() && !Subtarget.isAIXABI();
// Get processor type.
bool isPPC64 = Subtarget.isPPC64();
@@ -812,6 +812,9 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
: PPC::SUBFC);
const MCInstrDesc& SubtractImmCarryingInst = TII.get(isPPC64 ? PPC::SUBFIC8
: PPC::SUBFIC);
+ const MCInstrDesc &MoveFromCondRegInst = TII.get(isPPC64 ? PPC::MFCR8
+ : PPC::MFCR);
+ const MCInstrDesc &StoreWordInst = TII.get(isPPC64 ? PPC::STW8 : PPC::STW);
// Regarding this assert: Even though LR is saved in the caller's frame (i.e.,
// LROffset is positive), that slot is callee-owned. Because PPC32 SVR4 has no
@@ -873,12 +876,6 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
// indexed into with a simple STDU/STWU/STD/STW immediate offset operand.
bool isLargeFrame = !isInt<16>(NegFrameSize);
- assert((isPPC64 || !MustSaveCR) &&
- "Prologue CR saving supported only in 64-bit mode");
-
- if (MustSaveCR && isAIXABI)
- report_fatal_error("Prologue CR saving is unimplemented on AIX.");
-
// Check if we can move the stack update instruction (stdu) down the prologue
// past the callee saves. Hopefully this will avoid the situation where the
// saves are waiting for the update on the store with update to complete.
@@ -918,49 +915,42 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
}
}
- // If we need to spill the CR and the LR but we don't have two separate
- // registers available, we must spill them one at a time
- if (MustSaveCR && SingleScratchReg && MustSaveLR) {
+ // Where in the prologue we move the CR fields depends on how many scratch
+ // registers we have, and if we need to save the link register or not. This
+ // lambda is to avoid duplicating the logic in 2 places.
+ auto BuildMoveFromCR = [&]() {
+ if (isELFv2ABI && MustSaveCRs.size() == 1) {
// In the ELFv2 ABI, we are not required to save all CR fields.
- // If only one or two CR fields are clobbered, it is more efficient to use
- // mfocrf to selectively save just those fields, because mfocrf has short
+ // If only one CR field is clobbered, it is more efficient to use
+ // mfocrf to selectively save just that field, because mfocrf has short
// latency compares to mfcr.
- unsigned MfcrOpcode = PPC::MFCR8;
- unsigned CrState = RegState::ImplicitKill;
- if (isELFv2ABI && MustSaveCRs.size() == 1) {
- MfcrOpcode = PPC::MFOCRF8;
- CrState = RegState::Kill;
+ assert(isPPC64 && "V2 ABI is 64-bit only.");
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, dl, TII.get(PPC::MFOCRF8), TempReg);
+ MIB.addReg(MustSaveCRs[0], RegState::Kill);
+ } else {
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, dl, MoveFromCondRegInst, TempReg);
+ for (unsigned CRfield : MustSaveCRs)
+ MIB.addReg(CRfield, RegState::ImplicitKill);
}
- MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg);
- for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
- MIB.addReg(MustSaveCRs[i], CrState);
- BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8))
- .addReg(TempReg, getKillRegState(true))
- .addImm(getCRSaveOffset())
- .addReg(SPReg);
+ };
+
+ // If we need to spill the CR and the LR but we don't have two separate
+ // registers available, we must spill them one at a time
+ if (MustSaveCR && SingleScratchReg && MustSaveLR) {
+ BuildMoveFromCR();
+ BuildMI(MBB, MBBI, dl, StoreWordInst)
+ .addReg(TempReg, getKillRegState(true))
+ .addImm(CRSaveOffset)
+ .addReg(SPReg);
}
if (MustSaveLR)
BuildMI(MBB, MBBI, dl, MFLRInst, ScratchReg);
- if (MustSaveCR &&
- !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64
- // In the ELFv2 ABI, we are not required to save all CR fields.
- // If only one or two CR fields are clobbered, it is more efficient to use
- // mfocrf to selectively save just those fields, because mfocrf has short
- // latency compares to mfcr.
- unsigned MfcrOpcode = PPC::MFCR8;
- unsigned CrState = RegState::ImplicitKill;
- if (isELFv2ABI && MustSaveCRs.size() == 1) {
- MfcrOpcode = PPC::MFOCRF8;
- CrState = RegState::Kill;
- }
- MachineInstrBuilder MIB =
- BuildMI(MBB, MBBI, dl, TII.get(MfcrOpcode), TempReg);
- for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
- MIB.addReg(MustSaveCRs[i], CrState);
- }
+ if (MustSaveCR && !(SingleScratchReg && MustSaveLR))
+ BuildMoveFromCR();
if (HasRedZone) {
if (HasFP)
@@ -987,11 +977,11 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
.addReg(SPReg);
if (MustSaveCR &&
- !(SingleScratchReg && MustSaveLR)) { // will only occur for PPC64
+ !(SingleScratchReg && MustSaveLR)) {
assert(HasRedZone && "A red zone is always available on PPC64");
- BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8))
+ BuildMI(MBB, MBBI, dl, StoreWordInst)
.addReg(TempReg, getKillRegState(true))
- .addImm(getCRSaveOffset())
+ .addImm(CRSaveOffset)
.addReg(SPReg);
}
@@ -1295,7 +1285,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF,
// actually saved gets its own CFI record.
unsigned CRReg = isELFv2ABI? Reg : (unsigned) PPC::CR2;
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
- nullptr, MRI->getDwarfRegNum(CRReg, true), getCRSaveOffset()));
+ nullptr, MRI->getDwarfRegNum(CRReg, true), CRSaveOffset));
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
continue;
@@ -1376,7 +1366,10 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
: PPC::ADDI );
const MCInstrDesc& AddInst = TII.get( isPPC64 ? PPC::ADD8
: PPC::ADD4 );
-
+ const MCInstrDesc& LoadWordInst = TII.get( isPPC64 ? PPC::LWZ8
+ : PPC::LWZ);
+ const MCInstrDesc& MoveToCRInst = TII.get( isPPC64 ? PPC::MTOCRF8
+ : PPC::MTOCRF);
int LROffset = getReturnSaveOffset();
int FPOffset = 0;
@@ -1551,20 +1544,17 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
// value (although not the base register). Make sure it is not overwritten
// too early.
- assert((isPPC64 || !MustSaveCR) &&
- "Epilogue CR restoring supported only in 64-bit mode");
-
// If we need to restore both the LR and the CR and we only have one
// available scratch register, we must do them one at a time.
if (MustSaveCR && SingleScratchReg && MustSaveLR) {
// Here TempReg == ScratchReg, and in the absence of red zone ScratchReg
// is live here.
assert(HasRedZone && "Expecting red zone");
- BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ8), TempReg)
- .addImm(getCRSaveOffset())
+ BuildMI(MBB, MBBI, dl, LoadWordInst, TempReg)
+ .addImm(CRSaveOffset)
.addReg(SPReg);
for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
- BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i])
+ BuildMI(MBB, MBBI, dl, MoveToCRInst, MustSaveCRs[i])
.addReg(TempReg, getKillRegState(i == e-1));
}
@@ -1581,11 +1571,9 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
}
if (MustSaveCR && !(SingleScratchReg && MustSaveLR)) {
- // This will only occur for PPC64.
- assert(isPPC64 && "Expecting 64-bit mode");
assert(RBReg == SPReg && "Should be using SP as a base register");
- BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ8), TempReg)
- .addImm(getCRSaveOffset())
+ BuildMI(MBB, MBBI, dl, LoadWordInst, TempReg)
+ .addImm(CRSaveOffset)
.addReg(RBReg);
}
@@ -1640,9 +1628,9 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
}
if (MustSaveCR &&
- !(SingleScratchReg && MustSaveLR)) // will only occur for PPC64
+ !(SingleScratchReg && MustSaveLR))
for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i)
- BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i])
+ BuildMI(MBB, MBBI, dl, MoveToCRInst, MustSaveCRs[i])
.addReg(TempReg, getKillRegState(i == e-1));
if (MustSaveLR)
@@ -1780,17 +1768,17 @@ void PPCFrameLowering::determineCalleeSaves(MachineFunction &MF,
MFI.CreateFixedObject(-1 * TCSPDelta, TCSPDelta, true);
}
- // For 32-bit SVR4, allocate the nonvolatile CR spill slot iff the
- // function uses CR 2, 3, or 4. For 64-bit SVR4 we create a FixedStack
+ // Allocate the nonvolatile CR spill slot iff the function uses CR 2, 3, or 4.
+ // For 64-bit SVR4, and all flavors of AIX we create a FixedStack
// object at the offset of the CR-save slot in the linkage area. The actual
// save and restore of the condition register will be created as part of the
// prologue and epilogue insertion, but the FixedStack object is needed to
// keep the CalleSavedInfo valid.
- if (Subtarget.isSVR4ABI() &&
- (SavedRegs.test(PPC::CR2) || SavedRegs.test(PPC::CR3) ||
+ if ((SavedRegs.test(PPC::CR2) || SavedRegs.test(PPC::CR3) ||
SavedRegs.test(PPC::CR4))) {
const uint64_t SpillSize = 4; // Condition register is always 4 bytes.
- const int64_t SpillOffset = Subtarget.isPPC64() ? 8 : -4;
+ const int64_t SpillOffset =
+ Subtarget.isPPC64() ? 8 : Subtarget.isAIXABI() ? 4 : -4;
int FrameIdx =
MFI.CreateFixedObject(SpillSize, SpillOffset,
/* IsImmutable */ true, /* IsAliased */ false);
@@ -2141,11 +2129,6 @@ bool PPCFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
- // Currently, this function only handles SVR4 32- and 64-bit ABIs.
- // Return false otherwise to maintain pre-existing behavior.
- if (!Subtarget.isSVR4ABI())
- return false;
-
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII = *Subtarget.getInstrInfo();
PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
@@ -2185,7 +2168,7 @@ bool PPCFrameLowering::spillCalleeSavedRegisters(
// Insert the spill to the stack frame.
if (IsCRField) {
PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
- if (Subtarget.isPPC64()) {
+ if (!Subtarget.is32BitELFABI()) {
// The actual spill will happen at the start of the prologue.
FuncInfo->addMustSaveCR(Reg);
} else {
@@ -2305,12 +2288,6 @@ PPCFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
-
- // Currently, this function only handles SVR4 32- and 64-bit ABIs.
- // Return false otherwise to maintain pre-existing behavior.
- if (!Subtarget.isSVR4ABI())
- return false;
-
MachineFunction *MF = MBB.getParent();
const PPCInstrInfo &TII = *Subtarget.getInstrInfo();
PPCFunctionInfo *FI = MF->getInfo<PPCFunctionInfo>();
@@ -2356,7 +2333,7 @@ PPCFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
CR4Spilled = true;
continue;
} else {
- // When we first encounter a non-CR register after seeing at
+ // On 32-bit ELF when we first encounter a non-CR register after seeing at
// least one CR register, restore all spilled CRs together.
if (CR2Spilled || CR3Spilled || CR4Spilled) {
bool is31 = needsFP(*MF);
diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.h b/llvm/lib/Target/PowerPC/PPCFrameLowering.h
index ecddcedf58b3..573f3256edbc 100644
--- a/llvm/lib/Target/PowerPC/PPCFrameLowering.h
+++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.h
@@ -153,10 +153,6 @@ class PPCFrameLowering: public TargetFrameLowering {
/// base pointer.
unsigned getBasePointerSaveOffset() const;
- /// getCRSaveOffset - Return the previous frame offset to save the
- /// CR register.
- unsigned getCRSaveOffset() const { return CRSaveOffset; }
-
/// getLinkageSize - Return the size of the PowerPC ABI linkage area.
///
unsigned getLinkageSize() const { return LinkageSize; }
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index f0c070c89d0f..caa9d7b6b869 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -926,14 +926,15 @@ void PPCRegisterInfo::lowerVRSAVERestore(MachineBasicBlock::iterator II,
bool PPCRegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
unsigned Reg, int &FrameIdx) const {
- const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
- // For the nonvolatile condition registers (CR2, CR3, CR4) in an SVR4
- // ABI, return true to prevent allocating an additional frame slot.
- // For 64-bit, the CR save area is in the linkage area at SP+8; but we have
- // created a FrameIndex to that spill slot to keep the CalleSaveInfos valid.
- // For 32-bit, we have previously created the stack slot if needed, so return
- // its FrameIdx.
- if (Subtarget.isSVR4ABI() && PPC::CR2 <= Reg && Reg <= PPC::CR4) {
+ // For the nonvolatile condition registers (CR2, CR3, CR4) return true to
+ // prevent allocating an additional frame slot.
+ // For 64-bit ELF and AIX, the CR save area is in the linkage area at SP+8,
+ // for 32-bit AIX the CR save area is in the linkage area at SP+4.
+ // We have created a FrameIndex to that spill slot to keep the CalleSaveInfos
+ // valid.
+ // For 32-bit ELF, we have previously created the stack slot if needed, so
+ // return its FrameIdx.
+ if (PPC::CR2 <= Reg && Reg <= PPC::CR4) {
FrameIdx = MF.getInfo<PPCFunctionInfo>()->getCRSpillFrameIndex();
return true;
}
diff --git a/llvm/test/CodeGen/PowerPC/aix-crspill.ll b/llvm/test/CodeGen/PowerPC/aix-crspill.ll
new file mode 100644
index 000000000000..af41620e7507
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-crspill.ll
@@ -0,0 +1,81 @@
+; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -mcpu=pwr4 --mattr=-altivec \
+; RUN: --verify-machineinstrs < %s | FileCheck --check-prefix=64BIT %s
+
+; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -mcpu=pwr4 --mattr=-altivec \
+; RUN: --verify-machineinstrs < %s | FileCheck --check-prefix=32BIT %s
+
+define dso_local signext i32 @killOne(i32 signext %i) {
+entry:
+ tail call void asm sideeffect "# Clobber CR", "~{cr4}"()
+ %call = call signext i32 @do_something(i32 %i)
+ ret i32 %call
+}
+
+define dso_local signext i32 @killAll(i32 signext %i) {
+entry:
+ tail call void asm sideeffect "# Clobber CR", "~{cr0},~{cr1},~{cr2},~{cr3},~{cr4},~{cr5},~{cr6},~{cr7}" ()
+ %call = call signext i32 @do_something(i32 %i)
+ ret i32 %call
+}
+
+declare signext i32 @do_something(i32 signext)
+
+; 64BIT-LABEL: .killOne:
+
+; 64BIT: mflr 0
+; 64BIT-NEXT: std 0, 16(1)
+; 64BIT-NEXT: mfcr 12
+; 64BIT-NEXT: stw 12, 8(1)
+; 64BIT: stdu 1, -112(1)
+
+; 64BIT: # Clobber CR
+; 64BIT: bl .do_something
+
+; 64BIT: addi 1, 1, 112
+; 64BIT-NEXT: ld 0, 16(1)
+; 64BIT-NEXT: lwz 12, 8(1)
+; 64BIT-NEXT: mtlr 0
+; 64BIT-NEXT: mtocrf 8, 12
+; 64BIT: blr
+
+; 32BIT-LABEL: .killOne:
+
+; 32BIT: mflr 0
+; 32BIT-NEXT: stw 0, 8(1)
+; 32BIT-NEXT: mfcr 12
+; 32BIT-NEXT: stw 12, 4(1)
+; 32BIT: stwu 1, -64(1)
+
+; 32BIT: # Clobber CR
+; 32BIT: bl .do_something
+
+; 32BIT: addi 1, 1, 64
+; 32BIT-NEXT: lwz 0, 8(1)
+; 32BIT-NEXT: lwz 12, 4(1)
+; 32BIT-NEXT: mtlr 0
+; 32BIT-NEXT: mtocrf 8, 12
+; 32BIT: blr
+
+
+; 64BIT-LABEL: .killAll:
+
+; 64BIT: addi 1, 1, 112
+; 64BIT-NEXT: ld 0, 16(1)
+; 64BIT-NEXT: lwz 12, 8(1)
+; 64BIT-NEXT: mtlr 0
+; 64BIT-NEXT: mtocrf 32, 12
+; 64BIT-NEXT: mtocrf 16, 12
+; 64BIT-NEXT: mtocrf 8, 12
+; 64BIT-NEXT: blr
+
+
+; 32BIT-LABEL: .killAll:
+
+; 32BIT: addi 1, 1, 64
+; 32BIT-NEXT: lwz 0, 8(1)
+; 32BIT-NEXT: lwz 12, 4(1)
+; 32BIT-NEXT: mtlr 0
+; 32BIT-NEXT: mtocrf 32, 12
+; 32BIT-NEXT: mtocrf 16, 12
+; 32BIT-NEXT: mtocrf 8, 12
+; 32BIT-NEXT: blr
diff --git a/llvm/test/CodeGen/PowerPC/aix32-crsave.mir b/llvm/test/CodeGen/PowerPC/aix32-crsave.mir
new file mode 100644
index 000000000000..5a82bff33e97
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix32-crsave.mir
@@ -0,0 +1,66 @@
+# RUN: llc -mtriple powerpc-unknown-aix-xcoff -x mir -mcpu=pwr4 \
+# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
+# RUN: FileCheck %s --check-prefixes=CHECK
+
+---
+name: CRMultiSave
+alignment: 16
+tracksRegLiveness: true
+liveins:
+ - { reg: '$r3', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $r3
+ renamable $r29 = ANDI_rec killed renamable $r3, 1, implicit-def dead $cr0, implicit-def $cr0gt
+ renamable $cr2lt = COPY $cr0gt
+ renamable $cr4lt = COPY $cr0gt
+ renamable $r3 = COPY $r29
+ BLR implicit $lr, implicit $rm, implicit $r3
+
+ ; CHECK-LABEL: fixedStack:
+ ; CHECK: - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+ ; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr4',
+ ; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+ ; CHECK-NEXT: debug-info-location: '' }
+ ; CHECK-LABEL: stack:
+
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: liveins: $r3, $r29, $cr2, $cr4
+
+ ; CHECK: $r12 = MFCR implicit killed $cr2, implicit killed $cr4
+ ; CHECK-NEXT: STW killed $r12, 4, $r1
+
+ ; CHECK: $r12 = LWZ 4, $r1
+ ; CHECK-NEXT: $cr2 = MTOCRF $r12
+ ; CHECK-NEXT: $cr4 = MTOCRF killed $r12
+
+...
+---
+name: CR3Save
+alignment: 16
+tracksRegLiveness: true
+liveins:
+ - { reg: '$r3', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $r3
+ renamable $r14 = ANDI_rec killed renamable $r3, 1, implicit-def dead $cr0, implicit-def $cr0gt
+ renamable $cr3lt = COPY $cr0gt
+ renamable $r3 = COPY $r14
+ BLR implicit $lr, implicit $rm, implicit $r3
+
+ ; CHECK-LABEL: fixedStack:
+ ; CHECK: - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+ ; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr3',
+ ; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+ ; CHECK-NEXT: debug-info-location: '' }
+ ; CHECK-LABEL: stack:
+
+ ; CHECK: bb.0.entry:
+ ; CHECK-NEXT: liveins: $r3, $r14, $cr3
+
+ ; CHECK: $r12 = MFCR implicit killed $cr3
+ ; CHECK-NEXT: STW killed $r12, 4, $r1
+
+ ; CHECK: $r12 = LWZ 4, $r1
+ ; CHECK-NEXT: $cr3 = MTOCRF killed $r12
diff --git a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
new file mode 100644
index 000000000000..f52e305fb05c
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll
@@ -0,0 +1,136 @@
+; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu --verify-machineinstrs \
+; RUN: -stop-after=prologepilog < %s | FileCheck \
+; RUN: --check-prefixes=CHECK,CHECK64,ELFV2 %s
+
+; RUN: llc -mtriple=powerpc64-unknown-aix-xcoff -mcpu=pwr4 \
+; RUN: --verify-machineinstrs --mattr=-altivec -stop-after=prologepilog < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,CHECK64,V1ANDAIX %s
+
+; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 --verify-machineinstrs \
+; RUN: -stop-after=prologepilog < %s | FileCheck \
+; RUN: --check-prefixes=CHECK,CHECK64,V1ANDAIX %s
+
+; RUN: llc -mtriple=powerpc-unknown-aix-xcoff -mcpu=pwr4 \
+; RUN: --verify-machineinstrs --mattr=-altivec -stop-after=prologepilog < %s | \
+; RUN: FileCheck --check-prefixes=CHECK,CHECK32 %s
+
+define dso_local signext i32 @test(i32 signext %n) {
+entry:
+ %conv = sext i32 %n to i64
+ %0 = alloca double, i64 %conv, align 16
+ tail call void asm sideeffect "", "~{cr2}"()
+ %call = call signext i32 @do_something(double* nonnull %0)
+ ret i32 %call
+}
+
+declare signext i32 @do_something(double*)
+
+; CHECK: name: test
+; CHECK: alignment: 16
+; CHECK: liveins:
+; CHECK64: - { reg: '$x3', virtual-reg: '' }
+; CHECK32: - { reg: '$r3', virtual-reg: '' }
+
+; ELFV2: stackSize: 48
+; V1ANDAIX: stackSize: 128
+; CHECK32: stackSize: 80
+
+; ELFV2: maxCallFrameSize: 32
+; V1ANDAIX: maxCallFrameSize: 112
+; CHECK32: maxCallFrameSize: 64
+
+; CHECK64: fixedStack:
+; CHECK64-NEXT: - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+; CHECK64-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
+; CHECK64-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+; CHECK64-NEXT: debug-info-location: '' }
+; CHECK64-NEXT: - { id: 1, type: default, offset: -8, size: 8, alignment: 8, stack-id: default,
+; CHECK64-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+; CHECK64-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+; CHECK64-NEXT: stack:
+; CHECK64-NEXT: - { id: 0, name: '<unnamed alloca>', type: variable-sized, offset: -8,
+; CHECK64-NEXT: alignment: 1, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK64-NEXT: local-offset: 0, debug-info-variable: '', debug-info-expression: '',
+; CHECK64-NEXT: debug-info-location: '' }
+; CHECK64-NEXT: - { id: 1, name: '', type: default, offset: -16, size: 8, alignment: 8,
+; CHECK64-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK64-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+
+; CHECK32: fixedStack:
+; CHECK32-NEXT: - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default,
+; CHECK32-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
+; CHECK32-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+; CHECK32-NEXT: debug-info-location: '' }
+; CHECK32-NEXT: - { id: 1, type: default, offset: -4, size: 4, alignment: 4, stack-id: default,
+; CHECK32-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
+; CHECK32-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+; CHECK32-NEXT: stack:
+; CHECK32-NEXT: - { id: 0, name: '<unnamed alloca>', type: variable-sized, offset: -4,
+; CHECK32-NEXT: alignment: 1, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK32-NEXT: local-offset: 0, debug-info-variable: '', debug-info-expression: '',
+; CHECK32-NEXT: debug-info-location: '' }
+; CHECK32-NEXT: - { id: 1, name: '', type: default, offset: -8, size: 4, alignment: 4,
+; CHECK32-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true,
+; CHECK32-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+
+
+; CHECK64: bb.0.entry:
+; CHECK64-NEXT: liveins: $x3, $cr2
+
+; Prologue:
+; CHECK64: $x0 = MFLR8 implicit $lr8
+; ELFV2-NEXT: $x12 = MFOCRF8 killed $cr2
+; V1ANDAIX-NEXT: $x12 = MFCR8 implicit killed $cr2
+; CHECK64-DAG: STD $x31, -8, $x1
+; CHECK64-DAG: STD killed $x0, 16, $x1
+; CHECK64-DAG: STW8 killed $x12, 8, $x1
+
+; ELFV2-NEXT: $x1 = STDU $x1, -48, $x1
+; V1ANDAIX-NEXT: x1 = STDU $x1, -128, $x1
+
+; CHECK64: $x31 = OR8 $x1, $x1
+
+; ELFV2: $[[ORIGSP:x[0-9]+]] = ADDI8 $x31, 48
+; V1ANDAIX: $[[ORIGSP:x[0-9]+]] = ADDI8 $x31, 128
+; CHECK64: $x1 = STDUX killed $[[ORIGSP]], $x1, killed $x{{[0-9]}}
+; CHECK64: INLINEASM {{.*}} early-clobber $cr2
+; CHECK64: BL8_NOP
+
+
+; Epilogue:
+; CHECK64: $x1 = LD 0, $x1
+; CHECK64-DAG: $x0 = LD 16, $x1
+; CHECK64-DAG: $x12 = LWZ8 8, $x1
+; CHECK64-DAG: $x31 = LD -8, $x1
+; CHECK64: $cr2 = MTOCRF8 killed $x12
+; CHECK64-NEXT: MTLR8 $x0, implicit-def $lr8
+; CHECK64-NEXT: BLR8 implicit $lr8, implicit $rm, implicit $x3
+
+; CHECK32: bb.0.entry:
+; CHECK32-NEXT: liveins: $r3, $cr2
+
+; Prologue:
+; CHECK32: $r0 = MFLR implicit $lr
+; CHECK32-NEXT: $r12 = MFCR implicit killed $cr2
+; CHECK32-DAG: STW $r31, -4, $r1
+; CHECK32-DAG: STW killed $r0, 8, $r1
+; CHECK32-DAG: STW killed $r12, 4, $r1
+; CHECK32: $r1 = STWU $r1, -80, $r1
+
+; CHECK32: $r31 = OR $r1, $r1
+; CHECK32: $[[ORIGSP:r[0-9]+]] = ADDI $r31, 80
+; CHECK32: $r1 = STWUX killed $[[ORIGSP]], $r1, killed $r{{[0-9]}}
+; CHECK32: INLINEASM {{.*}} early-clobber $cr2
+; CHECK32: BL_NOP
+
+; Epilogue:
+; CHECK32: $r1 = LWZ 0, $r1
+; CHECK32-DAG: $r0 = LWZ 8, $r1
+; CHECK32-DAG: $r12 = LWZ 4, $r1
+; CHECK32-DAG: $r31 = LWZ -4, $r1
+; CHECK32: $cr2 = MTOCRF killed $r12
+; CHECK32-NEXT: MTLR $r0, implicit-def $lr
+; CHECK32-NEXT: BLR implicit $lr, implicit $rm, implicit $r3
diff --git a/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
deleted file mode 100644
index e2df5b4c0cda..000000000000
--- a/llvm/test/CodeGen/PowerPC/ppc64-alloca-crspill.ll
+++ /dev/null
@@ -1,66 +0,0 @@
-; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu --verify-machineinstrs \
-; RUN: -stop-after=prologepilog < %s | FileCheck %s
-
-define dso_local signext i32 @test(i32 signext %n) {
-entry:
- %conv = sext i32 %n to i64
- %0 = alloca double, i64 %conv, align 16
- tail call void asm sideeffect "", "~{cr2}"()
- %call = call signext i32 @do_something(double* nonnull %0)
- ret i32 %call
-}
-
-declare signext i32 @do_something(double*)
-
-; CHECK: name: test
-; CHECK: alignment: 16
-; CHECK: liveins:
-; CHECK: - { reg: '$x3', virtual-reg: '' }
-; CHECK: stackSize: 48
-; CHECK: maxCallFrameSize: 32
-
-; CHECK: fixedStack:
-; CHECK-NEXT: - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
-; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
-; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
-; CHECK-NEXT: debug-info-location: '' }
-; CHECK-NEXT: - { id: 1, type: default, offset: -8, size: 8, alignment: 8, stack-id: default,
-; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
-; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
-
-; CHECK-NEXT: stack:
-; CHECK-NEXT: - { id: 0, name: '<unnamed alloca>', type: variable-sized, offset: -8,
-; CHECK-NEXT: alignment: 1, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
-; CHECK-NEXT: local-offset: 0, debug-info-variable: '', debug-info-expression: '',
-; CHECK-NEXT: debug-info-location: '' }
-; CHECK-NEXT: - { id: 1, name: '', type: default, offset: -16, size: 8, alignment: 8,
-; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true,
-; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
-
-; CHECK: bb.0.entry:
-; CHECK-NEXT: liveins: $x3, $cr2
-
-; Prologue:
-; CHECK: $x0 = MFLR8 implicit $lr8
-; CHECK-NEXT: $x12 = MFOCRF8 killed $cr2
-; CHECK-DAG: STD $x31, -8, $x1
-; CHECK-DAG: STD killed $x0, 16, $x1
-; CHECK-DAG: STW8 killed $x12, 8, $x1
-; CHECK-NEXT: $x1 = STDU $x1, -48, $x1
-; CHECK: $x31 = OR8 $x1, $x1
-
-; CHECK: $[[ORIGSP:x[0-9]+]] = ADDI8 $x31, 48
-; CHECK: $x1 = STDUX killed $[[ORIGSP]], $x1, killed $x{{[0-9]}}
-; CHECK: INLINEASM {{.*}} early-clobber $cr2
-; CHECK: BL8_NOP @do_something
-
-
-; Epilogue:
-; CHECK: $x1 = LD 0, $x1
-; CHECK-DAG: $x0 = LD 16, $x1
-; CHECK-DAG: $x12 = LWZ8 8, $x1
-; CHECK-DAG: $x31 = LD -8, $x1
-; CHECK: $cr2 = MTOCRF8 killed $x12
-; CHECK-NEXT: MTLR8 $x0, implicit-def $lr8
-; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit $x3
-
diff --git a/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir b/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
index 6ddaca01eb59..b6a8748c8e3e 100644
--- a/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
+++ b/llvm/test/CodeGen/PowerPC/ppc64-crsave.mir
@@ -1,10 +1,18 @@
# RUN: llc -mtriple powerpc64le-unknown-linux-gnu -x mir -mcpu=pwr8 \
# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
-# RUN: FileCheck %s --check-prefixes=CHECK,PWR8
+# RUN: FileCheck %s --check-prefixes=CHECK,SAVEONE,ELF
# RUN: llc -mtriple powerpc64-unknown-linux-gnu -x mir -mcpu=pwr7 \
# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
-# RUN: FileCheck %s --check-prefixes=CHECK,PWR7
+# RUN: FileCheck %s --check-prefixes=CHECK,SAVEALL,ELF
+
+
+# RUN: llc -mtriple powerpc64-unknown-aix-xcoff -x mir -mcpu=pwr4 \
+# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
+# RUN: FileCheck %s --check-prefixes=CHECK,SAVEALL
+
+# TODO FIXME: We only check the save and restores of the callee saved gpr for
+# ELF becuase AIX callee saved registers haven't been properly implemented yet.
---
name: CRAllSave
@@ -21,19 +29,26 @@ body: |
renamable $x3 = COPY $x29
BLR8 implicit $lr8, implicit $rm, implicit $x3
+ ; CHECK-LABEL: fixedStack:
+ ; ELF: - { id: 1, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+ ; AIX: - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+ ; CHECK: isImmutable: true, isAliased: false, callee-saved-register: '$cr4',
+ ; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+ ; CHECK-NEXT: debug-info-location: '' }
+ ; CHECK-LABEL: stack:
+
; Verify the proper live-ins have been added in the prologue.
; CHECK: liveins: $x3, $x29, $cr2, $cr4
; CHECK: $x12 = MFCR8 implicit killed $cr2, implicit killed $cr4
- ; CHECK-DAG: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.0)
+ ; ELF-DAG: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.0)
; CHECK-DAG: STW8 killed $x12, 8, $x1
- ; CHECK: $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.0)
+ ; ELF: $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.0)
; CHECK: $x12 = LWZ8 8, $x1
; CHECK: $cr2 = MTOCRF8 $x12
; CHECK: $cr4 = MTOCRF8 killed $x12
-
...
---
name: CR2Save
@@ -49,17 +64,28 @@ body: |
renamable $x3 = COPY $x14
BLR8 implicit $lr8, implicit $rm, implicit $x3
- ; CHECK: CR2Save
+ ; CHECK-LABEL: CR2Save
+
+ ; CHECK-LABEL: fixedStack:
+ ; ELF: - { id: 1, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+ ; AIX: - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
+ ; CHECK: isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
+ ; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
+ ; CHECK-NEXT: debug-info-location: '' }
+ ; CHECK-LABEL: stack:
+
; Verify the proper live-ins have been added in the prologue.
; CHECK: liveins: $x3, $x14, $cr2
- ; PWR8: $x12 = MFOCRF8 killed $cr2
- ; PWR7: $x12 = MFCR8 implicit killed $cr2
+ ; ELF V2 ABI allows saving only the clobbered cr fields,
+ ; whereas the other ABIs do not.
+ ; SAVEONE: $x12 = MFOCRF8 killed $cr2
+ ; SAVEALL: $x12 = MFCR8 implicit killed $cr2
- ; CHECK-DAG: STD killed $x14, -144, $x1 :: (store 8 into %fixed-stack.0, align 16)
+ ; ELF-DAG: STD killed $x14, -144, $x1 :: (store 8 into %fixed-stack.0, align 16)
; CHECK-DAG: STW8 killed $x12, 8, $x1
- ; CHECK: $x14 = LD -144, $x1 :: (load 8 from %fixed-stack.0, align 16)
+ ; ELF: $x14 = LD -144, $x1 :: (load 8 from %fixed-stack.0, align 16)
; CHECK: $x12 = LWZ8 8, $x1
; CHECK: $cr2 = MTOCRF8 killed $x12
More information about the llvm-commits
mailing list