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 15import placeholder 16import expect 17import re 18 19from spirv_test_framework import inside_spirv_testsuite 20 21 22def empty_main_assembly(): 23 return """ 24 OpCapability Shader 25 OpMemoryModel Logical GLSL450 26 OpEntryPoint Vertex %4 "main" 27 OpName %4 "main" 28 %2 = OpTypeVoid 29 %3 = OpTypeFunction %2 30 %4 = OpFunction %2 None %3 31 %5 = OpLabel 32 OpReturn 33 OpFunctionEnd""" 34 35 36@inside_spirv_testsuite('SpirvOptBase') 37class TestAssemblyFileAsOnlyParameter(expect.ValidObjectFile1_3): 38 """Tests that spirv-opt accepts a SPIR-V object file.""" 39 40 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 41 output = placeholder.TempFileName('output.spv') 42 spirv_args = [shader, '-o', output] 43 expected_object_filenames = (output) 44 45 46@inside_spirv_testsuite('SpirvOptFlags') 47class TestHelpFlag(expect.ReturnCodeIsZero, expect.StdoutMatch): 48 """Test the --help flag.""" 49 50 spirv_args = ['--help'] 51 expected_stdout = re.compile(r'.*The SPIR-V binary is read from <input>') 52 53 54@inside_spirv_testsuite('SpirvOptFlags') 55class TestValidPassFlags(expect.ValidObjectFile1_3, 56 expect.ExecutedListOfPasses): 57 """Tests that spirv-opt accepts all valid optimization flags.""" 58 59 flags = [ 60 '--ccp', '--cfg-cleanup', '--combine-access-chains', '--compact-ids', 61 '--convert-local-access-chains', '--copy-propagate-arrays', 62 '--eliminate-common-uniform', '--eliminate-dead-branches', 63 '--eliminate-dead-code-aggressive', '--eliminate-dead-const', 64 '--eliminate-dead-functions', '--eliminate-dead-inserts', 65 '--eliminate-dead-variables', '--eliminate-insert-extract', 66 '--eliminate-local-multi-store', '--eliminate-local-single-block', 67 '--eliminate-local-single-store', '--flatten-decorations', 68 '--fold-spec-const-op-composite', '--freeze-spec-const', 69 '--if-conversion', '--inline-entry-points-exhaustive', '--loop-fission', 70 '20', '--loop-fusion', '5', '--loop-unroll', '--loop-unroll-partial', '3', 71 '--loop-peeling', '--merge-blocks', '--merge-return', '--loop-unswitch', 72 '--private-to-local', '--reduce-load-size', '--redundancy-elimination', 73 '--remove-duplicates', '--replace-invalid-opcode', '--ssa-rewrite', 74 '--scalar-replacement', '--scalar-replacement=42', '--strength-reduction', 75 '--strip-debug', '--strip-reflect', '--vector-dce', '--workaround-1209', 76 '--unify-const' 77 ] 78 expected_passes = [ 79 'ccp', 80 'cfg-cleanup', 81 'combine-access-chains', 82 'compact-ids', 83 'convert-local-access-chains', 84 'copy-propagate-arrays', 85 'eliminate-common-uniform', 86 'eliminate-dead-branches', 87 'eliminate-dead-code-aggressive', 88 'eliminate-dead-const', 89 'eliminate-dead-functions', 90 'eliminate-dead-inserts', 91 'eliminate-dead-variables', 92 # --eliminate-insert-extract runs the simplify-instructions pass. 93 'simplify-instructions', 94 'eliminate-local-multi-store', 95 'eliminate-local-single-block', 96 'eliminate-local-single-store', 97 'flatten-decorations', 98 'fold-spec-const-op-composite', 99 'freeze-spec-const', 100 'if-conversion', 101 'inline-entry-points-exhaustive', 102 'loop-fission', 103 'loop-fusion', 104 'loop-unroll', 105 'loop-unroll', 106 'loop-peeling', 107 'merge-blocks', 108 'merge-return', 109 'loop-unswitch', 110 'private-to-local', 111 'reduce-load-size', 112 'redundancy-elimination', 113 'remove-duplicates', 114 'replace-invalid-opcode', 115 'ssa-rewrite', 116 'scalar-replacement=100', 117 'scalar-replacement=42', 118 'strength-reduction', 119 'strip-debug', 120 'strip-reflect', 121 'vector-dce', 122 'workaround-1209', 123 'unify-const' 124 ] 125 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 126 output = placeholder.TempFileName('output.spv') 127 spirv_args = [shader, '-o', output, '--print-all'] + flags 128 expected_object_filenames = (output) 129 130 131@inside_spirv_testsuite('SpirvOptFlags') 132class TestPerformanceOptimizationPasses(expect.ValidObjectFile1_3, 133 expect.ExecutedListOfPasses): 134 """Tests that spirv-opt schedules all the passes triggered by -O.""" 135 136 flags = ['-O'] 137 expected_passes = [ 138 'eliminate-dead-branches', 139 'merge-return', 140 'inline-entry-points-exhaustive', 141 'eliminate-dead-code-aggressive', 142 'private-to-local', 143 'eliminate-local-single-block', 144 'eliminate-local-single-store', 145 'eliminate-dead-code-aggressive', 146 'scalar-replacement=100', 147 'convert-local-access-chains', 148 'eliminate-local-single-block', 149 'eliminate-local-single-store', 150 'eliminate-dead-code-aggressive', 151 'eliminate-local-multi-store', 152 'eliminate-dead-code-aggressive', 153 'ccp', 154 'eliminate-dead-code-aggressive', 155 'redundancy-elimination', 156 'combine-access-chains', 157 'simplify-instructions', 158 'vector-dce', 159 'eliminate-dead-inserts', 160 'eliminate-dead-branches', 161 'simplify-instructions', 162 'if-conversion', 163 'copy-propagate-arrays', 164 'reduce-load-size', 165 'eliminate-dead-code-aggressive', 166 'merge-blocks', 167 'redundancy-elimination', 168 'eliminate-dead-branches', 169 'merge-blocks', 170 'simplify-instructions', 171 ] 172 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 173 output = placeholder.TempFileName('output.spv') 174 spirv_args = [shader, '-o', output, '--print-all'] + flags 175 expected_object_filenames = (output) 176 177 178@inside_spirv_testsuite('SpirvOptFlags') 179class TestSizeOptimizationPasses(expect.ValidObjectFile1_3, 180 expect.ExecutedListOfPasses): 181 """Tests that spirv-opt schedules all the passes triggered by -Os.""" 182 183 flags = ['-Os'] 184 expected_passes = [ 185 'eliminate-dead-branches', 186 'merge-return', 187 'inline-entry-points-exhaustive', 188 'eliminate-dead-code-aggressive', 189 'private-to-local', 190 'scalar-replacement=100', 191 'convert-local-access-chains', 192 'eliminate-local-single-block', 193 'eliminate-local-single-store', 194 'eliminate-dead-code-aggressive', 195 'simplify-instructions', 196 'eliminate-dead-inserts', 197 'eliminate-local-multi-store', 198 'eliminate-dead-code-aggressive', 199 'ccp', 200 'eliminate-dead-code-aggressive', 201 'eliminate-dead-branches', 202 'if-conversion', 203 'eliminate-dead-code-aggressive', 204 'merge-blocks', 205 'simplify-instructions', 206 'eliminate-dead-inserts', 207 'redundancy-elimination', 208 'cfg-cleanup', 209 'eliminate-dead-code-aggressive', 210 ] 211 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 212 output = placeholder.TempFileName('output.spv') 213 spirv_args = [shader, '-o', output, '--print-all'] + flags 214 expected_object_filenames = (output) 215 216 217@inside_spirv_testsuite('SpirvOptFlags') 218class TestLegalizationPasses(expect.ValidObjectFile1_3, 219 expect.ExecutedListOfPasses): 220 """Tests that spirv-opt schedules all the passes triggered by --legalize-hlsl. 221 """ 222 223 flags = ['--legalize-hlsl'] 224 expected_passes = [ 225 'eliminate-dead-branches', 226 'merge-return', 227 'inline-entry-points-exhaustive', 228 'eliminate-dead-functions', 229 'private-to-local', 230 'eliminate-local-single-block', 231 'eliminate-local-single-store', 232 'eliminate-dead-code-aggressive', 233 'scalar-replacement=0', 234 'eliminate-local-single-block', 235 'eliminate-local-single-store', 236 'eliminate-dead-code-aggressive', 237 'eliminate-local-multi-store', 238 'eliminate-dead-code-aggressive', 239 'ccp', 240 'loop-unroll', 241 'eliminate-dead-branches', 242 'simplify-instructions', 243 'eliminate-dead-code-aggressive', 244 'copy-propagate-arrays', 245 'vector-dce', 246 'eliminate-dead-inserts', 247 'reduce-load-size', 248 'eliminate-dead-code-aggressive', 249 ] 250 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 251 output = placeholder.TempFileName('output.spv') 252 spirv_args = [shader, '-o', output, '--print-all'] + flags 253 expected_object_filenames = (output) 254 255 256@inside_spirv_testsuite('SpirvOptFlags') 257class TestScalarReplacementArgsNegative(expect.ErrorMessageSubstr): 258 """Tests invalid arguments to --scalar-replacement.""" 259 260 spirv_args = ['--scalar-replacement=-10'] 261 expected_error_substr = 'must have no arguments or a non-negative integer argument' 262 263 264@inside_spirv_testsuite('SpirvOptFlags') 265class TestScalarReplacementArgsInvalidNumber(expect.ErrorMessageSubstr): 266 """Tests invalid arguments to --scalar-replacement.""" 267 268 spirv_args = ['--scalar-replacement=a10f'] 269 expected_error_substr = 'must have no arguments or a non-negative integer argument' 270 271 272@inside_spirv_testsuite('SpirvOptFlags') 273class TestLoopFissionArgsNegative(expect.ErrorMessageSubstr): 274 """Tests invalid arguments to --loop-fission.""" 275 276 spirv_args = ['--loop-fission=-10'] 277 expected_error_substr = 'must have a positive integer argument' 278 279 280@inside_spirv_testsuite('SpirvOptFlags') 281class TestLoopFissionArgsInvalidNumber(expect.ErrorMessageSubstr): 282 """Tests invalid arguments to --loop-fission.""" 283 284 spirv_args = ['--loop-fission=a10f'] 285 expected_error_substr = 'must have a positive integer argument' 286 287 288@inside_spirv_testsuite('SpirvOptFlags') 289class TestLoopFusionArgsNegative(expect.ErrorMessageSubstr): 290 """Tests invalid arguments to --loop-fusion.""" 291 292 spirv_args = ['--loop-fusion=-10'] 293 expected_error_substr = 'must have a positive integer argument' 294 295 296@inside_spirv_testsuite('SpirvOptFlags') 297class TestLoopFusionArgsInvalidNumber(expect.ErrorMessageSubstr): 298 """Tests invalid arguments to --loop-fusion.""" 299 300 spirv_args = ['--loop-fusion=a10f'] 301 expected_error_substr = 'must have a positive integer argument' 302 303 304@inside_spirv_testsuite('SpirvOptFlags') 305class TestLoopUnrollPartialArgsNegative(expect.ErrorMessageSubstr): 306 """Tests invalid arguments to --loop-unroll-partial.""" 307 308 spirv_args = ['--loop-unroll-partial=-10'] 309 expected_error_substr = 'must have a positive integer argument' 310 311 312@inside_spirv_testsuite('SpirvOptFlags') 313class TestLoopUnrollPartialArgsInvalidNumber(expect.ErrorMessageSubstr): 314 """Tests invalid arguments to --loop-unroll-partial.""" 315 316 spirv_args = ['--loop-unroll-partial=a10f'] 317 expected_error_substr = 'must have a positive integer argument' 318 319 320@inside_spirv_testsuite('SpirvOptFlags') 321class TestLoopPeelingThresholdArgsNegative(expect.ErrorMessageSubstr): 322 """Tests invalid arguments to --loop-peeling-threshold.""" 323 324 spirv_args = ['--loop-peeling-threshold=-10'] 325 expected_error_substr = 'must have a positive integer argument' 326 327 328@inside_spirv_testsuite('SpirvOptFlags') 329class TestLoopPeelingThresholdArgsInvalidNumber(expect.ErrorMessageSubstr): 330 """Tests invalid arguments to --loop-peeling-threshold.""" 331 332 spirv_args = ['--loop-peeling-threshold=a10f'] 333 expected_error_substr = 'must have a positive integer argument' 334