Commit 9f9aa2c1 by Jim Stichnoth

Subzero: Count lookups of each constant value in the constant pool.

With "-verbose cpool", at the end it dumps counts of the number of times each pooled constant was looked up. The output is grouped by type and sorted by constant value, but it's easy to run it through "sort -nr" to see it ordered by popularity. BUG= none R=jpp@chromium.org Review URL: https://codereview.chromium.org/1768173002 .
parent 7e6aa5a1
...@@ -41,7 +41,7 @@ public: ...@@ -41,7 +41,7 @@ public:
uint32_t getSequenceNumber() const { return SequenceNumber; } uint32_t getSequenceNumber() const { return SequenceNumber; }
static constexpr VerboseMask defaultVerboseMask() { static constexpr VerboseMask defaultVerboseMask() {
return IceV_All & ~IceV_Status & ~IceV_AvailableRegs; return (IceV_NO_PER_PASS_DUMP_BEYOND << 1) - 1;
} }
/// Returns true if any of the specified options in the verbose mask are set. /// Returns true if any of the specified options in the verbose mask are set.
/// If the argument is omitted, it checks if any verbose options at all are /// If the argument is omitted, it checks if any verbose options at all are
......
...@@ -331,12 +331,13 @@ cl::list<Ice::VerboseItem> VerboseList( ...@@ -331,12 +331,13 @@ cl::list<Ice::VerboseItem> VerboseList(
clEnumValN(Ice::IceV_Folding, "fold", "Instruction folding details"), clEnumValN(Ice::IceV_Folding, "fold", "Instruction folding details"),
clEnumValN(Ice::IceV_RMW, "rmw", "ReadModifyWrite optimization"), clEnumValN(Ice::IceV_RMW, "rmw", "ReadModifyWrite optimization"),
clEnumValN(Ice::IceV_Loop, "loop", "Loop nest depth analysis"), clEnumValN(Ice::IceV_Loop, "loop", "Loop nest depth analysis"),
clEnumValN(Ice::IceV_Mem, "mem", "Memory usage details"),
clEnumValN(Ice::IceV_Status, "status", clEnumValN(Ice::IceV_Status, "status",
"Print the name of the function being translated"), "Print the name of the function being translated"),
clEnumValN(Ice::IceV_AvailableRegs, "registers", clEnumValN(Ice::IceV_AvailableRegs, "registers",
"Show available registers for register allocation"), "Show available registers for register allocation"),
clEnumValN(Ice::IceV_Mem, "mem", "Memory usage details"),
clEnumValN(Ice::IceV_GlobalInit, "global_init", "Global initializers"), clEnumValN(Ice::IceV_GlobalInit, "global_init", "Global initializers"),
clEnumValN(Ice::IceV_ConstPoolStats, "cpool", "Constant pool counters"),
clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), clEnumValN(Ice::IceV_All, "all", "Use all verbose options"),
clEnumValN(Ice::IceV_Most, "most", clEnumValN(Ice::IceV_Most, "most",
"Use all verbose options except 'regalloc,global_init'"), "Use all verbose options except 'regalloc,global_init'"),
......
...@@ -240,6 +240,7 @@ void CLCompileServer::run() { ...@@ -240,6 +240,7 @@ void CLCompileServer::run() {
} }
transferErrorCode(getReturnValue( transferErrorCode(getReturnValue(
ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value()))); ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
Ctx->dumpConstantLookupCounts();
} }
} // end of namespace Ice } // end of namespace Ice
...@@ -211,12 +211,18 @@ enum VerboseItem { ...@@ -211,12 +211,18 @@ enum VerboseItem {
IceV_Folding = 1 << 11, IceV_Folding = 1 << 11,
IceV_RMW = 1 << 12, IceV_RMW = 1 << 12,
IceV_Loop = 1 << 13, IceV_Loop = 1 << 13,
IceV_Status = 1 << 14, IceV_Mem = 1 << 14,
IceV_AvailableRegs = 1 << 15, // Leave some extra space to make it easier to add new per-pass items.
IceV_Mem = 1 << 16, IceV_NO_PER_PASS_DUMP_BEYOND = 1 << 19,
IceV_GlobalInit = 1 << 17, // Items greater than IceV_NO_PER_PASS_DUMP_BEYOND don't by themselves trigger
// per-pass Cfg dump output.
IceV_Status = 1 << 20,
IceV_AvailableRegs = 1 << 21,
IceV_GlobalInit = 1 << 22,
IceV_ConstPoolStats = 1 << 23,
IceV_All = ~IceV_None, IceV_All = ~IceV_None,
IceV_Most = IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit IceV_Most =
IceV_All & ~IceV_LinearScan & ~IceV_GlobalInit & IceV_ConstPoolStats
}; };
using VerboseMask = uint32_t; using VerboseMask = uint32_t;
......
...@@ -143,10 +143,13 @@ public: ...@@ -143,10 +143,13 @@ public:
TypePool() = default; TypePool() = default;
ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) { ValueType *getOrAdd(GlobalContext *Ctx, KeyType Key) {
auto Iter = Pool.find(Key); auto Iter = Pool.find(Key);
if (Iter != Pool.end()) if (Iter != Pool.end()) {
Iter->second->updateLookupCount();
return Iter->second; return Iter->second;
}
auto *Result = ValueType::create(Ctx, Ty, Key); auto *Result = ValueType::create(Ctx, Ty, Key);
Pool[Key] = Result; Pool[Key] = Result;
Result->updateLookupCount();
return Result; return Result;
} }
ConstantList getConstantPool() const { ConstantList getConstantPool() const {
...@@ -410,9 +413,8 @@ void GlobalContext::addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo) { ...@@ -410,9 +413,8 @@ void GlobalContext::addBlockInfoPtrs(VariableDeclaration *ProfileBlockInfo) {
void GlobalContext::lowerGlobals(const IceString &SectionSuffix) { void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
TimerMarker T(TimerStack::TT_emitGlobalInitializers, this); TimerMarker T(TimerStack::TT_emitGlobalInitializers, this);
const bool DumpGlobalVariables = const bool DumpGlobalVariables = BuildDefs::dump() &&
BuildDefs::dump() && (Flags.getVerbose() & IceV_GlobalInit) &&
(Flags.getVerbose() & IceV_GlobalInit & Cfg::defaultVerboseMask()) &&
Flags.getVerboseFocusOn().empty(); Flags.getVerboseFocusOn().empty();
if (DumpGlobalVariables) { if (DumpGlobalVariables) {
OstreamLocker L(this); OstreamLocker L(this);
...@@ -758,6 +760,35 @@ GlobalContext::~GlobalContext() { ...@@ -758,6 +760,35 @@ GlobalContext::~GlobalContext() {
Dtor(); Dtor();
} }
void GlobalContext::dumpConstantLookupCounts() {
if (!BuildDefs::dump())
return;
const bool DumpCounts = (Flags.getVerbose() & IceV_ConstPoolStats) &&
Flags.getVerboseFocusOn().empty();
if (!DumpCounts)
return;
OstreamLocker _(this);
Ostream &Str = getStrDump();
Str << "Constant pool use stats: count+value+type\n";
#define X(WhichPool) \
for (auto *C : getConstPool()->WhichPool.getConstantPool()) { \
Str << C->getLookupCount() << " "; \
C->dump(Str); \
Str << " " << C->getType() << "\n"; \
}
X(Integers1);
X(Integers8);
X(Integers16);
X(Integers32);
X(Integers64);
X(Floats);
X(Doubles);
X(Relocatables);
X(ExternRelocatables);
#undef X
}
// TODO(stichnot): Consider adding thread-local caches of constant pool entries // TODO(stichnot): Consider adding thread-local caches of constant pool entries
// to reduce contention. // to reduce contention.
......
...@@ -428,6 +428,8 @@ public: ...@@ -428,6 +428,8 @@ public:
/// Lowers the profile information. /// Lowers the profile information.
void lowerProfileData(); void lowerProfileData();
void dumpConstantLookupCounts();
/// Utility function to match a symbol name against a match string. This is /// Utility function to match a symbol name against a match string. This is
/// used in a few cases where we want to take some action on a particular /// used in a few cases where we want to take some action on a particular
/// function or symbol based on a command-line argument, such as changing the /// function or symbol based on a command-line argument, such as changing the
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
#include <limits> #include <limits>
#include <type_traits>
namespace Ice { namespace Ice {
...@@ -125,6 +126,9 @@ public: ...@@ -125,6 +126,9 @@ public:
(void)Ctx; (void)Ctx;
llvm::report_fatal_error("emitPoolLabel not defined for type"); llvm::report_fatal_error("emitPoolLabel not defined for type");
}; };
// Declare the lookup counter to take minimal space in a non-DUMP build.
using CounterType =
std::conditional<BuildDefs::dump(), uint64_t, uint8_t>::type;
void emit(const Cfg *Func) const override { emit(Func->getTarget()); } void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
virtual void emit(TargetLowering *Target) const = 0; virtual void emit(TargetLowering *Target) const = 0;
...@@ -141,19 +145,29 @@ public: ...@@ -141,19 +145,29 @@ public:
return false; return false;
} }
void setShouldBePooled(bool R) { shouldBePooled = R; } void setShouldBePooled(bool R) { ShouldBePooled = R; }
bool getShouldBePooled() const { return ShouldBePooled; }
bool getShouldBePooled() const { return shouldBePooled; } // This should be thread-safe because the constant pool lock is acquired
// before the method is invoked.
void updateLookupCount() {
if (!BuildDefs::dump())
return;
++LookupCount;
}
CounterType getLookupCount() const { return LookupCount; }
protected: protected:
Constant(OperandKind Kind, Type Ty) Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) {
: Operand(Kind, Ty), shouldBePooled(false) {
Vars = nullptr; Vars = nullptr;
NumVars = 0; NumVars = 0;
} }
/// Whether we should pool this constant. Usually Float/Double and pooled /// Whether we should pool this constant. Usually Float/Double and pooled
/// Integers should be flagged true. /// Integers should be flagged true.
bool shouldBePooled; bool ShouldBePooled = false;
/// Note: If ShouldBePooled is ever removed from the base class, we will want
/// to completely disable LookupCount in a non-DUMP build to save space.
CounterType LookupCount = 0;
}; };
/// ConstantPrimitive<> wraps a primitive type. /// ConstantPrimitive<> wraps a primitive type.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment