Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion llvm/include/llvm/CodeGen/MachineFrameInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,12 @@ class MachineFrameInfo {
StackID == TargetStackID::ScalablePredicateVector;
}

bool isScalableStackID(int ObjectIdx) const {
bool hasScalableStackID(int ObjectIdx) const {
uint8_t StackID = getStackID(ObjectIdx);
return isScalableStackID(StackID);
}

bool isScalableStackID(uint8_t StackID) const {
return StackID == TargetStackID::ScalableVector ||
StackID == TargetStackID::ScalablePredicateVector;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/StackFrameLayoutAnalysisPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ struct StackFrameLayoutAnalysis {
: Slot(Idx), Size(MFI.getObjectSize(Idx)),
Align(MFI.getObjectAlign(Idx).value()), Offset(Offset),
SlotTy(Invalid), Scalable(false) {
Scalable = MFI.isScalableStackID(Idx);
Scalable = MFI.hasScalableStackID(Idx);
if (MFI.isSpillSlotObjectIndex(Idx))
SlotTy = SlotType::Spill;
else if (MFI.isFixedObjectIndex(Idx))
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1610,7 +1610,8 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
int BaseOffset = -AFI->getTaggedBasePointerOffset();
Register FrameReg;
StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
MF, BaseOffset, false /*isFixed*/, false /*isSVE*/, FrameReg,
MF, BaseOffset, false /*isFixed*/, TargetStackID::Default /*StackID*/,
FrameReg,
/*PreferFP=*/false,
/*ForSimm=*/true);
Register SrcReg = FrameReg;
Expand Down
297 changes: 232 additions & 65 deletions llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions llvm/lib/Target/AArch64/AArch64FrameLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ class AArch64FrameLowering : public TargetFrameLowering {
bool ForSimm) const;
StackOffset resolveFrameOffsetReference(const MachineFunction &MF,
int64_t ObjectOffset, bool isFixed,
bool isSVE, Register &FrameReg,
bool PreferFP, bool ForSimm) const;
TargetStackID::Value StackID,
Register &FrameReg, bool PreferFP,
bool ForSimm) const;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
ArrayRef<CalleeSavedInfo> CSI,
Expand Down Expand Up @@ -155,7 +156,8 @@ class AArch64FrameLowering : public TargetFrameLowering {
/// Returns the size of the entire ZPR stackframe (calleesaves + spills).
StackOffset getZPRStackSize(const MachineFunction &MF) const;

/// Returns the size of the entire PPR stackframe (calleesaves + spills).
/// Returns the size of the entire PPR stackframe (calleesaves + spills +
/// hazard padding).
StackOffset getPPRStackSize(const MachineFunction &MF) const;

/// Returns the size of the entire SVE stackframe (PPRs + ZPRs).
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7497,7 +7497,7 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N,
int FI = cast<FrameIndexSDNode>(N)->getIndex();
// We can only encode VL scaled offsets, so only fold in frame indexes
// referencing SVE objects.
if (MFI.isScalableStackID(FI)) {
if (MFI.hasScalableStackID(FI)) {
Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
OffImm = CurDAG->getTargetConstant(0, SDLoc(N), MVT::i64);
return true;
Expand Down Expand Up @@ -7543,7 +7543,7 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexedSVE(SDNode *Root, SDValue N,
int FI = cast<FrameIndexSDNode>(Base)->getIndex();
// We can only encode VL scaled offsets, so only fold in frame indexes
// referencing SVE objects.
if (MFI.isScalableStackID(FI))
if (MFI.hasScalableStackID(FI))
Base = CurDAG->getTargetFrameIndex(FI, TLI->getPointerTy(DL));
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9256,7 +9256,7 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
(MI.getOpcode() == AArch64::ADDXri ||
MI.getOpcode() == AArch64::SUBXri)) {
const MachineOperand &MO = MI.getOperand(1);
if (MO.isFI() && MF.getFrameInfo().isScalableStackID(MO.getIndex()))
if (MO.isFI() && MF.getFrameInfo().hasScalableStackID(MO.getIndex()))
MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/false,
/*IsImplicit=*/true));
}
Expand Down Expand Up @@ -29608,7 +29608,7 @@ void AArch64TargetLowering::finalizeLowering(MachineFunction &MF) const {
// than doing it here in finalizeLowering.
if (MFI.hasStackProtectorIndex()) {
for (unsigned int i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
if (MFI.isScalableStackID(i) &&
if (MFI.hasScalableStackID(i) &&
MFI.getObjectSSPLayout(i) != MachineFrameInfo::SSPLK_None) {
MFI.setStackID(MFI.getStackProtectorIndex(),
TargetStackID::ScalableVector);
Expand Down
20 changes: 18 additions & 2 deletions llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
uint64_t StackSizeZPR = 0;
uint64_t StackSizePPR = 0;

/// Are SVE objects (vectors and predicates) split into separate regions on
/// the stack.
bool SplitSVEObjects = false;

/// HasCalculatedStackSizeSVE indicates whether StackSizeZPR/PPR is valid.
bool HasCalculatedStackSizeSVE = false;

Expand Down Expand Up @@ -336,7 +340,6 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {

bool isStackRealigned() const { return StackRealigned; }
void setStackRealigned(bool s) { StackRealigned = s; }

bool hasCalleeSaveStackFreeSpace() const {
return CalleeSaveStackHasFreeSpace;
}
Expand Down Expand Up @@ -438,6 +441,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
}

unsigned getSVECalleeSavedStackSize() const {
assert(!hasSplitSVEObjects() &&
"ZPRs and PPRs are split. Use get[ZPR|PPR]CalleeSavedStackSize()");
return getZPRCalleeSavedStackSize() + getPPRCalleeSavedStackSize();
}

Expand All @@ -446,6 +451,10 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
return NumLocalDynamicTLSAccesses;
}

bool isStackHazardIncludedInCalleeSaveArea() const {
return hasStackHazardSlotIndex() && !hasSplitSVEObjects();
}

std::optional<bool> hasRedZone() const { return HasRedZone; }
void setHasRedZone(bool s) { HasRedZone = s; }

Expand Down Expand Up @@ -481,7 +490,14 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
StackHazardCSRSlotIndex = Index;
}

bool hasSplitSVEObjects() const { return false; }
bool hasSplitSVEObjects() const { return SplitSVEObjects; }
void setSplitSVEObjects(bool s) { SplitSVEObjects = s; }

bool hasSVE_AAPCS(const MachineFunction &MF) const {
return hasSplitSVEObjects() || isSVECC() ||
MF.getFunction().getCallingConv() ==
CallingConv::AArch64_SVE_VectorCall;
}

SMEAttrs getSMEFnAttrs() const { return SMEFnAttrs; }

Expand Down
125 changes: 117 additions & 8 deletions llvm/lib/Target/AArch64/AArch64PrologueEpilogue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,38 +723,73 @@ void AArch64PrologueEmitter::emitPrologue() {
StackOffset PPRLocalsSize = AFL.getPPRStackSize(MF) - PPRCalleeSavesSize;
StackOffset ZPRLocalsSize = AFL.getZPRStackSize(MF) - ZPRCalleeSavesSize;

std::optional<MachineBasicBlock::iterator> ZPRCalleeSavesBegin,
ZPRCalleeSavesEnd, PPRCalleeSavesBegin, PPRCalleeSavesEnd;

StackOffset CFAOffset =
StackOffset::getFixed((int64_t)MFI.getStackSize() - NumBytes);
MachineBasicBlock::iterator AfterSVESavesI = AfterGPRSavesI;
if (!FPAfterSVECalleeSaves) {
// Process the SVE callee-saves to find the starts/ends of the ZPR and PPR
// areas.
PPRCalleeSavesBegin = AfterGPRSavesI;
if (PPRCalleeSavesSize) {
LLVM_DEBUG(dbgs() << "PPRCalleeSavedStackSize = "
<< PPRCalleeSavesSize.getScalable() << "\n");

assert(isPartOfPPRCalleeSaves(AfterSVESavesI) &&
assert(isPartOfPPRCalleeSaves(*PPRCalleeSavesBegin) &&
"Unexpected instruction");
while (isPartOfPPRCalleeSaves(AfterSVESavesI) &&
AfterSVESavesI != MBB.getFirstTerminator())
++AfterSVESavesI;
}
PPRCalleeSavesEnd = ZPRCalleeSavesBegin = AfterSVESavesI;
if (ZPRCalleeSavesSize) {
LLVM_DEBUG(dbgs() << "ZPRCalleeSavedStackSize = "
<< ZPRCalleeSavesSize.getScalable() << "\n");
assert(isPartOfZPRCalleeSaves(AfterSVESavesI) &&
assert(isPartOfZPRCalleeSaves(*ZPRCalleeSavesBegin) &&
"Unexpected instruction");
while (isPartOfZPRCalleeSaves(AfterSVESavesI) &&
AfterSVESavesI != MBB.getFirstTerminator())
++AfterSVESavesI;
}
ZPRCalleeSavesEnd = AfterSVESavesI;
}

if (EmitAsyncCFI)
emitCalleeSavedSVELocations(AfterSVESavesI);

if (AFI->hasSplitSVEObjects()) {
reportFatalInternalError("not implemented yet");
assert(!FPAfterSVECalleeSaves &&
"Cannot use FPAfterSVECalleeSaves with aarch64-split-sve-objects");
assert(!AFL.canUseRedZone(MF) &&
"Cannot use redzone with aarch64-split-sve-objects");
// TODO: Handle HasWinCFI/NeedsWinCFI?
assert(!NeedsWinCFI &&
"WinCFI with aarch64-split-sve-objects is not supported");

// Split ZPR and PPR allocation.
// Allocate PPR callee saves
allocateStackSpace(*PPRCalleeSavesBegin, 0, PPRCalleeSavesSize,
EmitAsyncCFI && !HasFP, CFAOffset,
MFI.hasVarSizedObjects() || ZPRCalleeSavesSize ||
ZPRLocalsSize || PPRLocalsSize);
CFAOffset += PPRCalleeSavesSize;

// Allocate PPR locals + ZPR callee saves
assert(PPRCalleeSavesEnd == ZPRCalleeSavesBegin &&
"Expected ZPR callee saves after PPR locals");
allocateStackSpace(*PPRCalleeSavesEnd, RealignmentPadding,
PPRLocalsSize + ZPRCalleeSavesSize,
EmitAsyncCFI && !HasFP, CFAOffset,
MFI.hasVarSizedObjects() || ZPRLocalsSize);
CFAOffset += PPRLocalsSize + ZPRCalleeSavesSize;

// Allocate ZPR locals
allocateStackSpace(*ZPRCalleeSavesEnd, RealignmentPadding,
ZPRLocalsSize + StackOffset::getFixed(NumBytes),
EmitAsyncCFI && !HasFP, CFAOffset,
MFI.hasVarSizedObjects());
} else {
// Allocate space for the callee saves (if any).
StackOffset LocalsSize =
Expand Down Expand Up @@ -1195,7 +1230,7 @@ void AArch64PrologueEmitter::emitCalleeSavedGPRLocations(
CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
for (const auto &Info : CSI) {
unsigned FrameIdx = Info.getFrameIdx();
if (MFI.isScalableStackID(FrameIdx))
if (MFI.hasScalableStackID(FrameIdx))
continue;

assert(!Info.isSpilledToReg() && "Spilling to registers not implemented");
Expand All @@ -1221,8 +1256,10 @@ void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
AFL.getOffsetOfLocalArea();
}

StackOffset PPRStackSize = AFL.getPPRStackSize(MF);
for (const auto &Info : CSI) {
if (!MFI.isScalableStackID(Info.getFrameIdx()))
int FI = Info.getFrameIdx();
if (!MFI.hasScalableStackID(FI))
continue;

// Not all unwinders may know about SVE registers, so assume the lowest
Expand All @@ -1233,9 +1270,13 @@ void AArch64PrologueEmitter::emitCalleeSavedSVELocations(
continue;

StackOffset Offset =
StackOffset::getScalable(MFI.getObjectOffset(Info.getFrameIdx())) -
StackOffset::getScalable(MFI.getObjectOffset(FI)) -
StackOffset::getFixed(AFI->getCalleeSavedStackSize(MFI));

if (AFI->hasSplitSVEObjects() &&
MFI.getStackID(FI) == TargetStackID::ScalableVector)
Offset -= PPRStackSize;

CFIBuilder.insertCFIInst(
createCFAOffset(RegInfo, Reg, Offset, IncomingVGOffsetFromDefCFA));
}
Expand Down Expand Up @@ -1512,7 +1553,75 @@ void AArch64EpilogueEmitter::emitEpilogue() {
emitCalleeSavedSVERestores(RestoreEnd);
}
} else if (AFI->hasSplitSVEObjects() && SVEStackSize) {
reportFatalInternalError("not implemented yet");
// TODO: Support stack realigment and variable-sized objects.
assert(!AFI->isStackRealigned() && !MFI.hasVarSizedObjects() &&
"unexpected stack realignment or variable sized objects with split "
"SVE stack objects");
// SplitSVEObjects. Determine the sizes and starts/ends of the ZPR and PPR
// areas.
auto ZPRCalleeSavedSize =
StackOffset::getScalable(AFI->getZPRCalleeSavedStackSize());
auto PPRCalleeSavedSize =
StackOffset::getScalable(AFI->getPPRCalleeSavedStackSize());
StackOffset PPRLocalsSize = PPRStackSize - PPRCalleeSavedSize;
StackOffset ZPRLocalsSize = ZPRStackSize - ZPRCalleeSavedSize;

MachineBasicBlock::iterator PPRRestoreBegin = FirstGPRRestoreI,
PPRRestoreEnd = FirstGPRRestoreI;
if (PPRCalleeSavedSize) {
PPRRestoreBegin = std::prev(PPRRestoreEnd);
while (PPRRestoreBegin != MBB.begin() &&
isPartOfPPRCalleeSaves(std::prev(PPRRestoreBegin)))
--PPRRestoreBegin;
}

MachineBasicBlock::iterator ZPRRestoreBegin = PPRRestoreBegin,
ZPRRestoreEnd = PPRRestoreBegin;
if (ZPRCalleeSavedSize) {
ZPRRestoreBegin = std::prev(ZPRRestoreEnd);
while (ZPRRestoreBegin != MBB.begin() &&
isPartOfZPRCalleeSaves(std::prev(ZPRRestoreBegin)))
--ZPRRestoreBegin;
}

auto CFAOffset =
SVEStackSize + StackOffset::getFixed(NumBytes + PrologueSaveSize);
if (PPRCalleeSavedSize || ZPRCalleeSavedSize) {
// Deallocate the non-SVE locals first before we can deallocate (and
// restore callee saves) from the SVE area.
auto NonSVELocals = StackOffset::getFixed(NumBytes);
emitFrameOffset(MBB, ZPRRestoreBegin, DL, AArch64::SP, AArch64::SP,
NonSVELocals, TII, MachineInstr::FrameDestroy, false,
false, nullptr, EmitCFI && !HasFP, CFAOffset);
NumBytes = 0;
CFAOffset -= NonSVELocals;
}

if (ZPRLocalsSize) {
emitFrameOffset(MBB, ZPRRestoreBegin, DL, AArch64::SP, AArch64::SP,
ZPRLocalsSize, TII, MachineInstr::FrameDestroy, false,
false, nullptr, EmitCFI && !HasFP, CFAOffset);
CFAOffset -= ZPRLocalsSize;
}

if (PPRLocalsSize || ZPRCalleeSavedSize) {
assert(PPRRestoreBegin == ZPRRestoreEnd &&
"Expected PPR restores after ZPR");
emitFrameOffset(MBB, PPRRestoreBegin, DL, AArch64::SP, AArch64::SP,
PPRLocalsSize + ZPRCalleeSavedSize, TII,
MachineInstr::FrameDestroy, false, false, nullptr,
EmitCFI && !HasFP, CFAOffset);
CFAOffset -= PPRLocalsSize + ZPRCalleeSavedSize;
}
if (PPRCalleeSavedSize) {
emitFrameOffset(MBB, PPRRestoreEnd, DL, AArch64::SP, AArch64::SP,
PPRCalleeSavedSize, TII, MachineInstr::FrameDestroy,
false, false, nullptr, EmitCFI && !HasFP, CFAOffset);
}

// We only emit CFI information for ZPRs so emit CFI after the ZPR restores.
if (EmitCFI)
emitCalleeSavedSVERestores(ZPRRestoreEnd);
}

if (!HasFP) {
Expand Down Expand Up @@ -1670,7 +1779,7 @@ void AArch64EpilogueEmitter::emitCalleeSavedRestores(
CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameDestroy);

for (const auto &Info : CSI) {
if (SVE != MFI.isScalableStackID(Info.getFrameIdx()))
if (SVE != MFI.hasScalableStackID(Info.getFrameIdx()))
continue;

MCRegister Reg = Info.getReg();
Expand Down
11 changes: 5 additions & 6 deletions llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ bool AArch64RegisterInfo::regNeedsCFI(MCRegister Reg,
const MCPhysReg *
AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
assert(MF && "Invalid MachineFunction pointer.");
auto &AFI = *MF->getInfo<AArch64FunctionInfo>();

if (MF->getFunction().getCallingConv() == CallingConv::GHC)
// GHC set of callee saved regs is empty as all those regs are
Expand Down Expand Up @@ -101,10 +102,7 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_Win_AArch64_AAPCS_SwiftTail_SaveList;
if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall)
return CSR_Win_AArch64_AAVPCS_SaveList;
if (MF->getFunction().getCallingConv() ==
CallingConv::AArch64_SVE_VectorCall)
return CSR_Win_AArch64_SVE_AAPCS_SaveList;
if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
if (AFI.hasSVE_AAPCS(*MF))
return CSR_Win_AArch64_SVE_AAPCS_SaveList;
return CSR_Win_AArch64_AAPCS_SaveList;
}
Expand Down Expand Up @@ -148,7 +146,7 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
// This is for OSes other than Windows; Windows is a separate case further
// above.
return CSR_AArch64_AAPCS_X18_SaveList;
if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
if (AFI.hasSVE_AAPCS(*MF))
return CSR_AArch64_SVE_AAPCS_SaveList;
return CSR_AArch64_AAPCS_SaveList;
}
Expand All @@ -158,6 +156,7 @@ AArch64RegisterInfo::getDarwinCalleeSavedRegs(const MachineFunction *MF) const {
assert(MF && "Invalid MachineFunction pointer.");
assert(MF->getSubtarget<AArch64Subtarget>().isTargetDarwin() &&
"Invalid subtarget for getDarwinCalleeSavedRegs");
auto &AFI = *MF->getInfo<AArch64FunctionInfo>();

if (MF->getFunction().getCallingConv() == CallingConv::CFGuard_Check)
report_fatal_error(
Expand Down Expand Up @@ -205,7 +204,7 @@ AArch64RegisterInfo::getDarwinCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_Darwin_AArch64_RT_AllRegs_SaveList;
if (MF->getFunction().getCallingConv() == CallingConv::Win64)
return CSR_Darwin_AArch64_AAPCS_Win64_SaveList;
if (MF->getInfo<AArch64FunctionInfo>()->isSVECC())
if (AFI.hasSVE_AAPCS(*MF))
return CSR_Darwin_AArch64_SVE_AAPCS_SaveList;
return CSR_Darwin_AArch64_AAPCS_SaveList;
}
Expand Down
Loading