using namespace llvm;
namespace llvm {
+// Map of potential specializations for each function. The FunctionSpecializer
+// keeps the discovered specialisation opportunities for the module in a single
+// vector, where the specialisations of each function form a contiguous range.
+// This map's value is the beginning and the end of that range.
+using SpecMap = DenseMap<Function *, std::pair<unsigned, unsigned>>;
+
+// Just a shorter abbreviation to improve indentation.
+using Cost = InstructionCost;
+
// Specialization signature, used to uniquely designate a specialization within
// a function.
struct SpecSig {
SpecSig Sig;
// Profitability of the specialization.
- InstructionCost Gain;
+ Cost Score;
// List of call sites, matching this specialization.
SmallVector<CallBase *> CallSites;
- Spec(Function *F, const SpecSig &S, InstructionCost G)
- : F(F), Sig(S), Gain(G) {}
- Spec(Function *F, const SpecSig &&S, InstructionCost G)
- : F(F), Sig(S), Gain(G) {}
+ Spec(Function *F, const SpecSig &S, Cost Score)
+ : F(F), Sig(S), Score(Score) {}
+ Spec(Function *F, const SpecSig &&S, Cost Score)
+ : F(F), Sig(S), Score(Score) {}
};
-// Map of potential specializations for each function. The FunctionSpecializer
-// keeps the discovered specialisation opportunities for the module in a single
-// vector, where the specialisations of each function form a contiguous range.
-// This map's value is the beginning and the end of that range.
-using SpecMap = DenseMap<Function *, std::pair<unsigned, unsigned>>;
-
class FunctionSpecializer {
/// The IPSCCP Solver.
/// @brief Find potential specialization opportunities.
/// @param F Function to specialize
- /// @param Cost Cost of specializing a function. Final gain is this cost
- /// minus benefit
+ /// @param SpecCost Cost of specializing a function. Final score is benefit
+ /// minus this cost.
/// @param AllSpecs A vector to add potential specializations to.
/// @param SM A map for a function's specialisation range
/// @return True, if any potential specializations were found
- bool findSpecializations(Function *F, InstructionCost Cost,
+ bool findSpecializations(Function *F, Cost SpecCost,
SmallVectorImpl<Spec> &AllSpecs, SpecMap &SM);
bool isCandidateFunction(Function *F);
Function *createSpecialization(Function *F, const SpecSig &S);
/// Compute and return the cost of specializing function \p F.
- InstructionCost getSpecializationCost(Function *F);
+ Cost getSpecializationCost(Function *F);
/// Compute a bonus for replacing argument \p A with constant \p C.
- InstructionCost getSpecializationBonus(Argument *A, Constant *C,
- const LoopInfo &LI);
+ Cost getSpecializationBonus(Argument *A, Constant *C, const LoopInfo &LI);
/// Determine if it is possible to specialise the function for constant values
/// of the formal parameter \p A.
if (!isCandidateFunction(&F))
continue;
- auto Cost = getSpecializationCost(&F);
- if (!Cost.isValid()) {
+ Cost SpecCost = getSpecializationCost(&F);
+ if (!SpecCost.isValid()) {
LLVM_DEBUG(dbgs() << "FnSpecialization: Invalid specialization cost for "
<< F.getName() << "\n");
continue;
}
LLVM_DEBUG(dbgs() << "FnSpecialization: Specialization cost for "
- << F.getName() << " is " << Cost << "\n");
+ << F.getName() << " is " << SpecCost << "\n");
- if (!findSpecializations(&F, Cost, AllSpecs, SM)) {
+ if (!findSpecializations(&F, SpecCost, AllSpecs, SM)) {
LLVM_DEBUG(
dbgs() << "FnSpecialization: No possible specializations found for "
<< F.getName() << "\n");
// Choose the most profitable specialisations, which fit in the module
// specialization budget, which is derived from maximum number of
// specializations per specialization candidate function.
- auto CompareGain = [&AllSpecs](unsigned I, unsigned J) {
- return AllSpecs[I].Gain > AllSpecs[J].Gain;
+ auto CompareScore = [&AllSpecs](unsigned I, unsigned J) {
+ return AllSpecs[I].Score > AllSpecs[J].Score;
};
const unsigned NSpecs =
std::min(NumCandidates * MaxClones, unsigned(AllSpecs.size()));
<< "FnSpecialization: Specializing the "
<< NSpecs
<< " most profitable candidates.\n");
- std::make_heap(BestSpecs.begin(), BestSpecs.begin() + NSpecs, CompareGain);
+ std::make_heap(BestSpecs.begin(), BestSpecs.begin() + NSpecs, CompareScore);
for (unsigned I = NSpecs, N = AllSpecs.size(); I < N; ++I) {
BestSpecs[NSpecs] = I;
- std::push_heap(BestSpecs.begin(), BestSpecs.end(), CompareGain);
- std::pop_heap(BestSpecs.begin(), BestSpecs.end(), CompareGain);
+ std::push_heap(BestSpecs.begin(), BestSpecs.end(), CompareScore);
+ std::pop_heap(BestSpecs.begin(), BestSpecs.end(), CompareScore);
}
}
for (unsigned I = 0; I < NSpecs; ++I) {
const Spec &S = AllSpecs[BestSpecs[I]];
dbgs() << "FnSpecialization: Function " << S.F->getName()
- << " , gain " << S.Gain << "\n";
+ << " , score " << S.Score << "\n";
for (const ArgInfo &Arg : S.Sig.Args)
dbgs() << "FnSpecialization: FormalArg = "
<< Arg.Formal->getNameOrAsOperand()
return Clone;
}
-bool FunctionSpecializer::findSpecializations(Function *F, InstructionCost Cost,
+bool FunctionSpecializer::findSpecializations(Function *F, Cost SpecCost,
SmallVectorImpl<Spec> &AllSpecs,
SpecMap &SM) {
// A mapping from a specialisation signature to the index of the respective
AllSpecs[Index].CallSites.push_back(&CS);
} else {
// Calculate the specialisation gain.
- InstructionCost Gain = 0 - Cost;
+ Cost Score = 0 - SpecCost;
for (ArgInfo &A : S.Args)
- Gain +=
+ Score +=
getSpecializationBonus(A.Formal, A.Actual, Solver.getLoopInfo(*F));
// Discard unprofitable specialisations.
- if (!ForceSpecialization && Gain <= 0)
+ if (!ForceSpecialization && Score <= 0)
continue;
// Create a new specialisation entry.
- auto &Spec = AllSpecs.emplace_back(F, S, Gain);
+ auto &Spec = AllSpecs.emplace_back(F, S, Score);
if (CS.getFunction() != F)
Spec.CallSites.push_back(&CS);
const unsigned Index = AllSpecs.size() - 1;
return true;
}
-Function *FunctionSpecializer::createSpecialization(Function *F, const SpecSig &S) {
+Function *FunctionSpecializer::createSpecialization(Function *F,
+ const SpecSig &S) {
Function *Clone = cloneCandidateFunction(F);
// The original function does not neccessarily have internal linkage, but the
}
/// Compute and return the cost of specializing function \p F.
-InstructionCost FunctionSpecializer::getSpecializationCost(Function *F) {
+Cost FunctionSpecializer::getSpecializationCost(Function *F) {
CodeMetrics &Metrics = analyzeFunction(F);
// If the code metrics reveal that we shouldn't duplicate the function, we
// shouldn't specialize it. Set the specialization cost to Invalid.
return Metrics.NumInsts * InlineConstants::getInstrCost();
}
-static InstructionCost getUserBonus(User *U, llvm::TargetTransformInfo &TTI,
- const LoopInfo &LI) {
+static Cost getUserBonus(User *U, TargetTransformInfo &TTI,
+ const LoopInfo &LI) {
auto *I = dyn_cast_or_null<Instruction>(U);
// If not an instruction we do not know how to evaluate.
// Keep minimum possible cost for now so that it doesnt affect
if (!I)
return std::numeric_limits<unsigned>::min();
- InstructionCost Cost =
+ Cost Bonus =
TTI.getInstructionCost(U, TargetTransformInfo::TCK_SizeAndLatency);
// Increase the cost if it is inside the loop.
unsigned LoopDepth = LI.getLoopDepth(I->getParent());
- Cost *= std::pow((double)AvgLoopIters, LoopDepth);
+ Bonus *= std::pow((double)AvgLoopIters, LoopDepth);
// Traverse recursively if there are more uses.
// TODO: Any other instructions to be added here?
if (I->mayReadFromMemory() || I->isCast())
for (auto *User : I->users())
- Cost += getUserBonus(User, TTI, LI);
+ Bonus += getUserBonus(User, TTI, LI);
- return Cost;
+ return Bonus;
}
/// Compute a bonus for replacing argument \p A with constant \p C.
-InstructionCost
-FunctionSpecializer::getSpecializationBonus(Argument *A, Constant *C,
- const LoopInfo &LI) {
+Cost FunctionSpecializer::getSpecializationBonus(Argument *A, Constant *C,
+ const LoopInfo &LI) {
Function *F = A->getParent();
auto &TTI = (GetTTI)(*F);
LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing bonus for constant: "
<< C->getNameOrAsOperand() << "\n");
- InstructionCost TotalCost = 0;
+ Cost TotalCost = 0;
for (auto *U : A->users()) {
TotalCost += getUserBonus(U, TTI, LI);
LLVM_DEBUG(dbgs() << "FnSpecialization: User cost ";
// Find the best matching specialisation.
const Spec *BestSpec = nullptr;
for (const Spec &S : make_range(Begin, End)) {
- if (!S.Clone || (BestSpec && S.Gain <= BestSpec->Gain))
+ if (!S.Clone || (BestSpec && S.Score <= BestSpec->Score))
continue;
if (any_of(S.Sig.Args, [CS, this](const ArgInfo &Arg) {