| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967 |
- // Copyright (c) 2018 Google LLC.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include <string>
- #include "effcee/effcee.h"
- #include "gmock/gmock.h"
- #include "test/opt/pass_fixture.h"
- namespace spvtools {
- namespace opt {
- namespace {
- using UnswitchTest = PassTest<::testing::Test>;
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 450 core
- uniform vec4 c;
- void main() {
- int i = 0;
- int j = 0;
- bool cond = c[0] == 0;
- for (; i < 10; i++, j++) {
- if (cond) {
- i++;
- }
- else {
- j++;
- }
- }
- }
- */
- TEST_F(UnswitchTest, SimpleUnswitch) {
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]]
- ; Loop specialized for false.
- ; CHECK: [[loop_f]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: [[phi_j:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_j:%\w+]] [[continue]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; [[loop_body]] = OpLabel
- ; CHECK: OpSelectionMerge [[sel_merge:%\w+]] None
- ; CHECK: OpBranchConditional %false [[bb1:%\w+]] [[bb2:%\w+]]
- ; CHECK: [[bb2]] = OpLabel
- ; CHECK-NEXT: [[inc_j:%\w+]] = OpIAdd %int [[phi_j]] %int_1
- ; CHECK-NEXT: OpBranch [[sel_merge]]
- ; CHECK: [[bb1]] = OpLabel
- ; CHECK-NEXT: [[inc_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK-NEXT: OpBranch [[sel_merge]]
- ; CHECK: [[sel_merge]] = OpLabel
- ; CHECK: OpBranch [[if_merge]]
- ; Loop specialized for true.
- ; CHECK: [[loop_t]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: [[phi_j:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_j:%\w+]] [[continue]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; [[loop_body]] = OpLabel
- ; CHECK: OpSelectionMerge [[sel_merge:%\w+]] None
- ; CHECK: OpBranchConditional %true [[bb1:%\w+]] [[bb2:%\w+]]
- ; CHECK: [[bb1]] = OpLabel
- ; CHECK-NEXT: [[inc_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK-NEXT: OpBranch [[sel_merge]]
- ; CHECK: [[bb2]] = OpLabel
- ; CHECK-NEXT: [[inc_j:%\w+]] = OpIAdd %int [[phi_j]] %int_1
- ; CHECK-NEXT: OpBranch [[sel_merge]]
- ; CHECK: [[sel_merge]] = OpLabel
- ; CHECK: OpBranch [[if_merge]]
- ; CHECK: [[if_merge]] = OpLabel
- ; CHECK-NEXT: OpReturn
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main"
- OpExecutionMode %main OriginLowerLeft
- OpSource GLSL 450
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %c DescriptorSet 0
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_UniformConstant_v4float = OpTypePointer UniformConstant %v4float
- %c = OpVariable %_ptr_UniformConstant_v4float UniformConstant
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_UniformConstant_float = OpTypePointer UniformConstant %float
- %float_0 = OpConstant %float 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %21 = OpAccessChain %_ptr_UniformConstant_float %c %uint_0
- %22 = OpLoad %float %21
- %24 = OpFOrdEqual %bool %22 %float_0
- OpBranch %25
- %25 = OpLabel
- %46 = OpPhi %int %int_0 %5 %43 %28
- %47 = OpPhi %int %int_0 %5 %45 %28
- OpLoopMerge %27 %28 None
- OpBranch %29
- %29 = OpLabel
- %32 = OpSLessThan %bool %46 %int_10
- OpBranchConditional %32 %26 %27
- %26 = OpLabel
- OpSelectionMerge %35 None
- OpBranchConditional %24 %34 %39
- %34 = OpLabel
- %38 = OpIAdd %int %46 %int_1
- OpBranch %35
- %39 = OpLabel
- %41 = OpIAdd %int %47 %int_1
- OpBranch %35
- %35 = OpLabel
- %48 = OpPhi %int %38 %34 %46 %39
- %49 = OpPhi %int %47 %34 %41 %39
- OpBranch %28
- %28 = OpLabel
- %43 = OpIAdd %int %48 %int_1
- %45 = OpIAdd %int %49 %int_1
- OpBranch %25
- %27 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 330 core
- in vec4 c;
- void main() {
- int i = 0;
- bool cond = c[0] == 0;
- for (; i < 10; i++) {
- if (cond) {
- i++;
- }
- else {
- return;
- }
- }
- }
- */
- TEST_F(UnswitchTest, UnswitchExit) {
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]]
- ; Loop specialized for false.
- ; CHECK: [[loop_f]] = OpLabel
- ; CHECK: OpReturn
- ; Loop specialized for true.
- ; CHECK: [[loop_t]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] {{%\w+}} [[merge]]
- ; Check that we have i+=2.
- ; CHECK: [[phi_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK: [[iv_i]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; CHECK: [[if_merge]] = OpLabel
- ; CHECK-NEXT: OpReturn
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 330
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %23 Uniform
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_0 = OpConstant %float 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %20 = OpAccessChain %_ptr_Input_float %c %uint_0
- %21 = OpLoad %float %20
- %23 = OpFOrdEqual %bool %21 %float_0
- OpBranch %24
- %24 = OpLabel
- %42 = OpPhi %int %int_0 %5 %41 %27
- OpLoopMerge %26 %27 None
- OpBranch %28
- %28 = OpLabel
- %31 = OpSLessThan %bool %42 %int_10
- OpBranchConditional %31 %25 %26
- %25 = OpLabel
- OpSelectionMerge %34 None
- OpBranchConditional %23 %33 %38
- %33 = OpLabel
- %37 = OpIAdd %int %42 %int_1
- OpBranch %34
- %38 = OpLabel
- OpReturn
- %34 = OpLabel
- OpBranch %27
- %27 = OpLabel
- %41 = OpIAdd %int %37 %int_1
- OpBranch %24
- %26 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 330 core
- in vec4 c;
- void main() {
- int i = 0;
- bool cond = c[0] == 0;
- for (; i < 10; i++) {
- if (cond) {
- continue;
- }
- else {
- i++;
- }
- }
- }
- */
- TEST_F(UnswitchTest, UnswitchContinue) {
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]]
- ; Loop specialized for false.
- ; CHECK: [[loop_f]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_f]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body:%\w+]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpBranchConditional %false
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; Loop specialized for true.
- ; CHECK: [[loop_t]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body:%\w+]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpBranchConditional %true
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; CHECK: [[if_merge]] = OpLabel
- ; CHECK-NEXT: OpReturn
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 330
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %23 Uniform
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_0 = OpConstant %float 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %20 = OpAccessChain %_ptr_Input_float %c %uint_0
- %21 = OpLoad %float %20
- %23 = OpFOrdEqual %bool %21 %float_0
- OpBranch %24
- %24 = OpLabel
- %42 = OpPhi %int %int_0 %5 %41 %27
- OpLoopMerge %26 %27 None
- OpBranch %28
- %28 = OpLabel
- %31 = OpSLessThan %bool %42 %int_10
- OpBranchConditional %31 %25 %26
- %25 = OpLabel
- OpSelectionMerge %34 None
- OpBranchConditional %23 %33 %36
- %33 = OpLabel
- OpBranch %27
- %36 = OpLabel
- %39 = OpIAdd %int %42 %int_1
- OpBranch %34
- %34 = OpLabel
- OpBranch %27
- %27 = OpLabel
- %43 = OpPhi %int %42 %33 %39 %34
- %41 = OpIAdd %int %43 %int_1
- OpBranch %24
- %26 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 330 core
- in vec4 c;
- void main() {
- int i = 0;
- bool cond = c[0] == 0;
- for (; i < 10; i++) {
- if (cond) {
- i++;
- }
- else {
- break;
- }
- }
- }
- */
- TEST_F(UnswitchTest, UnswitchKillLoop) {
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]]
- ; Loop specialized for false.
- ; CHECK: [[loop_f]] = OpLabel
- ; CHECK: OpBranch [[if_merge]]
- ; Loop specialized for true.
- ; CHECK: [[loop_t]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_t]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] {{%\w+}} [[merge]]
- ; Check that we have i+=2.
- ; CHECK: [[phi_i:%\w+]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK: [[iv_i]] = OpIAdd %int [[phi_i]] %int_1
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; CHECK: [[if_merge]] = OpLabel
- ; CHECK-NEXT: OpReturn
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 330
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %23 Uniform
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_0 = OpConstant %float 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %20 = OpAccessChain %_ptr_Input_float %c %uint_0
- %21 = OpLoad %float %20
- %23 = OpFOrdEqual %bool %21 %float_0
- OpBranch %24
- %24 = OpLabel
- %42 = OpPhi %int %int_0 %5 %41 %27
- OpLoopMerge %26 %27 None
- OpBranch %28
- %28 = OpLabel
- %31 = OpSLessThan %bool %42 %int_10
- OpBranchConditional %31 %25 %26
- %25 = OpLabel
- OpSelectionMerge %34 None
- OpBranchConditional %23 %33 %38
- %33 = OpLabel
- %37 = OpIAdd %int %42 %int_1
- OpBranch %34
- %38 = OpLabel
- OpBranch %26
- %34 = OpLabel
- OpBranch %27
- %27 = OpLabel
- %41 = OpIAdd %int %37 %int_1
- OpBranch %24
- %26 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 330 core
- in vec4 c;
- void main() {
- int i = 0;
- int cond = int(c[0]);
- for (; i < 10; i++) {
- switch (cond) {
- case 0:
- return;
- case 1:
- discard;
- case 2:
- break;
- default:
- break;
- }
- }
- bool cond2 = i == 9;
- }
- */
- TEST_F(UnswitchTest, UnswitchSwitch) {
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpConvertFToS
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpSwitch [[cst_cond]] [[default:%\w+]] 0 [[loop_0:%\w+]] 1 [[loop_1:%\w+]] 2 [[loop_2:%\w+]]
- ; Loop specialized for 2.
- ; CHECK: [[loop_2]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_2]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpSwitch %int_2
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; Loop specialized for 1.
- ; CHECK: [[loop_1]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_1]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpSwitch %int_1
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; Loop specialized for 0.
- ; CHECK: [[loop_0]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[loop_0]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpSwitch %int_0
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; Loop specialized for the default case.
- ; CHECK: [[default]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: [[phi_i:%\w+]] = OpPhi %int %int_0 [[default]] [[iv_i:%\w+]] [[continue:%\w+]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK: [[loop_exit:%\w+]] = OpSLessThan {{%\w+}} [[phi_i]] {{%\w+}}
- ; CHECK-NEXT: OpBranchConditional [[loop_exit]] [[loop_body:%\w+]] [[merge]]
- ; CHECK: [[loop_body]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpSwitch %uint_3
- ; CHECK: [[merge]] = OpLabel
- ; CHECK-NEXT: OpBranch [[if_merge]]
- ; CHECK: [[if_merge]] = OpLabel
- ; CHECK-NEXT: OpReturn
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 330
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %20 Uniform
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %int_10 = OpConstant %int 10
- %bool = OpTypeBool
- %int_1 = OpConstant %int 1
- %_ptr_Function_bool = OpTypePointer Function %bool
- %main = OpFunction %void None %3
- %5 = OpLabel
- %18 = OpAccessChain %_ptr_Input_float %c %uint_0
- %19 = OpLoad %float %18
- %20 = OpConvertFToS %int %19
- OpBranch %21
- %21 = OpLabel
- %49 = OpPhi %int %int_0 %5 %43 %24
- OpLoopMerge %23 %24 None
- OpBranch %25
- %25 = OpLabel
- %29 = OpSLessThan %bool %49 %int_10
- OpBranchConditional %29 %22 %23
- %22 = OpLabel
- OpSelectionMerge %35 None
- OpSwitch %20 %34 0 %31 1 %32 2 %33
- %34 = OpLabel
- OpBranch %35
- %31 = OpLabel
- OpReturn
- %32 = OpLabel
- OpKill
- %33 = OpLabel
- OpBranch %35
- %35 = OpLabel
- OpBranch %24
- %24 = OpLabel
- %43 = OpIAdd %int %49 %int_1
- OpBranch %21
- %23 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 440 core
- layout(location = 0)in vec4 c;
- void main() {
- int i = 0;
- int j = 0;
- int k = 0;
- bool cond = c[0] == 0;
- for (; i < 10; i++) {
- for (; j < 10; j++) {
- if (cond) {
- i++;
- } else {
- j++;
- }
- }
- }
- }
- */
- TEST_F(UnswitchTest, UnSwitchNested) {
- // Test that an branch can be unswitched out of two nested loops.
- const std::string text = R"(
- ; CHECK: [[cst_cond:%\w+]] = OpFOrdEqual
- ; CHECK-NEXT: OpSelectionMerge [[if_merge:%\w+]] None
- ; CHECK-NEXT: OpBranchConditional [[cst_cond]] [[loop_t:%\w+]] [[loop_f:%\w+]]
- ; Loop specialized for false
- ; CHECK: [[loop_f]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_f]] {{%\w+}} [[continue:%\w+]]
- ; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_f]] {{%\w+}} [[continue]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK-NOT: [[merge]] = OpLabel
- ; CHECK: OpLoopMerge
- ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
- ; CHECK: [[bb1]] = OpLabel
- ; CHECK-NEXT: OpSLessThan
- ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb2:%\w+]]
- ; CHECK: [[bb2]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpBranchConditional %false
- ; CHECK: [[merge]] = OpLabel
- ; Loop specialized for true. Same as first loop except the branch condition is true.
- ; CHECK: [[loop_t]] = OpLabel
- ; CHECK-NEXT: OpBranch [[loop:%\w+]]
- ; CHECK: [[loop]] = OpLabel
- ; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_t]] {{%\w+}} [[continue:%\w+]]
- ; CHECK-NEXT: {{%\w+}} = OpPhi %int %int_0 [[loop_t]] {{%\w+}} [[continue]]
- ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
- ; CHECK-NOT: [[merge]] = OpLabel
- ; CHECK: OpLoopMerge
- ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
- ; CHECK: [[bb1]] = OpLabel
- ; CHECK-NEXT: OpSLessThan
- ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb2:%\w+]]
- ; CHECK: [[bb2]] = OpLabel
- ; CHECK-NEXT: OpSelectionMerge
- ; CHECK-NEXT: OpBranchConditional %true
- ; CHECK: [[merge]] = OpLabel
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 440
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- OpDecorate %25 Uniform
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_0 = OpConstant %float 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %22 = OpAccessChain %_ptr_Input_float %c %uint_0
- %23 = OpLoad %float %22
- %25 = OpFOrdEqual %bool %23 %float_0
- OpBranch %26
- %26 = OpLabel
- %67 = OpPhi %int %int_0 %5 %52 %29
- %68 = OpPhi %int %int_0 %5 %70 %29
- OpLoopMerge %28 %29 None
- OpBranch %30
- %30 = OpLabel
- %33 = OpSLessThan %bool %67 %int_10
- OpBranchConditional %33 %27 %28
- %27 = OpLabel
- OpBranch %34
- %34 = OpLabel
- %69 = OpPhi %int %67 %27 %46 %37
- %70 = OpPhi %int %68 %27 %50 %37
- OpLoopMerge %36 %37 None
- OpBranch %38
- %38 = OpLabel
- %40 = OpSLessThan %bool %70 %int_10
- OpBranchConditional %40 %35 %36
- %35 = OpLabel
- OpSelectionMerge %43 None
- OpBranchConditional %25 %42 %47
- %42 = OpLabel
- %46 = OpIAdd %int %69 %int_1
- OpBranch %43
- %47 = OpLabel
- OpReturn
- %43 = OpLabel
- OpBranch %37
- %37 = OpLabel
- %50 = OpIAdd %int %70 %int_1
- OpBranch %34
- %36 = OpLabel
- OpBranch %29
- %29 = OpLabel
- %52 = OpIAdd %int %69 %int_1
- OpBranch %26
- %28 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- SinglePassRunAndMatch<LoopUnswitchPass>(text, true);
- }
- /*
- Generated from the following GLSL + --eliminate-local-multi-store
- #version 330 core
- in vec4 c;
- void main() {
- bool cond = false;
- if (c[0] == 0) {
- cond = c[1] == 0;
- } else {
- cond = c[2] == 0;
- }
- for (int i = 0; i < 10; i++) {
- if (cond) {
- i++;
- }
- }
- }
- */
- TEST_F(UnswitchTest, UnswitchNotUniform) {
- // Check that the unswitch is not triggered (condition loop invariant but not
- // uniform)
- const std::string text = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %c
- OpExecutionMode %main OriginUpperLeft
- OpSource GLSL 330
- OpName %main "main"
- OpName %c "c"
- OpDecorate %c Location 0
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %bool = OpTypeBool
- %_ptr_Function_bool = OpTypePointer Function %bool
- %float = OpTypeFloat 32
- %v4float = OpTypeVector %float 4
- %_ptr_Input_v4float = OpTypePointer Input %v4float
- %c = OpVariable %_ptr_Input_v4float Input
- %uint = OpTypeInt 32 0
- %uint_0 = OpConstant %uint 0
- %_ptr_Input_float = OpTypePointer Input %float
- %float_0 = OpConstant %float 0
- %uint_1 = OpConstant %uint 1
- %uint_2 = OpConstant %uint 2
- %int = OpTypeInt 32 1
- %_ptr_Function_int = OpTypePointer Function %int
- %int_0 = OpConstant %int 0
- %int_10 = OpConstant %int 10
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %3
- %5 = OpLabel
- %17 = OpAccessChain %_ptr_Input_float %c %uint_0
- %18 = OpLoad %float %17
- %20 = OpFOrdEqual %bool %18 %float_0
- OpSelectionMerge %22 None
- OpBranchConditional %20 %21 %27
- %21 = OpLabel
- %24 = OpAccessChain %_ptr_Input_float %c %uint_1
- %25 = OpLoad %float %24
- %26 = OpFOrdEqual %bool %25 %float_0
- OpBranch %22
- %27 = OpLabel
- %29 = OpAccessChain %_ptr_Input_float %c %uint_2
- %30 = OpLoad %float %29
- %31 = OpFOrdEqual %bool %30 %float_0
- OpBranch %22
- %22 = OpLabel
- %52 = OpPhi %bool %26 %21 %31 %27
- OpBranch %36
- %36 = OpLabel
- %53 = OpPhi %int %int_0 %22 %51 %39
- OpLoopMerge %38 %39 None
- OpBranch %40
- %40 = OpLabel
- %43 = OpSLessThan %bool %53 %int_10
- OpBranchConditional %43 %37 %38
- %37 = OpLabel
- OpSelectionMerge %46 None
- OpBranchConditional %52 %45 %46
- %45 = OpLabel
- %49 = OpIAdd %int %53 %int_1
- OpBranch %46
- %46 = OpLabel
- %54 = OpPhi %int %53 %37 %49 %45
- OpBranch %39
- %39 = OpLabel
- %51 = OpIAdd %int %54 %int_1
- OpBranch %36
- %38 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- auto result =
- SinglePassRunAndDisassemble<LoopUnswitchPass>(text, true, false);
- EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
- }
- TEST_F(UnswitchTest, DontUnswitchLatch) {
- // Check that the unswitch is not triggered for the latch branch.
- const std::string text = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main"
- OpExecutionMode %4 OriginUpperLeft
- OpSource ESSL 310
- %void = OpTypeVoid
- %3 = OpTypeFunction %void
- %bool = OpTypeBool
- %false = OpConstantFalse %bool
- %4 = OpFunction %void None %3
- %5 = OpLabel
- OpBranch %6
- %6 = OpLabel
- OpLoopMerge %8 %9 None
- OpBranch %7
- %7 = OpLabel
- OpBranch %9
- %9 = OpLabel
- OpBranchConditional %false %6 %8
- %8 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- auto result =
- SinglePassRunAndDisassemble<LoopUnswitchPass>(text, true, false);
- EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
- }
- TEST_F(UnswitchTest, DontUnswitchConstantCondition) {
- const std::string text = R"(
- OpCapability Shader
- %1 = OpExtInstImport "GLSL.std.450"
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main"
- OpExecutionMode %main OriginLowerLeft
- OpSource GLSL 450
- OpName %main "main"
- %void = OpTypeVoid
- %4 = OpTypeFunction %void
- %int = OpTypeInt 32 1
- %int_0 = OpConstant %int 0
- %bool = OpTypeBool
- %true = OpConstantTrue %bool
- %int_1 = OpConstant %int 1
- %main = OpFunction %void None %4
- %10 = OpLabel
- OpBranch %11
- %11 = OpLabel
- %12 = OpPhi %int %int_0 %10 %13 %14
- OpLoopMerge %15 %14 None
- OpBranch %16
- %16 = OpLabel
- %17 = OpSLessThan %bool %12 %int_1
- OpBranchConditional %17 %18 %15
- %18 = OpLabel
- OpSelectionMerge %19 None
- OpBranchConditional %true %20 %19
- %20 = OpLabel
- %21 = OpIAdd %int %12 %int_1
- OpBranch %19
- %19 = OpLabel
- %22 = OpPhi %int %21 %20 %12 %18
- OpBranch %14
- %14 = OpLabel
- %13 = OpIAdd %int %22 %int_1
- OpBranch %11
- %15 = OpLabel
- OpReturn
- OpFunctionEnd
- )";
- auto result =
- SinglePassRunAndDisassemble<LoopUnswitchPass>(text, true, false);
- EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
- }
- } // namespace
- } // namespace opt
- } // namespace spvtools
|