1 // Copyright (c) 2018 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <string> 16 17 #include "gmock/gmock.h" 18 #include "source/opt/simplification_pass.h" 19 #include "test/opt/assembly_builder.h" 20 #include "test/opt/pass_fixture.h" 21 22 namespace spvtools { 23 namespace opt { 24 namespace { 25 26 using SimplificationTest = PassTest<::testing::Test>; 27 28 TEST_F(SimplificationTest, StraightLineTest) { 29 // Testing that folding rules are combined in simple straight line code. 30 const std::string text = R"(OpCapability Shader 31 %1 = OpExtInstImport "GLSL.std.450" 32 OpMemoryModel Logical GLSL450 33 OpEntryPoint Fragment %main "main" %i %o 34 OpExecutionMode %main OriginUpperLeft 35 OpSource GLSL 430 36 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 37 OpSourceExtension "GL_GOOGLE_include_directive" 38 OpName %main "main" 39 OpName %i "i" 40 OpName %o "o" 41 OpDecorate %i Flat 42 OpDecorate %i Location 0 43 OpDecorate %o Location 0 44 %void = OpTypeVoid 45 %8 = OpTypeFunction %void 46 %int = OpTypeInt 32 1 47 %v4int = OpTypeVector %int 4 48 %int_0 = OpConstant %int 0 49 %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 50 %int_1 = OpConstant %int 1 51 %_ptr_Input_v4int = OpTypePointer Input %v4int 52 %i = OpVariable %_ptr_Input_v4int Input 53 %_ptr_Output_int = OpTypePointer Output %int 54 %o = OpVariable %_ptr_Output_int Output 55 %main = OpFunction %void None %8 56 %21 = OpLabel 57 %31 = OpCompositeInsert %v4int %int_1 %13 0 58 ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad 59 %23 = OpLoad %v4int %i 60 %33 = OpCompositeInsert %v4int %int_0 %23 0 61 %35 = OpCompositeExtract %int %31 0 62 ; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1 63 %37 = OpCompositeExtract %int %33 1 64 ; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int %int_1 [[extract]] 65 %29 = OpIAdd %int %35 %37 66 OpStore %o %29 67 OpReturn 68 OpFunctionEnd 69 )"; 70 71 SinglePassRunAndMatch<SimplificationPass>(text, false); 72 } 73 74 TEST_F(SimplificationTest, AcrossBasicBlocks) { 75 // Testing that folding rules are combined across basic blocks. 76 const std::string text = R"(OpCapability Shader 77 %1 = OpExtInstImport "GLSL.std.450" 78 OpMemoryModel Logical GLSL450 79 OpEntryPoint Fragment %main "main" %i %o 80 OpExecutionMode %main OriginUpperLeft 81 OpSource GLSL 430 82 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 83 OpSourceExtension "GL_GOOGLE_include_directive" 84 OpName %main "main" 85 OpName %i "i" 86 OpName %o "o" 87 OpDecorate %i Flat 88 OpDecorate %i Location 0 89 OpDecorate %o Location 0 90 %void = OpTypeVoid 91 %8 = OpTypeFunction %void 92 %int = OpTypeInt 32 1 93 %v4int = OpTypeVector %int 4 94 %int_0 = OpConstant %int 0 95 %_ptr_Input_v4int = OpTypePointer Input %v4int 96 %i = OpVariable %_ptr_Input_v4int Input 97 %uint = OpTypeInt 32 0 98 %uint_0 = OpConstant %uint 0 99 %_ptr_Input_int = OpTypePointer Input %int 100 %int_10 = OpConstant %int 10 101 %bool = OpTypeBool 102 %int_1 = OpConstant %int 1 103 %_ptr_Output_int = OpTypePointer Output %int 104 %o = OpVariable %_ptr_Output_int Output 105 %main = OpFunction %void None %8 106 %24 = OpLabel 107 ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i 108 %25 = OpLoad %v4int %i 109 %41 = OpCompositeInsert %v4int %int_0 %25 0 110 %27 = OpAccessChain %_ptr_Input_int %i %uint_0 111 %28 = OpLoad %int %27 112 %29 = OpSGreaterThan %bool %28 %int_10 113 OpSelectionMerge %30 None 114 OpBranchConditional %29 %31 %32 115 %31 = OpLabel 116 %43 = OpCopyObject %v4int %25 117 OpBranch %30 118 %32 = OpLabel 119 %45 = OpCopyObject %v4int %25 120 OpBranch %30 121 %30 = OpLabel 122 %50 = OpPhi %v4int %43 %31 %45 %32 123 ; CHECK: [[extract1:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0 124 %47 = OpCompositeExtract %int %50 0 125 ; CHECK: [[extract2:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 1 126 %49 = OpCompositeExtract %int %41 1 127 ; CHECK: [[add:%[a-zA-Z_\d]+]] = OpIAdd %int [[extract1]] [[extract2]] 128 %39 = OpIAdd %int %47 %49 129 OpStore %o %39 130 OpReturn 131 OpFunctionEnd 132 133 )"; 134 135 SinglePassRunAndMatch<SimplificationPass>(text, false); 136 } 137 138 TEST_F(SimplificationTest, ThroughLoops) { 139 // Testing that folding rules are applied multiple times to instructions 140 // to be able to propagate across loop iterations. 141 const std::string text = R"( 142 OpCapability Shader 143 %1 = OpExtInstImport "GLSL.std.450" 144 OpMemoryModel Logical GLSL450 145 OpEntryPoint Fragment %main "main" %o %i 146 OpExecutionMode %main OriginUpperLeft 147 OpSource GLSL 430 148 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 149 OpSourceExtension "GL_GOOGLE_include_directive" 150 OpName %main "main" 151 OpName %o "o" 152 OpName %i "i" 153 OpDecorate %o Location 0 154 OpDecorate %i Flat 155 OpDecorate %i Location 0 156 %void = OpTypeVoid 157 %8 = OpTypeFunction %void 158 %int = OpTypeInt 32 1 159 %v4int = OpTypeVector %int 4 160 %int_0 = OpConstant %int 0 161 ; CHECK: [[constant:%[a-zA-Z_\d]+]] = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 162 %13 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 163 %bool = OpTypeBool 164 %_ptr_Output_int = OpTypePointer Output %int 165 %o = OpVariable %_ptr_Output_int Output 166 %_ptr_Input_v4int = OpTypePointer Input %v4int 167 %i = OpVariable %_ptr_Input_v4int Input 168 %68 = OpUndef %v4int 169 %main = OpFunction %void None %8 170 %23 = OpLabel 171 ; CHECK: [[load:%[a-zA-Z_\d]+]] = OpLoad %v4int %i 172 %load = OpLoad %v4int %i 173 OpBranch %24 174 %24 = OpLabel 175 %67 = OpPhi %v4int %load %23 %64 %26 176 ; CHECK: OpLoopMerge [[merge_lab:%[a-zA-Z_\d]+]] 177 OpLoopMerge %25 %26 None 178 OpBranch %27 179 %27 = OpLabel 180 %48 = OpCompositeExtract %int %67 0 181 %30 = OpIEqual %bool %48 %int_0 182 OpBranchConditional %30 %31 %25 183 %31 = OpLabel 184 %50 = OpCompositeExtract %int %67 0 185 %54 = OpCompositeExtract %int %67 1 186 %58 = OpCompositeExtract %int %67 2 187 %62 = OpCompositeExtract %int %67 3 188 %64 = OpCompositeConstruct %v4int %50 %54 %58 %62 189 OpBranch %26 190 %26 = OpLabel 191 OpBranch %24 192 %25 = OpLabel 193 ; CHECK: [[merge_lab]] = OpLabel 194 ; CHECK: [[extract:%[a-zA-Z_\d]+]] = OpCompositeExtract %int [[load]] 0 195 %66 = OpCompositeExtract %int %67 0 196 ; CHECK-NEXT: OpStore %o [[extract]] 197 OpStore %o %66 198 OpReturn 199 OpFunctionEnd 200 )"; 201 202 SinglePassRunAndMatch<SimplificationPass>(text, false); 203 } 204 205 } // namespace 206 } // namespace opt 207 } // namespace spvtools 208