Home | History | Annotate | Download | only in opt
      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 import placeholder
     16 import expect
     17 import re
     18 
     19 from spirv_test_framework import inside_spirv_testsuite
     20 
     21 
     22 def 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')
     37 class 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')
     47 class 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')
     55 class 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')
    132 class 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')
    179 class 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')
    218 class 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')
    257 class 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')
    265 class 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')
    273 class 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')
    281 class 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')
    289 class 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')
    297 class 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')
    305 class 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')
    313 class 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')
    321 class 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')
    329 class 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