ImplicitNullChecks.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. #include "llvm/ADT/DenseSet.h"
  28. #include "llvm/ADT/SmallVector.h"
  29. #include "llvm/ADT/Statistic.h"
  30. #include "llvm/CodeGen/Passes.h"
  31. #include "llvm/CodeGen/MachineFunction.h"
  32. #include "llvm/CodeGen/MachineMemOperand.h"
  33. #include "llvm/CodeGen/MachineOperand.h"
  34. #include "llvm/CodeGen/MachineFunctionPass.h"
  35. #include "llvm/CodeGen/MachineInstrBuilder.h"
  36. #include "llvm/CodeGen/MachineRegisterInfo.h"
  37. #include "llvm/CodeGen/MachineModuleInfo.h"
  38. #include "llvm/IR/BasicBlock.h"
  39. #include "llvm/IR/Instruction.h"
  40. #include "llvm/Support/CommandLine.h"
  41. #include "llvm/Support/Debug.h"
  42. #include "llvm/Target/TargetSubtargetInfo.h"
  43. #include "llvm/Target/TargetInstrInfo.h"
  44. using namespace llvm;
  45. static cl::opt<unsigned> PageSize("imp-null-check-page-size",
  46. cl::desc("The page size of the target in "
  47. "bytes"),
  48. cl::init(4096));
  49. #define DEBUG_TYPE "implicit-null-checks"
  50. STATISTIC(NumImplicitNullChecks,
  51. "Number of explicit null checks made implicit");
  52. namespace {
  53. class ImplicitNullChecks : public MachineFunctionPass {
  54. /// Represents one null check that can be made implicit.
  55. struct NullCheck {
  56. // The memory operation the null check can be folded into.
  57. MachineInstr *MemOperation;
  58. // The instruction actually doing the null check (Ptr != 0).
  59. MachineInstr *CheckOperation;
  60. // The block the check resides in.
  61. MachineBasicBlock *CheckBlock;
  62. // The block branched to if the pointer is non-null.
  63. MachineBasicBlock *NotNullSucc;
  64. // The block branched to if the pointer is null.
  65. MachineBasicBlock *NullSucc;
  66. NullCheck()
  67. : MemOperation(), CheckOperation(), CheckBlock(), NotNullSucc(),
  68. NullSucc() {}
  69. explicit NullCheck(MachineInstr *memOperation, MachineInstr *checkOperation,
  70. MachineBasicBlock *checkBlock,
  71. MachineBasicBlock *notNullSucc,
  72. MachineBasicBlock *nullSucc)
  73. : MemOperation(memOperation), CheckOperation(checkOperation),
  74. CheckBlock(checkBlock), NotNullSucc(notNullSucc), NullSucc(nullSucc) {
  75. }
  76. };
  77. const TargetInstrInfo *TII = nullptr;
  78. const TargetRegisterInfo *TRI = nullptr;
  79. MachineModuleInfo *MMI = nullptr;
  80. bool analyzeBlockForNullChecks(MachineBasicBlock &MBB,
  81. SmallVectorImpl<NullCheck> &NullCheckList);
  82. MachineInstr *insertFaultingLoad(MachineInstr *LoadMI, MachineBasicBlock *MBB,
  83. MCSymbol *HandlerLabel);
  84. void rewriteNullChecks(ArrayRef<NullCheck> NullCheckList);
  85. public:
  86. static char ID;
  87. ImplicitNullChecks() : MachineFunctionPass(ID) {
  88. initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
  89. }
  90. bool runOnMachineFunction(MachineFunction &MF) override;
  91. };
  92. }
  93. bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) {
  94. TII = MF.getSubtarget().getInstrInfo();
  95. TRI = MF.getRegInfo().getTargetRegisterInfo();
  96. MMI = &MF.getMMI();
  97. SmallVector<NullCheck, 16> NullCheckList;
  98. for (auto &MBB : MF)
  99. analyzeBlockForNullChecks(MBB, NullCheckList);
  100. if (!NullCheckList.empty())
  101. rewriteNullChecks(NullCheckList);
  102. return !NullCheckList.empty();
  103. }
  104. /// Analyze MBB to check if its terminating branch can be turned into an
  105. /// implicit null check. If yes, append a description of the said null check to
  106. /// NullCheckList and return true, else return false.
  107. bool ImplicitNullChecks::analyzeBlockForNullChecks(
  108. MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) {
  109. typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate;
  110. MDNode *BranchMD =
  111. MBB.getBasicBlock()
  112. ? MBB.getBasicBlock()->getTerminator()->getMetadata("make.implicit")
  113. : nullptr;
  114. if (!BranchMD)
  115. return false;
  116. MachineBranchPredicate MBP;
  117. if (TII->AnalyzeBranchPredicate(MBB, MBP, true))
  118. return false;
  119. // Is the predicate comparing an integer to zero?
  120. if (!(MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 &&
  121. (MBP.Predicate == MachineBranchPredicate::PRED_NE ||
  122. MBP.Predicate == MachineBranchPredicate::PRED_EQ)))
  123. return false;
  124. // If we cannot erase the test instruction itself, then making the null check
  125. // implicit does not buy us much.
  126. if (!MBP.SingleUseCondition)
  127. return false;
  128. MachineBasicBlock *NotNullSucc, *NullSucc;
  129. if (MBP.Predicate == MachineBranchPredicate::PRED_NE) {
  130. NotNullSucc = MBP.TrueDest;
  131. NullSucc = MBP.FalseDest;
  132. } else {
  133. NotNullSucc = MBP.FalseDest;
  134. NullSucc = MBP.TrueDest;
  135. }
  136. // We handle the simplest case for now. We can potentially do better by using
  137. // the machine dominator tree.
  138. if (NotNullSucc->pred_size() != 1)
  139. return false;
  140. // Starting with a code fragment like:
  141. //
  142. // test %RAX, %RAX
  143. // jne LblNotNull
  144. //
  145. // LblNull:
  146. // callq throw_NullPointerException
  147. //
  148. // LblNotNull:
  149. // Inst0
  150. // Inst1
  151. // ...
  152. // Def = Load (%RAX + <offset>)
  153. // ...
  154. //
  155. //
  156. // we want to end up with
  157. //
  158. // Def = TrappingLoad (%RAX + <offset>), LblNull
  159. // jmp LblNotNull ;; explicit or fallthrough
  160. //
  161. // LblNotNull:
  162. // Inst0
  163. // Inst1
  164. // ...
  165. //
  166. // LblNull:
  167. // callq throw_NullPointerException
  168. //
  169. unsigned PointerReg = MBP.LHS.getReg();
  170. // As we scan NotNullSucc for a suitable load instruction, we keep track of
  171. // the registers defined and used by the instructions we scan past. This bit
  172. // of information lets us decide if it is legal to hoist the load instruction
  173. // we find (if we do find such an instruction) to before NotNullSucc.
  174. DenseSet<unsigned> RegDefs, RegUses;
  175. // Returns true if it is safe to reorder MI to before NotNullSucc.
  176. auto IsSafeToHoist = [&](MachineInstr *MI) {
  177. // Right now we don't want to worry about LLVM's memory model. This can be
  178. // made more precise later.
  179. for (auto *MMO : MI->memoperands())
  180. if (!MMO->isUnordered())
  181. return false;
  182. for (auto &MO : MI->operands()) {
  183. if (MO.isReg() && MO.getReg()) {
  184. for (unsigned Reg : RegDefs)
  185. if (TRI->regsOverlap(Reg, MO.getReg()))
  186. return false; // We found a write-after-write or read-after-write
  187. if (MO.isDef())
  188. for (unsigned Reg : RegUses)
  189. if (TRI->regsOverlap(Reg, MO.getReg()))
  190. return false; // We found a write-after-read
  191. }
  192. }
  193. return true;
  194. };
  195. for (auto MII = NotNullSucc->begin(), MIE = NotNullSucc->end(); MII != MIE;
  196. ++MII) {
  197. MachineInstr *MI = &*MII;
  198. unsigned BaseReg, Offset;
  199. if (TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
  200. if (MI->mayLoad() && !MI->isPredicable() && BaseReg == PointerReg &&
  201. Offset < PageSize && MI->getDesc().getNumDefs() == 1 &&
  202. IsSafeToHoist(MI)) {
  203. NullCheckList.emplace_back(MI, MBP.ConditionDef, &MBB, NotNullSucc,
  204. NullSucc);
  205. return true;
  206. }
  207. // MI did not match our criteria for conversion to a trapping load. Check
  208. // if we can continue looking.
  209. if (MI->mayStore() || MI->hasUnmodeledSideEffects())
  210. return false;
  211. for (auto *MMO : MI->memoperands())
  212. // Right now we don't want to worry about LLVM's memory model.
  213. if (!MMO->isUnordered())
  214. return false;
  215. // It _may_ be okay to reorder a later load instruction across MI. Make a
  216. // note of its operands so that we can make the legality check if we find a
  217. // suitable load instruction:
  218. for (auto &MO : MI->operands()) {
  219. if (!MO.isReg() || !MO.getReg())
  220. continue;
  221. if (MO.isDef())
  222. RegDefs.insert(MO.getReg());
  223. else
  224. RegUses.insert(MO.getReg());
  225. }
  226. }
  227. return false;
  228. }
  229. /// Wrap a machine load instruction, LoadMI, into a FAULTING_LOAD_OP machine
  230. /// instruction. The FAULTING_LOAD_OP instruction does the same load as LoadMI
  231. /// (defining the same register), and branches to HandlerLabel if the load
  232. /// faults. The FAULTING_LOAD_OP instruction is inserted at the end of MBB.
  233. MachineInstr *ImplicitNullChecks::insertFaultingLoad(MachineInstr *LoadMI,
  234. MachineBasicBlock *MBB,
  235. MCSymbol *HandlerLabel) {
  236. DebugLoc DL;
  237. unsigned NumDefs = LoadMI->getDesc().getNumDefs();
  238. assert(NumDefs == 1 && "other cases unhandled!");
  239. (void)NumDefs;
  240. unsigned DefReg = LoadMI->defs().begin()->getReg();
  241. assert(std::distance(LoadMI->defs().begin(), LoadMI->defs().end()) == 1 &&
  242. "expected exactly one def!");
  243. auto MIB = BuildMI(MBB, DL, TII->get(TargetOpcode::FAULTING_LOAD_OP), DefReg)
  244. .addSym(HandlerLabel)
  245. .addImm(LoadMI->getOpcode());
  246. for (auto &MO : LoadMI->uses())
  247. MIB.addOperand(MO);
  248. MIB.setMemRefs(LoadMI->memoperands_begin(), LoadMI->memoperands_end());
  249. return MIB;
  250. }
  251. /// Rewrite the null checks in NullCheckList into implicit null checks.
  252. void ImplicitNullChecks::rewriteNullChecks(
  253. ArrayRef<ImplicitNullChecks::NullCheck> NullCheckList) {
  254. DebugLoc DL;
  255. for (auto &NC : NullCheckList) {
  256. MCSymbol *HandlerLabel = MMI->getContext().createTempSymbol();
  257. // Remove the conditional branch dependent on the null check.
  258. unsigned BranchesRemoved = TII->RemoveBranch(*NC.CheckBlock);
  259. (void)BranchesRemoved;
  260. assert(BranchesRemoved > 0 && "expected at least one branch!");
  261. // Insert a faulting load where the conditional branch was originally. We
  262. // check earlier ensures that this bit of code motion is legal. We do not
  263. // touch the successors list for any basic block since we haven't changed
  264. // control flow, we've just made it implicit.
  265. insertFaultingLoad(NC.MemOperation, NC.CheckBlock, HandlerLabel);
  266. NC.MemOperation->eraseFromParent();
  267. NC.CheckOperation->eraseFromParent();
  268. // Insert an *unconditional* branch to not-null successor.
  269. TII->InsertBranch(*NC.CheckBlock, NC.NotNullSucc, nullptr, /*Cond=*/None,
  270. DL);
  271. // Emit the HandlerLabel as an EH_LABEL.
  272. BuildMI(*NC.NullSucc, NC.NullSucc->begin(), DL,
  273. TII->get(TargetOpcode::EH_LABEL)).addSym(HandlerLabel);
  274. NumImplicitNullChecks++;
  275. }
  276. }
  277. char ImplicitNullChecks::ID = 0;
  278. char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
  279. INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
  280. "Implicit null checks", false, false)
  281. INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
  282. "Implicit null checks", false, false)