Implement workaround to deal with older glslang loop output.

The problem case is when continue block == loop header block.
Add some special cases to deal with this scenario.
This commit is contained in:
Hans-Kristian Arntzen 2016-04-01 12:37:29 +02:00
Родитель e50e04c247
Коммит 97f81ba1e2
2 изменённых файлов: 16 добавлений и 6 удалений

Просмотреть файл

@ -451,7 +451,7 @@ namespace spir2cross
inline uint32_t vector_size() const { return m.c[0].vecsize; }
inline uint32_t columns() const { return m.columns; }
SPIRConstant(uint32_t constant_type, const uint32_t *elements, uint32_t num_elements) :
SPIRConstant(uint32_t constant_type, const uint32_t *elements, uint32_t num_elements) :
constant_type(constant_type)
{
subconstants.insert(end(subconstants), elements, elements + num_elements);
@ -539,8 +539,8 @@ namespace spir2cross
ConstantMatrix m;
bool specialization = false; // If the constant is a specialization constant.
// For composites which are constant arrays, etc.
std::vector<uint32_t> subconstants;
// For composites which are constant arrays, etc.
std::vector<uint32_t> subconstants;
};
class Variant

Просмотреть файл

@ -1438,7 +1438,12 @@ void Compiler::parse(const Instruction &i)
loop_block.insert(block->self);
loop_merge_target.insert(block->merge_block);
continue_block.insert(block->continue_block);
// Don't add loop headers to continue blocks,
// which would make it impossible branch into the loop header since
// they are treated as continues.
if (block->continue_block != block->self)
continue_block.insert(block->continue_block);
break;
}
@ -1606,12 +1611,17 @@ bool Compiler::execution_is_branchless(const SPIRBlock &from, const SPIRBlock &t
SPIRBlock::ContinueBlockType Compiler::continue_block_type(const SPIRBlock &continue_block) const
{
auto &dominator = get<SPIRBlock>(continue_block.loop_dominator);
// The block was deemed too complex during code emit, pick conservative fallback paths.
if (continue_block.complex_continue)
return SPIRBlock::ComplexLoop;
// In older glslang output continue block can be equal to the loop header.
// In this case, execution is clearly branchless, so just assume a while loop header here.
if (continue_block.merge == SPIRBlock::MergeLoop)
return SPIRBlock::WhileLoop;
auto &dominator = get<SPIRBlock>(continue_block.loop_dominator);
if (execution_is_noop(continue_block, dominator))
return SPIRBlock::WhileLoop;
else if (execution_is_branchless(continue_block, dominator))