Skip to content

[AArch64] New subtarget features to control ldp and stp formation, fo… #66098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2023
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
20 changes: 18 additions & 2 deletions llvm/lib/Target/AArch64/AArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,18 @@ def FeatureD128 : SubtargetFeature<"d128", "HasD128",
"and Instructions (FEAT_D128, FEAT_LVA3, FEAT_SYSREG128, FEAT_SYSINSTR128)",
[FeatureLSE128]>;

def FeatureDisableLdp : SubtargetFeature<"disable-ldp", "HasDisableLdp",
"true", "Do not emit ldp">;

def FeatureDisableStp : SubtargetFeature<"disable-stp", "HasDisableStp",
"true", "Do not emit stp">;

def FeatureLdpAlignedOnly : SubtargetFeature<"ldp-aligned-only", "HasLdpAlignedOnly",
"true", "In order to emit ldp, first check if the load will be aligned to 2 * element_size">;

def FeatureStpAlignedOnly : SubtargetFeature<"stp-aligned-only", "HasStpAlignedOnly",
"true", "In order to emit stp, first check if the store will be aligned to 2 * element_size">;

//===----------------------------------------------------------------------===//
// Architectures.
//
Expand Down Expand Up @@ -1239,7 +1251,9 @@ def TuneAmpere1 : SubtargetFeature<"ampere1", "ARMProcFamily", "Ampere1",
FeatureArithmeticBccFusion,
FeatureCmpBccFusion,
FeatureFuseAddress,
FeatureFuseLiterals]>;
FeatureFuseLiterals,
FeatureLdpAlignedOnly,
FeatureStpAlignedOnly]>;

def TuneAmpere1A : SubtargetFeature<"ampere1a", "ARMProcFamily", "Ampere1A",
"Ampere Computing Ampere-1A processors", [
Expand All @@ -1252,7 +1266,9 @@ def TuneAmpere1A : SubtargetFeature<"ampere1a", "ARMProcFamily", "Ampere1A",
FeatureCmpBccFusion,
FeatureFuseAddress,
FeatureFuseLiterals,
FeatureFuseLiterals]>;
FeatureFuseLiterals,
FeatureLdpAlignedOnly,
FeatureStpAlignedOnly]>;

def ProcessorFeatures {
list<SubtargetFeature> A53 = [HasV8_0aOps, FeatureCRC, FeatureCrypto,
Expand Down
33 changes: 33 additions & 0 deletions llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2136,6 +2136,14 @@ bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
if (!TII->isCandidateToMergeOrPair(MI))
return false;

// If disable-ldp feature is opted, do not emit ldp.
if (MI.mayLoad() && Subtarget->hasDisableLdp())
return false;

// If disable-stp feature is opted, do not emit stp.
if (MI.mayStore() && Subtarget->hasDisableStp())
return false;

// Early exit if the offset is not possible to match. (6 bits of positive
// range, plus allow an extra one in case we find a later insn that matches
// with Offset-1)
Expand All @@ -2159,6 +2167,31 @@ bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) {
// Keeping the iterator straight is a pain, so we let the merge routine tell
// us what the next instruction is after it's done mucking about.
auto Prev = std::prev(MBBI);

// Fetch the memoperand of the load/store that is a candidate for
// combination.
MachineMemOperand *MemOp =
MI.memoperands_empty() ? nullptr : MI.memoperands().front();

// Get the needed alignments to check them if
// ldp-aligned-only/stp-aligned-only features are opted.
uint64_t MemAlignment = MemOp ? MemOp->getAlign().value() : -1;
uint64_t TypeAlignment = MemOp ? Align(MemOp->getSize()).value() : -1;

// If a load arrives and ldp-aligned-only feature is opted, check that the
// alignment of the source pointer is at least double the alignment of the
// type.
if (MI.mayLoad() && Subtarget->hasLdpAlignedOnly() && MemOp &&
MemAlignment < 2 * TypeAlignment)
return false;

// If a store arrives and stp-aligned-only feature is opted, check that the
// alignment of the source pointer is at least double the alignment of the
// type.
if (MI.mayStore() && Subtarget->hasStpAlignedOnly() && MemOp &&
MemAlignment < 2 * TypeAlignment)
return false;

MBBI = mergePairedInsns(MBBI, Paired, Flags);
// Collect liveness info for instructions between Prev and the new position
// MBBI.
Expand Down
Loading