Reactor: Add support for specifying and modifying default configuration settings.
rr::Config holds the full reactor configuration state.
rr::Config::Edit holds edits on a config, which can be applied on top of the current defaults.
Default configurations are updated atomically, preventing modifications to the default state from tearing.
Bug: b/137167988
Change-Id: Ib05f2cfc31ab22fb9a891a267fffe33c18691028
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/33768
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index bcc2f7e..178c075 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -55,6 +55,18 @@
namespace
{
+ // Default configuration settings. Must be accessed under mutex lock.
+ std::mutex defaultConfigLock;
+ rr::Config &defaultConfig()
+ {
+ // This uses a static in a function to avoid the cost of a global static
+ // initializer. See http://neugierig.org/software/chromium/notes/2011/08/static-initializers.html
+ static rr::Config config = rr::Config::Edit()
+ .set(rr::Optimization::Level::Default)
+ .apply({});
+ return config;
+ }
+
Ice::GlobalContext *context = nullptr;
Ice::Cfg *function = nullptr;
Ice::CfgNode *basicBlock = nullptr;
@@ -77,6 +89,19 @@
#define __x86_64__ 1
#endif
+ static Ice::OptLevel toIce(rr::Optimization::Level level)
+ {
+ switch (level)
+ {
+ case rr::Optimization::Level::None: return Ice::Opt_0;
+ case rr::Optimization::Level::Less: return Ice::Opt_1;
+ case rr::Optimization::Level::Default: return Ice::Opt_2;
+ case rr::Optimization::Level::Aggressive: return Ice::Opt_2;
+ default: UNREACHABLE("Unknown Optimization Level %d", int(level));
+ }
+ return Ice::Opt_2;
+ }
+
class CPUID
{
public:
@@ -204,8 +229,6 @@
return Ice::typeWidthInBytes(T(type));
}
- Optimization optimization[10] = {InstructionCombining, Disabled};
-
using ElfHeader = std::conditional<sizeof(void*) == 8, Elf64_Ehdr, Elf32_Ehdr>::type;
using SectionHeader = std::conditional<sizeof(void*) == 8, Elf64_Shdr, Elf32_Shdr>::type;
@@ -548,7 +571,7 @@
Flags.setTargetInstructionSet(CPUID::SSE4_1 ? Ice::X86InstructionSet_SSE4_1 : Ice::X86InstructionSet_SSE2);
#endif
Flags.setOutFileType(Ice::FT_Elf);
- Flags.setOptLevel(Ice::Opt_2);
+ Flags.setOptLevel(toIce(getDefaultConfig().getOptimization().getLevel()));
Flags.setApplicationBinaryInterface(Ice::ABI_Platform);
Flags.setVerbose(false ? Ice::IceV_Most : Ice::IceV_None);
Flags.setDisableHybridAssembly(true);
@@ -585,7 +608,26 @@
::codegenMutex.unlock();
}
- Routine *Nucleus::acquireRoutine(const char *name, OptimizationLevel optimizationLevel)
+ void Nucleus::setDefaultConfig(const Config &cfg)
+ {
+ std::unique_lock<std::mutex> lock(::defaultConfigLock);
+ ::defaultConfig() = cfg;
+ }
+
+ void Nucleus::adjustDefaultConfig(const Config::Edit &cfgEdit)
+ {
+ std::unique_lock<std::mutex> lock(::defaultConfigLock);
+ auto &config = ::defaultConfig();
+ config = cfgEdit.apply(config);
+ }
+
+ Config Nucleus::getDefaultConfig()
+ {
+ std::unique_lock<std::mutex> lock(::defaultConfigLock);
+ return ::defaultConfig();
+ }
+
+ Routine *Nucleus::acquireRoutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */)
{
if(basicBlock->getInsts().empty() || basicBlock->getInsts().back().getKind() != Ice::Inst::Ret)
{
@@ -594,7 +636,7 @@
::function->setFunctionName(Ice::GlobalString::createWithString(::context, name));
- optimize();
+ rr::optimize(::function);
::function->translate();
ASSERT(!::function->hasError());
@@ -624,11 +666,6 @@
return handoffRoutine;
}
- void Nucleus::optimize()
- {
- rr::optimize(::function);
- }
-
Value *Nucleus::allocateStackVariable(Type *t, int arraySize)
{
Ice::Type type = T(t);
@@ -3506,7 +3543,7 @@
void FlushDebug() {}
void Nucleus::createCoroutine(Type *YieldType, std::vector<Type*> &Params) { UNIMPLEMENTED("createCoroutine"); }
- Routine* Nucleus::acquireCoroutine(const char *name, OptimizationLevel optimizationLevel) { UNIMPLEMENTED("acquireCoroutine"); return nullptr; }
+ Routine* Nucleus::acquireCoroutine(const char *name, const Config::Edit &cfgEdit /* = Config::Edit::None */) { UNIMPLEMENTED("acquireCoroutine"); return nullptr; }
void Nucleus::yield(Value* val) { UNIMPLEMENTED("Yield"); }
}