//===-- ShrinkWrapping.cpp - Reduce spills/restores of callee-saved regs --===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a shrink wrapping variant of prolog/epilog insertion:
// - Spills and restores of callee-saved registers (CSRs) are placed in the
// machine CFG to tightly surround their uses so that execution paths that
// do not use CSRs do not pay the spill/restore penalty.
//
// - Avoiding placment of spills/restores in loops: if a CSR is used inside a
// loop the spills are placed in the loop preheader, and restores are
// placed in the loop exit nodes (the successors of loop _exiting_ nodes).
//
// - Covering paths without CSR uses:
// If a region in a CFG uses CSRs and has multiple entry and/or exit points,
// the use info for the CSRs inside the region is propagated outward in the
// CFG to ensure validity of the spill/restore placements. This decreases
// the effectiveness of shrink wrapping but does not require edge splitting
// in the machine CFG.
//
// This shrink wrapping implementation uses an iterative analysis to determine
// which basic blocks require spills and restores for CSRs.
//
// This pass uses MachineDominators and MachineLoopInfo. Loop information
// is used to prevent placement of callee-saved register spills/restores
// in the bodies of loops.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "shrink-wrap"
#include "PrologEpilogInserter.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <sstream>
using namespace llvm;
STATISTIC(numSRReduced, "Number of CSR spills+restores reduced.");
// Shrink Wrapping:
static cl::opt<bool>
ShrinkWrapping("shrink-wrap",
cl::desc("Shrink wrap callee-saved register spills/restores"));
// Shrink wrap only the specified function, a debugging aid.
static cl::opt<std::string>
ShrinkWrapFunc("shrink-wrap-func", cl::Hidden,
cl::desc("Shrink wrap the specified function"),
cl::value_desc("funcname"),
cl::init(""));
// Debugging level for shrink wrapping.
enum ShrinkWrapDebugLevel {
Disabled, BasicInfo, Iterations, Details
};
static cl::opt<enum ShrinkWrapDebugLevel>
ShrinkWrapDebugging("shrink-wrap-dbg", cl::Hidden,
cl::desc("Print shrink wrapping debugging information"),
cl::values(
clEnumVal(Disabled , "disable debug output"),
clEnumVal(BasicInfo , "print basic DF sets"),
clEnumVal(Iterations, "print SR sets for each iteration"),
clEnumVal(Details , "print all DF sets"),
clEnumValEnd));
void PEI::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
if (ShrinkWrapping || ShrinkWrapFunc != "") {
AU.addRequired<MachineLoopInfo>();
AU.addRequired<MachineDominatorTree>();
}
AU.addPreserved<MachineLoopInfo>();
AU.addPreserved<MachineDominatorTree>();
AU.addRequired<TargetPassConfig>();
MachineFunctionPass::getAnalysisUsage(AU);
}
//===----------------------------------------------------------------------===//
// ShrinkWrapping implementation
//===----------------------------------------------------------------------===//
// Convienences for dealing with machine loops.
MachineBasicBlock* PEI::getTopLevelLoopPreheader(MachineLoop* LP) {
assert(LP && "Machine loop is NULL.");
MachineBasicBlock* PHDR = LP->getLoopPreheader();
MachineLoop* PLP = LP->getParentLoop();
while (PLP) {
PHDR = PLP->getLoopPreheader();
PLP = PLP->getParentLoop();
}
return PHDR;
}
MachineLoop* PEI::getTopLevelLoopParent(MachineLoop *LP) {
if (LP == 0)
return 0;
MachineLoop* PLP = LP->getParentLoop();
while (PLP) {
LP = PLP;
PLP = PLP->getParentLoop();
}
return LP;
}
bool