diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-01-20 00:06:14 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-01-20 00:06:14 +0000 |
commit | 16901a3e200af39e1ea8ef44db7359ef9417917e (patch) | |
tree | 1f42497f16dce29fbced7973ddb428f4acc3e0ce /llvm/lib/CodeGen/MachineSink.cpp | |
parent | 7d866cb145950f2a164e62b9cfb67b9ece2a1497 (diff) | |
download | bcm5719-llvm-16901a3e200af39e1ea8ef44db7359ef9417917e.tar.gz bcm5719-llvm-16901a3e200af39e1ea8ef44db7359ef9417917e.zip |
[MachineSink] Don't break ImplicitNulls
Summary:
This teaches MachineSink to not sink instructions that might break the
implicit null check optimization that runs later. This should not
affect frontends that do not use implicit null checks.
Reviewers: aadg, reames, hfinkel, atrick
Subscribers: majnemer, llvm-commits
Differential Revision: http://reviews.llvm.org/D14632
llvm-svn: 258254
Diffstat (limited to 'llvm/lib/CodeGen/MachineSink.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineSink.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp index 5e6d6190c63..a10bd7f52e7 100644 --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachinePostDominators.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -673,6 +674,49 @@ MachineBasicBlock *MachineSinking::FindSuccToSinkTo(MachineInstr *MI, return SuccToSinkTo; } +/// \brief Return true if MI is likely to be usable as a memory operation by the +/// implicit null check optimization. +/// +/// This is a "best effort" heuristic, and should not be relied upon for +/// correctness. This returning true does not guarantee that the implicit null +/// check optimization is legal over MI, and this returning false does not +/// guarantee MI cannot possibly be used to do a null check. +static bool SinkingPreventsImplicitNullCheck(MachineInstr *MI, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + typedef TargetInstrInfo::MachineBranchPredicate MachineBranchPredicate; + + auto *MBB = MI->getParent(); + if (MBB->pred_size() != 1) + return false; + + auto *PredMBB = *MBB->pred_begin(); + auto *PredBB = PredMBB->getBasicBlock(); + + // Frontends that don't use implicit null checks have no reason to emit + // branches with make.implicit metadata, and this function should always + // return false for them. + if (!PredBB || + !PredBB->getTerminator()->getMetadata(LLVMContext::MD_make_implicit)) + return false; + + unsigned BaseReg, Offset; + if (!TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI)) + return false; + + if (!(MI->mayLoad() && !MI->isPredicable())) + return false; + + MachineBranchPredicate MBP; + if (TII->AnalyzeBranchPredicate(*PredMBB, MBP, false)) + return false; + + return MBP.LHS.isReg() && MBP.RHS.isImm() && MBP.RHS.getImm() == 0 && + (MBP.Predicate == MachineBranchPredicate::PRED_NE || + MBP.Predicate == MachineBranchPredicate::PRED_EQ) && + MBP.LHS.getReg() == BaseReg; +} + /// SinkInstruction - Determine whether it is safe to sink the specified machine /// instruction out of its current block into a successor. bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore, @@ -691,6 +735,11 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore, if (MI->isConvergent()) return false; + // Don't break implicit null checks. This is a performance heuristic, and not + // required for correctness. + if (SinkingPreventsImplicitNullCheck(MI, TII, TRI)) + return false; + // FIXME: This should include support for sinking instructions within the // block they are currently in to shorten the live ranges. We often get // instructions sunk into the top of a large block, but it would be better to |