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_6): 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_6, 56 expect.ExecutedListOfPasses): 57 """Tests that spirv-opt accepts all valid optimization flags.""" 58 59 flags = [ 60 '--wrap-opkill', '--ccp', '--cfg-cleanup', '--combine-access-chains', '--compact-ids', 61 '--convert-local-access-chains', '--copy-propagate-arrays', 62 '--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-nonsemantic', '--vector-dce', '--workaround-1209', 76 '--unify-const', '--graphics-robust-access', '--wrap-opkill', '--amd-ext-to-khr' 77 ] 78 expected_passes = [ 79 'wrap-opkill', 80 'ccp', 81 'cfg-cleanup', 82 'combine-access-chains', 83 'compact-ids', 84 'convert-local-access-chains', 85 'copy-propagate-arrays', 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 'ssa-rewrite', 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-nonsemantic', 121 'vector-dce', 122 'workaround-1209', 123 'unify-const', 124 'graphics-robust-access', 125 'wrap-opkill', 126 'amd-ext-to-khr' 127 ] 128 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 129 output = placeholder.TempFileName('output.spv') 130 spirv_args = [shader, '-o', output, '--print-all'] + flags 131 expected_object_filenames = (output) 132 133 134@inside_spirv_testsuite('SpirvOptFlags') 135class TestPerformanceOptimizationPasses(expect.ValidObjectFile1_6, 136 expect.ExecutedListOfPasses): 137 """Tests that spirv-opt schedules all the passes triggered by -O.""" 138 139 flags = ['-O'] 140 expected_passes = [ 141 'wrap-opkill', 142 'eliminate-dead-branches', 143 'merge-return', 144 'inline-entry-points-exhaustive', 145 'eliminate-dead-functions', 146 'eliminate-dead-code-aggressive', 147 'private-to-local', 148 'eliminate-local-single-block', 149 'eliminate-local-single-store', 150 'eliminate-dead-code-aggressive', 151 'scalar-replacement=100', 152 'convert-local-access-chains', 153 'eliminate-local-single-block', 154 'eliminate-local-single-store', 155 'eliminate-dead-code-aggressive', 156 'ssa-rewrite', 157 'eliminate-dead-code-aggressive', 158 'ccp', 159 'eliminate-dead-code-aggressive', 160 'loop-unroll', 161 'eliminate-dead-branches', 162 'redundancy-elimination', 163 'combine-access-chains', 164 'simplify-instructions', 165 'scalar-replacement=100', 166 'convert-local-access-chains', 167 'eliminate-local-single-block', 168 'eliminate-local-single-store', 169 'eliminate-dead-code-aggressive', 170 'ssa-rewrite', 171 'eliminate-dead-code-aggressive', 172 'vector-dce', 173 'eliminate-dead-inserts', 174 'eliminate-dead-branches', 175 'simplify-instructions', 176 'if-conversion', 177 'copy-propagate-arrays', 178 'reduce-load-size', 179 'eliminate-dead-code-aggressive', 180 'merge-blocks', 181 'redundancy-elimination', 182 'eliminate-dead-branches', 183 'merge-blocks', 184 'simplify-instructions', 185 ] 186 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 187 output = placeholder.TempFileName('output.spv') 188 spirv_args = [shader, '-o', output, '--print-all'] + flags 189 expected_object_filenames = (output) 190 191 192@inside_spirv_testsuite('SpirvOptFlags') 193class TestSizeOptimizationPasses(expect.ValidObjectFile1_6, 194 expect.ExecutedListOfPasses): 195 """Tests that spirv-opt schedules all the passes triggered by -Os.""" 196 197 flags = ['-Os'] 198 expected_passes = [ 199 'wrap-opkill', 200 'eliminate-dead-branches', 201 'merge-return', 202 'inline-entry-points-exhaustive', 203 'eliminate-dead-functions', 204 'private-to-local', 205 'scalar-replacement=0', 206 'ssa-rewrite', 207 'ccp', 208 'loop-unroll', 209 'eliminate-dead-branches', 210 'simplify-instructions', 211 'scalar-replacement=0', 212 'eliminate-local-single-store', 213 'if-conversion', 214 'simplify-instructions', 215 'eliminate-dead-code-aggressive', 216 'eliminate-dead-branches', 217 'merge-blocks', 218 'convert-local-access-chains', 219 'eliminate-local-single-block', 220 'eliminate-dead-code-aggressive', 221 'copy-propagate-arrays', 222 'vector-dce', 223 'eliminate-dead-inserts', 224 'eliminate-dead-members', 225 'eliminate-local-single-store', 226 'merge-blocks', 227 'ssa-rewrite', 228 'redundancy-elimination', 229 'simplify-instructions', 230 'eliminate-dead-code-aggressive', 231 'cfg-cleanup', 232 ] 233 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 234 output = placeholder.TempFileName('output.spv') 235 spirv_args = [shader, '-o', output, '--print-all'] + flags 236 expected_object_filenames = (output) 237 238 239@inside_spirv_testsuite('SpirvOptFlags') 240class TestLegalizationPasses(expect.ValidObjectFile1_6, 241 expect.ExecutedListOfPasses): 242 """Tests that spirv-opt schedules all the passes triggered by --legalize-hlsl. 243 """ 244 245 flags = ['--legalize-hlsl'] 246 expected_passes = [ 247 'wrap-opkill', 248 'eliminate-dead-branches', 249 'merge-return', 250 'inline-entry-points-exhaustive', 251 'eliminate-dead-functions', 252 'private-to-local', 253 'fix-storage-class', 254 'eliminate-local-single-block', 255 'eliminate-local-single-store', 256 'eliminate-dead-code-aggressive', 257 'scalar-replacement=0', 258 'eliminate-local-single-block', 259 'eliminate-local-single-store', 260 'eliminate-dead-code-aggressive', 261 'ssa-rewrite', 262 'eliminate-dead-code-aggressive', 263 'ccp', 264 'loop-unroll', 265 'eliminate-dead-branches', 266 'simplify-instructions', 267 'eliminate-dead-code-aggressive', 268 'copy-propagate-arrays', 269 'vector-dce', 270 'eliminate-dead-inserts', 271 'reduce-load-size', 272 'eliminate-dead-code-aggressive', 273 ] 274 shader = placeholder.FileSPIRVShader(empty_main_assembly(), '.spvasm') 275 output = placeholder.TempFileName('output.spv') 276 spirv_args = [shader, '-o', output, '--print-all'] + flags 277 expected_object_filenames = (output) 278 279 280@inside_spirv_testsuite('SpirvOptFlags') 281class TestScalarReplacementArgsNegative(expect.ErrorMessageSubstr): 282 """Tests invalid arguments to --scalar-replacement.""" 283 284 spirv_args = ['--scalar-replacement=-10'] 285 expected_error_substr = 'must have no arguments or a non-negative integer argument' 286 287 288@inside_spirv_testsuite('SpirvOptFlags') 289class TestScalarReplacementArgsInvalidNumber(expect.ErrorMessageSubstr): 290 """Tests invalid arguments to --scalar-replacement.""" 291 292 spirv_args = ['--scalar-replacement=a10f'] 293 expected_error_substr = 'must have no arguments or a non-negative integer argument' 294 295 296@inside_spirv_testsuite('SpirvOptFlags') 297class TestLoopFissionArgsNegative(expect.ErrorMessageSubstr): 298 """Tests invalid arguments to --loop-fission.""" 299 300 spirv_args = ['--loop-fission=-10'] 301 expected_error_substr = 'must have a positive integer argument' 302 303 304@inside_spirv_testsuite('SpirvOptFlags') 305class TestLoopFissionArgsInvalidNumber(expect.ErrorMessageSubstr): 306 """Tests invalid arguments to --loop-fission.""" 307 308 spirv_args = ['--loop-fission=a10f'] 309 expected_error_substr = 'must have a positive integer argument' 310 311 312@inside_spirv_testsuite('SpirvOptFlags') 313class TestLoopFusionArgsNegative(expect.ErrorMessageSubstr): 314 """Tests invalid arguments to --loop-fusion.""" 315 316 spirv_args = ['--loop-fusion=-10'] 317 expected_error_substr = 'must have a positive integer argument' 318 319 320@inside_spirv_testsuite('SpirvOptFlags') 321class TestLoopFusionArgsInvalidNumber(expect.ErrorMessageSubstr): 322 """Tests invalid arguments to --loop-fusion.""" 323 324 spirv_args = ['--loop-fusion=a10f'] 325 expected_error_substr = 'must have a positive integer argument' 326 327 328@inside_spirv_testsuite('SpirvOptFlags') 329class TestLoopUnrollPartialArgsNegative(expect.ErrorMessageSubstr): 330 """Tests invalid arguments to --loop-unroll-partial.""" 331 332 spirv_args = ['--loop-unroll-partial=-10'] 333 expected_error_substr = 'must have a positive integer argument' 334 335 336@inside_spirv_testsuite('SpirvOptFlags') 337class TestLoopUnrollPartialArgsInvalidNumber(expect.ErrorMessageSubstr): 338 """Tests invalid arguments to --loop-unroll-partial.""" 339 340 spirv_args = ['--loop-unroll-partial=a10f'] 341 expected_error_substr = 'must have a positive integer argument' 342 343 344@inside_spirv_testsuite('SpirvOptFlags') 345class TestLoopPeelingThresholdArgsNegative(expect.ErrorMessageSubstr): 346 """Tests invalid arguments to --loop-peeling-threshold.""" 347 348 spirv_args = ['--loop-peeling-threshold=-10'] 349 expected_error_substr = 'must have a positive integer argument' 350 351 352@inside_spirv_testsuite('SpirvOptFlags') 353class TestLoopPeelingThresholdArgsInvalidNumber(expect.ErrorMessageSubstr): 354 """Tests invalid arguments to --loop-peeling-threshold.""" 355 356 spirv_args = ['--loop-peeling-threshold=a10f'] 357 expected_error_substr = 'must have a positive integer argument' 358