Go to the documentation of this file.
34 #define DEBUG_TYPE "aarch64-stack-tagging-pre-ra"
42 "Unconditionally apply unchecked-ld-st optimization (even for large "
43 "stack frames, or in the presence of variable sized allocas)."),
48 "apply unchecked-ld-st when the target is definitely within range"),
53 cl::desc(
"Apply first slot optimization for stack tagging "
54 "(eliminate ADDG Rt, Rn, 0, 0)."));
74 bool mayUseUncheckedLoadStore();
75 void uncheckUsesOf(
unsigned TaggedReg,
int FI);
76 void uncheckLoadsAndStores();
77 std::optional<int> findFirstSlotCandidate();
81 return "AArch64 Stack Tagging PreRA";
94 "AArch64 Stack Tagging PreRA Pass",
false,
false)
99 return new AArch64StackTaggingPreRA();
104 case AArch64::LDRBBui:
105 case AArch64::LDRHHui:
106 case AArch64::LDRWui:
107 case AArch64::LDRXui:
109 case AArch64::LDRBui:
110 case AArch64::LDRHui:
111 case AArch64::LDRSui:
112 case AArch64::LDRDui:
113 case AArch64::LDRQui:
115 case AArch64::LDRSHWui:
116 case AArch64::LDRSHXui:
118 case AArch64::LDRSBWui:
119 case AArch64::LDRSBXui:
121 case AArch64::LDRSWui:
123 case AArch64::STRBBui:
124 case AArch64::STRHHui:
125 case AArch64::STRWui:
126 case AArch64::STRXui:
128 case AArch64::STRBui:
129 case AArch64::STRHui:
130 case AArch64::STRSui:
131 case AArch64::STRDui:
132 case AArch64::STRQui:
140 case AArch64::LDPSWi:
153 bool AArch64StackTaggingPreRA::mayUseUncheckedLoadStore() {
170 unsigned FrameSize = 0;
173 bool EntireFrameReachableFromSP = FrameSize < 0xf00;
177 void AArch64StackTaggingPreRA::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);
194 void AArch64StackTaggingPreRA::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) {}
208 : FI(
MI.getOperand(1).getIndex()),
Tag(
MI.getOperand(4).getImm()) {}
209 bool operator==(
const SlotWithTag &Other)
const {
223 static bool isEqual(
const SlotWithTag &A,
const SlotWithTag &
B) {
240 std::optional<int> AArch64StackTaggingPreRA::findFirstSlotCandidate() {
255 LLVM_DEBUG(
dbgs() <<
"AArch64StackTaggingPreRA::findFirstSlotCandidate\n");
260 SlotWithTag MaxScoreST{-1, -1};
262 for (
auto *
I : ReTags) {
267 Register RetagReg =
I->getOperand(0).getReg();
273 WorkList.push_back(RetagReg);
275 while (!WorkList.empty()) {
278 unsigned Opcode = UseI.getOpcode();
279 if (Opcode == AArch64::STGOffset || Opcode == AArch64::ST2GOffset ||
280 Opcode == AArch64::STZGOffset || Opcode == AArch64::STZ2GOffset ||
281 Opcode == AArch64::STGPi || Opcode == AArch64::STGloop ||
282 Opcode == AArch64::STZGloop || Opcode == AArch64::STGloop_wback ||
283 Opcode == AArch64::STZGloop_wback)
286 Register DstReg = UseI.getOperand(0).getReg();
288 WorkList.push_back(DstReg);
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;
338 bool AArch64StackTaggingPreRA::runOnMachineFunction(
MachineFunction &Func) {
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();
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())
392 I->eraseFromParent();
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
This is an optimization pass for GlobalISel generic memory operations.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual const TargetInstrInfo * getInstrInfo() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
void setImm(int64_t immVal)
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
bool isObjectPreAllocated(int ObjectIdx) const
Return true if the object was pre-allocated into the local block.
void setTaggedBasePointerIndex(int Index)
int getObjectIndexEnd() const
Return one past the maximum frame object index.
unsigned const TargetRegisterInfo * TRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
An information struct used to provide DenseMap with the various necessary components for a given valu...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind)
Represent the analysis usage information of a pass.
const HexagonInstrInfo * TII
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MachineOperand class - Representation of each machine instruction operand.
static unsigned getHashValue(const SlotWithTag &V)
@ SSPLK_None
Did not trigger a stack protector.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
static bool isSlotPreAllocated(MachineFrameInfo *MFI, int FI)
static SlotWithTag getEmptyKey()
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
aarch64 stack tagging pre ra
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Representation of each machine instruction.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
static Register UseReg(const MachineOperand &MO)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
initializer< Ty > init(const Ty &Val)
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...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
bool operator==(uint64_t V1, const APInt &V2)
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)."))
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
INITIALIZE_PASS_BEGIN(AArch64StackTaggingPreRA, "aarch64-stack-tagging-pre-ra", "AArch64 Stack Tagging PreRA Pass", false, false) INITIALIZE_PASS_END(AArch64StackTaggingPreRA
bool insert(const value_type &X)
Insert a new element into the SetVector.
void initializeAArch64StackTaggingPreRAPass(PassRegistry &)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
FunctionPass * createAArch64StackTaggingPreRAPass()
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static SlotWithTag getTombstoneKey()
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
static bool isUncheckedLoadOrStoreOpcode(unsigned Opcode)
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")))
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Pass interface - Implemented by all 'passes'.
std::optional< std::vector< StOtherPiece > > Other
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
S is passed via registers r2 But gcc stores them to the stack
A SetVector that performs no allocations if smaller than a certain size.
FunctionPass class - This class is used to implement most global optimizations.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
static bool isEqual(const SlotWithTag &A, const SlotWithTag &B)