Track partial writes as well.

We will need this for LUT promotion.
This commit is contained in:
Hans-Kristian Arntzen 2018-07-04 16:46:25 +02:00
parent 7216129377
commit 6fdadb9218
2 changed files with 32 additions and 13 deletions

View File

@ -3750,12 +3750,16 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
uint32_t ptr = args[0]; uint32_t ptr = args[0];
auto *var = compiler.maybe_get_backing_variable(ptr); auto *var = compiler.maybe_get_backing_variable(ptr);
if (var && var->storage == StorageClassFunction)
accessed_variables_to_block[var->self].insert(current_block->self);
// If we store through an access chain, we have a partial write. // If we store through an access chain, we have a partial write.
if (var && var->self == ptr && var->storage == StorageClassFunction) if (var)
complete_write_variables_to_block[var->self].insert(current_block->self); {
accessed_variables_to_block[var->self].insert(current_block->self);
if (var->self == ptr)
complete_write_variables_to_block[var->self].insert(current_block->self);
else
partial_write_variables_to_block[var->self].insert(current_block->self);
}
// Might try to store a Phi variable here. // Might try to store a Phi variable here.
notify_variable_access(args[1], current_block->self); notify_variable_access(args[1], current_block->self);
@ -3770,7 +3774,7 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
uint32_t ptr = args[2]; uint32_t ptr = args[2];
auto *var = compiler.maybe_get<SPIRVariable>(ptr); auto *var = compiler.maybe_get<SPIRVariable>(ptr);
if (var && var->storage == StorageClassFunction) if (var)
accessed_variables_to_block[var->self].insert(current_block->self); accessed_variables_to_block[var->self].insert(current_block->self);
for (uint32_t i = 3; i < length; i++) for (uint32_t i = 3; i < length; i++)
@ -3794,15 +3798,19 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
uint32_t lhs = args[0]; uint32_t lhs = args[0];
uint32_t rhs = args[1]; uint32_t rhs = args[1];
auto *var = compiler.maybe_get_backing_variable(lhs); auto *var = compiler.maybe_get_backing_variable(lhs);
if (var && var->storage == StorageClassFunction)
accessed_variables_to_block[var->self].insert(current_block->self);
// If we store through an access chain, we have a partial write. // If we store through an access chain, we have a partial write.
if (var && var->self == lhs) if (var)
complete_write_variables_to_block[var->self].insert(current_block->self); {
accessed_variables_to_block[var->self].insert(current_block->self);
if (var->self == lhs)
complete_write_variables_to_block[var->self].insert(current_block->self);
else
partial_write_variables_to_block[var->self].insert(current_block->self);
}
var = compiler.maybe_get_backing_variable(rhs); var = compiler.maybe_get_backing_variable(rhs);
if (var && var->storage == StorageClassFunction) if (var)
accessed_variables_to_block[var->self].insert(current_block->self); accessed_variables_to_block[var->self].insert(current_block->self);
break; break;
} }
@ -3813,7 +3821,7 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
return false; return false;
auto *var = compiler.maybe_get_backing_variable(args[2]); auto *var = compiler.maybe_get_backing_variable(args[2]);
if (var && var->storage == StorageClassFunction) if (var)
accessed_variables_to_block[var->self].insert(current_block->self); accessed_variables_to_block[var->self].insert(current_block->self);
// Might try to copy a Phi variable here. // Might try to copy a Phi variable here.
@ -3827,7 +3835,7 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
return false; return false;
uint32_t ptr = args[2]; uint32_t ptr = args[2];
auto *var = compiler.maybe_get_backing_variable(ptr); auto *var = compiler.maybe_get_backing_variable(ptr);
if (var && var->storage == StorageClassFunction) if (var)
accessed_variables_to_block[var->self].insert(current_block->self); accessed_variables_to_block[var->self].insert(current_block->self);
// Loaded value is a temporary. // Loaded value is a temporary.
@ -3840,13 +3848,19 @@ bool Compiler::AnalyzeVariableScopeAccessHandler::handle(spv::Op op, const uint3
if (length < 3) if (length < 3)
return false; return false;
bool is_pure = compiler.function_is_pure(compiler.get<SPIRFunction>(args[2]));
length -= 3; length -= 3;
args += 3; args += 3;
for (uint32_t i = 0; i < length; i++) for (uint32_t i = 0; i < length; i++)
{ {
auto *var = compiler.maybe_get_backing_variable(args[i]); auto *var = compiler.maybe_get_backing_variable(args[i]);
if (var && var->storage == StorageClassFunction) if (var)
{
accessed_variables_to_block[var->self].insert(current_block->self); accessed_variables_to_block[var->self].insert(current_block->self);
if (!is_pure) // Assume we can get partial writes to this variable.
partial_write_variables_to_block[var->self].insert(current_block->self);
}
// Cannot easily prove if argument we pass to a function is completely written. // Cannot easily prove if argument we pass to a function is completely written.
// Usually, functions write to a dummy variable, // Usually, functions write to a dummy variable,
@ -3925,6 +3939,10 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry)
// For each variable which is statically accessed. // For each variable which is statically accessed.
for (auto &var : handler.accessed_variables_to_block) for (auto &var : handler.accessed_variables_to_block)
{ {
// Only deal with variables which are considered local variables in this function.
if (find(begin(entry.local_variables), end(entry.local_variables), var.first) == end(entry.local_variables))
continue;
DominatorBuilder builder(cfg); DominatorBuilder builder(cfg);
auto &blocks = var.second; auto &blocks = var.second;
auto &type = expression_type(var.first); auto &type = expression_type(var.first);

View File

@ -887,6 +887,7 @@ protected:
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> accessed_temporaries_to_block; std::unordered_map<uint32_t, std::unordered_set<uint32_t>> accessed_temporaries_to_block;
std::unordered_map<uint32_t, uint32_t> result_id_to_type; std::unordered_map<uint32_t, uint32_t> result_id_to_type;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> complete_write_variables_to_block; std::unordered_map<uint32_t, std::unordered_set<uint32_t>> complete_write_variables_to_block;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> partial_write_variables_to_block;
const SPIRBlock *current_block = nullptr; const SPIRBlock *current_block = nullptr;
}; };