Support do-while where test is negative.
This commit is contained in:
parent
70ff96b03f
commit
ef24337849
@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
do
|
||||
{
|
||||
j = ((j + i) + 1) * j;
|
||||
i++;
|
||||
} while (!(i == 20));
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
int _13;
|
||||
for (int _12 = 0; !(_12 == 16); _12 = _13)
|
||||
{
|
||||
_13 = _12 + 1;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
int _13;
|
||||
for (int _12 = 0; _12 != 16; _12 = _13)
|
||||
{
|
||||
_13 = _12 + 1;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
int _13;
|
||||
for (int _12 = 0; !(_12 == 16); _12 = _13)
|
||||
{
|
||||
_13 = _12 + 1;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (!(i == 20))
|
||||
{
|
||||
j = ((j + i) + 1) * j;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
51
shaders-no-opt/asm/frag/do-while-loop-inverted-test.asm.frag
Normal file
51
shaders-no-opt/asm/frag/do-while-loop-inverted-test.asm.frag
Normal file
@ -0,0 +1,51 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 7
|
||||
; Bound: 28
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %i "i"
|
||||
OpName %j "j"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_20 = OpConstant %int 20
|
||||
%bool = OpTypeBool
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%i = OpVariable %_ptr_Function_int Function
|
||||
%j = OpVariable %_ptr_Function_int Function
|
||||
OpStore %i %int_0
|
||||
OpStore %j %int_0
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
OpLoopMerge %13 %14 None
|
||||
OpBranch %12
|
||||
%12 = OpLabel
|
||||
%15 = OpLoad %int %j
|
||||
%16 = OpLoad %int %i
|
||||
%17 = OpIAdd %int %15 %16
|
||||
%19 = OpIAdd %int %17 %int_1
|
||||
%20 = OpLoad %int %j
|
||||
%21 = OpIMul %int %19 %20
|
||||
OpStore %j %21
|
||||
%22 = OpLoad %int %i
|
||||
%23 = OpIAdd %int %22 %int_1
|
||||
OpStore %i %23
|
||||
OpBranch %14
|
||||
%14 = OpLabel
|
||||
%24 = OpLoad %int %i
|
||||
%27 = OpIEqual %bool %24 %int_20
|
||||
OpBranchConditional %27 %13 %11
|
||||
%13 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -0,0 +1,37 @@
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_16 = OpConstant %int 16
|
||||
%bool = OpTypeBool
|
||||
%int_1 = OpConstant %int 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpBranch %8
|
||||
%8 = OpLabel
|
||||
%10 = OpPhi %int %12 %7 %int_0 %5
|
||||
OpLoopMerge %6 %7 None
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
%16 = OpIEqual %bool %10 %int_16
|
||||
OpBranchConditional %16 %18 %19
|
||||
%18 = OpLabel
|
||||
OpBranch %6
|
||||
%19 = OpLabel
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%21 = OpIAdd %int %10 %int_1
|
||||
OpBranch %7
|
||||
%7 = OpLabel
|
||||
%12 = OpPhi %int %21 %17
|
||||
OpBranch %8
|
||||
%6 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -0,0 +1,37 @@
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_16 = OpConstant %int 16
|
||||
%bool = OpTypeBool
|
||||
%int_1 = OpConstant %int 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpBranch %8
|
||||
%8 = OpLabel
|
||||
%10 = OpPhi %int %12 %7 %int_0 %5
|
||||
OpLoopMerge %6 %7 None
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
%16 = OpINotEqual %bool %10 %int_16
|
||||
OpBranchConditional %16 %19 %18
|
||||
%18 = OpLabel
|
||||
OpBranch %6
|
||||
%19 = OpLabel
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%21 = OpIAdd %int %10 %int_1
|
||||
OpBranch %7
|
||||
%7 = OpLabel
|
||||
%12 = OpPhi %int %21 %17
|
||||
OpBranch %8
|
||||
%6 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
35
shaders-no-opt/asm/frag/for-loop-inverted-test.asm.frag
Normal file
35
shaders-no-opt/asm/frag/for-loop-inverted-test.asm.frag
Normal file
@ -0,0 +1,35 @@
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_16 = OpConstant %int 16
|
||||
%bool = OpTypeBool
|
||||
%int_1 = OpConstant %int 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
OpBranch %8
|
||||
%8 = OpLabel
|
||||
%10 = OpPhi %int %12 %7 %int_0 %5
|
||||
OpLoopMerge %6 %7 None
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
%16 = OpIEqual %bool %10 %int_16
|
||||
OpBranchConditional %16 %6 %19
|
||||
%19 = OpLabel
|
||||
OpBranch %17
|
||||
%17 = OpLabel
|
||||
%21 = OpIAdd %int %10 %int_1
|
||||
OpBranch %7
|
||||
%7 = OpLabel
|
||||
%12 = OpPhi %int %21 %17
|
||||
OpBranch %8
|
||||
%6 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
53
shaders-no-opt/asm/frag/while-loop-inverted-test.asm.frag
Normal file
53
shaders-no-opt/asm/frag/while-loop-inverted-test.asm.frag
Normal file
@ -0,0 +1,53 @@
|
||||
; SPIR-V
|
||||
; Version: 1.0
|
||||
; Generator: Khronos Glslang Reference Front End; 7
|
||||
; Bound: 29
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %i "i"
|
||||
OpName %j "j"
|
||||
%void = OpTypeVoid
|
||||
%3 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_20 = OpConstant %int 20
|
||||
%bool = OpTypeBool
|
||||
%int_1 = OpConstant %int 1
|
||||
%main = OpFunction %void None %3
|
||||
%5 = OpLabel
|
||||
%i = OpVariable %_ptr_Function_int Function
|
||||
%j = OpVariable %_ptr_Function_int Function
|
||||
OpStore %i %int_0
|
||||
OpStore %j %int_0
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
OpLoopMerge %13 %14 None
|
||||
OpBranch %15
|
||||
%15 = OpLabel
|
||||
%16 = OpLoad %int %i
|
||||
%19 = OpIEqual %bool %16 %int_20
|
||||
OpBranchConditional %19 %13 %12
|
||||
%12 = OpLabel
|
||||
%20 = OpLoad %int %j
|
||||
%21 = OpLoad %int %i
|
||||
%22 = OpIAdd %int %20 %21
|
||||
%24 = OpIAdd %int %22 %int_1
|
||||
%25 = OpLoad %int %j
|
||||
%26 = OpIMul %int %24 %25
|
||||
OpStore %j %26
|
||||
%27 = OpLoad %int %i
|
||||
%28 = OpIAdd %int %27 %int_1
|
||||
OpStore %i %28
|
||||
OpBranch %14
|
||||
%14 = OpLabel
|
||||
OpBranch %11
|
||||
%13 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
@ -1611,8 +1611,20 @@ SPIRBlock::ContinueBlockType Compiler::continue_block_type(const SPIRBlock &bloc
|
||||
return SPIRBlock::ForLoop;
|
||||
else
|
||||
{
|
||||
const auto *false_block = maybe_get<SPIRBlock>(block.false_block);
|
||||
const auto *true_block = maybe_get<SPIRBlock>(block.true_block);
|
||||
const auto *merge_block = maybe_get<SPIRBlock>(dominator.merge_block);
|
||||
|
||||
bool positive_do_while = block.true_block == dominator.self &&
|
||||
(block.false_block == dominator.merge_block ||
|
||||
(false_block && merge_block && execution_is_noop(*false_block, *merge_block)));
|
||||
|
||||
bool negative_do_while = block.false_block == dominator.self &&
|
||||
(block.true_block == dominator.merge_block ||
|
||||
(true_block && merge_block && execution_is_noop(*true_block, *merge_block)));
|
||||
|
||||
if (block.merge == SPIRBlock::MergeNone && block.terminator == SPIRBlock::Select &&
|
||||
block.true_block == dominator.self && block.false_block == dominator.merge_block)
|
||||
(positive_do_while || negative_do_while))
|
||||
{
|
||||
return SPIRBlock::DoWhileLoop;
|
||||
}
|
||||
|
@ -10205,7 +10205,7 @@ void CompilerGLSL::propagate_loop_dominators(const SPIRBlock &block)
|
||||
// FIXME: This currently cannot handle complex continue blocks
|
||||
// as in do-while.
|
||||
// This should be seen as a "trivial" continue block.
|
||||
string CompilerGLSL::emit_continue_block(uint32_t continue_block)
|
||||
string CompilerGLSL::emit_continue_block(uint32_t continue_block, bool follow_true_block, bool follow_false_block)
|
||||
{
|
||||
auto *block = &get<SPIRBlock>(continue_block);
|
||||
|
||||
@ -10233,11 +10233,20 @@ string CompilerGLSL::emit_continue_block(uint32_t continue_block)
|
||||
block = &get<SPIRBlock>(block->next_block);
|
||||
}
|
||||
// For do while blocks. The last block will be a select block.
|
||||
else if (block->true_block)
|
||||
else if (block->true_block && follow_true_block)
|
||||
{
|
||||
flush_phi(continue_block, block->true_block);
|
||||
block = &get<SPIRBlock>(block->true_block);
|
||||
}
|
||||
else if (block->false_block && follow_false_block)
|
||||
{
|
||||
flush_phi(continue_block, block->false_block);
|
||||
block = &get<SPIRBlock>(block->false_block);
|
||||
}
|
||||
else
|
||||
{
|
||||
SPIRV_CROSS_THROW("Invalid continue block detected!");
|
||||
}
|
||||
}
|
||||
|
||||
// Restore old pointer.
|
||||
@ -10400,7 +10409,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
|
||||
emit_block_hints(block);
|
||||
if (method != SPIRBlock::MergeToSelectContinueForLoop)
|
||||
{
|
||||
auto continue_block = emit_continue_block(block.continue_block);
|
||||
auto continue_block = emit_continue_block(block.continue_block, false, false);
|
||||
statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
|
||||
}
|
||||
else
|
||||
@ -10476,7 +10485,7 @@ bool CompilerGLSL::attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method
|
||||
target_block = child.false_block;
|
||||
}
|
||||
|
||||
auto continue_block = emit_continue_block(block.continue_block);
|
||||
auto continue_block = emit_continue_block(block.continue_block, false, false);
|
||||
emit_block_hints(block);
|
||||
statement("for (", initializer, "; ", condition, "; ", continue_block, ")");
|
||||
break;
|
||||
@ -10617,6 +10626,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
{
|
||||
flush_undeclared_variables(block);
|
||||
emit_while_loop_initializers(block);
|
||||
emitted_for_loop_header = true;
|
||||
// We have some temporaries where the loop header is the dominator.
|
||||
// We risk a case where we have code like:
|
||||
// for (;;) { create-temporary; break; } consume-temporary;
|
||||
@ -10908,7 +10918,12 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
// Make sure that we run the continue block to get the expressions set, but this
|
||||
// should become an empty string.
|
||||
// We have no fallbacks if we cannot forward everything to temporaries ...
|
||||
auto statements = emit_continue_block(block.continue_block);
|
||||
const auto &continue_block = get<SPIRBlock>(block.continue_block);
|
||||
bool positive_test =
|
||||
execution_is_noop(get<SPIRBlock>(continue_block.true_block),
|
||||
get<SPIRBlock>(continue_block.loop_dominator));
|
||||
|
||||
auto statements = emit_continue_block(block.continue_block, positive_test, !positive_test);
|
||||
if (!statements.empty())
|
||||
{
|
||||
// The DoWhile block has side effects, force ComplexLoop pattern next pass.
|
||||
@ -10916,7 +10931,12 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
force_recompile = true;
|
||||
}
|
||||
|
||||
end_scope_decl(join("while (", to_expression(get<SPIRBlock>(block.continue_block).condition), ")"));
|
||||
// Might have to invert the do-while test here.
|
||||
auto condition = to_expression(continue_block.condition);
|
||||
if (!positive_test)
|
||||
condition = join("!", enclose_expression(condition));
|
||||
|
||||
end_scope_decl(join("while (", condition, ")"));
|
||||
}
|
||||
else
|
||||
end_scope();
|
||||
|
@ -403,7 +403,7 @@ protected:
|
||||
std::string constant_value_macro_name(uint32_t id);
|
||||
void emit_constant(const SPIRConstant &constant);
|
||||
void emit_specialization_constant_op(const SPIRConstantOp &constant);
|
||||
std::string emit_continue_block(uint32_t continue_block);
|
||||
std::string emit_continue_block(uint32_t continue_block, bool follow_true_block, bool follow_false_block);
|
||||
bool attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method);
|
||||
void propagate_loop_dominators(const SPIRBlock &block);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user