Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
88fbb97
[FnSpecialization] Only accept codesize savings if strictly greater t…
bababuck Sep 9, 2025
92297fc
[FnSpecialization] Add new test for chained specialization
bababuck Sep 30, 2025
5ea8869
[FnSpecialization] Refactor SpecCall::CallSites to contain a data str…
bababuck Sep 29, 2025
ca8182b
[FnSpecialization] Refactor main loop in run() to pull out the loop l…
bababuck Sep 29, 2025
24cc5b0
[FnSpecialization] Refactor logic for actually performing the special…
bababuck Sep 29, 2025
32ef1d7
[FnSpecialization] Pass a Spec to runOneSpec() rather than a Function
bababuck Sep 30, 2025
d6a2c96
[FnSpecialization] Use the same UniqueSpecs across entire run()
bababuck Sep 30, 2025
37b9a5d
[FnSpecialization] Don't rely on UniqueSpec to determine if specializ…
bababuck Sep 30, 2025
2bc068b
[FnSpecialization] Modify SpecMap to hold a pointer to every speciali…
bababuck Sep 29, 2025
6a8cfdc
[FnSpecialization] (1/6) Enable function specialization chaining
bababuck Sep 30, 2025
6e0c258
[FnSpecialization] (2/6) Avoid creating standalone specializations wh…
bababuck Sep 30, 2025
5070b85
[FnSpecialization] (3/6) Don't consider specializations that are only…
bababuck Sep 30, 2025
2cff314
[FnSpecialization] (4/6) Cache scoring metrics as part of Spec
bababuck Sep 30, 2025
49725f4
[FnSpecialization] (5/6) Use an explicit structure for tracking visit…
bababuck Sep 30, 2025
1b5a006
[FnSpecialization] (6/6) Update tests for prior set of changes
bababuck Sep 30, 2025
841a08e
[FnSpecialization] Allow chains to form via recrusive folding
bababuck Sep 30, 2025
fc70c01
[FnSpecialization] Allow chains to form when collapsing PHI nodes
bababuck Sep 29, 2025
fb21dc6
[FnSpecialization] Refactor CallUsersT to contain Idx/Constant pairs
bababuck Oct 1, 2025
da77758
[FnSpecialization] If the Argument number is greater than the number …
bababuck Oct 1, 2025
9773c8b
[FnSpecialization] Allow specialization of indirect function calls ex…
bababuck Oct 1, 2025
706fb4a
[FnSpecialization] Allow functions that are too small to specailize a…
bababuck Sep 30, 2025
8f94438
[FnSpecialization] Don't specialize chained functions that take varia…
bababuck Oct 8, 2025
54f89a3
Lint fix
bababuck Oct 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 87 additions & 19 deletions llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,14 @@
#include "llvm/Transforms/Utils/SizeOpts.h"

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>>;
struct Spec;

// Map of potential specializations for each function.
using SpecMap = DenseMap<Function *, SmallVector<unsigned>>;

using CallUserT = SmallMapVector<
CallBase *,
std::pair<SmallVector<std::pair<unsigned, Constant *>, 4>, Function *>, 4>;

// Just a shorter abbreviation to improve indentation.
using Cost = InstructionCost;
Expand All @@ -124,6 +127,14 @@ struct SpecSig {
}
};

enum CallSiteStatusT { AWAITING_PARENT, HAS_PARENT, NO_PARENT };

struct SpecCall {
CallBase *CallSite;
CallSiteStatusT Status;
unsigned Parent;
};

