diff options
Diffstat (limited to 'lib/CodeGen/ImplicitNullChecks.cpp')
-rw-r--r-- | lib/CodeGen/ImplicitNullChecks.cpp | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/lib/CodeGen/ImplicitNullChecks.cpp b/lib/CodeGen/ImplicitNullChecks.cpp index e308f49ec4e8..308b6d293d3d 100644 --- a/lib/CodeGen/ImplicitNullChecks.cpp +++ b/lib/CodeGen/ImplicitNullChecks.cpp @@ -1,4 +1,4 @@ -//===-- ImplicitNullChecks.cpp - Fold null checks into memory accesses ----===// +//===- ImplicitNullChecks.cpp - Fold null checks into memory accesses -----===// // // The LLVM Compiler Infrastructure // @@ -26,38 +26,50 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/CodeGen/FaultMaps.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Instruction.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h" +#include <cassert> +#include <cstdint> +#include <iterator> using namespace llvm; static cl::opt<int> PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), - cl::init(4096)); + cl::init(4096), cl::Hidden); static cl::opt<unsigned> MaxInstsToConsider( "imp-null-max-insts-to-consider", cl::desc("The max number of instructions to consider hoisting loads over " "(the algorithm is quadratic over this number)"), - cl::init(8)); + cl::Hidden, cl::init(8)); #define DEBUG_TYPE "implicit-null-checks" @@ -152,7 +164,6 @@ class ImplicitNullChecks : public MachineFunctionPass { const TargetInstrInfo *TII = nullptr; const TargetRegisterInfo *TRI = nullptr; AliasAnalysis *AA = nullptr; - MachineModuleInfo *MMI = nullptr; MachineFrameInfo *MFI = nullptr; bool analyzeBlockForNullChecks(MachineBasicBlock &MBB, @@ -166,6 +177,7 @@ class ImplicitNullChecks : public MachineFunctionPass { AR_MayAlias, AR_WillAliasEverything }; + /// Returns AR_NoAlias if \p MI memory operation does not alias with /// \p PrevMI, AR_MayAlias if they may alias and AR_WillAliasEverything if /// they may alias and any further memory operation may alias with \p PrevMI. @@ -176,6 +188,7 @@ class ImplicitNullChecks : public MachineFunctionPass { SR_Unsuitable, SR_Impossible }; + /// Return SR_Suitable if \p MI a memory operation that can be used to /// implicitly null check the value in \p PointerReg, SR_Unsuitable if /// \p MI cannot be used to null check and SR_Impossible if there is @@ -200,6 +213,7 @@ public: } bool runOnMachineFunction(MachineFunction &MF) override; + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<AAResultsWrapperPass>(); MachineFunctionPass::getAnalysisUsage(AU); @@ -211,7 +225,7 @@ public: } }; -} +} // end anonymous namespace bool ImplicitNullChecks::canHandle(const MachineInstr *MI) { if (MI->isCall() || MI->hasUnmodeledSideEffects()) @@ -230,7 +244,7 @@ ImplicitNullChecks::DependenceResult ImplicitNullChecks::computeDependence(const MachineInstr *MI, ArrayRef<MachineInstr *> Block) { assert(llvm::all_of(Block, canHandle) && "Check this first!"); - assert(!llvm::is_contained(Block, MI) && "Block must be exclusive of MI!"); + assert(!is_contained(Block, MI) && "Block must be exclusive of MI!"); Optional<ArrayRef<MachineInstr *>::iterator> Dep; @@ -280,7 +294,6 @@ bool ImplicitNullChecks::canReorder(const MachineInstr *A, bool ImplicitNullChecks::runOnMachineFunction(MachineFunction &MF) { TII = MF.getSubtarget().getInstrInfo(); TRI = MF.getRegInfo().getTargetRegisterInfo(); - MMI = &MF.getMMI(); MFI = &MF.getFrameInfo(); AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); @@ -356,7 +369,7 @@ ImplicitNullChecks::isSuitableMemoryOp(MachineInstr &MI, unsigned PointerReg, // We want the mem access to be issued at a sane offset from PointerReg, // so that if PointerReg is null then the access reliably page faults. if (!((MI.mayLoad() || MI.mayStore()) && !MI.isPredicable() && - Offset < PageSize)) + -PageSize < Offset && Offset < PageSize)) return SR_Unsuitable; // Finally, check whether the current memory access aliases with previous one. @@ -390,8 +403,10 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI, // We don't want to reason about speculating loads. Note -- at this point // we should have already filtered out all of the other non-speculatable // things, like calls and stores. + // We also do not want to hoist stores because it might change the memory + // while the FaultingMI may result in faulting. assert(canHandle(DependenceMI) && "Should never have reached here!"); - if (DependenceMI->mayLoad()) + if (DependenceMI->mayLoadOrStore()) return false; for (auto &DependenceMO : DependenceMI->operands()) { @@ -406,7 +421,7 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI, // test %rcx, %rcx // je _null_block // _non_null_block: - // %rdx<def> = INST + // %rdx = INST // ... // // This restriction does not apply to the faulting load inst because in @@ -441,7 +456,7 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI, /// NullCheckList and return true, else return false. bool ImplicitNullChecks::analyzeBlockForNullChecks( MachineBasicBlock &MBB, SmallVectorImpl<NullCheck> &NullCheckList) { - typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate; + using MachineBranchPredicate = TargetInstrInfo::MachineBranchPredicate; MDNode *BranchMD = nullptr; if (auto *BB = MBB.getBasicBlock()) @@ -483,7 +498,7 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( // Starting with a code fragment like: // - // test %RAX, %RAX + // test %rax, %rax // jne LblNotNull // // LblNull: @@ -493,13 +508,13 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( // Inst0 // Inst1 // ... - // Def = Load (%RAX + <offset>) + // Def = Load (%rax + <offset>) // ... // // // we want to end up with // - // Def = FaultingLoad (%RAX + <offset>), LblNull + // Def = FaultingLoad (%rax + <offset>), LblNull // jmp LblNotNull ;; explicit or fallthrough // // LblNotNull: @@ -513,11 +528,11 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( // // To see why this is legal, consider the two possibilities: // - // 1. %RAX is null: since we constrain <offset> to be less than PageSize, the + // 1. %rax is null: since we constrain <offset> to be less than PageSize, the // load instruction dereferences the null page, causing a segmentation // fault. // - // 2. %RAX is not null: in this case we know that the load cannot fault, as + // 2. %rax is not null: in this case we know that the load cannot fault, as // otherwise the load would've faulted in the original program too and the // original program would've been undefined. // @@ -555,7 +570,7 @@ bool ImplicitNullChecks::analyzeBlockForNullChecks( } // If MI re-defines the PointerReg then we cannot move further. - if (any_of(MI.operands(), [&](MachineOperand &MO) { + if (llvm::any_of(MI.operands(), [&](MachineOperand &MO) { return MO.isReg() && MO.getReg() && MO.isDef() && TRI->regsOverlap(MO.getReg(), PointerReg); })) @@ -674,9 +689,10 @@ void ImplicitNullChecks::rewriteNullChecks( } } - char ImplicitNullChecks::ID = 0; + char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID; + INITIALIZE_PASS_BEGIN(ImplicitNullChecks, DEBUG_TYPE, "Implicit null checks", false, false) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) |