#pragma once
#if ENABLE(B3_JIT)
#include "AirArgInlines.h"
#include "AirBlockWorklist.h"
#include "AirCode.h"
#include "AirInstInlines.h"
#include <wtf/HashMap.h>
#include <wtf/ListDump.h>
namespace JSC { namespace B3 { namespace Air {
class Code;
template<typename Thing>
class UseCounts {
public:
struct Counts {
void dump(PrintStream& out) const
{
out.print(
"{numWarmUses = ", numWarmUses, ", numColdUses = ", numColdUses, ", numDefs = ",
numDefs, "}");
}
double numWarmUses { 0 };
double numColdUses { 0 };
double numDefs { 0 };
double numConstDefs { 0 };
};
UseCounts(Code& code)
{
BlockWorklist fastWorklist;
fastWorklist.push(code[0]);
while (BasicBlock* block = fastWorklist.pop()) {
for (FrequentedBlock& successor : block->successors()) {
if (!successor.isRare())
fastWorklist.push(successor.block());
}
}
for (BasicBlock* block : code) {
double frequency = block->frequency();
if (!fastWorklist.saw(block))
frequency *= Options::rareBlockPenalty();
for (Inst& inst : *block) {
inst.forEach<Thing>(
[&] (Thing& arg, Arg::Role role, Bank, Width) {
Counts& counts = m_counts.add(arg, Counts()).iterator->value;
if (Arg::isWarmUse(role))
counts.numWarmUses += frequency;
if (Arg::isColdUse(role))
counts.numColdUses += frequency;
if (Arg::isAnyDef(role))
counts.numDefs += frequency;
});
if ((inst.kind.opcode == Move || inst.kind.opcode == Move32)
&& inst.args[0].isSomeImm()
&& inst.args[1].is<Thing>())
m_counts.add(inst.args[1].as<Thing>(), Counts()).iterator->value.numConstDefs++;
}
}
}
const Counts* operator[](const Thing& arg) const
{
auto iter = m_counts.find(arg);
if (iter == m_counts.end())
return nullptr;
return &iter->value;
}
void dump(PrintStream& out) const
{
out.print(mapDump(m_counts));
}
private:
HashMap<Thing, Counts> m_counts;
};
} } }
#endif // ENABLE(B3_JIT)