// Specialization instance.
struct Spec {
// Original function.
Expand All @@ -141,13 +152,47 @@ struct Spec {
// Number of instructions in the specialization.
unsigned CodeSize;

// Cumulative function size of the chain
unsigned FuncSize;

// Latency savings
unsigned Latency;

// Benefit from inlining
unsigned InlineScore;

// List of call sites, matching this specialization.
SmallVector<CallBase *> CallSites;
SmallVector<SpecCall> CallSites;

Spec(Function *F, const SpecSig &S, unsigned Score, unsigned CodeSize)
: F(F), Sig(S), Score(Score), CodeSize(CodeSize) {}
Spec(Function *F, const SpecSig &&S, unsigned Score, unsigned CodeSize)
: F(F), Sig(S), Score(Score), CodeSize(CodeSize) {}
bool AllChains = true;

void addCall(SpecCall SC) {
CallSites.push_back(SC);
AllChains = AllChains && SC.Status != CallSiteStatusT::NO_PARENT;
}

// List Sub-Specializations
SmallVector<unsigned> SubSpecs;

// Index within AllSpecs
unsigned Loc = 0;

bool SpecializeOnOwn = true;

Spec(Function *F, CallBase *CallSite, const SpecSig &S,
CallSiteStatusT Status)
: F(F), Clone(nullptr), Sig(S), Score(), CodeSize(), FuncSize(),
InlineScore(), CallSites() {
addCall({CallSite, Status, /*Parent*/ 0});
}
Spec(Function *F, CallBase *CallSite, CallSiteStatusT Status)
: F(F), Clone(nullptr), Sig(), Score(), CodeSize(), FuncSize(),
InlineScore(), CallSites() {
addCall({CallSite, Status, /*Parent*/ 0});
}
Spec(Function *F)
: F(F), Clone(nullptr), Sig(), Score(), CodeSize(), FuncSize(),
InlineScore(), CallSites() {}
};

class InstCostVisitor : public InstVisitor<InstCostVisitor, Constant *> {
Expand Down Expand Up @@ -180,9 +225,11 @@ class InstCostVisitor : public InstVisitor<InstCostVisitor, Constant *> {
return Solver.isBlockExecutable(BB) && !DeadBlocks.contains(BB);
}

LLVM_ABI Cost getCodeSizeSavingsForArg(Argument *A, Constant *C);
LLVM_ABI Cost getCodeSizeSavingsForArg(Argument *A, Constant *C,
CallUserT *CallUsers = nullptr);

LLVM_ABI Cost getCodeSizeSavingsFromPendingPHIs();
LLVM_ABI Cost
getCodeSizeSavingsFromPendingPHIs(CallUserT *CallUsers = nullptr);

LLVM_ABI Cost getLatencySavingsForKnownConstants();

Expand All @@ -194,7 +241,9 @@ class InstCostVisitor : public InstVisitor<InstCostVisitor, Constant *> {
bool canEliminateSuccessor(BasicBlock *BB, BasicBlock *Succ) const;

Cost getCodeSizeSavingsForUser(Instruction *User, Value *Use = nullptr,
Constant *C = nullptr);
Constant *C = nullptr,
CallUserT *CallUsers = nullptr,
llvm::Use *UseEdge = nullptr);

Cost estimateBasicBlocks(SmallVectorImpl<BasicBlock *> &WorkList);
Cost estimateSwitchInst(SwitchInst &I);
Expand Down Expand Up @@ -247,6 +296,7 @@ class FunctionSpecializer {

SmallPtrSet<Function *, 32> Specializations;
SmallPtrSet<Function *, 32> DeadFunctions;
SmallPtrSet<Function *, 32> VisitedFunctions;
DenseMap<Function *, CodeMetrics> FunctionMetrics;
DenseMap<Function *, unsigned> FunctionGrowth;
unsigned NGlobals = 0;
Expand Down Expand Up @@ -295,9 +345,26 @@ class FunctionSpecializer {
/// @param FuncSize Cost of specializing a function.
/// @param AllSpecs A vector to add potential specializations to.
/// @param SM A map for a function's specialisation range
/// @param CurrentChain Current chain of function calls.
/// @return True, if any potential specializations were found
bool findSpecializations(unsigned FuncSize, SmallVectorImpl<Spec> &AllSpecs,
SpecMap &SM, Spec &InS,
DenseMap<SpecSig, unsigned> &UniqueSpecs,
SmallPtrSet<Function *, 4> &CurrentChain);

/// @brief Find specialization opportunities for a given function.
/// @param S Specialization to complete, possibly with a Callsite attached.
/// @param Chained Is this call part of a chain build?
/// @param SM A map for a function's specialisation range
/// @param AllSpecs A vector to add potential specializations to.
/// @param UniqueSpecs Map of existing specializations.
/// @param CurrentChain Current chain of function calls.
/// site.
/// @return True, if any potential specializations were found
bool findSpecializations(Function *F, unsigned FuncSize,
SmallVectorImpl<Spec> &AllSpecs, SpecMap &SM);
bool runOneSpec(Spec &S, bool Chained, SpecMap &SM,
SmallVectorImpl<Spec> &AllSpecs,
DenseMap<SpecSig, unsigned> &UniqueSpecs,
SmallPtrSet<Function *, 4> CurrentChain);

/// Compute the inlining bonus for replacing argument \p A with constant \p C.
unsigned getInliningBonus(Argument *A, Constant *C);
Expand All @@ -308,7 +375,8 @@ class FunctionSpecializer {
/// @param F Function to specialize
/// @param S Which specialization to create
/// @return The new, cloned function
Function *createSpecialization(Function *F, const SpecSig &S);
Function *createSpecialization(Function *F, const SpecSig &S,
ValueToValueMapTy &Mappings);

/// Determine if it is possible to specialise the function for constant values
/// of the formal parameter \p A.
Expand All @@ -320,9 +388,9 @@ class FunctionSpecializer {

/// @brief Find and update calls to \p F, which match a specialization
/// @param F Orginal function
/// @param Begin Start of a range of possibly matching specialisations
/// @param End End of a range (exclusive) of possibly matching specialisations
void updateCallSites(Function *F, const Spec *Begin, const Spec *End);
/// @param Specs Vector of possibly matching specialisations
void updateCallSites(Function *F, const SmallVector<unsigned> &Specs,
SmallVector<Spec, 32> AllSpecs);
};
} // namespace llvm

Expand Down
Loading
Loading