LLVM  3.7.0
ImplicitNullChecks.cpp
Go to the documentation of this file.
1 //===-- 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 
28 #include "llvm/ADT/DenseSet.h"
29 #include "llvm/ADT/SmallVector.h"
30 #include "llvm/ADT/Statistic.h"
31 #include "llvm/CodeGen/Passes.h"
39 #include "llvm/IR/BasicBlock.h"
40 #include "llvm/IR/Instruction.h"
42 #include "llvm/Support/Debug.h"
45 
46 using namespace llvm;
47 
48 static cl::opt<unsigned> PageSize("imp-null-check-page-size",
49  cl::desc("The page size of the target in "
50  "bytes"),
51  cl::init(4096));
52 
53 #define DEBUG_TYPE "implicit-null-checks"
54 
55 STATISTIC(NumImplicitNullChecks,
56  "Number of explicit null checks made implicit");
57 
58 namespace {
59 
60 class 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 
72  // The block branched to if the pointer is non-null.
73  MachineBasicBlock *NotNullSucc;
74 
75  // The block branched to if the pointer is null.
76  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,
98  MCSymbol *HandlerLabel);
99  void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
100 
101 public:
102  static char ID;
103 
104  ImplicitNullChecks() : MachineFunctionPass(ID) {
106  }
107 
108  bool runOnMachineFunction(MachineFunction &MF) override;
109 };
110 }
111 
112 bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
113  TII = MF.getSubtarget().getInstrInfo();
114  TRI = MF.getRegInfo().getTargetRegisterInfo();
115  MMI = &MF.getMMI();
116 
117  SmallVector<NullCheck, 16> NullCheckList;
118 
119  for (auto &MBB : MF)
120  analyzeBlockForNullChecks(MBB, NullCheckList);
121 
122  if (!NullCheckList.empty())
123  rewriteNullChecks(NullCheckList);
124 
125  return !NullCheckList.empty();
126 }
127 
128 /// Analyze MBB to check if its terminating branch can be turned into an
129 /// implicit null check. If yes, append a description of the said null check to
130 /// NullCheckList and return true, else return false.
131 bool ImplicitNullChecks::analyzeBlockForNullChecks(
132  MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
133  typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
134 
135  MDNode *BranchMD =
136  MBB.getBasicBlock()
137  ? MBB.getBasicBlock()->getTerminator()->getMetadata("make.implicit")
138  : nullptr;
139  if (!BranchMD)
140  return false;
141 
142  MachineBranchPredicate MBP;
143 
144  if (TII->AnalyzeBranchPredicate(MBB, MBP, true))
145  return false;
146 
147  // Is the predicate comparing an integer to zero?
148  if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
149  (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
150  MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
151  return false;
152 
153  // If we cannot erase the test instruction itself, then making the null check
154  // implicit does not buy us much.
155  if (!MBP.SingleUseCondition)
156  return false;
157 
158  MachineBasicBlock *NotNullSucc, *NullSucc;
159 
160  if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
161  NotNullSucc = MBP.TrueDest;
162  NullSucc = MBP.FalseDest;
163  } else {
164  NotNullSucc = MBP.FalseDest;
165  NullSucc = MBP.TrueDest;
166  }
167 
168  // We handle the simplest case for now. We can potentially do better by using
169  // the machine dominator tree.
170  if (NotNullSucc->pred_size() != 1)
171  return false;
172 
173  // Starting with a code fragment like:
174  //
175  // test %RAX, %RAX
176  // jne LblNotNull
177  //
178  // LblNull:
179  // callq throw_NullPointerException
180  //
181  // LblNotNull:
182  // Inst0
183  // Inst1
184  // ...
185  // Def = Load (%RAX + <offset>)
186  // ...
187  //
188  //
189  // we want to end up with
190  //
191  // Def = TrappingLoad (%RAX + <offset>), LblNull
192  // jmp LblNotNull ;; explicit or fallthrough
193  //
194  // LblNotNull:
195  // Inst0
196  // Inst1
197  // ...
198  //
199  // LblNull:
200  // callq throw_NullPointerException
201  //
202 
203  unsigned PointerReg = MBP.LHS.getReg();
204 
205  // As we scan NotNullSucc for a suitable load instruction, we keep track of
206  // the registers defined and used by the instructions we scan past. This bit
207  // of information lets us decide if it is legal to hoist the load instruction
208  // we find (if we do find such an instruction) to before NotNullSucc.
209  DenseSet<unsigned> RegDefs, RegUses;
210 
211  // Returns true if it is safe to reorder MI to before NotNullSucc.
212  auto IsSafeToHoist = [&](MachineInstr *MI) {
213  // Right now we don't want to worry about LLVM's memory model. This can be
214  // made more precise later.
215  for (auto *MMO : MI->memoperands())
216  if (!MMO->isUnordered())
217  return false;
218 
219  for (auto &MO : MI->operands()) {
220  if (MO.isReg() && MO.getReg()) {
221  for (unsigned Reg : RegDefs)
222  if (TRI->regsOverlap(Reg, MO.getReg()))
223  return false; // We found a write-after-write or read-after-write
224 
225  if (MO.isDef())
226  for (unsigned Reg : RegUses)
227  if (TRI->regsOverlap(Reg, MO.getReg()))
228  return false; // We found a write-after-read
229  }
230  }
231 
232  return true;
233  };
234 
235  for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE;
236  ++MII) {
237  MachineInstr *MI = &*MII;
238  unsigned BaseReg, Offset;
239  if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
240  if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg &&
241  Offset < PageSize && MI->getDesc().getNumDefs() == 1 &&
242  IsSafeToHoist(MI)) {
243  NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc,
244  NullSucc);
245  return true;
246  }
247 
248  // MI did not match our criteria for conversion to a trapping load. Check
249  // if we can continue looking.
250 
251  if (MI->mayStore() || MI->hasUnmodeledSideEffects())
252  return false;
253 
254  for (auto *MMO : MI->memoperands())
255  // Right now we don't want to worry about LLVM's memory model.
256  if (!MMO->isUnordered())
257  return false;
258 
259  // It _may_ be okay to reorder a later load instruction across MI. Make a
260  // note of its operands so that we can make the legality check if we find a
261  // suitable load instruction:
262 
263  for (auto &MO : MI->operands()) {
264  if (!MO.isReg() || !MO.getReg())
265  continue;
266 
267  if (MO.isDef())
268  RegDefs.insert(MO.getReg());
269  else
270  RegUses.insert(MO.getReg());
271  }
272  }
273 
274  return false;
275 }
276 
277 /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
278 /// instruction. The FAULTING_LOAD_OP instruction does the same load as LoadMI
279 /// (defining the same register), and branches to HandlerLabel if the load
280 /// faults. The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
281 MachineInstr *ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
282  MachineBasicBlock *MBB,
283  MCSymbol *HandlerLabel) {
284  DebugLoc DL;
285  unsigned NumDefs = LoadMI->getDesc().getNumDefs();
286  assert(NumDefs == 1 && "other cases unhandled!");
287  (void)NumDefs;
288 
289  unsigned DefReg = LoadMI->defs().begin()->getReg();
290  assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
291  "expected exactly one def!");
292 
293  auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
294  .addSym(HandlerLabel)
295  .addImm(LoadMI->getOpcode());
296 
297  for (auto &MO : LoadMI->uses())
298  MIB.addOperand(MO);
299 
300  MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
301 
302  return MIB;
303 }
304 
305 /// Rewrite the null checks in NullCheckList into implicit null checks.
306 void ImplicitNullChecks::rewriteNullChecks(
308  DebugLoc DL;
309 
310  for (auto &NC : NullCheckList) {
311  MCSymbol *HandlerLabel = MMI->getContext().createTempSymbol();
312 
313  // Remove the conditional branch dependent on the null check.
314  unsigned BranchesRemoved = TII->RemoveBranch(*NC.CheckBlock);
315  (void)BranchesRemoved;
316  assert(BranchesRemoved > 0 && "expected at least one branch!");
317 
318  // Insert a faulting load where the conditional branch was originally. We
319  // check earlier ensures that this bit of code motion is legal. We do not
320  // touch the successors list for any basic block since we haven't changed
321  // control flow, we've just made it implicit.
322  insertFaultingLoad(NC.MemOperation, NC.CheckBlock, HandlerLabel);
323  NC.MemOperation->eraseFromParent();
324  NC.CheckOperation->eraseFromParent();
325 
326  // Insert an *unconditional* branch to not-null successor.
327  TII->InsertBranch(*NC.CheckBlock, NC.NotNullSucc, nullptr, /*Cond=*/None,
328  DL);
329 
330  // Emit the HandlerLabel as an EH_LABEL.
331  BuildMI(*NC.NullSucc, NC.NullSucc->begin(), DL,
332  TII->get(TargetOpcode::EH_LABEL)).addSym(HandlerLabel);
333 
334  NumImplicitNullChecks++;
335  }
336 }
337 
338 char ImplicitNullChecks::ID = 0;
340 INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
341  "Implicit null checks", false, false)
342 INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
343  "Implicit null checks", false, false)
const NoneType None
Definition: None.h:23
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
iterator_range< mop_iterator > uses()
Definition: MachineInstr.h:325
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Definition: MCInstrDesc.h:191
DenseSet - This implements a dense probed hash-table based set.
Definition: DenseSet.h:39
INITIALIZE_PASS_BEGIN(ImplicitNullChecks,"implicit-null-checks","Implicit null checks", false, false) INITIALIZE_PASS_END(ImplicitNullChecks
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Definition: MachineInstr.h:579
bool isPredicable(QueryType Type=AllInBundle) const
Return true if this instruction has a predicate operand that controls execution.
Definition: MachineInstr.h:457
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:264
A debug info location.
Definition: DebugLoc.h:34
Metadata node.
Definition: Metadata.h:740
iterator_range< mmo_iterator > memoperands()
Definition: MachineInstr.h:344
iterator_range< mop_iterator > operands()
Definition: MachineInstr.h:295
Represents a predicate at the MachineFunction level.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
const TargetRegisterInfo * getTargetRegisterInfo() const
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:75
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APInt.h:33
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
Definition: MachineInstr.h:566
implicit null Implicit null false
Reg
All possible values of the reg field in the ModR/M byte.
const MachineInstrBuilder & addImm(int64_t Val) const
addImm - Add a new immediate operand.
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
Definition: SmallVector.h:57
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
const BasicBlock * getBasicBlock() const
getBasicBlock - Return the LLVM basic block that this instance corresponded to originally.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
TargetInstrInfo - Interface to description of machine instruction set.
mmo_iterator memoperands_end() const
Definition: MachineInstr.h:341
Loading instruction that may page fault, bundled with associated information on how to handle such a ...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:325
const MachineInstrBuilder & setMemRefs(MachineInstr::mmo_iterator b, MachineInstr::mmo_iterator e) const
unsigned RemoveBranch(MachineBasicBlock &MBB) const override
iterator_range< mop_iterator > defs()
Definition: MachineInstr.h:317
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
void initializeImplicitNullChecksPass(PassRegistry &)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
char & ImplicitNullChecksID
ImplicitNullChecks - This pass folds null pointer checks into nearby memory operations.
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:147
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
MDNode * getMetadata(unsigned KindID) const
getMetadata - Get the metadata of given kind attached to this Instruction.
Definition: Instruction.h:167
#define NC
Definition: regutils.h:42
Representation of each machine instruction.
Definition: MachineInstr.h:51
implicit null checks
void emplace_back(ArgTypes &&...Args)
Definition: SmallVector.h:652
static cl::opt< unsigned > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in ""bytes"), cl::init(4096))
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.cpp:124
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, DebugLoc DL) const override
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
MachineModuleInfo & getMMI() const
unsigned pred_size() const
MachineModuleInfo - This class contains meta information specific to a module.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
Definition: MachineInstr.h:340