13
13
14
14
"""
15
15
Run a mlir file through imex-opt using a user provided pass pipeline
16
- and run resulting output through mlir-runner.
17
- The pass pipeline is provided either in a file or as a string; expected
16
+ and optionally(On by default and turned off by option --no-mlir-runner)
17
+ run resulting output through an mlir runner
18
+ (Default is mlir-cpu-runner and can be overridden by option --runner).
19
+ After that, optionally(Option --filecheck), output can be passed to FileCheck utility.
20
+ The pass pipeline for imex-opt is provided either in a file or as a string; expected
18
21
syntax is similar to mlir-opt's syntax.
19
22
20
23
If provided in a file passes can be separted by newline or ',' and
@@ -32,10 +35,14 @@ func.func(scf-bufferize,
32
35
Pass pipelines privded as strings will not be modified.
33
36
34
37
All unknown arguments will be forwarded to mlir-runner. Currently there is no
35
- option to forward user-provided args to imex-opt.
38
+ option to forward user-provided args directly to imex-opt.
39
+ Options --imex-print-before-all and --imex-print-after-all gets converted
40
+ into --mlir-print-ir-before-all, --mlir-print-ir-after-all and forwarded to
41
+ imex-opt to enable printing IR before and after running passes.
42
+ Option --check-prefix gets forwarded to FileCheck.
36
43
37
44
To use this in a lit test, you can do something similar to
38
- `// RUN: %python_executable %imex-runner -i %s --pass-pipeline-file=%p/ptensor.pp -e main -entry-point-result=void --shared-libs=%mlir_c_runner_utils --shared-libs= %mlir_runner_utils | FileCheck %s `
45
+ `// RUN: %python_executable %imex-runner -i %s --pass-pipeline-file=%p/ptensor.pp -e main -entry-point-result=void --shared-libs=%mlir_c_runner_utils, %mlir_runner_utils --filecheck `
39
46
"""
40
47
41
48
import os , sys , re
@@ -44,23 +51,52 @@ import argparse
44
51
import subprocess
45
52
46
53
imex_enable_vulkan_runner = @IMEX_ENABLE_VULKAN_RUNNER @
54
+ imex_enable_l0_runtime = @IMEX_ENABLE_L0_RUNTIME @
55
+ imex_enable_sycl_runtime = @IMEX_ENABLE_SYCL_RUNTIME @
56
+
47
57
runner_choices = ['mlir-cpu-runner' ]
58
+ enabled_features = []
59
+ all_features = ['vulkan-runner' , 'l0-runtime' , 'sycl-runtime' ]
48
60
if imex_enable_vulkan_runner :
49
- runner_choices += ['mlir-vulkan-runner' ]
61
+ runner_choices .append ('mlir-vulkan-runner' )
62
+ enabled_features .append ('vulkan-runner' )
63
+ if imex_enable_l0_runtime :
64
+ enabled_features .append ('l0-runtime' )
65
+ if imex_enable_sycl_runtime :
66
+ enabled_features .append ('sycl-runtime' )
67
+
68
+ class SplitArgs (argparse .Action ):
69
+ def __call__ (self , parser , namespace , values , option_string = None ):
70
+ setattr (namespace , self .dest , values .split (',' ))
50
71
51
72
parser = argparse .ArgumentParser (
52
- description = "run imex-opt and pipe into mlir- runner"
73
+ description = "Run imex-opt, optionally pipe result into selected mlir runner (default: mlir-cpu- runner) and then optionally pipe output into FileCheck "
53
74
)
54
75
parser .add_argument ("--input-file" , "-i" , default = None , help = "input MLIR file" )
55
76
parser .add_argument ("--pass-pipeline-file" , "-f" , default = None , help = "file defining pass pipeline" )
56
77
parser .add_argument ("--pass-pipeline" , "-p" , default = None , help = "pass pipeline (string)" )
57
78
parser .add_argument ("--imex-print-before-all" , "-b" , action = 'store_true' , dest = 'before' , help = "print ir before all passes" )
58
79
parser .add_argument ("--imex-print-after-all" , "-a" , action = 'store_true' , dest = 'after' , help = "print ir after all passes" )
59
80
parser .add_argument ("--no-mlir-runner" , "-n" , action = 'store_true' , dest = 'no_mlir_runner' , help = "skip mlir runner" )
81
+ parser .add_argument ("--filecheck" , action = 'store_true' , dest = 'run_filecheck' , help = "run FileCheck" )
82
+ parser .add_argument ("--check-prefix" , default = None , help = "change check prefix (default: CHECK) used by FileCheck" )
60
83
parser .add_argument ("--runner" , "-r" , default = "mlir-cpu-runner" , choices = runner_choices , help = "mlir runner name" )
84
+ parser .add_argument ('--requires' , default = enabled_features , action = SplitArgs , help = "skip if any of the required in the comma separated list is missing." )
61
85
62
86
args , unknown = parser .parse_known_args ()
63
87
88
+ # Check if requirements are valid
89
+ required_features = args .requires
90
+ if not set (required_features ) <= set (all_features ):
91
+ print ('Invalid option passed to --requires' )
92
+ print ('your options were: ' , * required_features )
93
+ print ('valid options are: ' , * all_features )
94
+ exit (1 )
95
+
96
+ # Skip runner if requirements are not met be enabled features
97
+ if not set (required_features ) <= set (enabled_features ):
98
+ exit (0 )
99
+
64
100
ppipeline = None
65
101
if args .pass_pipeline_file :
66
102
with open (args .pass_pipeline_file , 'r' ) as infile :
@@ -82,6 +118,36 @@ if args.pass_pipeline_file:
82
118
imex_binary_dir = '@IMEX_BINARY_DIR@'
83
119
llvm_binary_dir = '@LLVM_BINARY_DIR@'
84
120
121
+ def run_pipeline (cmds ):
122
+ """
123
+ Run commands in PIPE, return the last process in chain.
124
+ stdout of intermediate commands are sent to PIPE.
125
+ stdout of last command is not sent to PIPE.
126
+ """
127
+ first_cmd , * rest_cmds = cmds
128
+ if len (cmds ) == 1 :
129
+ procs = [subprocess .Popen (first_cmd )]
130
+ else :
131
+ procs = [subprocess .Popen (first_cmd , stdout = subprocess .PIPE )]
132
+ if len (cmds ) == 2 :
133
+ last_stdout = procs [- 1 ].stdout
134
+ cmd = rest_cmds [- 1 ]
135
+ proc = subprocess .Popen (cmd , stdin = last_stdout )
136
+ procs .append (proc )
137
+ else :
138
+ for cmd in rest_cmds [:- 1 ]:
139
+ last_stdout = procs [- 1 ].stdout
140
+ proc = subprocess .Popen (cmd , stdin = last_stdout , stdout = subprocess .PIPE )
141
+ procs .append (proc )
142
+ last_stdout = procs [- 1 ].stdout
143
+ cmd = rest_cmds [- 1 ]
144
+ proc = subprocess .Popen (cmd , stdin = last_stdout )
145
+ procs .append (proc )
146
+ return procs [- 1 ]
147
+
148
+ # All commands to create a pipeline
149
+ cmds = []
150
+
85
151
# build imex-opt command
86
152
cmd = [os .path .normpath (os .path .join (imex_binary_dir , 'bin' , 'imex-opt' ))]
87
153
if ppipeline :
@@ -94,14 +160,28 @@ if args.before:
94
160
cmd .append (f'--mlir-print-ir-before-all' )
95
161
if args .after :
96
162
cmd .append (f'--mlir-print-ir-after-all' )
97
- # run and feed into pipe
98
- if args .no_mlir_runner :
99
- subprocess .run (cmd )
100
- else :
101
- p1 = subprocess .Popen (cmd , stdout = subprocess .PIPE )
102
- # build mlir-opt command: all unknown args will be passed to imex-opt
163
+ cmds .append (cmd )
164
+
165
+ # build runner command
166
+ if not args .no_mlir_runner :
167
+ # build runner command: all unknown args will be passed to the runner
103
168
cmd = [os .path .normpath (os .path .join (llvm_binary_dir , 'bin' , args .runner ))] + unknown
104
- # get stdout from imex-opt and pipe into mlir-opt
105
- p2 = subprocess .Popen (cmd , stdin = p1 .stdout )
106
- p1 .wait ()
107
- p2 .wait ()
169
+ cmds .append (cmd )
170
+
171
+ # build FileCheck command
172
+ if args .run_filecheck :
173
+ cmd = [os .path .normpath (os .path .join (llvm_binary_dir , 'bin' , 'FileCheck' ))]
174
+ if args .check_prefix :
175
+ cmd .append (f'--check-prefix={ args .check_prefix } ' )
176
+ if not args .input_file :
177
+ print ('Error: --input-file is required for filecheck' )
178
+ exit (1 )
179
+ cmd .append (args .input_file )
180
+ cmds .append (cmd )
181
+
182
+ # Run command pipeline
183
+ last_proc = run_pipeline (cmds )
184
+
185
+ # Wait for last command completion and exit with returncode
186
+ last_proc .wait ()
187
+ exit (last_proc .returncode )
0 commit comments