30#define DEBUG_TYPE "aarch64-stack-tagging-pre-ra"
37 "Unconditionally apply unchecked-ld-st optimization (even for large "
38 "stack frames, or in the presence of variable sized allocas)."),
43 "apply unchecked-ld-st when the target is definitely within range"),
48 cl::desc(
"Apply first slot optimization for stack tagging "
49 "(eliminate ADDG Rt, Rn, 0, 0)."));
67 bool mayUseUncheckedLoadStore();
68 void uncheckUsesOf(
unsigned TaggedReg,
int FI);
69 void uncheckLoadsAndStores();
70 std::optional<int> findFirstSlotCandidate();
74 return "AArch64 Stack Tagging PreRA";
84char AArch64StackTaggingPreRA::ID = 0;
87 "AArch64 Stack Tagging PreRA Pass",
false,
false)
92 return new AArch64StackTaggingPreRA();
97 case AArch64::LDRBBui:
98 case AArch64::LDRHHui:
100 case AArch64::LDRXui:
102 case AArch64::LDRBui:
103 case AArch64::LDRHui:
104 case AArch64::LDRSui:
105 case AArch64::LDRDui:
106 case AArch64::LDRQui:
108 case AArch64::LDRSHWui:
109 case AArch64::LDRSHXui:
111 case AArch64::LDRSBWui:
112 case AArch64::LDRSBXui:
114 case AArch64::LDRSWui:
116 case AArch64::STRBBui:
117 case AArch64::STRHHui:
118 case AArch64::STRWui:
119 case AArch64::STRXui:
121 case AArch64::STRBui:
122 case AArch64::STRHui:
123 case AArch64::STRSui:
124 case AArch64::STRDui:
125 case AArch64::STRQui:
133 case AArch64::LDPSWi:
146bool AArch64StackTaggingPreRA::mayUseUncheckedLoadStore() {
163 unsigned FrameSize = 0;
164 for (
unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i)
165 FrameSize += MFI->getObjectSize(i);
166 bool EntireFrameReachableFromSP = FrameSize < 0xf00;
167 return !MFI->hasVarSizedObjects() && EntireFrameReachableFromSP;
170void AArch64StackTaggingPreRA::uncheckUsesOf(
unsigned TaggedReg,
int FI) {
175 unsigned OpIdx =
TII->getLoadStoreImmIdx(UseI.getOpcode()) - 1;
176 if (UseI.getOperand(
OpIdx).isReg() &&
177 UseI.getOperand(
OpIdx).getReg() == TaggedReg) {
178 UseI.getOperand(
OpIdx).ChangeToFrameIndex(FI);
181 }
else if (UseI.isCopy() && UseI.getOperand(0).getReg().isVirtual()) {
182 uncheckUsesOf(UseI.getOperand(0).getReg(), FI);
187void AArch64StackTaggingPreRA::uncheckLoadsAndStores() {
188 for (
auto *
I : ReTags) {
189 Register TaggedReg =
I->getOperand(0).getReg();
190 int FI =
I->getOperand(1).getIndex();
191 uncheckUsesOf(TaggedReg, FI);
199 SlotWithTag(
int FI,
int Tag) : FI(FI),
Tag(
Tag) {}
201 : FI(
MI.getOperand(1).getIndex()),
Tag(
MI.getOperand(4).
getImm()) {}
216 static bool isEqual(
const SlotWithTag &
A,
const SlotWithTag &
B) {
233std::optional<int> AArch64StackTaggingPreRA::findFirstSlotCandidate() {
248 LLVM_DEBUG(
dbgs() <<
"AArch64StackTaggingPreRA::findFirstSlotCandidate\n");
253 SlotWithTag MaxScoreST{-1, -1};
255 for (
auto *
I : ReTags) {
260 Register RetagReg =
I->getOperand(0).getReg();
268 while (!WorkList.
empty()) {
270 for (
auto &UseI :
MRI->use_instructions(
UseReg)) {
271 unsigned Opcode = UseI.getOpcode();
272 if (Opcode == AArch64::STGi || Opcode == AArch64::ST2Gi ||
273 Opcode == AArch64::STZGi || Opcode == AArch64::STZ2Gi ||
274 Opcode == AArch64::STGPi || Opcode == AArch64::STGloop ||
275 Opcode == AArch64::STZGloop || Opcode == AArch64::STGloop_wback ||
276 Opcode == AArch64::STZGloop_wback)
279 Register DstReg = UseI.getOperand(0).getReg();
290 int TotalScore = RetagScore[
ST] += Score;
291 if (TotalScore > MaxScore ||
292 (TotalScore == MaxScore &&
ST.FI > MaxScoreST.FI)) {
293 MaxScore = TotalScore;
298 if (MaxScoreST.FI < 0)
302 if (MaxScoreST.Tag == 0)
303 return MaxScoreST.FI;
306 SlotWithTag SwapST{-1, -1};
307 for (
auto *
I : ReTags) {
318 for (
auto *&
I : ReTags) {
321 if (ST == MaxScoreST) {
323 }
else if (ST == SwapST) {
324 TagOp.
setImm(MaxScoreST.Tag);
327 return MaxScoreST.FI;
330bool AArch64StackTaggingPreRA::runOnMachineFunction(
MachineFunction &Func) {
332 MRI = &MF->getRegInfo();
336 MF->getSubtarget().getRegisterInfo());
337 MFI = &MF->getFrameInfo();
342 LLVM_DEBUG(
dbgs() <<
"********** AArch64 Stack Tagging PreRA **********\n"
343 <<
"********** Function: " << MF->getName() <<
'\n');
346 for (
auto &BB : *MF) {
348 if (
I.getOpcode() == AArch64::TAGPstack) {
349 ReTags.push_back(&
I);
350 int FI =
I.getOperand(1).getIndex();
353 assert(
I.getOperand(2).getImm() == 0);
360 for (
int FI : TaggedSlots)
366 if (mayUseUncheckedLoadStore())
367 uncheckLoadsAndStores();
372 std::optional<int> BaseSlot = findFirstSlotCandidate();
374 AFI->setTaggedBasePointerIndex(*BaseSlot);
376 for (
auto *
I : ReTags) {
377 int FI =
I->getOperand(1).getIndex();
378 int Tag =
I->getOperand(4).getImm();
380 if (Tag == 0 && FI == BaseSlot) {
381 BuildMI(*
I->getParent(),
I, {},
TII->get(AArch64::COPY),
382 I->getOperand(0).getReg())
384 I->eraseFromParent();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 stack tagging pre ra
static bool isSlotPreAllocated(MachineFrameInfo *MFI, int FI)
static cl::opt< UncheckedLdStMode > ClUncheckedLdSt("stack-tagging-unchecked-ld-st", cl::Hidden, cl::init(UncheckedSafe), cl::desc("Unconditionally apply unchecked-ld-st optimization (even for large " "stack frames, or in the presence of variable sized allocas)."), cl::values(clEnumValN(UncheckedNever, "never", "never apply unchecked-ld-st"), clEnumValN(UncheckedSafe, "safe", "apply unchecked-ld-st when the target is definitely within range"), clEnumValN(UncheckedAlways, "always", "always apply unchecked-ld-st")))
static cl::opt< bool > ClFirstSlot("stack-tagging-first-slot-opt", cl::Hidden, cl::init(true), cl::desc("Apply first slot optimization for stack tagging " "(eliminate ADDG Rt, Rn, 0, 0)."))
static bool isUncheckedLoadOrStoreOpcode(unsigned Opcode)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
std::optional< std::vector< StOtherPiece > > Other
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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...
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Pass interface - Implemented by all 'passes'.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
StringRef - 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
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.
FunctionPass * createAArch64StackTaggingPreRAPass()
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...
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
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 SlotWithTag getTombstoneKey()
static SlotWithTag getEmptyKey()
static unsigned getHashValue(const SlotWithTag &V)
An information struct used to provide DenseMap with the various necessary components for a given valu...