Skip to content

Commit a548ede

Browse files
[AArch64][SME]Check streaming mode when using SME2 instruction in fra… (llvm#109680)
…me lowering SME instructions can only be used in streaming mode. PTRUE for predicated counter and the ld/st pair can be used when: sve2.1 is available or sme2 available in function in streaming mode. Previously the frame lowering only checking if sme2 available when building the machine instruction. This fix checks if sme2 is available and is subtarget in streaming mode
1 parent f5c02dd commit a548ede

File tree

3 files changed

+489
-5
lines changed

3 files changed

+489
-5
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,11 @@ static cl::opt<bool>
285285
StackHazardInNonStreaming("aarch64-stack-hazard-in-non-streaming",
286286
cl::init(false), cl::Hidden);
287287

288+
static cl::opt<bool> DisableMultiVectorSpillFill(
289+
"aarch64-disable-multivector-spill-fill",
290+
cl::desc("Disable use of LD/ST pairs for SME2 or SVE2p1"), cl::init(false),
291+
cl::Hidden);
292+
288293
STATISTIC(NumRedZoneFunctions, "Number of functions using red zone");
289294

290295
/// Returns how much of the incoming argument stack area (in bytes) we should
@@ -2954,6 +2959,24 @@ unsigned findFreePredicateReg(BitVector &SavedRegs) {
29542959
return AArch64::NoRegister;
29552960
}
29562961

2962+
// The multivector LD/ST are available only for SME or SVE2p1 targets
2963+
bool enableMultiVectorSpillFill(const AArch64Subtarget &Subtarget,
2964+
MachineFunction &MF) {
2965+
if (DisableMultiVectorSpillFill)
2966+
return false;
2967+
2968+
SMEAttrs FuncAttrs(MF.getFunction());
2969+
bool IsLocallyStreaming =
2970+
FuncAttrs.hasStreamingBody() && !FuncAttrs.hasStreamingInterface();
2971+
2972+
// Only when in streaming mode SME2 instructions can be safely used.
2973+
// It is not safe to use SME2 instructions when in streaming compatible or
2974+
// locally streaming mode.
2975+
return Subtarget.hasSVE2p1() ||
2976+
(Subtarget.hasSME2() &&
2977+
(!IsLocallyStreaming && Subtarget.isStreaming()));
2978+
}
2979+
29572980
static void computeCalleeSaveRegisterPairs(
29582981
MachineFunction &MF, ArrayRef<CalleeSavedInfo> CSI,
29592982
const TargetRegisterInfo *TRI, SmallVectorImpl<RegPairInfo> &RegPairs,
@@ -3330,7 +3353,7 @@ bool AArch64FrameLowering::spillCalleeSavedRegisters(
33303353
MF.getSubtarget<AArch64Subtarget>();
33313354
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
33323355
unsigned PnReg = AFI->getPredicateRegForFillSpill();
3333-
assert(((Subtarget.hasSVE2p1() || Subtarget.hasSME2()) && PnReg != 0) &&
3356+
assert((PnReg != 0 && enableMultiVectorSpillFill(Subtarget, MF)) &&
33343357
"Expects SVE2.1 or SME2 target and a predicate register");
33353358
#ifdef EXPENSIVE_CHECKS
33363359
auto IsPPR = [](const RegPairInfo &c) {
@@ -3508,7 +3531,7 @@ bool AArch64FrameLowering::restoreCalleeSavedRegisters(
35083531
[[maybe_unused]] const AArch64Subtarget &Subtarget =
35093532
MF.getSubtarget<AArch64Subtarget>();
35103533
unsigned PnReg = AFI->getPredicateRegForFillSpill();
3511-
assert(((Subtarget.hasSVE2p1() || Subtarget.hasSME2()) && PnReg != 0) &&
3534+
assert((PnReg != 0 && enableMultiVectorSpillFill(Subtarget, MF)) &&
35123535
"Expects SVE2.1 or SME2 target and a predicate register");
35133536
#ifdef EXPENSIVE_CHECKS
35143537
assert(!(PPRBegin < ZPRBegin) &&
@@ -3722,7 +3745,7 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
37223745
SavedRegs.test(CSRegs[i ^ 1]));
37233746
}
37243747

3725-
if (HasPairZReg && (Subtarget.hasSVE2p1() || Subtarget.hasSME2())) {
3748+
if (HasPairZReg && enableMultiVectorSpillFill(Subtarget, MF)) {
37263749
AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
37273750
// Find a suitable predicate register for the multi-vector spill/fill
37283751
// instructions.

0 commit comments

Comments
 (0)