1 //===- ImplicitNullChecks.cpp - Fold null checks into memory accesses -----===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass turns explicit null checks of the form
18 // faulting_load_op("movl (%r10), %esi", throw_npe)
21 // With the help of a runtime that understands the .fault_maps section,
22 // faulting_load_op branches to throw_npe if executing movl (%r10), %esi incurs
24 // Store and LoadStore are also supported.
26 //===----------------------------------------------------------------------===//
28 #include "llvm/ADT/ArrayRef.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/SmallVector.h"
31 #include "llvm/ADT/Statistic.h"
32 #include "llvm/Analysis/AliasAnalysis.h"
33 #include "llvm/Analysis/MemoryLocation.h"
34 #include "llvm/CodeGen/FaultMaps.h"
35 #include "llvm/CodeGen/MachineBasicBlock.h"
36 #include "llvm/CodeGen/MachineFunction.h"
37 #include "llvm/CodeGen/MachineFunctionPass.h"
38 #include "llvm/CodeGen/MachineInstr.h"
39 #include "llvm/CodeGen/MachineInstrBuilder.h"
40 #include "llvm/CodeGen/MachineMemOperand.h"
41 #include "llvm/CodeGen/MachineOperand.h"
42 #include "llvm/CodeGen/MachineRegisterInfo.h"
43 #include "llvm/CodeGen/PseudoSourceValue.h"
44 #include "llvm/CodeGen/TargetInstrInfo.h"
45 #include "llvm/CodeGen/TargetOpcodes.h"
46 #include "llvm/CodeGen/TargetRegisterInfo.h"
47 #include "llvm/CodeGen/TargetSubtargetInfo.h"
48 #include "llvm/IR/BasicBlock.h"
49 #include "llvm/IR/DebugLoc.h"
50 #include "llvm/IR/LLVMContext.h"
51 #include "llvm/InitializePasses.h"
52 #include "llvm/MC/MCInstrDesc.h"
53 #include "llvm/MC/MCRegisterInfo.h"
54 #include "llvm/Pass.h"
55 #include "llvm/Support/CommandLine.h"
62 static cl::opt
<int> PageSize("imp-null-check-page-size",
63 cl::desc("The page size of the target in bytes"),
64 cl::init(4096), cl::Hidden
);
66 static cl::opt
<unsigned> MaxInstsToConsider(
67 "imp-null-max-insts-to-consider",
68 cl::desc("The max number of instructions to consider hoisting loads over "
69 "(the algorithm is quadratic over this number)"),
70 cl::Hidden
, cl::init(8));
72 #define DEBUG_TYPE "implicit-null-checks"
74 STATISTIC(NumImplicitNullChecks
,
75 "Number of explicit null checks made implicit");
79 class ImplicitNullChecks
: public MachineFunctionPass
{
80 /// Return true if \c computeDependence can process \p MI.
81 static bool canHandle(const MachineInstr
*MI
);
83 /// Helper function for \c computeDependence. Return true if \p A
84 /// and \p B do not have any dependences between them, and can be
85 /// re-ordered without changing program semantics.
86 bool canReorder(const MachineInstr
*A
, const MachineInstr
*B
);
88 /// A data type for representing the result computed by \c
89 /// computeDependence. States whether it is okay to reorder the
90 /// instruction passed to \c computeDependence with at most one
92 struct DependenceResult
{
93 /// Can we actually re-order \p MI with \p Insts (see \c
94 /// computeDependence).
97 /// If non-std::nullopt, then an instruction in \p Insts that also must be
99 std::optional
<ArrayRef
<MachineInstr
*>::iterator
> PotentialDependence
;
101 /*implicit*/ DependenceResult(
103 std::optional
<ArrayRef
<MachineInstr
*>::iterator
> PotentialDependence
)
104 : CanReorder(CanReorder
), PotentialDependence(PotentialDependence
) {
105 assert((!PotentialDependence
|| CanReorder
) &&
106 "!CanReorder && PotentialDependence.hasValue() not allowed!");
110 /// Compute a result for the following question: can \p MI be
111 /// re-ordered from after \p Insts to before it.
113 /// \c canHandle should return true for all instructions in \p
115 DependenceResult
computeDependence(const MachineInstr
*MI
,
116 ArrayRef
<MachineInstr
*> Block
);
118 /// Represents one null check that can be made implicit.
120 // The memory operation the null check can be folded into.
121 MachineInstr
*MemOperation
;
123 // The instruction actually doing the null check (Ptr != 0).
124 MachineInstr
*CheckOperation
;
126 // The block the check resides in.
127 MachineBasicBlock
*CheckBlock
;
129 // The block branched to if the pointer is non-null.
130 MachineBasicBlock
*NotNullSucc
;
132 // The block branched to if the pointer is null.
133 MachineBasicBlock
*NullSucc
;
135 // If this is non-null, then MemOperation has a dependency on this
136 // instruction; and it needs to be hoisted to execute before MemOperation.
137 MachineInstr
*OnlyDependency
;
140 explicit NullCheck(MachineInstr
*memOperation
, MachineInstr
*checkOperation
,
141 MachineBasicBlock
*checkBlock
,
142 MachineBasicBlock
*notNullSucc
,
143 MachineBasicBlock
*nullSucc
,
144 MachineInstr
*onlyDependency
)
145 : MemOperation(memOperation
), CheckOperation(checkOperation
),
146 CheckBlock(checkBlock
), NotNullSucc(notNullSucc
), NullSucc(nullSucc
),
147 OnlyDependency(onlyDependency
) {}
149 MachineInstr
*getMemOperation() const { return MemOperation
; }
151 MachineInstr
*getCheckOperation() const { return CheckOperation
; }
153 MachineBasicBlock
*getCheckBlock() const { return CheckBlock
; }
155 MachineBasicBlock
*getNotNullSucc() const { return NotNullSucc
; }
157 MachineBasicBlock
*getNullSucc() const { return NullSucc
; }
159 MachineInstr
*getOnlyDependency() const { return OnlyDependency
; }
162 const TargetInstrInfo
*TII
= nullptr;
163 const TargetRegisterInfo
*TRI
= nullptr;
164 AliasAnalysis
*AA
= nullptr;
165 MachineFrameInfo
*MFI
= nullptr;
167 bool analyzeBlockForNullChecks(MachineBasicBlock
&MBB
,
168 SmallVectorImpl
<NullCheck
> &NullCheckList
);
169 MachineInstr
*insertFaultingInstr(MachineInstr
*MI
, MachineBasicBlock
*MBB
,
170 MachineBasicBlock
*HandlerMBB
);
171 void rewriteNullChecks(ArrayRef
<NullCheck
> NullCheckList
);
176 AR_WillAliasEverything
179 /// Returns AR_NoAlias if \p MI memory operation does not alias with
180 /// \p PrevMI, AR_MayAlias if they may alias and AR_WillAliasEverything if
181 /// they may alias and any further memory operation may alias with \p PrevMI.
182 AliasResult
areMemoryOpsAliased(const MachineInstr
&MI
,
183 const MachineInstr
*PrevMI
) const;
185 enum SuitabilityResult
{
191 /// Return SR_Suitable if \p MI a memory operation that can be used to
192 /// implicitly null check the value in \p PointerReg, SR_Unsuitable if
193 /// \p MI cannot be used to null check and SR_Impossible if there is
194 /// no sense to continue lookup due to any other instruction will not be able
195 /// to be used. \p PrevInsts is the set of instruction seen since
196 /// the explicit null check on \p PointerReg.
197 SuitabilityResult
isSuitableMemoryOp(const MachineInstr
&MI
,
199 ArrayRef
<MachineInstr
*> PrevInsts
);
201 /// Returns true if \p DependenceMI can clobber the liveIns in NullSucc block
202 /// if it was hoisted to the NullCheck block. This is used by caller
203 /// canHoistInst to decide if DependenceMI can be hoisted safely.
204 bool canDependenceHoistingClobberLiveIns(MachineInstr
*DependenceMI
,
205 MachineBasicBlock
*NullSucc
);
207 /// Return true if \p FaultingMI can be hoisted from after the
208 /// instructions in \p InstsSeenSoFar to before them. Set \p Dependence to a
209 /// non-null value if we also need to (and legally can) hoist a dependency.
210 bool canHoistInst(MachineInstr
*FaultingMI
,
211 ArrayRef
<MachineInstr
*> InstsSeenSoFar
,
212 MachineBasicBlock
*NullSucc
, MachineInstr
*&Dependence
);
217 ImplicitNullChecks() : MachineFunctionPass(ID
) {
218 initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry());
221 bool runOnMachineFunction(MachineFunction
&MF
) override
;
223 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
224 AU
.addRequired
<AAResultsWrapperPass
>();
225 MachineFunctionPass::getAnalysisUsage(AU
);
228 MachineFunctionProperties
getRequiredProperties() const override
{
229 return MachineFunctionProperties().set(
230 MachineFunctionProperties::Property::NoVRegs
);
234 } // end anonymous namespace
236 bool ImplicitNullChecks::canHandle(const MachineInstr
*MI
) {
237 if (MI
->isCall() || MI
->mayRaiseFPException() ||
238 MI
->hasUnmodeledSideEffects())
240 auto IsRegMask
= [](const MachineOperand
&MO
) { return MO
.isRegMask(); };
243 assert(llvm::none_of(MI
->operands(), IsRegMask
) &&
244 "Calls were filtered out above!");
246 auto IsUnordered
= [](MachineMemOperand
*MMO
) { return MMO
->isUnordered(); };
247 return llvm::all_of(MI
->memoperands(), IsUnordered
);
250 ImplicitNullChecks::DependenceResult
251 ImplicitNullChecks::computeDependence(const MachineInstr
*MI
,
252 ArrayRef
<MachineInstr
*> Block
) {
253 assert(llvm::all_of(Block
, canHandle
) && "Check this first!");
254 assert(!is_contained(Block
, MI
) && "Block must be exclusive of MI!");
256 std::optional
<ArrayRef
<MachineInstr
*>::iterator
> Dep
;
258 for (auto I
= Block
.begin(), E
= Block
.end(); I
!= E
; ++I
) {
259 if (canReorder(*I
, MI
))
262 if (Dep
== std::nullopt
) {
263 // Found one possible dependency, keep track of it.
266 // We found two dependencies, so bail out.
267 return {false, std::nullopt
};
274 bool ImplicitNullChecks::canReorder(const MachineInstr
*A
,
275 const MachineInstr
*B
) {
276 assert(canHandle(A
) && canHandle(B
) && "Precondition!");
278 // canHandle makes sure that we _can_ correctly analyze the dependencies
279 // between A and B here -- for instance, we should not be dealing with heap
280 // load-store dependencies here.
282 for (const auto &MOA
: A
->operands()) {
283 if (!(MOA
.isReg() && MOA
.getReg()))
286 Register RegA
= MOA
.getReg();
287 for (const auto &MOB
: B
->operands()) {
288 if (!(MOB
.isReg() && MOB
.getReg()))
291 Register RegB
= MOB
.getReg();
293 if (TRI
->regsOverlap(RegA
, RegB
) && (MOA
.isDef() || MOB
.isDef()))
301 bool ImplicitNullChecks::runOnMachineFunction(MachineFunction
&MF
) {
302 TII
= MF
.getSubtarget().getInstrInfo();
303 TRI
= MF
.getRegInfo().getTargetRegisterInfo();
304 MFI
= &MF
.getFrameInfo();
305 AA
= &getAnalysis
<AAResultsWrapperPass
>().getAAResults();
307 SmallVector
<NullCheck
, 16> NullCheckList
;
310 analyzeBlockForNullChecks(MBB
, NullCheckList
);
312 if (!NullCheckList
.empty())
313 rewriteNullChecks(NullCheckList
);
315 return !NullCheckList
.empty();
318 // Return true if any register aliasing \p Reg is live-in into \p MBB.
319 static bool AnyAliasLiveIn(const TargetRegisterInfo
*TRI
,
320 MachineBasicBlock
*MBB
, unsigned Reg
) {
321 for (MCRegAliasIterator
AR(Reg
, TRI
, /*IncludeSelf*/ true); AR
.isValid();
323 if (MBB
->isLiveIn(*AR
))
328 ImplicitNullChecks::AliasResult
329 ImplicitNullChecks::areMemoryOpsAliased(const MachineInstr
&MI
,
330 const MachineInstr
*PrevMI
) const {
331 // If it is not memory access, skip the check.
332 if (!(PrevMI
->mayStore() || PrevMI
->mayLoad()))
334 // Load-Load may alias
335 if (!(MI
.mayStore() || PrevMI
->mayStore()))
337 // We lost info, conservatively alias. If it was store then no sense to
338 // continue because we won't be able to check against it further.
339 if (MI
.memoperands_empty())
340 return MI
.mayStore() ? AR_WillAliasEverything
: AR_MayAlias
;
341 if (PrevMI
->memoperands_empty())
342 return PrevMI
->mayStore() ? AR_WillAliasEverything
: AR_MayAlias
;
344 for (MachineMemOperand
*MMO1
: MI
.memoperands()) {
345 // MMO1 should have a value due it comes from operation we'd like to use
346 // as implicit null check.
347 assert(MMO1
->getValue() && "MMO1 should have a Value!");
348 for (MachineMemOperand
*MMO2
: PrevMI
->memoperands()) {
349 if (const PseudoSourceValue
*PSV
= MMO2
->getPseudoValue()) {
350 if (PSV
->mayAlias(MFI
))
355 MemoryLocation::getAfter(MMO1
->getValue(), MMO1
->getAAInfo()),
356 MemoryLocation::getAfter(MMO2
->getValue(), MMO2
->getAAInfo())))
363 ImplicitNullChecks::SuitabilityResult
364 ImplicitNullChecks::isSuitableMemoryOp(const MachineInstr
&MI
,
366 ArrayRef
<MachineInstr
*> PrevInsts
) {
367 // Implementation restriction for faulting_op insertion
368 // TODO: This could be relaxed if we find a test case which warrants it.
369 if (MI
.getDesc().getNumDefs() > 1)
370 return SR_Unsuitable
;
372 if (!MI
.mayLoadOrStore() || MI
.isPredicable())
373 return SR_Unsuitable
;
374 auto AM
= TII
->getAddrModeFromMemoryOp(MI
, TRI
);
375 if (!AM
|| AM
->Form
!= ExtAddrMode::Formula::Basic
)
376 return SR_Unsuitable
;
378 const Register BaseReg
= AddrMode
.BaseReg
, ScaledReg
= AddrMode
.ScaledReg
;
379 int64_t Displacement
= AddrMode
.Displacement
;
381 // We need the base of the memory instruction to be same as the register
382 // where the null check is performed (i.e. PointerReg).
383 if (BaseReg
!= PointerReg
&& ScaledReg
!= PointerReg
)
384 return SR_Unsuitable
;
385 const MachineRegisterInfo
&MRI
= MI
.getMF()->getRegInfo();
386 unsigned PointerRegSizeInBits
= TRI
->getRegSizeInBits(PointerReg
, MRI
);
387 // Bail out of the sizes of BaseReg, ScaledReg and PointerReg are not the
390 TRI
->getRegSizeInBits(BaseReg
, MRI
) != PointerRegSizeInBits
) ||
392 TRI
->getRegSizeInBits(ScaledReg
, MRI
) != PointerRegSizeInBits
))
393 return SR_Unsuitable
;
395 // Returns true if RegUsedInAddr is used for calculating the displacement
396 // depending on addressing mode. Also calculates the Displacement.
397 auto CalculateDisplacementFromAddrMode
= [&](Register RegUsedInAddr
,
398 int64_t Multiplier
) {
399 // The register can be NoRegister, which is defined as zero for all targets.
400 // Consider instruction of interest as `movq 8(,%rdi,8), %rax`. Here the
401 // ScaledReg is %rdi, while there is no BaseReg.
404 assert(Multiplier
&& "expected to be non-zero!");
405 MachineInstr
*ModifyingMI
= nullptr;
406 for (auto It
= std::next(MachineBasicBlock::const_reverse_iterator(&MI
));
407 It
!= MI
.getParent()->rend(); It
++) {
408 const MachineInstr
*CurrMI
= &*It
;
409 if (CurrMI
->modifiesRegister(RegUsedInAddr
, TRI
)) {
410 ModifyingMI
= const_cast<MachineInstr
*>(CurrMI
);
416 // Check for the const value defined in register by ModifyingMI. This means
417 // all other previous values for that register has been invalidated.
419 if (!TII
->getConstValDefinedInReg(*ModifyingMI
, RegUsedInAddr
, ImmVal
))
421 // Calculate the reg size in bits, since this is needed for bailing out in
423 int32_t RegSizeInBits
= TRI
->getRegSizeInBits(RegUsedInAddr
, MRI
);
424 APInt
ImmValC(RegSizeInBits
, ImmVal
, true /*IsSigned*/);
425 APInt
MultiplierC(RegSizeInBits
, Multiplier
);
426 assert(MultiplierC
.isStrictlyPositive() &&
427 "expected to be a positive value!");
429 // Sign of the product depends on the sign of the ImmVal, since Multiplier
430 // is always positive.
431 APInt Product
= ImmValC
.smul_ov(MultiplierC
, IsOverflow
);
434 APInt
DisplacementC(64, Displacement
, true /*isSigned*/);
435 DisplacementC
= Product
.sadd_ov(DisplacementC
, IsOverflow
);
439 // We only handle diplacements upto 64 bits wide.
440 if (DisplacementC
.getActiveBits() > 64)
442 Displacement
= DisplacementC
.getSExtValue();
446 // If a register used in the address is constant, fold it's effect into the
447 // displacement for ease of analysis.
448 bool BaseRegIsConstVal
= false, ScaledRegIsConstVal
= false;
449 if (CalculateDisplacementFromAddrMode(BaseReg
, 1))
450 BaseRegIsConstVal
= true;
451 if (CalculateDisplacementFromAddrMode(ScaledReg
, AddrMode
.Scale
))
452 ScaledRegIsConstVal
= true;
454 // The register which is not null checked should be part of the Displacement
455 // calculation, otherwise we do not know whether the Displacement is made up
456 // by some symbolic values.
457 // This matters because we do not want to incorrectly assume that load from
458 // falls in the zeroth faulting page in the "sane offset check" below.
459 if ((BaseReg
&& BaseReg
!= PointerReg
&& !BaseRegIsConstVal
) ||
460 (ScaledReg
&& ScaledReg
!= PointerReg
&& !ScaledRegIsConstVal
))
461 return SR_Unsuitable
;
463 // We want the mem access to be issued at a sane offset from PointerReg,
464 // so that if PointerReg is null then the access reliably page faults.
465 if (!(-PageSize
< Displacement
&& Displacement
< PageSize
))
466 return SR_Unsuitable
;
468 // Finally, check whether the current memory access aliases with previous one.
469 for (auto *PrevMI
: PrevInsts
) {
470 AliasResult AR
= areMemoryOpsAliased(MI
, PrevMI
);
471 if (AR
== AR_WillAliasEverything
)
472 return SR_Impossible
;
473 if (AR
== AR_MayAlias
)
474 return SR_Unsuitable
;
479 bool ImplicitNullChecks::canDependenceHoistingClobberLiveIns(
480 MachineInstr
*DependenceMI
, MachineBasicBlock
*NullSucc
) {
481 for (const auto &DependenceMO
: DependenceMI
->operands()) {
482 if (!(DependenceMO
.isReg() && DependenceMO
.getReg()))
485 // Make sure that we won't clobber any live ins to the sibling block by
486 // hoisting Dependency. For instance, we can't hoist INST to before the
487 // null check (even if it safe, and does not violate any dependencies in
488 // the non_null_block) if %rdx is live in to _null_block.
496 // This restriction does not apply to the faulting load inst because in
497 // case the pointer loaded from is in the null page, the load will not
498 // semantically execute, and affect machine state. That is, if the load
499 // was loading into %rax and it faults, the value of %rax should stay the
500 // same as it would have been had the load not have executed and we'd have
501 // branched to NullSucc directly.
502 if (AnyAliasLiveIn(TRI
, NullSucc
, DependenceMO
.getReg()))
507 // The dependence does not clobber live-ins in NullSucc block.
511 bool ImplicitNullChecks::canHoistInst(MachineInstr
*FaultingMI
,
512 ArrayRef
<MachineInstr
*> InstsSeenSoFar
,
513 MachineBasicBlock
*NullSucc
,
514 MachineInstr
*&Dependence
) {
515 auto DepResult
= computeDependence(FaultingMI
, InstsSeenSoFar
);
516 if (!DepResult
.CanReorder
)
519 if (!DepResult
.PotentialDependence
) {
520 Dependence
= nullptr;
524 auto DependenceItr
= *DepResult
.PotentialDependence
;
525 auto *DependenceMI
= *DependenceItr
;
527 // We don't want to reason about speculating loads. Note -- at this point
528 // we should have already filtered out all of the other non-speculatable
529 // things, like calls and stores.
530 // We also do not want to hoist stores because it might change the memory
531 // while the FaultingMI may result in faulting.
532 assert(canHandle(DependenceMI
) && "Should never have reached here!");
533 if (DependenceMI
->mayLoadOrStore())
536 if (canDependenceHoistingClobberLiveIns(DependenceMI
, NullSucc
))
540 computeDependence(DependenceMI
, {InstsSeenSoFar
.begin(), DependenceItr
});
542 if (!DepDepResult
.CanReorder
|| DepDepResult
.PotentialDependence
)
545 Dependence
= DependenceMI
;
549 /// Analyze MBB to check if its terminating branch can be turned into an
550 /// implicit null check. If yes, append a description of the said null check to
551 /// NullCheckList and return true, else return false.
552 bool ImplicitNullChecks::analyzeBlockForNullChecks(
553 MachineBasicBlock
&MBB
, SmallVectorImpl
<NullCheck
> &NullCheckList
) {
554 using MachineBranchPredicate
= TargetInstrInfo::MachineBranchPredicate
;
556 MDNode
*BranchMD
= nullptr;
557 if (auto *BB
= MBB
.getBasicBlock())
558 BranchMD
= BB
->getTerminator()->getMetadata(LLVMContext::MD_make_implicit
);
563 MachineBranchPredicate MBP
;
565 if (TII
->analyzeBranchPredicate(MBB
, MBP
, true))
568 // Is the predicate comparing an integer to zero?
569 if (!(MBP
.LHS
.isReg() && MBP
.RHS
.isImm() && MBP
.RHS
.getImm() == 0 &&
570 (MBP
.Predicate
== MachineBranchPredicate::PRED_NE
||
571 MBP
.Predicate
== MachineBranchPredicate::PRED_EQ
)))
574 // If there is a separate condition generation instruction, we chose not to
575 // transform unless we can remove both condition and consuming branch.
576 if (MBP
.ConditionDef
&& !MBP
.SingleUseCondition
)
579 MachineBasicBlock
*NotNullSucc
, *NullSucc
;
581 if (MBP
.Predicate
== MachineBranchPredicate::PRED_NE
) {
582 NotNullSucc
= MBP
.TrueDest
;
583 NullSucc
= MBP
.FalseDest
;
585 NotNullSucc
= MBP
.FalseDest
;
586 NullSucc
= MBP
.TrueDest
;
589 // We handle the simplest case for now. We can potentially do better by using
590 // the machine dominator tree.
591 if (NotNullSucc
->pred_size() != 1)
594 const Register PointerReg
= MBP
.LHS
.getReg();
596 if (MBP
.ConditionDef
) {
597 // To prevent the invalid transformation of the following code:
610 // faulting_load_op("movl (%rax), %r10", throw_npe)
613 // we must ensure that there are no instructions between the 'test' and
614 // conditional jump that modify %rax.
615 assert(MBP
.ConditionDef
->getParent() == &MBB
&&
616 "Should be in basic block");
618 for (auto I
= MBB
.rbegin(); MBP
.ConditionDef
!= &*I
; ++I
)
619 if (I
->modifiesRegister(PointerReg
, TRI
))
622 // Starting with a code fragment like:
628 // callq throw_NullPointerException
634 // Def = Load (%rax + <offset>)
638 // we want to end up with
640 // Def = FaultingLoad (%rax + <offset>), LblNull
641 // jmp LblNotNull ;; explicit or fallthrough
649 // callq throw_NullPointerException
652 // To see why this is legal, consider the two possibilities:
654 // 1. %rax is null: since we constrain <offset> to be less than PageSize, the
655 // load instruction dereferences the null page, causing a segmentation
658 // 2. %rax is not null: in this case we know that the load cannot fault, as
659 // otherwise the load would've faulted in the original program too and the
660 // original program would've been undefined.
662 // This reasoning cannot be extended to justify hoisting through arbitrary
663 // control flow. For instance, in the example below (in pseudo-C)
665 // if (ptr == null) { throw_npe(); unreachable; }
666 // if (some_cond) { return 42; }
667 // v = ptr->field; // LD
670 // we cannot (without code duplication) use the load marked "LD" to null check
671 // ptr -- clause (2) above does not apply in this case. In the above program
672 // the safety of ptr->field can be dependent on some_cond; and, for instance,
673 // ptr could be some non-null invalid reference that never gets loaded from
674 // because some_cond is always true.
676 SmallVector
<MachineInstr
*, 8> InstsSeenSoFar
;
678 for (auto &MI
: *NotNullSucc
) {
679 if (!canHandle(&MI
) || InstsSeenSoFar
.size() >= MaxInstsToConsider
)
682 MachineInstr
*Dependence
;
683 SuitabilityResult SR
= isSuitableMemoryOp(MI
, PointerReg
, InstsSeenSoFar
);
684 if (SR
== SR_Impossible
)
686 if (SR
== SR_Suitable
&&
687 canHoistInst(&MI
, InstsSeenSoFar
, NullSucc
, Dependence
)) {
688 NullCheckList
.emplace_back(&MI
, MBP
.ConditionDef
, &MBB
, NotNullSucc
,
689 NullSucc
, Dependence
);
693 // If MI re-defines the PointerReg in a way that changes the value of
694 // PointerReg if it was null, then we cannot move further.
695 if (!TII
->preservesZeroValueInReg(&MI
, PointerReg
, TRI
))
697 InstsSeenSoFar
.push_back(&MI
);
703 /// Wrap a machine instruction, MI, into a FAULTING machine instruction.
704 /// The FAULTING instruction does the same load/store as MI
705 /// (defining the same register), and branches to HandlerMBB if the mem access
706 /// faults. The FAULTING instruction is inserted at the end of MBB.
707 MachineInstr
*ImplicitNullChecks::insertFaultingInstr(
708 MachineInstr
*MI
, MachineBasicBlock
*MBB
, MachineBasicBlock
*HandlerMBB
) {
709 const unsigned NoRegister
= 0; // Guaranteed to be the NoRegister value for
713 unsigned NumDefs
= MI
->getDesc().getNumDefs();
714 assert(NumDefs
<= 1 && "other cases unhandled!");
716 unsigned DefReg
= NoRegister
;
718 DefReg
= MI
->getOperand(0).getReg();
719 assert(NumDefs
== 1 && "expected exactly one def!");
722 FaultMaps::FaultKind FK
;
725 MI
->mayStore() ? FaultMaps::FaultingLoadStore
: FaultMaps::FaultingLoad
;
727 FK
= FaultMaps::FaultingStore
;
729 auto MIB
= BuildMI(MBB
, DL
, TII
->get(TargetOpcode::FAULTING_OP
), DefReg
)
732 .addImm(MI
->getOpcode());
734 for (auto &MO
: MI
->uses()) {
736 MachineOperand NewMO
= MO
;
738 NewMO
.setIsKill(false);
740 assert(MO
.isDef() && "Expected def or use");
741 NewMO
.setIsDead(false);
749 MIB
.setMemRefs(MI
->memoperands());
754 /// Rewrite the null checks in NullCheckList into implicit null checks.
755 void ImplicitNullChecks::rewriteNullChecks(
756 ArrayRef
<ImplicitNullChecks::NullCheck
> NullCheckList
) {
759 for (const auto &NC
: NullCheckList
) {
760 // Remove the conditional branch dependent on the null check.
761 unsigned BranchesRemoved
= TII
->removeBranch(*NC
.getCheckBlock());
762 (void)BranchesRemoved
;
763 assert(BranchesRemoved
> 0 && "expected at least one branch!");
765 if (auto *DepMI
= NC
.getOnlyDependency()) {
766 DepMI
->removeFromParent();
767 NC
.getCheckBlock()->insert(NC
.getCheckBlock()->end(), DepMI
);
770 // Insert a faulting instruction where the conditional branch was
771 // originally. We check earlier ensures that this bit of code motion
772 // is legal. We do not touch the successors list for any basic block
773 // since we haven't changed control flow, we've just made it implicit.
774 MachineInstr
*FaultingInstr
= insertFaultingInstr(
775 NC
.getMemOperation(), NC
.getCheckBlock(), NC
.getNullSucc());
776 // Now the values defined by MemOperation, if any, are live-in of
777 // the block of MemOperation.
778 // The original operation may define implicit-defs alongside
780 MachineBasicBlock
*MBB
= NC
.getMemOperation()->getParent();
781 for (const MachineOperand
&MO
: FaultingInstr
->all_defs()) {
782 Register Reg
= MO
.getReg();
783 if (!Reg
|| MBB
->isLiveIn(Reg
))
788 if (auto *DepMI
= NC
.getOnlyDependency()) {
789 for (auto &MO
: DepMI
->all_defs()) {
790 if (!MO
.getReg() || MO
.isDead())
792 if (!NC
.getNotNullSucc()->isLiveIn(MO
.getReg()))
793 NC
.getNotNullSucc()->addLiveIn(MO
.getReg());
797 NC
.getMemOperation()->eraseFromParent();
798 if (auto *CheckOp
= NC
.getCheckOperation())
799 CheckOp
->eraseFromParent();
801 // Insert an *unconditional* branch to not-null successor - we expect
802 // block placement to remove fallthroughs later.
803 TII
->insertBranch(*NC
.getCheckBlock(), NC
.getNotNullSucc(), nullptr,
804 /*Cond=*/std::nullopt
, DL
);
806 NumImplicitNullChecks
++;
810 char ImplicitNullChecks::ID
= 0;
812 char &llvm::ImplicitNullChecksID
= ImplicitNullChecks::ID
;
814 INITIALIZE_PASS_BEGIN(ImplicitNullChecks
, DEBUG_TYPE
,
815 "Implicit null checks", false, false)
816 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
817 INITIALIZE_PASS_END(ImplicitNullChecks
, DEBUG_TYPE
,
818 "Implicit null checks", false, false)