Track partial writes as well.
We will need this for LUT promotion.
This commit is contained in:
parent
7216129377
commit
6fdadb9218
@ -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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user