Add gfx950 mfma instructions to ROCDL dialect (#123361)
[llvm-project.git] / llvm / lib / Target / X86 / X86ArgumentStackSlotRebase.cpp
blob89a2146227bdd4231e33e0c28ce5311794c20bfc
1 //===---- X86ArgumentStackSlotRebase.cpp - rebase argument stack slot -----===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass replace the frame register with a GPR virtual register and set
10 // the stack offset for each instruction which reference argument from stack.
12 //===----------------------------------------------------------------------===//
14 #include "X86.h"
15 #include "X86MachineFunctionInfo.h"
16 #include "X86RegisterInfo.h"
17 #include "X86Subtarget.h"
18 #include "llvm/CodeGen/MachineBasicBlock.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/TargetRegisterInfo.h"
26 #include "llvm/CodeGen/TargetSubtargetInfo.h"
27 #include "llvm/IR/Attributes.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/InitializePasses.h"
30 #include "llvm/Pass.h"
32 using namespace llvm;
34 #define DEBUG_TYPE "x86argumentstackrebase"
36 namespace {
38 class X86ArgumentStackSlotPass : public MachineFunctionPass {
40 public:
41 static char ID; // Pass identification, replacement for typeid
43 explicit X86ArgumentStackSlotPass() : MachineFunctionPass(ID) {}
45 bool runOnMachineFunction(MachineFunction &MF) override;
47 void getAnalysisUsage(AnalysisUsage &AU) const override {
48 AU.setPreservesCFG();
49 MachineFunctionPass::getAnalysisUsage(AU);
53 } // end anonymous namespace
55 char X86ArgumentStackSlotPass::ID = 0;
57 INITIALIZE_PASS(X86ArgumentStackSlotPass, DEBUG_TYPE, "Argument Stack Rebase",
58 false, false)
60 FunctionPass *llvm::createX86ArgumentStackSlotPass() {
61 return new X86ArgumentStackSlotPass();
64 static Register getArgBaseReg(MachineFunction &MF) {
65 MachineRegisterInfo &MRI = MF.getRegInfo();
66 const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
67 const Function &F = MF.getFunction();
68 CallingConv::ID CC = F.getCallingConv();
69 Register NoReg;
70 const TargetRegisterClass *RC = nullptr;
71 switch (CC) {
72 // We need a virtual register in case there is inline assembly
73 // clobber argument base register.
74 case CallingConv::C:
75 RC = STI.is64Bit() ? &X86::GR64_ArgRefRegClass : &X86::GR32_ArgRefRegClass;
76 break;
77 case CallingConv::X86_RegCall:
78 // FIXME: For regcall there is no scratch register on 32-bit target.
79 // We may use a callee saved register as argument base register and
80 // save it before being changed as base pointer. We need DW_CFA to
81 // indicate where the callee saved register is saved, so that it can
82 // be correctly unwind.
83 // push ebx
84 // mov ebx, esp
85 // and esp, -128
86 // ...
87 // pop ebx
88 // ret
89 RC = STI.is64Bit() ? &X86::GR64_ArgRefRegClass : nullptr;
90 break;
91 // TODO: Refine register class for each calling convention.
92 default:
93 break;
95 if (RC)
96 return MRI.createVirtualRegister(RC);
97 else
98 return NoReg;
101 bool X86ArgumentStackSlotPass::runOnMachineFunction(MachineFunction &MF) {
102 const Function &F = MF.getFunction();
103 MachineFrameInfo &MFI = MF.getFrameInfo();
104 const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
105 const X86RegisterInfo *TRI = STI.getRegisterInfo();
106 const X86InstrInfo *TII = STI.getInstrInfo();
107 X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
108 bool Changed = false;
110 if (F.hasFnAttribute(Attribute::Naked))
111 return false;
112 // Only support Linux and ELF.
113 if (!STI.isTargetLinux() && !STI.isTargetELF())
114 return false;
115 if (!TRI->hasBasePointer(MF))
116 return false;
117 // Don't support X32
118 if (STI.isTarget64BitILP32())
119 return false;
121 Register BasePtr = TRI->getBaseRegister();
122 auto IsBaseRegisterClobbered = [&]() {
123 for (MachineBasicBlock &MBB : MF) {
124 for (MachineInstr &MI : MBB) {
125 if (!MI.isInlineAsm())
126 continue;
127 for (MachineOperand &MO : MI.operands()) {
128 if (!MO.isReg())
129 continue;
130 Register Reg = MO.getReg();
131 if (!Reg.isPhysical())
132 continue;
133 if (TRI->isSuperOrSubRegisterEq(BasePtr, Reg))
134 return true;
138 return false;
140 if (!IsBaseRegisterClobbered())
141 return false;
143 Register ArgBaseReg = getArgBaseReg(MF);
144 if (!ArgBaseReg.isValid())
145 return false;
146 // leal 4(%esp), %reg
147 MachineBasicBlock &MBB = MF.front();
148 MachineBasicBlock::iterator MBBI = MBB.begin();
149 DebugLoc DL;
150 // Emit instruction to copy get stack pointer to a virtual register
151 // and save the instruction to x86 machine functon info. We can get
152 // physical register of ArgBaseReg after register allocation. The
153 // stack slot is used to save/restore argument base pointer. We can
154 // get the index from the instruction.
155 unsigned SlotSize = TRI->getSlotSize();
156 int FI = MFI.CreateSpillStackObject(SlotSize, Align(SlotSize));
157 // Use pseudo LEA to prevent the instruction from being eliminated.
158 // TODO: if it is duplicated we can expand it to lea.
159 MachineInstr *LEA =
160 BuildMI(MBB, MBBI, DL,
161 TII->get(STI.is64Bit() ? X86::PLEA64r : X86::PLEA32r), ArgBaseReg)
162 .addFrameIndex(FI)
163 .addImm(1)
164 .addUse(X86::NoRegister)
165 .addImm(SlotSize)
166 .addUse(X86::NoRegister)
167 .setMIFlag(MachineInstr::FrameSetup);
168 X86FI->setStackPtrSaveMI(LEA);
170 for (MachineBasicBlock &MBB : MF) {
171 for (MachineInstr &MI : MBB) {
172 int I = 0;
173 for (MachineOperand &MO : MI.operands()) {
174 if (MO.isFI()) {
175 int Idx = MO.getIndex();
176 if (!MFI.isFixedObjectIndex(Idx))
177 continue;
178 int64_t Offset = MFI.getObjectOffset(Idx);
179 if (Offset < 0)
180 continue;
181 // TODO replace register for debug instruction
182 if (MI.isDebugInstr())
183 continue;
184 // Replace frame register with argument base pointer and its offset.
185 TRI->eliminateFrameIndex(MI.getIterator(), I, ArgBaseReg, Offset);
186 Changed = true;
188 ++I;
193 return Changed;