llvm.org GIT mirror llvm / b4b2cc0
Merging r323915: ------------------------------------------------------------------------ r323915 | chandlerc | 2018-01-31 12:56:37 -0800 (Wed, 31 Jan 2018) | 17 lines [x86] Make the retpoline thunk insertion a machine function pass. Summary: This removes the need for a machine module pass using some deeply questionable hacks. This should address PR36123 which is a case where in full LTO the memory usage of a machine module pass actually ended up being significant. We should revert this on trunk as soon as we understand and fix the memory usage issue, but we should include this in any backports of retpolines themselves. Reviewers: echristo, MatzeB Subscribers: sanjoy, mcrosier, mehdi_amini, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D42726 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@324009 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 1 year, 6 months ago
3 changed file(s) with 89 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
9999 FunctionPass *createX86EvexToVexInsts();
100100
101101 /// This pass creates the thunks for the retpoline feature.
102 ModulePass *createX86RetpolineThunksPass();
102 FunctionPass *createX86RetpolineThunksPass();
103103
104104 InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM,
105105 X86Subtarget &,
3737
3838 #define DEBUG_TYPE "x86-retpoline-thunks"
3939
40 static const char ThunkNamePrefix[] = "__llvm_retpoline_";
41 static const char R11ThunkName[] = "__llvm_retpoline_r11";
42 static const char EAXThunkName[] = "__llvm_retpoline_eax";
43 static const char ECXThunkName[] = "__llvm_retpoline_ecx";
44 static const char EDXThunkName[] = "__llvm_retpoline_edx";
45 static const char PushThunkName[] = "__llvm_retpoline_push";
46
4047 namespace {
41 class X86RetpolineThunks : public ModulePass {
48 class X86RetpolineThunks : public MachineFunctionPass {
4249 public:
4350 static char ID;
4451
45 X86RetpolineThunks() : ModulePass(ID) {}
52 X86RetpolineThunks() : MachineFunctionPass(ID) {}
4653
4754 StringRef getPassName() const override { return "X86 Retpoline Thunks"; }
4855
49 bool runOnModule(Module &M) override;
56 bool doInitialization(Module &M) override;
57 bool runOnMachineFunction(MachineFunction &F) override;
5058
5159 void getAnalysisUsage(AnalysisUsage &AU) const override {
60 MachineFunctionPass::getAnalysisUsage(AU);
5261 AU.addRequired();
5362 AU.addPreserved();
5463 }
6069 const X86Subtarget *STI;
6170 const X86InstrInfo *TII;
6271
63 Function *createThunkFunction(Module &M, StringRef Name);
72 bool InsertedThunks;
73
74 void createThunkFunction(Module &M, StringRef Name);
6475 void insertRegReturnAddrClobber(MachineBasicBlock &MBB, unsigned Reg);
6576 void insert32BitPushReturnAddrClobber(MachineBasicBlock &MBB);
66 void createThunk(Module &M, StringRef NameSuffix,
67 Optional Reg = None);
77 void populateThunk(MachineFunction &MF, Optional Reg = None);
6878 };
6979
7080 } // end anonymous namespace
7181
72 ModulePass *llvm::createX86RetpolineThunksPass() {
82 FunctionPass *llvm::createX86RetpolineThunksPass() {
7383 return new X86RetpolineThunks();
7484 }
7585
7686 char X86RetpolineThunks::ID = 0;
7787
78 bool X86RetpolineThunks::runOnModule(Module &M) {
88 bool X86RetpolineThunks::doInitialization(Module &M) {
89 InsertedThunks = false;
90 return false;
91 }
92
93 bool X86RetpolineThunks::runOnMachineFunction(MachineFunction &MF) {
7994 DEBUG(dbgs() << getPassName() << '\n');
8095
81 auto *TPC = getAnalysisIfAvailable();
82 assert(TPC && "X86-specific target pass should not be run without a target "
83 "pass config!");
96 TM = &MF.getTarget();;
97 STI = &MF.getSubtarget();
98 TII = STI->getInstrInfo();
99 Is64Bit = TM->getTargetTriple().getArch() == Triple::x86_64;
84100
85101 MMI = &getAnalysis();
86 TM = &TPC->getTM();
87 Is64Bit = TM->getTargetTriple().getArch() == Triple::x86_64;
88
89 // Only add a thunk if we have at least one function that has the retpoline
90 // feature enabled in its subtarget.
91 // FIXME: Conditionalize on indirect calls so we don't emit a thunk when
92 // nothing will end up calling it.
93 // FIXME: It's a little silly to look at every function just to enumerate
94 // the subtargets, but eventually we'll want to look at them for indirect
95 // calls, so maybe this is OK.
96 if (!llvm::any_of(M, [&](const Function &F) {
97 // Save the subtarget we find for use in emitting the subsequent
98 // thunk.
99 STI = &TM->getSubtarget(F);
100 return STI->useRetpoline() && !STI->useRetpolineExternalThunk();
101 }))
102 return false;
103
104 // If we have a relevant subtarget, get the instr info as well.
105 TII = STI->getInstrInfo();
106
102 Module &M = const_cast(*MMI->getModule());
103
104 // If this function is not a thunk, check to see if we need to insert
105 // a thunk.
106 if (!MF.getName().startswith(ThunkNamePrefix)) {
107 // If we've already inserted a thunk, nothing else to do.
108 if (InsertedThunks)
109 return false;
110
111 // Only add a thunk if one of the functions has the retpoline feature
112 // enabled in its subtarget, and doesn't enable external thunks.
113 // FIXME: Conditionalize on indirect calls so we don't emit a thunk when
114 // nothing will end up calling it.
115 // FIXME: It's a little silly to look at every function just to enumerate
116 // the subtargets, but eventually we'll want to look at them for indirect
117 // calls, so maybe this is OK.
118 if (!STI->useRetpoline() || STI->useRetpolineExternalThunk())
119 return false;
120
121 // Otherwise, we need to insert the thunk.
122 // WARNING: This is not really a well behaving thing to do in a function
123 // pass. We extract the module and insert a new function (and machine
124 // function) directly into the module.
125 if (Is64Bit)
126 createThunkFunction(M, R11ThunkName);
127 else
128 for (StringRef Name :
129 {EAXThunkName, ECXThunkName, EDXThunkName, PushThunkName})
130 createThunkFunction(M, Name);
131 InsertedThunks = true;
132 return true;
133 }
134
135 // If this *is* a thunk function, we need to populate it with the correct MI.
107136 if (Is64Bit) {
137 assert(MF.getName() == "__llvm_retpoline_r11" &&
138 "Should only have an r11 thunk on 64-bit targets");
139
108140 // __llvm_retpoline_r11:
109141 // callq .Lr11_call_target
110142 // .Lr11_capture_spec:
115147 // .Lr11_call_target:
116148 // movq %r11, (%rsp)
117149 // retq
118
119 createThunk(M, "r11", X86::R11);
150 populateThunk(MF, X86::R11);
120151 } else {
121152 // For 32-bit targets we need to emit a collection of thunks for various
122153 // possible scratch registers as well as a fallback that is used when
160191 // popl 8(%esp) # Pop RA to final RA
161192 // popl (%esp) # Pop callee to next top of stack
162193 // retl # Ret to callee
163 createThunk(M, "eax", X86::EAX);
164 createThunk(M, "ecx", X86::ECX);
165 createThunk(M, "edx", X86::EDX);
166 createThunk(M, "push");
194 if (MF.getName() == EAXThunkName)
195 populateThunk(MF, X86::EAX);
196 else if (MF.getName() == ECXThunkName)
197 populateThunk(MF, X86::ECX);
198 else if (MF.getName() == EDXThunkName)
199 populateThunk(MF, X86::EDX);
200 else if (MF.getName() == PushThunkName)
201 populateThunk(MF);
202 else
203 llvm_unreachable("Invalid thunk name on x86-32!");
167204 }
168205
169206 return true;
170207 }
171208
172 Function *X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
209 void X86RetpolineThunks::createThunkFunction(Module &M, StringRef Name) {
210 assert(Name.startswith(ThunkNamePrefix) &&
211 "Created a thunk with an unexpected prefix!");
212
173213 LLVMContext &Ctx = M.getContext();
174214 auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
175215 Function *F =
189229 IRBuilder<> Builder(Entry);
190230
191231 Builder.CreateRetVoid();
192 return F;
193232 }
194233
195234 void X86RetpolineThunks::insertRegReturnAddrClobber(MachineBasicBlock &MBB,
199238 addRegOffset(BuildMI(&MBB, DebugLoc(), TII->get(MovOpc)), SPReg, false, 0)
200239 .addReg(Reg);
201240 }
241
202242 void X86RetpolineThunks::insert32BitPushReturnAddrClobber(
203243 MachineBasicBlock &MBB) {
204244 // The instruction sequence we use to replace the return address without
224264 false, 0);
225265 }
226266
227 void X86RetpolineThunks::createThunk(Module &M, StringRef NameSuffix,
228 Optional Reg) {
229 Function &F =
230 *createThunkFunction(M, (Twine("__llvm_retpoline_") + NameSuffix).str());
231 MachineFunction &MF = MMI->getOrCreateMachineFunction(F);
232
267 void X86RetpolineThunks::populateThunk(MachineFunction &MF,
268 Optional Reg) {
233269 // Set MF properties. We never use vregs...
234270 MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
235271
236 BasicBlock &OrigEntryBB = F.getEntryBlock();
237 MachineBasicBlock *Entry = MF.CreateMachineBasicBlock(&OrigEntryBB);
238 MachineBasicBlock *CaptureSpec = MF.CreateMachineBasicBlock(&OrigEntryBB);
239 MachineBasicBlock *CallTarget = MF.CreateMachineBasicBlock(&OrigEntryBB);
240
241 MF.push_back(Entry);
272 MachineBasicBlock *Entry = &MF.front();
273 Entry->clear();
274
275 MachineBasicBlock *CaptureSpec = MF.CreateMachineBasicBlock(Entry->getBasicBlock());
276 MachineBasicBlock *CallTarget = MF.CreateMachineBasicBlock(Entry->getBasicBlock());
242277 MF.push_back(CaptureSpec);
243278 MF.push_back(CallTarget);
244279
5555 ; CHECK-NEXT: Machine Natural Loop Construction
5656 ; CHECK-NEXT: Insert XRay ops
5757 ; CHECK-NEXT: Implement the 'patchable-function' attribute
58 ; CHECK-NEXT: X86 Retpoline Thunks
59 ; CHECK-NEXT: FunctionPass Manager
58 ; CHECK-NEXT: X86 Retpoline Thunks
6059 ; CHECK-NEXT: Lazy Machine Block Frequency Analysis
6160 ; CHECK-NEXT: Machine Optimization Remark Emitter
6261 ; CHECK-NEXT: MachineDominator Tree Construction