blob: 9b2bedb52c04e6eecbf646f38900ccb74a780356 [file] [log] [blame]
Sanjoy Das69fad072015-06-15 18:44:27 +00001//===-- ImplicitNullChecks.cpp - Fold null checks into memory accesses ----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass turns explicit null checks of the form
11//
12// test %r10, %r10
13// je throw_npe
14// movl (%r10), %esi
15// ...
16//
17// to
18//
19// faulting_load_op("movl (%r10), %esi", throw_npe)
20// ...
21//
22// With the help of a runtime that understands the .fault_maps section,
23// faulting_load_op branches to throw_npe if executing movl (%r10), %esi incurs
24// a page fault.
25//
26//===----------------------------------------------------------------------===//
27
Sanjoy Dasb7718452015-07-09 20:13:25 +000028#include "llvm/ADT/DenseSet.h"
Sanjoy Das69fad072015-06-15 18:44:27 +000029#include "llvm/ADT/SmallVector.h"
Sanjoy Das8ee6a302015-07-06 23:32:10 +000030#include "llvm/ADT/Statistic.h"
Sanjoy Das69fad072015-06-15 18:44:27 +000031#include "llvm/CodeGen/Passes.h"
32#include "llvm/CodeGen/MachineFunction.h"
Sanjoy Dasb7718452015-07-09 20:13:25 +000033#include "llvm/CodeGen/MachineMemOperand.h"
Sanjoy Das69fad072015-06-15 18:44:27 +000034#include "llvm/CodeGen/MachineOperand.h"
35#include "llvm/CodeGen/MachineFunctionPass.h"
36#include "llvm/CodeGen/MachineInstrBuilder.h"
37#include "llvm/CodeGen/MachineRegisterInfo.h"
38#include "llvm/CodeGen/MachineModuleInfo.h"
39#include "llvm/IR/BasicBlock.h"
40#include "llvm/IR/Instruction.h"
Chen Li00038782015-08-04 04:41:34 +000041#include "llvm/IR/LLVMContext.h"
Sanjoy Das69fad072015-06-15 18:44:27 +000042#include "llvm/Support/CommandLine.h"
43#include "llvm/Support/Debug.h"
44#include "llvm/Target/TargetSubtargetInfo.h"
45#include "llvm/Target/TargetInstrInfo.h"
46
47using namespace llvm;
48
Chad Rosierc27a18f2016-03-09 16:00:35 +000049static cl::opt<int> PageSize("imp-null-check-page-size",
50 cl::desc("The page size of the target in bytes"),
51 cl::init(4096));
Sanjoy Das69fad072015-06-15 18:44:27 +000052
Sanjoy Das8ee6a302015-07-06 23:32:10 +000053#define DEBUG_TYPE "implicit-null-checks"
54
55STATISTIC(NumImplicitNullChecks,
56 "Number of explicit null checks made implicit");
57
Sanjoy Das69fad072015-06-15 18:44:27 +000058namespace {
59
60class ImplicitNullChecks : public MachineFunctionPass {
61 /// Represents one null check that can be made implicit.
62 struct NullCheck {
63 // The memory operation the null check can be folded into.
64 MachineInstr *MemOperation;
65
66 // The instruction actually doing the null check (Ptr != 0).
67 MachineInstr *CheckOperation;
68
69 // The block the check resides in.
70 MachineBasicBlock *CheckBlock;
71
Eric Christopher572e03a2015-06-19 01:53:21 +000072 // The block branched to if the pointer is non-null.
Sanjoy Das69fad072015-06-15 18:44:27 +000073 MachineBasicBlock *NotNullSucc;
74
Eric Christopher572e03a2015-06-19 01:53:21 +000075 // The block branched to if the pointer is null.
Sanjoy Das69fad072015-06-15 18:44:27 +000076 MachineBasicBlock *NullSucc;
77
78 NullCheck()
79 : MemOperation(), CheckOperation(), CheckBlock(), NotNullSucc(),
80 NullSucc() {}
81
82 explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation,
83 MachineBasicBlock *checkBlock,
84 MachineBasicBlock *notNullSucc,
85 MachineBasicBlock *nullSucc)
86 : MemOperation(memOperation), CheckOperation(checkOperation),
87 CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc) {
88 }
89 };
90
91 const TargetInstrInfo *TII = nullptr;
92 const TargetRegisterInfo *TRI = nullptr;
93 MachineModuleInfo *MMI = nullptr;
94
95 bool analyzeBlockForNullChecks(MachineBasicBlock &MBB,
96 SmallVectorImpl<NullCheck> &NullCheckList);
97 MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB,
Quentin Colombet4e1d3892016-05-02 22:58:54 +000098 MachineBasicBlock *HandlerMBB);
Sanjoy Das69fad072015-06-15 18:44:27 +000099 void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
100
101public:
102 static char ID;
103
104 ImplicitNullChecks() : MachineFunctionPass(ID) {
105 initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
106 }
107
108 bool runOnMachineFunction(MachineFunction &MF) override;
Derek Schuffad154c82016-03-28 17:05:30 +0000109
110 MachineFunctionProperties getRequiredProperties() const override {
111 return MachineFunctionProperties().set(
112 MachineFunctionProperties::Property::AllVRegsAllocated);
113 }
Sanjoy Das69fad072015-06-15 18:44:27 +0000114};
Sanjoy Dasedc394f2015-11-12 20:51:44 +0000115
116/// \brief Detect re-ordering hazards and dependencies.
117///
118/// This class keeps track of defs and uses, and can be queried if a given
119/// machine instruction can be re-ordered from after the machine instructions
120/// seen so far to before them.
121class HazardDetector {
122 DenseSet<unsigned> RegDefs;
123 DenseSet<unsigned> RegUses;
124 const TargetRegisterInfo &TRI;
125 bool hasSeenClobber;
126
127public:
128 explicit HazardDetector(const TargetRegisterInfo &TRI) :
129 TRI(TRI), hasSeenClobber(false) {}
130
131 /// \brief Make a note of \p MI for later queries to isSafeToHoist.
132 ///
133 /// May clobber this HazardDetector instance. \see isClobbered.
134 void rememberInstruction(MachineInstr *MI);
135
136 /// \brief Return true if it is safe to hoist \p MI from after all the
137 /// instructions seen so far (via rememberInstruction) to before it.
138 bool isSafeToHoist(MachineInstr *MI);
139
140 /// \brief Return true if this instance of HazardDetector has been clobbered
141 /// (i.e. has no more useful information).
142 ///
143 /// A HazardDetecter is clobbered when it sees a construct it cannot
144 /// understand, and it would have to return a conservative answer for all
145 /// future queries. Having a separate clobbered state lets the client code
146 /// bail early, without making queries about all of the future instructions
147 /// (which would have returned the most conservative answer anyway).
148 ///
149 /// Calling rememberInstruction or isSafeToHoist on a clobbered HazardDetector
150 /// is an error.
151 bool isClobbered() { return hasSeenClobber; }
152};
153}
154
155
156void HazardDetector::rememberInstruction(MachineInstr *MI) {
157 assert(!isClobbered() &&
158 "Don't add instructions to a clobbered hazard detector");
159
160 if (MI->mayStore() || MI->hasUnmodeledSideEffects()) {
161 hasSeenClobber = true;
162 return;
163 }
164
165 for (auto *MMO : MI->memoperands()) {
166 // Right now we don't want to worry about LLVM's memory model.
167 if (!MMO->isUnordered()) {
168 hasSeenClobber = true;
169 return;
170 }
171 }
172
173 for (auto &MO : MI->operands()) {
174 if (!MO.isReg() || !MO.getReg())
175 continue;
176
177 if (MO.isDef())
178 RegDefs.insert(MO.getReg());
179 else
180 RegUses.insert(MO.getReg());
181 }
182}
183
184bool HazardDetector::isSafeToHoist(MachineInstr *MI) {
185 assert(!isClobbered() && "isSafeToHoist cannot do anything useful!");
186
187 // Right now we don't want to worry about LLVM's memory model. This can be
188 // made more precise later.
189 for (auto *MMO : MI->memoperands())
190 if (!MMO->isUnordered())
191 return false;
192
193 for (auto &MO : MI->operands()) {
194 if (MO.isReg() && MO.getReg()) {
195 for (unsigned Reg : RegDefs)
196 if (TRI.regsOverlap(Reg, MO.getReg()))
197 return false; // We found a write-after-write or read-after-write
198
199 if (MO.isDef())
200 for (unsigned Reg : RegUses)
201 if (TRI.regsOverlap(Reg, MO.getReg()))
202 return false; // We found a write-after-read
203 }
204 }
205
206 return true;
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000207}
Sanjoy Das69fad072015-06-15 18:44:27 +0000208
209bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
210 TII = MF.getSubtarget().getInstrInfo();
211 TRI = MF.getRegInfo().getTargetRegisterInfo();
212 MMI = &MF.getMMI();
213
214 SmallVector<NullCheck, 16> NullCheckList;
215
216 for (auto &MBB : MF)
217 analyzeBlockForNullChecks(MBB, NullCheckList);
218
219 if (!NullCheckList.empty())
220 rewriteNullChecks(NullCheckList);
221
222 return !NullCheckList.empty();
223}
224
225/// Analyze MBB to check if its terminating branch can be turned into an
226/// implicit null check. If yes, append a description of the said null check to
227/// NullCheckList and return true, else return false.
228bool ImplicitNullChecks::analyzeBlockForNullChecks(
229 MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
230 typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
231
Sanjoy Dase8b81642015-11-12 20:51:49 +0000232 MDNode *BranchMD = nullptr;
233 if (auto *BB = MBB.getBasicBlock())
234 BranchMD = BB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit);
235
Sanjoy Das9c41a932015-06-30 21:22:32 +0000236 if (!BranchMD)
237 return false;
238
Sanjoy Das69fad072015-06-15 18:44:27 +0000239 MachineBranchPredicate MBP;
240
241 if (TII->AnalyzeBranchPredicate(MBB, MBP, true))
242 return false;
243
244 // Is the predicate comparing an integer to zero?
245 if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
246 (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
247 MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
248 return false;
249
250 // If we cannot erase the test instruction itself, then making the null check
251 // implicit does not buy us much.
252 if (!MBP.SingleUseCondition)
253 return false;
254
255 MachineBasicBlock *NotNullSucc, *NullSucc;
256
257 if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
258 NotNullSucc = MBP.TrueDest;
259 NullSucc = MBP.FalseDest;
260 } else {
261 NotNullSucc = MBP.FalseDest;
262 NullSucc = MBP.TrueDest;
263 }
264
265 // We handle the simplest case for now. We can potentially do better by using
266 // the machine dominator tree.
267 if (NotNullSucc->pred_size() != 1)
268 return false;
269
270 // Starting with a code fragment like:
271 //
272 // test %RAX, %RAX
273 // jne LblNotNull
274 //
275 // LblNull:
276 // callq throw_NullPointerException
277 //
278 // LblNotNull:
Sanjoy Dasb7718452015-07-09 20:13:25 +0000279 // Inst0
280 // Inst1
281 // ...
Sanjoy Das69fad072015-06-15 18:44:27 +0000282 // Def = Load (%RAX + <offset>)
283 // ...
284 //
285 //
286 // we want to end up with
287 //
Sanjoy Dasac9c5b12015-11-13 08:14:00 +0000288 // Def = FaultingLoad (%RAX + <offset>), LblNull
Sanjoy Das69fad072015-06-15 18:44:27 +0000289 // jmp LblNotNull ;; explicit or fallthrough
290 //
291 // LblNotNull:
Sanjoy Dasb7718452015-07-09 20:13:25 +0000292 // Inst0
293 // Inst1
Sanjoy Das69fad072015-06-15 18:44:27 +0000294 // ...
295 //
296 // LblNull:
297 // callq throw_NullPointerException
298 //
Sanjoy Dasac9c5b12015-11-13 08:14:00 +0000299 //
300 // To see why this is legal, consider the two possibilities:
301 //
302 // 1. %RAX is null: since we constrain <offset> to be less than PageSize, the
303 // load instruction dereferences the null page, causing a segmentation
304 // fault.
305 //
306 // 2. %RAX is not null: in this case we know that the load cannot fault, as
307 // otherwise the load would've faulted in the original program too and the
308 // original program would've been undefined.
309 //
310 // This reasoning cannot be extended to justify hoisting through arbitrary
311 // control flow. For instance, in the example below (in pseudo-C)
312 //
313 // if (ptr == null) { throw_npe(); unreachable; }
314 // if (some_cond) { return 42; }
315 // v = ptr->field; // LD
316 // ...
317 //
318 // we cannot (without code duplication) use the load marked "LD" to null check
319 // ptr -- clause (2) above does not apply in this case. In the above program
320 // the safety of ptr->field can be dependent on some_cond; and, for instance,
321 // ptr could be some non-null invalid reference that never gets loaded from
322 // because some_cond is always true.
Sanjoy Das69fad072015-06-15 18:44:27 +0000323
324 unsigned PointerReg = MBP.LHS.getReg();
Sanjoy Dasb7718452015-07-09 20:13:25 +0000325
Sanjoy Dasedc394f2015-11-12 20:51:44 +0000326 HazardDetector HD(*TRI);
Sanjoy Dasb7718452015-07-09 20:13:25 +0000327
328 for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE;
329 ++MII) {
330 MachineInstr *MI = &*MII;
Chad Rosierc27a18f2016-03-09 16:00:35 +0000331 unsigned BaseReg;
332 int64_t Offset;
Sanjoy Dasb7718452015-07-09 20:13:25 +0000333 if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
334 if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg &&
Sanjoy Das93d608c2015-07-20 20:31:39 +0000335 Offset < PageSize && MI->getDesc().getNumDefs() <= 1 &&
Sanjoy Dasedc394f2015-11-12 20:51:44 +0000336 HD.isSafeToHoist(MI)) {
Sanjoy Dasb7718452015-07-09 20:13:25 +0000337 NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc,
338 NullSucc);
339 return true;
340 }
341
Sanjoy Dasedc394f2015-11-12 20:51:44 +0000342 HD.rememberInstruction(MI);
343 if (HD.isClobbered())
Sanjoy Dasb7718452015-07-09 20:13:25 +0000344 return false;
Sanjoy Dasb7718452015-07-09 20:13:25 +0000345 }
346
Sanjoy Das69fad072015-06-15 18:44:27 +0000347 return false;
348}
349
350/// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
351/// instruction. The FAULTING_LOAD_OP instruction does the same load as LoadMI
Quentin Colombet4e1d3892016-05-02 22:58:54 +0000352/// (defining the same register), and branches to HandlerMBB if the load
Sanjoy Das69fad072015-06-15 18:44:27 +0000353/// faults. The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
Quentin Colombet4e1d3892016-05-02 22:58:54 +0000354MachineInstr *
355ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
356 MachineBasicBlock *MBB,
357 MachineBasicBlock *HandlerMBB) {
Sanjoy Das93d608c2015-07-20 20:31:39 +0000358 const unsigned NoRegister = 0; // Guaranteed to be the NoRegister value for
359 // all targets.
360
Sanjoy Das69fad072015-06-15 18:44:27 +0000361 DebugLoc DL;
362 unsigned NumDefs = LoadMI->getDesc().getNumDefs();
Sanjoy Das93d608c2015-07-20 20:31:39 +0000363 assert(NumDefs <= 1 && "other cases unhandled!");
Sanjoy Das69fad072015-06-15 18:44:27 +0000364
Sanjoy Das93d608c2015-07-20 20:31:39 +0000365 unsigned DefReg = NoRegister;
366 if (NumDefs != 0) {
367 DefReg = LoadMI->defs().begin()->getReg();
368 assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
369 "expected exactly one def!");
370 }
Sanjoy Das69fad072015-06-15 18:44:27 +0000371
372 auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
Quentin Colombet4e1d3892016-05-02 22:58:54 +0000373 .addMBB(HandlerMBB)
Sanjoy Das69fad072015-06-15 18:44:27 +0000374 .addImm(LoadMI->getOpcode());
375
376 for (auto &MO : LoadMI->uses())
377 MIB.addOperand(MO);
378
379 MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
380
381 return MIB;
382}
383
384/// Rewrite the null checks in NullCheckList into implicit null checks.
385void ImplicitNullChecks::rewriteNullChecks(
386 ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
387 DebugLoc DL;
388
389 for (auto &NC : NullCheckList) {
Sanjoy Das69fad072015-06-15 18:44:27 +0000390 // Remove the conditional branch dependent on the null check.
391 unsigned BranchesRemoved = TII->RemoveBranch(*NC.CheckBlock);
392 (void)BranchesRemoved;
393 assert(BranchesRemoved > 0 && "expected at least one branch!");
394
395 // Insert a faulting load where the conditional branch was originally. We
396 // check earlier ensures that this bit of code motion is legal. We do not
397 // touch the successors list for any basic block since we haven't changed
398 // control flow, we've just made it implicit.
Quentin Colombet12b69912016-04-27 23:26:40 +0000399 MachineInstr *FaultingLoad =
Quentin Colombet4e1d3892016-05-02 22:58:54 +0000400 insertFaultingLoad(NC.MemOperation, NC.CheckBlock, NC.NullSucc);
Quentin Colombet26dab3a2016-05-03 18:09:06 +0000401 // Now the values defined by MemOperation, if any, are live-in of
402 // the block of MemOperation.
403 // The original load operation may define implicit-defs alongside
404 // the loaded value.
405 MachineBasicBlock *MBB = NC.MemOperation->getParent();
406 for (const MachineOperand &MO : FaultingLoad->operands()) {
407 if (!MO.isReg() || !MO.isDef())
408 continue;
409 unsigned Reg = MO.getReg();
410 if (!Reg || MBB->isLiveIn(Reg))
411 continue;
412 MBB->addLiveIn(Reg);
Quentin Colombet12b69912016-04-27 23:26:40 +0000413 }
Sanjoy Dasc3a8e392015-07-09 20:13:31 +0000414 NC.MemOperation->eraseFromParent();
Sanjoy Das69fad072015-06-15 18:44:27 +0000415 NC.CheckOperation->eraseFromParent();
416
417 // Insert an *unconditional* branch to not-null successor.
418 TII->InsertBranch(*NC.CheckBlock, NC.NotNullSucc, nullptr, /*Cond=*/None,
419 DL);
420
Sanjoy Das8ee6a302015-07-06 23:32:10 +0000421 NumImplicitNullChecks++;
Sanjoy Das69fad072015-06-15 18:44:27 +0000422 }
423}
424
425char ImplicitNullChecks::ID = 0;
426char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
427INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
428 "Implicit null checks", false, false)
429INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
430 "Implicit null checks", false, false)