Commit 54313fbf by Nicolas Capens Committed by Nicolas Capens

Report back the Subzero optimizer results

This change adds a callback mechanism to report how many instructions of certain types are left after the optimization passes have been run. This enables unit tests to check that the desired optimization actually took place, instead of just checking correct execution results. Bug: b/180665600 Change-Id: I3916d327138516a0a0778be2b3fdd5b000fc9bdb Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52989 Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com>
parent bc1a66c7
......@@ -1781,6 +1781,12 @@ Value *Nucleus::createConstantString(const char *v)
return V(ptr);
}
void Nucleus::setOptimizerCallback(OptimizerCallback *callback)
{
// The LLVM backend does not produce optimizer reports.
(void)callback;
}
Type *Void::type()
{
return T(llvm::Type::getVoidTy(*jit->context));
......
......@@ -333,6 +333,20 @@ public:
static Type *getContainedType(Type *vectorType);
static Type *getPointerType(Type *elementType);
static Type *getPrintfStorageType(Type *valueType);
// Diagnostic utilities
struct OptimizerReport
{
int allocas = 0;
int loads = 0;
int stores = 0;
};
using OptimizerCallback = void(const OptimizerReport *report);
// Sets the callback to be used by the next optimizer invocation (during acquireRoutine),
// for reporting stats about the resulting IR code. For testing only.
static void setOptimizerCallback(OptimizerCallback *callback);
};
} // namespace rr
......
......@@ -24,6 +24,11 @@ namespace {
class Optimizer
{
public:
Optimizer(rr::Nucleus::OptimizerReport *report)
: report(report)
{
}
void run(Ice::Cfg *function);
private:
......@@ -46,6 +51,8 @@ private:
static std::size_t storeSize(const Ice::Inst *instruction);
static bool loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *store);
void collectDiagnostics();
Ice::Cfg *function;
Ice::GlobalContext *context;
......@@ -88,6 +95,8 @@ private:
bool hasLoadStoreInsts(Ice::CfgNode *node) const;
std::vector<Ice::Operand *> operandsWithUses;
rr::Nucleus::OptimizerReport *report = nullptr;
};
void Optimizer::run(Ice::Cfg *function)
......@@ -115,6 +124,8 @@ void Optimizer::run(Ice::Cfg *function)
setUses(operand, nullptr);
}
operandsWithUses.clear();
collectDiagnostics();
}
// Eliminates allocas which store the address of other allocas.
......@@ -719,6 +730,38 @@ bool Optimizer::loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *sto
return true;
}
void Optimizer::collectDiagnostics()
{
if(report)
{
*report = {};
for(auto *basicBlock : function->getNodes())
{
for(auto &inst : basicBlock->getInsts())
{
if(inst.isDeleted())
{
continue;
}
if(llvm::isa<Ice::InstAlloca>(inst))
{
report->allocas++;
}
else if(isLoad(inst))
{
report->loads++;
}
else if(isStore(inst))
{
report->stores++;
}
}
}
}
}
Optimizer::Uses *Optimizer::getUses(Ice::Operand *operand)
{
Optimizer::Uses *uses = (Optimizer::Uses *)operand->Ice::Operand::getExternalData();
......@@ -846,9 +889,9 @@ void Optimizer::Uses::erase(Ice::Inst *instruction)
namespace rr {
void optimize(Ice::Cfg *function)
void optimize(Ice::Cfg *function, Nucleus::OptimizerReport *report)
{
Optimizer optimizer;
Optimizer optimizer(report);
optimizer.run(function);
}
......
......@@ -15,11 +15,13 @@
#ifndef rr_Optimizer_hpp
#define rr_Optimizer_hpp
#include "Nucleus.hpp"
#include "src/IceCfg.h"
namespace rr {
void optimize(Ice::Cfg *function);
void optimize(Ice::Cfg *function, Nucleus::OptimizerReport *report = nullptr);
} // namespace rr
......
......@@ -241,6 +241,9 @@ marl::Scheduler &getOrCreateScheduler()
return *scheduler;
}
rr::Nucleus::OptimizerCallback *optimizerCallback = nullptr;
} // Anonymous namespace
namespace {
......@@ -1008,7 +1011,17 @@ static std::shared_ptr<Routine> acquireRoutine(Ice::Cfg *const (&functions)[Coun
currFunc->setFunctionName(Ice::GlobalString::createWithString(::context, names[i]));
rr::optimize(currFunc);
if(::optimizerCallback)
{
Nucleus::OptimizerReport report;
rr::optimize(currFunc, &report);
::optimizerCallback(&report);
::optimizerCallback = nullptr;
}
else
{
rr::optimize(currFunc);
}
currFunc->computeInOutEdges();
ASSERT_MSG(!currFunc->hasError(), "%s", currFunc->getError().c_str());
......@@ -2186,6 +2199,11 @@ Value *Nucleus::createConstantString(const char *v)
return V(IceConstantData(v, strlen(v) + 1));
}
void Nucleus::setOptimizerCallback(OptimizerCallback *callback)
{
::optimizerCallback = callback;
}
Type *Void::type()
{
return T(Ice::IceType_void);
......
......@@ -395,7 +395,6 @@ TEST(ReactorUnitTests, ConstantPointer)
// This test excercises the Optimizer::eliminateLoadsFollowingSingleStore() optimization pass.
// The three load operations for `y` should get eliminated.
// TODO(b/180665600): Check that the optimization took place.
TEST(ReactorUnitTests, EliminateLoadsFollowingSingleStore)
{
FunctionT<int(int)> function;
......@@ -415,6 +414,12 @@ TEST(ReactorUnitTests, EliminateLoadsFollowingSingleStore)
Return(z);
}
Nucleus::setOptimizerCallback([](const Nucleus::OptimizerReport *report) {
EXPECT_EQ(report->allocas, 2);
EXPECT_EQ(report->loads, 2);
EXPECT_EQ(report->stores, 2);
});
auto routine = function(testName().c_str());
int result = routine(11);
......@@ -423,7 +428,6 @@ TEST(ReactorUnitTests, EliminateLoadsFollowingSingleStore)
// This test excercises the Optimizer::propagateAlloca() optimization pass.
// The pointer variable should not get stored to / loaded from memory.
// TODO(b/180665600): Check that the optimization took place.
TEST(ReactorUnitTests, PropagateAlloca)
{
FunctionT<int(int)> function;
......@@ -443,6 +447,12 @@ TEST(ReactorUnitTests, PropagateAlloca)
Return(Int(*p)); // TODO(b/179694472): Support Return(*p)
}
Nucleus::setOptimizerCallback([](const Nucleus::OptimizerReport *report) {
EXPECT_EQ(report->allocas, 1);
EXPECT_EQ(report->loads, 1);
EXPECT_EQ(report->stores, 1);
});
auto routine = function(testName().c_str());
int result = routine(true);
......
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