Run shrink wrapping in parallel

Summary:
Shrink wrapping is an expensive part of frame optimizations if
performed on all functions. This diff makes it run in parallel,
reducing wall time.

(cherry picked from FBD16092651)
This commit is contained in:
laith sakka 2019-07-02 10:48:43 -07:00 committed by Maksim Panchenko
parent 7d42835418
commit fde5a2b470
17 changed files with 190 additions and 110 deletions

View File

@ -1846,7 +1846,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
DEBUG(dbgs() << "last block was marked as a fall-through in " << *this
<< '\n');
}
// Assign landing pads and throwers info.
recomputeLandingPads();
@ -2571,7 +2571,7 @@ bool BinaryFunction::finalizeCFIState() {
DEBUG(dbgs() << "Trying to fix CFI states for each BB after reordering.\n");
DEBUG(dbgs() << "This is the list of CFI states for each BB of " << *this
<< ": ");
int32_t State = 0;
bool SeenCold = false;
auto Sep = "";
@ -2645,7 +2645,7 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
bool EmitCodeOnly, bool LabelsForOffsets) {
if (!EmitCodeOnly && EmitColdPart && hasConstantIsland())
duplicateConstantIslands();
// Track first emitted instruction with debug info.
bool FirstInstr = true;
for (auto BB : layout()) {
@ -2725,7 +2725,7 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
auto OriginalAddress =
BC.MIB->tryGetAnnotationAs<uint64_t>(Instr, "SDTMarker").get();
auto *SDTLabel = BC.SDTMarkers[OriginalAddress].Label;
// A given symbol should only be emitted as a label once
if (SDTLabel->isUndefined())
Streamer.EmitLabel(SDTLabel);
@ -3744,7 +3744,11 @@ bool BinaryFunction::replaceJumpTableEntryIn(BinaryBasicBlock *BB,
BinaryBasicBlock *BinaryFunction::splitEdge(BinaryBasicBlock *From,
BinaryBasicBlock *To) {
// Create intermediate BB
MCSymbol *Tmp = BC.Ctx->createTempSymbol("SplitEdge", true);
MCSymbol *Tmp;
{
std::unique_lock<std::shared_timed_mutex> WrLock(BC.CtxMutex);
Tmp = BC.Ctx->createTempSymbol("SplitEdge", true);
}
// Link new BBs to the original input offset of the From BB, so we can map
// samples recorded in new BBs back to the original BB seem in the input
// binary (if using BAT)
@ -3871,13 +3875,13 @@ SMLoc BinaryFunction::emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc,
// Always emit is_stmt at the beginning of function fragment.
if (FirstInstr)
Flags |= DWARF2_FLAG_IS_STMT;
BC.Ctx->setCurrentDwarfLoc(
CurrentFilenum,
CurrentRow.Line,
CurrentRow.Line,
CurrentRow.Column,
Flags,
CurrentRow.Isa,
Flags,
CurrentRow.Isa,
CurrentRow.Discriminator);
BC.Ctx->setDwarfCompileUnitID(FunctionUnitIndex);

View File

@ -555,8 +555,10 @@ public:
return count(*Expressions[PointIdx], Expr);
}
InstrsDataflowAnalysis(const BinaryContext &BC, BinaryFunction &BF)
: DataflowAnalysis<Derived, BitVector, Backward, StatePrinterTy>(BC, BF) {}
InstrsDataflowAnalysis(const BinaryContext &BC, BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocId = 0)
: DataflowAnalysis<Derived, BitVector, Backward, StatePrinterTy>(
BC, BF, AllocId) {}
virtual ~InstrsDataflowAnalysis() {}
};

View File

@ -19,7 +19,7 @@ ReachingDefOrUse</*Def=*/true> &DataflowInfoManager::getReachingDefs() {
if (RD)
return *RD;
assert(RA && "RegAnalysis required");
RD.reset(new ReachingDefOrUse<true>(*RA, BC, BF));
RD.reset(new ReachingDefOrUse<true>(*RA, BC, BF, None, AllocatorId));
RD->run();
return *RD;
}
@ -32,7 +32,7 @@ ReachingDefOrUse</*Def=*/false> &DataflowInfoManager::getReachingUses() {
if (RU)
return *RU;
assert(RA && "RegAnalysis required");
RU.reset(new ReachingDefOrUse<false>(*RA, BC, BF));
RU.reset(new ReachingDefOrUse<false>(*RA, BC, BF, None, AllocatorId));
RU->run();
return *RU;
}
@ -45,7 +45,7 @@ LivenessAnalysis &DataflowInfoManager::getLivenessAnalysis() {
if (LA)
return *LA;
assert(RA && "RegAnalysis required");
LA.reset(new LivenessAnalysis(*RA, BC, BF));
LA.reset(new LivenessAnalysis(*RA, BC, BF, AllocatorId));
LA->run();
return *LA;
}
@ -58,7 +58,7 @@ StackReachingUses &DataflowInfoManager::getStackReachingUses() {
if (SRU)
return *SRU;
assert(FA && "FrameAnalysis required");
SRU.reset(new StackReachingUses(*FA, BC, BF));
SRU.reset(new StackReachingUses(*FA, BC, BF, AllocatorId));
SRU->run();
return *SRU;
}
@ -70,7 +70,7 @@ void DataflowInfoManager::invalidateStackReachingUses() {
DominatorAnalysis<false> &DataflowInfoManager::getDominatorAnalysis() {
if (DA)
return *DA;
DA.reset(new DominatorAnalysis<false>(BC, BF));
DA.reset(new DominatorAnalysis<false>(BC, BF, AllocatorId));
DA->run();
return *DA;
}
@ -82,7 +82,7 @@ void DataflowInfoManager::invalidateDominatorAnalysis() {
DominatorAnalysis<true> &DataflowInfoManager::getPostDominatorAnalysis() {
if (PDA)
return *PDA;
PDA.reset(new DominatorAnalysis<true>(BC, BF));
PDA.reset(new DominatorAnalysis<true>(BC, BF, AllocatorId));
PDA->run();
return *PDA;
}
@ -94,7 +94,7 @@ void DataflowInfoManager::invalidatePostDominatorAnalysis() {
StackPointerTracking &DataflowInfoManager::getStackPointerTracking() {
if (SPT)
return *SPT;
SPT.reset(new StackPointerTracking(BC, BF));
SPT.reset(new StackPointerTracking(BC, BF, AllocatorId));
SPT->run();
return *SPT;
}
@ -107,7 +107,7 @@ void DataflowInfoManager::invalidateStackPointerTracking() {
ReachingInsns<false> &DataflowInfoManager::getReachingInsns() {
if (RI)
return *RI;
RI.reset(new ReachingInsns<false>(BC, BF));
RI.reset(new ReachingInsns<false>(BC, BF, AllocatorId));
RI->run();
return *RI;
}
@ -119,7 +119,7 @@ void DataflowInfoManager::invalidateReachingInsns() {
ReachingInsns<true> &DataflowInfoManager::getReachingInsnsBackwards() {
if (RIB)
return *RIB;
RIB.reset(new ReachingInsns<true>(BC, BF));
RIB.reset(new ReachingInsns<true>(BC, BF, AllocatorId));
RIB->run();
return *RIB;
}
@ -131,7 +131,8 @@ void DataflowInfoManager::invalidateReachingInsnsBackwards() {
StackAllocationAnalysis &DataflowInfoManager::getStackAllocationAnalysis() {
if (SAA)
return *SAA;
SAA.reset(new StackAllocationAnalysis(BC, BF, getStackPointerTracking()));
SAA.reset(new StackAllocationAnalysis(BC, BF, getStackPointerTracking(),
AllocatorId));
SAA->run();
return *SAA;
}

View File

@ -47,10 +47,15 @@ class DataflowInfoManager {
std::unique_ptr<std::unordered_map<const MCInst *, BinaryBasicBlock *>>
InsnToBB;
// Id of the allocator to be used for annotations added by any of the managed
// analysis
MCPlusBuilder::AllocatorIdTy AllocatorId;
public:
DataflowInfoManager(const BinaryContext &BC, BinaryFunction &BF,
const RegAnalysis *RA, const FrameAnalysis *FA)
: RA(RA), FA(FA), BC(BC), BF(BF){};
const RegAnalysis *RA, const FrameAnalysis *FA,
MCPlusBuilder::AllocatorIdTy AllocId = 0)
: RA(RA), FA(FA), BC(BC), BF(BF), AllocatorId(AllocId){};
/// Helper function to fetch the parent BB associated with a program point
/// If PP is a BB itself, then return itself (cast to a BinaryBasicBlock)

View File

@ -35,8 +35,11 @@ class DominatorAnalysis
Backward>;
public:
DominatorAnalysis(const BinaryContext &BC, BinaryFunction &BF)
: InstrsDataflowAnalysis<DominatorAnalysis<Backward>, Backward>(BC, BF) {}
DominatorAnalysis(const BinaryContext &BC, BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocId)
: InstrsDataflowAnalysis<DominatorAnalysis<Backward>, Backward>(BC, BF,
AllocId) {
}
virtual ~DominatorAnalysis() {}
SmallSetVector<ProgramPoint, 4> getDominanceFrontierFor(const MCInst &Dom) {
@ -102,8 +105,6 @@ public:
}
void run() {
NamedRegionTimer T1("DA", "Dominator Analysis", "Dataflow", "Dataflow",
opts::TimeOpts);
InstrsDataflowAnalysis<DominatorAnalysis<Backward>, Backward>::run();
}

View File

@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//
#include "FrameOptimizer.h"
#include "ParallelUtilities.h"
#include "ShrinkWrapping.h"
#include "StackAvailableExpressions.h"
#include "StackReachingUses.h"
@ -46,7 +47,7 @@ RemoveStores("frame-opt-rm-stores",
cl::init(false),
cl::ZeroOrMore,
cl::cat(BoltOptCategory));
} // namespace opts
namespace llvm {
@ -246,8 +247,8 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
RA = std::make_unique<RegAnalysis>(BC, &BC.getBinaryFunctions(), CG.get());
}
// Our main loop: perform caller-saved register optimizations, then
// callee-saved register optimizations (shrink wrapping).
// Perform caller-saved register optimizations, then callee-saved register
// optimizations (shrink wrapping)
for (auto &I : BC.getBinaryFunctions()) {
if (!FA->hasFrameInfo(I.second))
continue;
@ -261,11 +262,13 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
<< " ) exceeds our hotness threshold ( "
<< BC.getHotThreshold() << " )\n");
}
{
NamedRegionTimer T1("removeloads", "remove loads", "FOP", "FOP breakdown",
opts::TimeOpts);
removeUnnecessaryLoads(*RA, *FA, BC, I.second);
}
if (opts::RemoveStores) {
NamedRegionTimer T1("removestores", "remove stores", "FOP",
"FOP breakdown", opts::TimeOpts);
@ -274,14 +277,13 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
// Don't even start shrink wrapping if no profiling info is available
if (I.second.getKnownExecutionCount() == 0)
continue;
{
NamedRegionTimer T1("movespills", "move spills", "FOP", "FOP breakdown",
opts::TimeOpts);
DataflowInfoManager Info(BC, I.second, RA.get(), FA.get());
ShrinkWrapping SW(*FA, BC, I.second, Info);
if (SW.perform())
FuncsChanged.insert(&I.second);
}
}
{
NamedRegionTimer T1("shrinkwrapping", "shrink wrapping", "FOP",
"FOP breakdown", opts::TimeOpts);
performShrinkWrapping(*RA, *FA, BC);
}
outs() << "BOLT-INFO: FOP optimized " << NumRedundantLoads
@ -296,5 +298,63 @@ void FrameOptimizerPass::runOnFunctions(BinaryContext &BC) {
ShrinkWrapping::printStats();
}
void FrameOptimizerPass::performShrinkWrapping(const RegAnalysis &RA,
const FrameAnalysis &FA,
BinaryContext &BC) {
// Initialize necessary annotations to allow safe parallel accesses to
// annotation index in MIB
BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getSaveTagName());
BC.MIB->getOrCreateAnnotationIndex(CalleeSavedAnalysis::getRestoreTagName());
BC.MIB->getOrCreateAnnotationIndex(StackLayoutModifier::getTodoTagName());
BC.MIB->getOrCreateAnnotationIndex(StackLayoutModifier::getSlotTagName());
BC.MIB->getOrCreateAnnotationIndex(
StackLayoutModifier::getOffsetCFIRegTagName());
BC.MIB->getOrCreateAnnotationIndex("ReachingDefs");
BC.MIB->getOrCreateAnnotationIndex("ReachingUses");
BC.MIB->getOrCreateAnnotationIndex("LivenessAnalysis");
BC.MIB->getOrCreateAnnotationIndex("StackReachingUses");
BC.MIB->getOrCreateAnnotationIndex("PostDominatorAnalysis");
BC.MIB->getOrCreateAnnotationIndex("DominatorAnalysis");
BC.MIB->getOrCreateAnnotationIndex("StackPointerTracking");
BC.MIB->getOrCreateAnnotationIndex("StackPointerTrackingForInternalCalls");
BC.MIB->getOrCreateAnnotationIndex("StackAvailableExpressions");
BC.MIB->getOrCreateAnnotationIndex("StackAllocationAnalysis");
BC.MIB->getOrCreateAnnotationIndex("ShrinkWrap-Todo");
BC.MIB->getOrCreateAnnotationIndex("PredictiveStackPointerTracking");
BC.MIB->getOrCreateAnnotationIndex("ReachingInsnsBackward");
BC.MIB->getOrCreateAnnotationIndex("ReachingInsns");
BC.MIB->getOrCreateAnnotationIndex("AccessesDeletedPos");
BC.MIB->getOrCreateAnnotationIndex("DeleteMe");
ParallelUtilities::PredicateTy SkipPredicate = [&](const BinaryFunction &BF) {
if (!FA.hasFrameInfo(BF))
return true;
if (opts::FrameOptimization == FOP_HOT &&
(BF.getKnownExecutionCount() < BC.getHotThreshold()))
return true;
if (BF.getKnownExecutionCount() == 0)
return true;
return false;
};
ParallelUtilities::WorkFuncWithAllocTy WorkFunction =
[&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocatorId) {
DataflowInfoManager Info(BC, BF, &RA, &FA, AllocatorId);
ShrinkWrapping SW(FA, BC, BF, Info, AllocatorId);
if (SW.perform()) {
std::lock_guard<std::mutex> Lock(FuncsChangedMutex);
FuncsChanged.insert(&BF);
}
};
ParallelUtilities::runOnEachFunctionWithUniqueAllocId(
BC, ParallelUtilities::SchedulingPolicy::SP_INST_QUADRATIC, WorkFunction,
SkipPredicate, "shrink-wrapping");
}
} // namespace bolt
} // namespace llvm

View File

@ -86,6 +86,8 @@ class FrameOptimizerPass : public BinaryFunctionPass {
DenseSet<const BinaryFunction *> FuncsChanged;
std::mutex FuncsChangedMutex;
/// Perform a dataflow analysis in \p BF to reveal unnecessary reloads from
/// the frame. Use the analysis to convert memory loads to register moves or
/// immediate loads. Delete redundant register moves.
@ -99,6 +101,10 @@ class FrameOptimizerPass : public BinaryFunctionPass {
const BinaryContext &BC,
BinaryFunction &BF);
/// Perform shrinkwrapping step
void performShrinkWrapping(const RegAnalysis &RA, const FrameAnalysis &FA,
BinaryContext &BC);
public:
explicit FrameOptimizerPass(const cl::opt<bool> &PrintPass)
: BinaryFunctionPass(PrintPass) {}

View File

@ -38,8 +38,8 @@ class LivenessAnalysis
public:
LivenessAnalysis(const RegAnalysis &RA, const BinaryContext &BC,
BinaryFunction &BF)
: Parent(BC, BF), RA(RA), NumRegs(BC.MRI->getNumRegs()) {}
BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId)
: Parent(BC, BF, AllocId), RA(RA), NumRegs(BC.MRI->getNumRegs()) {}
virtual ~LivenessAnalysis();
bool isAlive(ProgramPoint PP, MCPhysReg Reg) const {
@ -50,8 +50,6 @@ public:
}
void run() {
NamedRegionTimer T1("LA", "Liveness Analysis", "Dataflow", "Dataflow",
opts::TimeOpts);
Parent::run();
}

View File

@ -36,9 +36,10 @@ class ReachingDefOrUse
public:
ReachingDefOrUse(const RegAnalysis &RA, const BinaryContext &BC,
BinaryFunction &BF, Optional<MCPhysReg> TrackingReg = None)
: InstrsDataflowAnalysis<ReachingDefOrUse<Def>, !Def>(BC, BF), RA(RA),
TrackingReg(TrackingReg) {}
BinaryFunction &BF, Optional<MCPhysReg> TrackingReg = None,
MCPlusBuilder::AllocatorIdTy AllocId = 0)
: InstrsDataflowAnalysis<ReachingDefOrUse<Def>, !Def>(BC, BF, AllocId),
RA(RA), TrackingReg(TrackingReg) {}
virtual ~ReachingDefOrUse() {}
bool isReachedBy(MCPhysReg Reg, ExprIterator Candidates) {
@ -60,8 +61,6 @@ public:
}
void run() {
NamedRegionTimer T1("RD", "Reaching Defs", "Dataflow", "Dataflow",
opts::TimeOpts);
InstrsDataflowAnalysis<ReachingDefOrUse<Def>, !Def>::run();
}

View File

@ -29,8 +29,9 @@ class ReachingInsns
friend class DataflowAnalysis<ReachingInsns<Backward>, BitVector, Backward>;
public:
ReachingInsns(const BinaryContext &BC, BinaryFunction &BF)
: InstrsDataflowAnalysis<ReachingInsns, Backward>(BC, BF) {}
ReachingInsns(const BinaryContext &BC, BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocId = 0)
: InstrsDataflowAnalysis<ReachingInsns, Backward>(BC, BF, AllocId) {}
virtual ~ReachingInsns() {}
bool isInLoop(const BinaryBasicBlock &BB) {
@ -46,8 +47,6 @@ public:
}
void run() {
NamedRegionTimer T1("RI", "Reaching Insns", "Dataflow", "Dataflow",
opts::TimeOpts);
InstrsDataflowAnalysis<ReachingInsns<Backward>, Backward>::run();
}

View File

@ -102,7 +102,7 @@ void CalleeSavedAnalysis::analyzeSaves() {
CalleeSaved.set(FIE->RegOrImm);
SaveFIEByReg[FIE->RegOrImm] = &*FIE;
SavingCost[FIE->RegOrImm] += InsnToBB[&Inst]->getKnownExecutionCount();
BC.MIB->addAnnotation(Inst, getSaveTag(), FIE->RegOrImm);
BC.MIB->addAnnotation(Inst, getSaveTag(), FIE->RegOrImm, AllocatorId);
OffsetsByReg[FIE->RegOrImm] = FIE->StackOffset;
DEBUG(dbgs() << "Logging new candidate for Callee-Saved Reg: "
<< FIE->RegOrImm << "\n");
@ -153,7 +153,8 @@ void CalleeSavedAnalysis::analyzeRestores() {
<< "\n");
if (LoadFIEByReg[FIE->RegOrImm] == nullptr)
LoadFIEByReg[FIE->RegOrImm] = &*FIE;
BC.MIB->addAnnotation(Inst, getRestoreTag(), FIE->RegOrImm);
BC.MIB->addAnnotation(Inst, getRestoreTag(), FIE->RegOrImm,
AllocatorId);
HasRestores.set(FIE->RegOrImm);
}
Prev = &Inst;
@ -311,7 +312,7 @@ void StackLayoutModifier::checkStackPointerRestore(MCInst &Point) {
// We are restoring SP to an old value based on FP. Mark it as a stack
// access to be fixed later.
BC.MIB->addAnnotation(Point, getSlotTag(), Output);
BC.MIB->addAnnotation(Point, getSlotTag(), Output, AllocatorId);
}
void StackLayoutModifier::classifyStackAccesses() {
@ -354,7 +355,7 @@ void StackLayoutModifier::classifyStackAccesses() {
// We are free to go. Add it as available stack slot which we know how
// to move it.
AvailableRegions[FIEX->StackOffset] = FIEX->Size;
BC.MIB->addAnnotation(Inst, getSlotTag(), FIEX->StackOffset);
BC.MIB->addAnnotation(Inst, getSlotTag(), FIEX->StackOffset, AllocatorId);
RegionToRegMap[FIEX->StackOffset].insert(FIEX->RegOrImm);
RegToRegionMap[FIEX->RegOrImm].insert(FIEX->StackOffset);
DEBUG(dbgs() << "Adding region " << FIEX->StackOffset << " size "
@ -371,7 +372,7 @@ void StackLayoutModifier::classifyCFIs() {
auto recordAccess = [&](MCInst *Inst, int64_t Offset) {
const uint16_t Reg = BC.MRI->getLLVMRegNum(CfaReg, /*isEH=*/false);
if (Reg == BC.MIB->getStackPointer() || Reg == BC.MIB->getFramePointer()) {
BC.MIB->addAnnotation(*Inst, getSlotTag(), Offset);
BC.MIB->addAnnotation(*Inst, getSlotTag(), Offset, AllocatorId);
DEBUG(dbgs() << "Recording CFI " << Offset << "\n");
} else {
IsSimple = false;
@ -400,12 +401,14 @@ void StackLayoutModifier::classifyCFIs() {
recordAccess(&Inst, CFI->getOffset());
BC.MIB->addAnnotation(Inst, getOffsetCFIRegTag(),
BC.MRI->getLLVMRegNum(CFI->getRegister(),
/*isEH=*/false));
/*isEH=*/false),
AllocatorId);
break;
case MCCFIInstruction::OpSameValue:
BC.MIB->addAnnotation(Inst, getOffsetCFIRegTag(),
BC.MRI->getLLVMRegNum(CFI->getRegister(),
/*isEH=*/false));
/*isEH=*/false),
AllocatorId);
break;
case MCCFIInstruction::OpRememberState:
CFIStack.push(std::make_pair(CfaOffset, CfaReg));
@ -432,7 +435,7 @@ void StackLayoutModifier::classifyCFIs() {
void StackLayoutModifier::scheduleChange(
MCInst &Inst, StackLayoutModifier::WorklistItem Item) {
auto &WList = BC.MIB->getOrCreateAnnotationAs<std::vector<WorklistItem>>(
Inst, getTodoTag());
Inst, getTodoTag(), AllocatorId);
WList.push_back(Item);
}
@ -510,7 +513,7 @@ bool StackLayoutModifier::collapseRegion(MCInst *Alloc, int64_t RegionAddr,
}
if (Slot == RegionAddr) {
BC.MIB->addAnnotation(Inst, "AccessesDeletedPos", 0U);
BC.MIB->addAnnotation(Inst, "AccessesDeletedPos", 0U, AllocatorId);
continue;
}
if (BC.MIB->isPush(Inst) || BC.MIB->isPop(Inst)) {
@ -1454,13 +1457,13 @@ protected:
public:
PredictiveStackPointerTracking(const BinaryContext &BC, BinaryFunction &BF,
decltype(ShrinkWrapping::Todo) &TodoMap,
DataflowInfoManager &Info)
: StackPointerTrackingBase<PredictiveStackPointerTracking>(BC, BF),
DataflowInfoManager &Info,
MCPlusBuilder::AllocatorIdTy AllocatorId = 0)
: StackPointerTrackingBase<PredictiveStackPointerTracking>(BC, BF,
AllocatorId),
TodoMap(TodoMap), Info(Info) {}
void run() {
NamedRegionTimer T1("PSPT", "Predictive Stack Pointer Tracking", "Dataflow",
"Dataflow", opts::TimeOpts);
StackPointerTrackingBase<PredictiveStackPointerTracking>::run();
}
};
@ -1553,7 +1556,7 @@ void ShrinkWrapping::rebuildCFIForSP() {
continue;
auto *CFI = BF.getCFIFor(Inst);
if (CFI->getOperation() == MCCFIInstruction::OpDefCfaOffset)
BC.MIB->addAnnotation(Inst, "DeleteMe", 0U);
BC.MIB->addAnnotation(Inst, "DeleteMe", 0U, AllocatorId);
}
}
@ -1812,7 +1815,7 @@ BBIterTy ShrinkWrapping::processInsertionsList(
}
bool ShrinkWrapping::processInsertions() {
PredictiveStackPointerTracking PSPT(BC, BF, Todo, Info);
PredictiveStackPointerTracking PSPT(BC, BF, Todo, Info, AllocatorId);
PSPT.run();
bool Changes{false};

View File

@ -27,6 +27,8 @@ class CalleeSavedAnalysis {
const BinaryContext &BC;
BinaryFunction &BF;
DataflowInfoManager &Info;
MCPlusBuilder::AllocatorIdTy AllocatorId;
Optional<unsigned> SaveTagIndex;
Optional<unsigned> RestoreTagIndex;
@ -39,12 +41,6 @@ class CalleeSavedAnalysis {
/// function.
void analyzeRestores();
/// Returns the identifying string used to annotate instructions with metadata
/// for this analysis. These are deleted in the destructor.
static StringRef getSaveTagName() {
return StringRef("CSA-SavedReg");
}
unsigned getSaveTag() {
if (SaveTagIndex)
return *SaveTagIndex;
@ -52,10 +48,6 @@ class CalleeSavedAnalysis {
return *SaveTagIndex;
}
static StringRef getRestoreTagName() {
return StringRef("CSA-RestoredReg");
}
unsigned getRestoreTag() {
if (RestoreTagIndex)
return *RestoreTagIndex;
@ -72,8 +64,9 @@ public:
std::vector<const FrameIndexEntry*> LoadFIEByReg;
CalleeSavedAnalysis(const FrameAnalysis &FA, const BinaryContext &BC,
BinaryFunction &BF, DataflowInfoManager &Info)
: FA(FA), BC(BC), BF(BF), Info(Info),
BinaryFunction &BF, DataflowInfoManager &Info,
MCPlusBuilder::AllocatorIdTy AllocId)
: FA(FA), BC(BC), BF(BF), Info(Info), AllocatorId(AllocId),
CalleeSaved(BC.MRI->getNumRegs(), false),
OffsetsByReg(BC.MRI->getNumRegs(), 0LL),
HasRestores(BC.MRI->getNumRegs(), false),
@ -112,6 +105,17 @@ public:
/// instructions).
std::vector<MCInst *> getSavesByReg(uint16_t Reg);
std::vector<MCInst *> getRestoresByReg(uint16_t Reg);
/// Returns the identifying string used to annotate instructions with metadata
/// for this analysis. These are deleted in the destructor.
static StringRef getSaveTagName() {
return StringRef("CSA-SavedReg");
}
static StringRef getRestoreTagName() {
return StringRef("CSA-RestoredReg");
}
};
/// Identifies in a given binary function all stack regions being used and allow
@ -122,6 +126,7 @@ class StackLayoutModifier {
const BinaryContext &BC;
BinaryFunction &BF;
DataflowInfoManager &Info;
MCPlusBuilder::AllocatorIdTy AllocatorId;
// Keep track of stack slots we know how to safely move
std::map<int64_t, int64_t> AvailableRegions;
@ -217,20 +222,11 @@ private:
return *OffsetCFIRegTagIndex;
}
static StringRef getTodoTagName() {
return StringRef("SLM-TodoTag");
}
static StringRef getSlotTagName() {
return StringRef("SLM-SlotTag");
}
static StringRef getOffsetCFIRegTagName() {
return StringRef("SLM-OffsetCFIReg");
}
public:
StackLayoutModifier(const FrameAnalysis &FA, const BinaryContext &BC,
BinaryFunction &BF, DataflowInfoManager &Info)
: FA(FA), BC(BC), BF(BF), Info(Info) {}
BinaryFunction &BF, DataflowInfoManager &Info,
MCPlusBuilder::AllocatorIdTy AllocId)
: FA(FA), BC(BC), BF(BF), Info(Info), AllocatorId(AllocId) {}
~StackLayoutModifier() {
for (auto &BB : BF) {
@ -283,6 +279,19 @@ public:
/// Perform initial assessment of the function trying to understand its stack
/// accesses.
void initialize();
static StringRef getTodoTagName() {
return StringRef("SLM-TodoTag");
}
static StringRef getSlotTagName() {
return StringRef("SLM-SlotTag");
}
static StringRef getOffsetCFIRegTagName() {
return StringRef("SLM-OffsetCFIReg");
}
};
/// Implements a pass to optimize callee-saved register spills. These spills
@ -294,6 +303,7 @@ class ShrinkWrapping {
const BinaryContext &BC;
BinaryFunction &BF;
DataflowInfoManager &Info;
MCPlusBuilder::AllocatorIdTy AllocatorId;
StackLayoutModifier SLM;
/// For each CSR, store a vector of all CFI indexes deleted as a consequence
/// of moving this Callee-Saved Reg
@ -381,7 +391,7 @@ private:
void scheduleChange(ProgramPoint PP, T&& ...Item) {
if (PP.isInst()) {
auto &WList = BC.MIB->getOrCreateAnnotationAs<std::vector<WorklistItem>>(
*PP.getInst(), getAnnotationIndex());
*PP.getInst(), getAnnotationIndex(), AllocatorId);
WList.emplace_back(std::forward<T>(Item)...);
return;
}
@ -398,7 +408,7 @@ private:
BB = *BB->succ_begin();
}
auto &WList = BC.MIB->getOrCreateAnnotationAs<std::vector<WorklistItem>>(
*BB->begin(), getAnnotationIndex());
*BB->begin(), getAnnotationIndex(), AllocatorId);
WList.emplace_back(std::forward<T>(Item)...);
}
@ -517,9 +527,10 @@ private:
public:
ShrinkWrapping(const FrameAnalysis &FA, const BinaryContext &BC,
BinaryFunction &BF, DataflowInfoManager &Info)
: FA(FA), BC(BC), BF(BF), Info(Info), SLM(FA, BC, BF, Info),
CSA(FA, BC, BF, Info) {}
BinaryFunction &BF, DataflowInfoManager &Info,
MCPlusBuilder::AllocatorIdTy AllocId)
: FA(FA), BC(BC), BF(BF), Info(Info), AllocatorId(AllocId),
SLM(FA, BC, BF, Info, AllocId), CSA(FA, BC, BF, Info, AllocId) {}
~ShrinkWrapping() {
for (auto &BB : BF) {

View File

@ -35,14 +35,13 @@ class StackAllocationAnalysis
public:
StackAllocationAnalysis(const BinaryContext &BC, BinaryFunction &BF,
StackPointerTracking &SPT)
: InstrsDataflowAnalysis<StackAllocationAnalysis, false>(BC, BF),
StackPointerTracking &SPT,
MCPlusBuilder::AllocatorIdTy AllocId)
: InstrsDataflowAnalysis<StackAllocationAnalysis, false>(BC, BF, AllocId),
SPT(SPT) {}
virtual ~StackAllocationAnalysis() {}
void run() {
NamedRegionTimer T1("SAA", "Stack Allocation Analysis", "Dataflow",
"Dataflow", opts::TimeOpts);
InstrsDataflowAnalysis<StackAllocationAnalysis, false>::run();
}

View File

@ -36,8 +36,6 @@ public:
virtual ~StackAvailableExpressions() {}
void run() {
NamedRegionTimer T1("SAE", "Stack Available Expressions", "Dataflow",
"Dataflow", opts::TimeOpts);
InstrsDataflowAnalysis<StackAvailableExpressions>::run();
}

View File

@ -18,7 +18,6 @@
namespace opts {
extern llvm::cl::opt<bool> TimeOpts;
extern llvm::cl::opt<bool> NoThreads;
} // namespace opts
namespace llvm {
@ -206,8 +205,6 @@ public:
virtual ~StackPointerTracking() {}
void run() {
NamedRegionTimer T1("SPT", "Stack Pointer Tracking", "Dataflow", "Dataflow",
opts::TimeOpts && opts::NoThreads);
StackPointerTrackingBase<StackPointerTracking>::run();
}
};

View File

@ -32,8 +32,9 @@ class StackReachingUses
public:
StackReachingUses(const FrameAnalysis &FA, const BinaryContext &BC,
BinaryFunction &BF)
: InstrsDataflowAnalysis(BC, BF), FA(FA) {}
BinaryFunction &BF,
MCPlusBuilder::AllocatorIdTy AllocId = 0)
: InstrsDataflowAnalysis(BC, BF, AllocId), FA(FA) {}
virtual ~StackReachingUses() {}
/// Return true if the stack position written by the store in \p StoreFIE was
@ -51,8 +52,6 @@ public:
bool IncludeLocalAccesses = true) const;
void run() {
NamedRegionTimer T1("SRU", "Stack Reaching Uses", "Dataflow", "Dataflow",
opts::TimeOpts);
InstrsDataflowAnalysis<StackReachingUses, true>::run();
}

View File

@ -84,8 +84,6 @@ public:
}
void run() {
NamedRegionTimer T1("SPTIC", "Stack Pointer Tracking for Internal Calls",
"Dataflow", "Dataflow", opts::TimeOpts);
StackPointerTrackingBase<StackPointerTrackingForInternalCalls>::run();
}
};