diff options
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp index 26752369a771..1edfc0931055 100644 --- a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp @@ -61,15 +61,42 @@ bool GIMatchTableExecutor::isBaseWithConstantOffset( bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const { + auto IntoMIIter = IntoMI.getIterator(); + // Immediate neighbours are already folded. if (MI.getParent() == IntoMI.getParent() && - std::next(MI.getIterator()) == IntoMI.getIterator()) + std::next(MI.getIterator()) == IntoMIIter) return true; // Convergent instructions cannot be moved in the CFG. if (MI.isConvergent() && MI.getParent() != IntoMI.getParent()) return false; - return !MI.mayLoadOrStore() && !MI.mayRaiseFPException() && - !MI.hasUnmodeledSideEffects() && MI.implicit_operands().empty(); + if (MI.isLoadFoldBarrier()) + return false; + + // If the load is simple, check instructions between MI and IntoMI + if (MI.mayLoad() && MI.getParent() == IntoMI.getParent()) { + if (MI.memoperands_empty()) + return false; + auto &MMO = **(MI.memoperands_begin()); + if (MMO.isAtomic() || MMO.isVolatile()) + return false; + + // Ensure instructions between MI and IntoMI are not affected when combined + unsigned Iter = 0; + const unsigned MaxIter = 20; + for (auto &CurrMI : + instructionsWithoutDebug(MI.getIterator(), IntoMI.getIterator())) { + if (CurrMI.isLoadFoldBarrier()) + return false; + + if (Iter++ == MaxIter) + return false; + } + + return true; + } + + return !MI.mayLoad(); } |
