2 * Copyright © 2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * \file test_optpass.cpp
27 * Standalone test for optimization passes.
29 * This file provides the "optpass" command for the standalone
30 * glsl_test app. It accepts either GLSL or high-level IR as input,
31 * and performs the optimiation passes specified on the command line.
32 * It outputs the IR, both before and after optimiations.
41 #include "ir_optimization.h"
43 #include "ir_reader.h"
44 #include "standalone_scaffolding.h"
48 static string
read_stdin_to_eof()
56 do_optimization(struct exec_list
*ir
, const char *optimization
,
57 const struct gl_shader_compiler_options
*options
)
65 if (sscanf(optimization
, "do_common_optimization ( %d ) ", &int_0
) == 1) {
66 return do_common_optimization(ir
, int_0
!= 0, false, options
, true);
67 } else if (strcmp(optimization
, "do_algebraic") == 0) {
68 return do_algebraic(ir
, true, options
);
69 } else if (strcmp(optimization
, "do_constant_folding") == 0) {
70 return do_constant_folding(ir
);
71 } else if (strcmp(optimization
, "do_constant_variable") == 0) {
72 return do_constant_variable(ir
);
73 } else if (strcmp(optimization
, "do_constant_variable_unlinked") == 0) {
74 return do_constant_variable_unlinked(ir
);
75 } else if (strcmp(optimization
, "do_copy_propagation") == 0) {
76 return do_copy_propagation(ir
);
77 } else if (strcmp(optimization
, "do_copy_propagation_elements") == 0) {
78 return do_copy_propagation_elements(ir
);
79 } else if (strcmp(optimization
, "do_constant_propagation") == 0) {
80 return do_constant_propagation(ir
);
81 } else if (strcmp(optimization
, "do_dead_code") == 0) {
82 return do_dead_code(ir
, false);
83 } else if (strcmp(optimization
, "do_dead_code_local") == 0) {
84 return do_dead_code_local(ir
);
85 } else if (strcmp(optimization
, "do_dead_code_unlinked") == 0) {
86 return do_dead_code_unlinked(ir
);
87 } else if (strcmp(optimization
, "do_dead_functions") == 0) {
88 return do_dead_functions(ir
);
89 } else if (strcmp(optimization
, "do_function_inlining") == 0) {
90 return do_function_inlining(ir
);
91 } else if (sscanf(optimization
,
92 "do_lower_jumps ( %d , %d , %d , %d , %d ) ",
93 &int_0
, &int_1
, &int_2
, &int_3
, &int_4
) == 5) {
94 return do_lower_jumps(ir
, int_0
!= 0, int_1
!= 0, int_2
!= 0,
95 int_3
!= 0, int_4
!= 0);
96 } else if (strcmp(optimization
, "do_lower_texture_projection") == 0) {
97 return do_lower_texture_projection(ir
);
98 } else if (strcmp(optimization
, "do_if_simplification") == 0) {
99 return do_if_simplification(ir
);
100 } else if (sscanf(optimization
, "lower_if_to_cond_assign ( %d ) ",
102 return lower_if_to_cond_assign(ir
, int_0
);
103 } else if (strcmp(optimization
, "do_mat_op_to_vec") == 0) {
104 return do_mat_op_to_vec(ir
);
105 } else if (strcmp(optimization
, "do_noop_swizzle") == 0) {
106 return do_noop_swizzle(ir
);
107 } else if (strcmp(optimization
, "do_structure_splitting") == 0) {
108 return do_structure_splitting(ir
);
109 } else if (strcmp(optimization
, "do_swizzle_swizzle") == 0) {
110 return do_swizzle_swizzle(ir
);
111 } else if (strcmp(optimization
, "do_tree_grafting") == 0) {
112 return do_tree_grafting(ir
);
113 } else if (strcmp(optimization
, "do_vec_index_to_cond_assign") == 0) {
114 return do_vec_index_to_cond_assign(ir
);
115 } else if (strcmp(optimization
, "do_vec_index_to_swizzle") == 0) {
116 return do_vec_index_to_swizzle(ir
);
117 } else if (strcmp(optimization
, "lower_discard") == 0) {
118 return lower_discard(ir
);
119 } else if (sscanf(optimization
, "lower_instructions ( %d ) ",
121 return lower_instructions(ir
, int_0
);
122 } else if (strcmp(optimization
, "lower_noise") == 0) {
123 return lower_noise(ir
);
124 } else if (sscanf(optimization
, "lower_variable_index_to_cond_assign "
125 "( %d , %d , %d , %d ) ", &int_0
, &int_1
, &int_2
,
127 return lower_variable_index_to_cond_assign(ir
, int_0
!= 0, int_1
!= 0,
128 int_2
!= 0, int_3
!= 0);
129 } else if (sscanf(optimization
, "lower_quadop_vector ( %d ) ",
131 return lower_quadop_vector(ir
, int_0
!= 0);
132 } else if (strcmp(optimization
, "optimize_redundant_jumps") == 0) {
133 return optimize_redundant_jumps(ir
);
135 printf("Unrecognized optimization %s\n", optimization
);
142 do_optimization_passes(struct exec_list
*ir
, char **optimizations
,
143 int num_optimizations
, bool quiet
,
144 const struct gl_shader_compiler_options
*options
)
146 GLboolean overall_progress
= false;
148 for (int i
= 0; i
< num_optimizations
; ++i
) {
149 const char *optimization
= optimizations
[i
];
151 printf("*** Running optimization %s...", optimization
);
153 GLboolean progress
= do_optimization(ir
, optimization
, options
);
155 printf("%s\n", progress
? "progress" : "no progress");
157 validate_ir_tree(ir
);
159 overall_progress
= overall_progress
|| progress
;
162 return overall_progress
;
165 int test_optpass(int argc
, char **argv
)
167 int input_format_ir
= 0; /* 0=glsl, 1=ir */
169 int shader_type
= GL_VERTEX_SHADER
;
172 const struct option optpass_opts
[] = {
173 { "input-ir", no_argument
, &input_format_ir
, 1 },
174 { "input-glsl", no_argument
, &input_format_ir
, 0 },
175 { "loop", no_argument
, &loop
, 1 },
176 { "vertex-shader", no_argument
, &shader_type
, GL_VERTEX_SHADER
},
177 { "fragment-shader", no_argument
, &shader_type
, GL_FRAGMENT_SHADER
},
178 { "quiet", no_argument
, &quiet
, 1 },
184 while ((c
= getopt_long(argc
, argv
, "", optpass_opts
, &idx
)) != -1) {
186 printf("*** usage: %s optpass <optimizations> <options>\n", argv
[0]);
188 printf("Possible options are:\n");
189 printf(" --input-ir: input format is IR\n");
190 printf(" --input-glsl: input format is GLSL (the default)\n");
191 printf(" --loop: run optimizations repeatedly until no progress\n");
192 printf(" --vertex-shader: test with a vertex shader (the default)\n");
193 printf(" --fragment-shader: test with a fragment shader\n");
198 struct gl_context local_ctx
;
199 struct gl_context
*ctx
= &local_ctx
;
200 initialize_context_to_defaults(ctx
, API_OPENGL_COMPAT
);
202 ctx
->Driver
.NewShader
= _mesa_new_shader
;
203 ir_variable::temporaries_allocate_names
= true;
205 struct gl_shader
*shader
= rzalloc(NULL
, struct gl_shader
);
206 shader
->Type
= shader_type
;
207 shader
->Stage
= _mesa_shader_enum_to_shader_stage(shader_type
);
209 string input
= read_stdin_to_eof();
211 struct _mesa_glsl_parse_state
*state
212 = new(shader
) _mesa_glsl_parse_state(ctx
, shader
->Stage
, shader
);
214 if (input_format_ir
) {
215 shader
->ir
= new(shader
) exec_list
;
216 _mesa_glsl_initialize_types(state
);
217 _mesa_glsl_read_ir(state
, shader
->ir
, input
.c_str(), true);
219 shader
->Source
= input
.c_str();
220 const char *source
= shader
->Source
;
221 state
->error
= glcpp_preprocess(state
, &source
, &state
->info_log
,
222 state
->extensions
, ctx
) != 0;
225 _mesa_glsl_lexer_ctor(state
, source
);
226 _mesa_glsl_parse(state
);
227 _mesa_glsl_lexer_dtor(state
);
230 shader
->ir
= new(shader
) exec_list
;
231 if (!state
->error
&& !state
->translation_unit
.is_empty())
232 _mesa_ast_to_hir(shader
->ir
, state
);
235 /* Print out the initial IR */
236 if (!state
->error
&& !quiet
) {
237 printf("*** pre-optimization IR:\n");
238 _mesa_print_ir(stdout
, shader
->ir
, state
);
242 /* Optimization passes */
245 const struct gl_shader_compiler_options
*options
=
246 &ctx
->Const
.ShaderCompilerOptions
[_mesa_shader_enum_to_shader_stage(shader_type
)];
248 progress
= do_optimization_passes(shader
->ir
, &argv
[optind
],
249 argc
- optind
, quiet
!= 0, options
);
250 } while (loop
&& progress
);
253 /* Print out the resulting IR */
256 printf("*** resulting IR:\n");
258 _mesa_print_ir(stdout
, shader
->ir
, state
);
265 printf("*** error(s) occurred:\n");
266 printf("%s\n", state
->info_log
);