#include "llvm/Target/TargetInstrInfo.h"
// To access TargetInstrInfo.
#include "llvm/Target/TargetSubtargetInfo.h"
-#include "llvm/Support/CommandLine.h"
#define DEBUG_TYPE "shrink-wrap"
using namespace llvm;
-static cl::opt<cl::boolOrDefault>
- EnableShrinkWrapOpt("enable-shrink-wrap", cl::Hidden,
- cl::desc("enable the shrink-wrapping pass"));
-
STATISTIC(NumFunc, "Number of functions");
STATISTIC(NumCandidates, "Number of shrink-wrapping candidates");
STATISTIC(NumCandidatesDropped,
"Number of shrink-wrapping candidates dropped because of frequency");
+static cl::opt<cl::boolOrDefault>
+ EnableShrinkWrapOpt("enable-shrink-wrap", cl::Hidden,
+ cl::desc("enable the shrink-wrapping pass"));
+
namespace {
/// \brief Class to determine where the safe point to insert the
/// prologue and epilogue are.
/// shrink-wrapping.
bool ArePointsInteresting() const { return Save != Entry && Save && Restore; }
+ /// \brief Check if shrink wrapping is enabled for this target and function.
+ static bool isShrinkWrapEnabled(const MachineFunction &MF);
+
public:
static char ID;
ShrinkWrap() : MachineFunctionPass(ID) {
initializeShrinkWrapPass(*PassRegistry::getPassRegistry());
}
-
- ShrinkWrap(std::function<bool(const MachineFunction &)> Ftor) :
- MachineFunctionPass(ID), PredicateFtor(Ftor) {
- initializeShrinkWrapPass(*PassRegistry::getPassRegistry());
- }
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
/// \brief Perform the shrink-wrapping analysis and update
/// the MachineFrameInfo attached to \p MF with the results.
bool runOnMachineFunction(MachineFunction &MF) override;
-
-private:
- /// \brief Predicate function to determine if shrink wrapping should run.
- ///
- /// This function will be run at the beginning of shrink wrapping and
- /// determine whether shrink wrapping should run on the given MachineFunction.
- /// \param[in] MF The MachineFunction to run shrink wrapping on.
- /// \return true if shrink wrapping should be run, false otherwise.
- std::function<bool(const MachineFunction &MF)> PredicateFtor;
};
} // End anonymous namespace.
// Fix (C).
if (Save && Restore && Save != Restore &&
MLI->getLoopFor(Save) != MLI->getLoopFor(Restore)) {
- if (MLI->getLoopDepth(Save) > MLI->getLoopDepth(Restore))
- // Push Save outside of this loop.
- Save = FindIDom<>(*Save, Save->predecessors(), *MDT);
- else
+ if (MLI->getLoopDepth(Save) > MLI->getLoopDepth(Restore)) {
+ // Push Save outside of this loop if immediate dominator is different
+ // from save block. If immediate dominator is not different, bail out.
+ MachineBasicBlock *IDom = FindIDom<>(*Save, Save->predecessors(), *MDT);
+ if (IDom != Save)
+ Save = IDom;
+ else {
+ Save = nullptr;
+ break;
+ }
+ }
+ else {
+ // If the loop does not exit, there is no point in looking
+ // for a post-dominator outside the loop.
+ SmallVector<MachineBasicBlock*, 4> ExitBlocks;
+ MLI->getLoopFor(Restore)->getExitingBlocks(ExitBlocks);
// Push Restore outside of this loop.
- Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT);
+ // Look for the immediate post-dominator of the loop exits.
+ MachineBasicBlock *IPdom = Restore;
+ for (MachineBasicBlock *LoopExitBB: ExitBlocks) {
+ IPdom = FindIDom<>(*IPdom, LoopExitBB->successors(), *MPDT);
+ if (!IPdom)
+ break;
+ }
+ // If the immediate post-dominator is not in a less nested loop,
+ // then we are stuck in a program with an infinite loop.
+ // In that case, we will not find a safe point, hence, bail out.
+ if (IPdom && MLI->getLoopDepth(IPdom) < MLI->getLoopDepth(Restore))
+ Restore = IPdom;
+ else {
+ Restore = nullptr;
+ break;
+ }
+ }
}
}
}
bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) {
- if (PredicateFtor && !PredicateFtor(MF))
- return false;
-
- if (MF.empty() || skipOptnoneFunction(*MF.getFunction()))
+ if (MF.empty() || !isShrinkWrapEnabled(MF))
return false;
DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n');
return false;
}
-/// If EnableShrinkWrap is set run shrink wrapping on the given Machine
-/// Function. Otherwise, shrink wrapping is disabled.
-/// This function can be overridden in each target-specific TargetPassConfig
-/// class to allow different predicate logic for each target.
-bool TargetPassConfig::runShrinkWrap(const MachineFunction &Fn) const {
+bool ShrinkWrap::isShrinkWrapEnabled(const MachineFunction &MF) {
+ const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
+
switch (EnableShrinkWrapOpt) {
+ case cl::BOU_UNSET:
+ return TFI->enableShrinkWrapping(MF);
+ // If EnableShrinkWrap is set, it takes precedence on whatever the
+ // target sets. The rational is that we assume we want to test
+ // something related to shrink-wrapping.
case cl::BOU_TRUE:
return true;
- case cl::BOU_UNSET:
case cl::BOU_FALSE:
return false;
}
llvm_unreachable("Invalid shrink-wrapping state");
}
-
-/// Create a ShrinkWrap FunctionPass using the runShrinkWrap predicate
-/// function.
-FunctionPass *TargetPassConfig::createShrinkWrapPass() {
- std::function<bool(const MachineFunction &Fn)> Ftor =
- std::bind(&TargetPassConfig::runShrinkWrap, this, std::placeholders::_1);
- return new ShrinkWrap(Ftor);
-}