[CodeGen] Parse frame-pointer attribute once when creating MachineFunction (#191974)
TargetOptions::DisableFramePointerElim is hot and showing up in compile-time profiles via AArch64FrameLowering::hasFPImpl on aarch64-O0-g builds. Repeatedly looking up the function attribute is expensive. Parsing it once at MachineFunction initialisation and storing as FramePointerKind on MachineFrameInfo is a -0.21% geomean improvement on CTMark stage1-aarch64-O0-g. Also helps debug builds on other targets. https://llvm-compile-time-tracker.com/compare.php?from=215f35eb8f1c313ac135ad47db1cc0b99b3ae694&to=51f6617517177bea1cc49baeab3acaf62d5e9df9&stat=instructions%3Au
This commit is contained in:
parent
920b203fe2
commit
f2efeabe31
8 changed files with 126 additions and 18 deletions
|
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
|
@ -144,6 +145,16 @@ template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
|
|||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<FramePointerKind> {
|
||||
static void enumeration(IO &IO, FramePointerKind &FP) {
|
||||
IO.enumCase(FP, "none", FramePointerKind::None);
|
||||
IO.enumCase(FP, "non-leaf", FramePointerKind::NonLeaf);
|
||||
IO.enumCase(FP, "all", FramePointerKind::All);
|
||||
IO.enumCase(FP, "reserved", FramePointerKind::Reserved);
|
||||
IO.enumCase(FP, "non-leaf-no-reserve", FramePointerKind::NonLeafNoReserve);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ScalarTraits<MaybeAlign> {
|
||||
static void output(const MaybeAlign &Alignment, void *,
|
||||
llvm::raw_ostream &out) {
|
||||
|
|
@ -702,6 +713,7 @@ struct MachineFrameInfo {
|
|||
unsigned MaxAlignment = 0;
|
||||
bool AdjustsStack = false;
|
||||
bool HasCalls = false;
|
||||
FramePointerKind FramePointerPolicy = FramePointerKind::None;
|
||||
StringValue StackProtector;
|
||||
StringValue FunctionContext;
|
||||
unsigned MaxCallFrameSize = ~0u; ///< ~0u means: not computed yet.
|
||||
|
|
@ -724,6 +736,7 @@ struct MachineFrameInfo {
|
|||
OffsetAdjustment == Other.OffsetAdjustment &&
|
||||
MaxAlignment == Other.MaxAlignment &&
|
||||
AdjustsStack == Other.AdjustsStack && HasCalls == Other.HasCalls &&
|
||||
FramePointerPolicy == Other.FramePointerPolicy &&
|
||||
StackProtector == Other.StackProtector &&
|
||||
FunctionContext == Other.FunctionContext &&
|
||||
MaxCallFrameSize == Other.MaxCallFrameSize &&
|
||||
|
|
@ -751,6 +764,7 @@ template <> struct MappingTraits<MachineFrameInfo> {
|
|||
YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0);
|
||||
YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false);
|
||||
YamlIO.mapOptional("hasCalls", MFI.HasCalls, false);
|
||||
YamlIO.mapOptional("framePointerPolicy", MFI.FramePointerPolicy);
|
||||
YamlIO.mapOptional("stackProtector", MFI.StackProtector,
|
||||
StringValue()); // Don't print it out when it's empty.
|
||||
YamlIO.mapOptional("functionContext", MFI.FunctionContext,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/CodeGen/Register.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
#include "llvm/Support/Alignment.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
|
@ -279,6 +280,10 @@ private:
|
|||
/// Set to true if this function has any function calls.
|
||||
bool HasCalls = false;
|
||||
|
||||
/// Frame-pointer policy for this function to avoid repeated attribute
|
||||
/// lookups in hot paths.
|
||||
FramePointerKind FramePointerPolicy = FramePointerKind::None;
|
||||
|
||||
/// The frame index for the stack protector.
|
||||
int StackProtectorIdx = -1;
|
||||
|
||||
|
|
@ -641,6 +646,11 @@ public:
|
|||
bool hasCalls() const { return HasCalls; }
|
||||
void setHasCalls(bool V) { HasCalls = V; }
|
||||
|
||||
FramePointerKind getFramePointerPolicy() const { return FramePointerPolicy; }
|
||||
void setFramePointerPolicy(FramePointerKind Kind) {
|
||||
FramePointerPolicy = Kind;
|
||||
}
|
||||
|
||||
/// Returns true if the function contains opaque dynamic stack adjustments.
|
||||
bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; }
|
||||
void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; }
|
||||
|
|
|
|||
|
|
@ -900,6 +900,8 @@ bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS,
|
|||
MFI.ensureMaxAlignment(Align(YamlMFI.MaxAlignment));
|
||||
MFI.setAdjustsStack(YamlMFI.AdjustsStack);
|
||||
MFI.setHasCalls(YamlMFI.HasCalls);
|
||||
if (YamlMFI.FramePointerPolicy != FramePointerKind::None)
|
||||
MFI.setFramePointerPolicy(YamlMFI.FramePointerPolicy);
|
||||
if (YamlMFI.MaxCallFrameSize != ~0u)
|
||||
MFI.setMaxCallFrameSize(YamlMFI.MaxCallFrameSize);
|
||||
MFI.setCVBytesOfCalleeSavedRegisters(YamlMFI.CVBytesOfCalleeSavedRegisters);
|
||||
|
|
|
|||
|
|
@ -364,6 +364,7 @@ static void convertMFI(ModuleSlotTracker &MST, yaml::MachineFrameInfo &YamlMFI,
|
|||
YamlMFI.MaxAlignment = MFI.getMaxAlign().value();
|
||||
YamlMFI.AdjustsStack = MFI.adjustsStack();
|
||||
YamlMFI.HasCalls = MFI.hasCalls();
|
||||
YamlMFI.FramePointerPolicy = MFI.getFramePointerPolicy();
|
||||
YamlMFI.MaxCallFrameSize = MFI.isMaxCallFrameSizeComputed()
|
||||
? MFI.getMaxCallFrameSize() : ~0u;
|
||||
YamlMFI.CVBytesOfCalleeSavedRegisters =
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||
|
|
@ -162,6 +163,21 @@ static inline Align getFnStackAlignment(const TargetSubtargetInfo &STI,
|
|||
return STI.getFrameLowering()->getStackAlign();
|
||||
}
|
||||
|
||||
static FramePointerKind getFramePointerPolicy(const Function &F) {
|
||||
Attribute FPAttr = F.getFnAttribute("frame-pointer");
|
||||
if (!FPAttr.isValid())
|
||||
return FramePointerKind::None;
|
||||
|
||||
StringRef FP = FPAttr.getValueAsString();
|
||||
return StringSwitch<FramePointerKind>(FP)
|
||||
.Case("all", FramePointerKind::All)
|
||||
.Case("non-leaf", FramePointerKind::NonLeaf)
|
||||
.Case("non-leaf-no-reserve", FramePointerKind::NonLeafNoReserve)
|
||||
.Case("reserved", FramePointerKind::Reserved)
|
||||
.Case("none", FramePointerKind::None)
|
||||
.Default(FramePointerKind::None);
|
||||
}
|
||||
|
||||
MachineFunction::MachineFunction(Function &F, const TargetMachine &Target,
|
||||
const TargetSubtargetInfo &STI, MCContext &Ctx,
|
||||
unsigned FunctionNum)
|
||||
|
|
@ -203,6 +219,7 @@ void MachineFunction::init() {
|
|||
FrameInfo = new (Allocator) MachineFrameInfo(
|
||||
getFnStackAlignment(STI, F), /*StackRealignable=*/CanRealignSP,
|
||||
/*ForcedRealign=*/ForceRealignSP && CanRealignSP);
|
||||
FrameInfo->setFramePointerPolicy(getFramePointerPolicy(F));
|
||||
|
||||
setUnsafeStackSize(F, *FrameInfo);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
|
|
@ -22,31 +21,33 @@ using namespace llvm;
|
|||
/// DisableFramePointerElim - This returns true if frame pointer elimination
|
||||
/// optimization should be disabled for the given machine function.
|
||||
bool TargetOptions::DisableFramePointerElim(const MachineFunction &MF) const {
|
||||
const Function &F = MF.getFunction();
|
||||
|
||||
Attribute FPAttr = F.getFnAttribute("frame-pointer");
|
||||
if (!FPAttr.isValid())
|
||||
return false;
|
||||
StringRef FP = FPAttr.getValueAsString();
|
||||
if (FP == "all")
|
||||
FramePointerKind FP = MF.getFrameInfo().getFramePointerPolicy();
|
||||
switch (FP) {
|
||||
case FramePointerKind::All:
|
||||
return true;
|
||||
if (FP == "non-leaf" || FP == "non-leaf-no-reserve")
|
||||
case FramePointerKind::NonLeaf:
|
||||
case FramePointerKind::NonLeafNoReserve:
|
||||
return MF.getFrameInfo().hasCalls();
|
||||
if (FP == "none" || FP == "reserved")
|
||||
case FramePointerKind::None:
|
||||
case FramePointerKind::Reserved:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("unknown frame pointer flag");
|
||||
}
|
||||
|
||||
bool TargetOptions::FramePointerIsReserved(const MachineFunction &MF) const {
|
||||
const Function &F = MF.getFunction();
|
||||
Attribute FPAttr = F.getFnAttribute("frame-pointer");
|
||||
if (!FPAttr.isValid())
|
||||
FramePointerKind FP = MF.getFrameInfo().getFramePointerPolicy();
|
||||
switch (FP) {
|
||||
case FramePointerKind::All:
|
||||
case FramePointerKind::NonLeaf:
|
||||
case FramePointerKind::Reserved:
|
||||
return true;
|
||||
case FramePointerKind::NonLeafNoReserve:
|
||||
return MF.getFrameInfo().hasCalls();
|
||||
case FramePointerKind::None:
|
||||
return false;
|
||||
|
||||
return StringSwitch<bool>(FPAttr.getValueAsString())
|
||||
.Cases({"all", "non-leaf", "reserved"}, true)
|
||||
.Case(("non-leaf-no-reserve"), MF.getFrameInfo().hasCalls())
|
||||
.Case("none", false);
|
||||
}
|
||||
llvm_unreachable("unknown frame pointer flag");
|
||||
}
|
||||
|
||||
/// HonorSignDependentRoundingFPMath - Return true if the codegen must assume
|
||||
|
|
|
|||
|
|
@ -20,6 +20,26 @@
|
|||
ret i32 %c
|
||||
}
|
||||
|
||||
define void @test_framePointerPolicy_none() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_framePointerPolicy_non_leaf() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_framePointerPolicy_all() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_framePointerPolicy_reserved() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_framePointerPolicy_non_leaf_no_reserve() {
|
||||
ret void
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
name: test
|
||||
|
|
@ -36,6 +56,7 @@ tracksRegLiveness: true
|
|||
# CHECK-NEXT: maxAlignment:
|
||||
# CHECK-NEXT: adjustsStack: false
|
||||
# CHECK-NEXT: hasCalls: false
|
||||
# CHECK-NEXT: framePointerPolicy: none
|
||||
# CHECK-NEXT: stackProtector: ''
|
||||
# CHECK-NEXT: functionContext: ''
|
||||
# CHECK-NEXT: maxCallFrameSize:
|
||||
|
|
@ -70,6 +91,7 @@ stack:
|
|||
# CHECK-NEXT: maxAlignment:
|
||||
# CHECK-NEXT: adjustsStack: true
|
||||
# CHECK-NEXT: hasCalls: true
|
||||
# CHECK-NEXT: framePointerPolicy: none
|
||||
# CHECK-NEXT: stackProtector: ''
|
||||
# CHECK-NEXT: functionContext: '%stack.0'
|
||||
# CHECK-NEXT: maxCallFrameSize: 4
|
||||
|
|
@ -100,4 +122,43 @@ frameInfo:
|
|||
body: |
|
||||
bb.0.entry:
|
||||
...
|
||||
---
|
||||
name: test_framePointerPolicy_none
|
||||
|
||||
# CHECK: test_framePointerPolicy_none
|
||||
# CHECK: framePointerPolicy: none
|
||||
frameInfo:
|
||||
framePointerPolicy: none
|
||||
...
|
||||
---
|
||||
name: test_framePointerPolicy_non_leaf
|
||||
|
||||
# CHECK: test_framePointerPolicy_non_leaf
|
||||
# CHECK: framePointerPolicy: non-leaf
|
||||
frameInfo:
|
||||
framePointerPolicy: non-leaf
|
||||
...
|
||||
---
|
||||
name: test_framePointerPolicy_all
|
||||
|
||||
# CHECK: test_framePointerPolicy_all
|
||||
# CHECK: framePointerPolicy: all
|
||||
frameInfo:
|
||||
framePointerPolicy: all
|
||||
...
|
||||
---
|
||||
name: test_framePointerPolicy_reserved
|
||||
|
||||
# CHECK: test_framePointerPolicy_reserved
|
||||
# CHECK: framePointerPolicy: reserved
|
||||
frameInfo:
|
||||
framePointerPolicy: reserved
|
||||
...
|
||||
---
|
||||
name: test_framePointerPolicy_non_leaf_no_reserve
|
||||
|
||||
# CHECK: test_framePointerPolicy_non_leaf_no_reserve
|
||||
# CHECK: framePointerPolicy: non-leaf-no-reserve
|
||||
frameInfo:
|
||||
framePointerPolicy: non-leaf-no-reserve
|
||||
...
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
# RESULT-NEXT: maxAlignment: 64
|
||||
# RESULT-NEXT: adjustsStack: true
|
||||
# RESULT-NEXT: hasCalls: true
|
||||
# RESULT-NEXT: framePointerPolicy: none
|
||||
# RESULT-NEXT: stackProtector: '%stack.9.guard'
|
||||
# RESULT-NEXT: maxCallFrameSize: 420
|
||||
# RESULT-NEXT: cvBytesOfCalleeSavedRegisters: 48
|
||||
|
|
@ -110,6 +111,7 @@ frameInfo:
|
|||
maxAlignment: 1
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
framePointerPolicy: none
|
||||
stackProtector: '%stack.9'
|
||||
maxCallFrameSize: 420
|
||||
cvBytesOfCalleeSavedRegisters: 48
|
||||
|
|
|
|||
Loading…
Reference in a new issue