29#define DEBUG_TYPE "aarch64-stack-tagging-pre-ra"
33class AArch64StackTaggingPreRAImpl {
47 bool mayUseUncheckedLoadStore();
48 void uncheckUsesOf(
unsigned TaggedReg,
int FI);
49 void uncheckLoadsAndStores();
50 std::optional<int> findFirstSlotCandidate();
61 return AArch64StackTaggingPreRAImpl().run(MF);
65 return "AArch64 Stack Tagging PreRA";
75char AArch64StackTaggingPreRALegacy::ID = 0;
78 "aarch64-stack-tagging-pre-ra",
79 "AArch64 Stack Tagging PreRA Pass",
false,
false)
81 "aarch64-stack-tagging-pre-ra",
85 return new AArch64StackTaggingPreRALegacy();
91 if (AArch64StackTaggingPreRAImpl().
run(MF)) {
101 case AArch64::LDRBBui:
102 case AArch64::LDRHHui:
103 case AArch64::LDRWui:
104 case AArch64::LDRXui:
106 case AArch64::LDRBui:
107 case AArch64::LDRHui:
108 case AArch64::LDRSui:
109 case AArch64::LDRDui:
110 case AArch64::LDRQui:
112 case AArch64::LDRSHWui:
113 case AArch64::LDRSHXui:
115 case AArch64::LDRSBWui:
116 case AArch64::LDRSBXui:
118 case AArch64::LDRSWui:
120 case AArch64::STRBBui:
121 case AArch64::STRHHui:
122 case AArch64::STRWui:
123 case AArch64::STRXui:
125 case AArch64::STRBui:
126 case AArch64::STRHui:
127 case AArch64::STRSui:
128 case AArch64::STRDui:
129 case AArch64::STRQui:
137 case AArch64::LDPSWi:
150bool AArch64StackTaggingPreRAImpl::mayUseUncheckedLoadStore() {
153 .stack_tagging_unchecked_ld_st;
170 unsigned FrameSize = 0;
171 for (
unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i)
172 FrameSize += MFI->getObjectSize(i);
173 bool EntireFrameReachableFromSP = FrameSize < 0xf00;
174 return !MFI->hasVarSizedObjects() && EntireFrameReachableFromSP;
177void AArch64StackTaggingPreRAImpl::uncheckUsesOf(
unsigned TaggedReg,
int FI) {
182 unsigned OpIdx =
TII->getLoadStoreImmIdx(UseI.getOpcode()) - 1;
183 if (UseI.getOperand(OpIdx).isReg() &&
184 UseI.getOperand(OpIdx).getReg() == TaggedReg) {
185 UseI.getOperand(OpIdx).ChangeToFrameIndex(FI);
188 }
else if (UseI.isCopy() && UseI.getOperand(0).getReg().isVirtual()) {
189 uncheckUsesOf(UseI.getOperand(0).getReg(), FI);
194void AArch64StackTaggingPreRAImpl::uncheckLoadsAndStores() {
195 for (
auto *
I : ReTags) {
196 Register TaggedReg =
I->getOperand(0).getReg();
197 int FI =
I->getOperand(1).getIndex();
198 uncheckUsesOf(TaggedReg, FI);
206 SlotWithTag(
int FI,
int Tag) : FI(FI),
Tag(
Tag) {}
207 explicit SlotWithTag(
const MachineInstr &
MI)
208 : FI(
MI.getOperand(1).getIndex()),
Tag(
MI.getOperand(4).
getImm()) {}
221 static bool isEqual(
const SlotWithTag &
A,
const SlotWithTag &
B) {
238std::optional<int> AArch64StackTaggingPreRAImpl::findFirstSlotCandidate() {
254 dbgs() <<
"AArch64StackTaggingPreRAImpl::findFirstSlotCandidate\n");
257 .stack_tagging_first_slot_opt)
261 SlotWithTag MaxScoreST{-1, -1};
263 for (
auto *
I : ReTags) {
268 Register RetagReg =
I->getOperand(0).getReg();
276 while (!WorkList.
empty()) {
278 for (
auto &UseI : MRI->use_instructions(
UseReg)) {
279 unsigned Opcode = UseI.getOpcode();
280 if (Opcode == AArch64::STGi || Opcode == AArch64::ST2Gi ||
281 Opcode == AArch64::STZGi || Opcode == AArch64::STZ2Gi ||
282 Opcode == AArch64::STGPi || Opcode == AArch64::STGloop ||
283 Opcode == AArch64::STZGloop || Opcode == AArch64::STGloop_wback ||
284 Opcode == AArch64::STZGloop_wback)
287 Register DstReg = UseI.getOperand(0).getReg();
298 int TotalScore = RetagScore[
ST] += Score;
299 if (TotalScore > MaxScore ||
300 (TotalScore == MaxScore &&
ST.FI > MaxScoreST.FI)) {
301 MaxScore = TotalScore;
306 if (MaxScoreST.FI < 0)
310 if (MaxScoreST.Tag == 0)
311 return MaxScoreST.FI;
314 SlotWithTag SwapST{-1, -1};
315 for (
auto *
I : ReTags) {
326 for (
auto *&
I : ReTags) {
329 if (ST == MaxScoreST) {
331 }
else if (ST == SwapST) {
332 TagOp.
setImm(MaxScoreST.Tag);
335 return MaxScoreST.FI;
340 MRI = &MF->getRegInfo();
344 MF->getSubtarget().getRegisterInfo());
345 MFI = &MF->getFrameInfo();
350 LLVM_DEBUG(
dbgs() <<
"********** AArch64 Stack Tagging PreRA **********\n"
351 <<
"********** Function: " << MF->getName() <<
'\n');
354 for (
auto &BB : *MF) {
356 if (
I.getOpcode() == AArch64::TAGPstack) {
357 ReTags.push_back(&
I);
358 int FI =
I.getOperand(1).getIndex();
361 assert(
I.getOperand(2).getImm() == 0);
368 for (
int FI : TaggedSlots)
374 if (mayUseUncheckedLoadStore())
375 uncheckLoadsAndStores();
380 std::optional<int> BaseSlot = findFirstSlotCandidate();
382 AFI->setTaggedBasePointerIndex(*BaseSlot);
384 for (
auto *
I : ReTags) {
385 int FI =
I->getOperand(1).getIndex();
386 int Tag =
I->getOperand(4).getImm();
388 if (
Tag == 0 && FI == BaseSlot) {
389 BuildMI(*
I->getParent(),
I, {},
TII->get(AArch64::COPY),
390 I->getOperand(0).getReg())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isSlotPreAllocated(MachineFrameInfo *MFI, int FI)
static bool isUncheckedLoadOrStoreOpcode(unsigned Opcode)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file implements a set that has insertion order iteration characteristics.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const AArch64Options & getCLOpts() const
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
@ SSPLK_None
Did not trigger a stack protector.
bool getUseLocalStackAllocationBlock() const
Get whether the local allocation blob should be allocated together or let PEI allocate the locals in ...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64StackTaggingPreRALegacyPass()
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
static bool isEqual(const SlotWithTag &A, const SlotWithTag &B)
static unsigned getHashValue(const SlotWithTag &V)
An information struct used to provide DenseMap with the various necessary components for a given valu...