1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2011 Intel Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker /**
25*61046927SAndroid Build Coastguard Worker * \file test_optpass.cpp
26*61046927SAndroid Build Coastguard Worker *
27*61046927SAndroid Build Coastguard Worker * Standalone test for optimization passes.
28*61046927SAndroid Build Coastguard Worker *
29*61046927SAndroid Build Coastguard Worker * This file provides the "optpass" command for the standalone
30*61046927SAndroid Build Coastguard Worker * glsl_test app. It accepts either GLSL or high-level IR as input,
31*61046927SAndroid Build Coastguard Worker * and performs the optimiation passes specified on the command line.
32*61046927SAndroid Build Coastguard Worker * It outputs the IR, both before and after optimiations.
33*61046927SAndroid Build Coastguard Worker */
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker #include <string>
36*61046927SAndroid Build Coastguard Worker #include <iostream>
37*61046927SAndroid Build Coastguard Worker #include <sstream>
38*61046927SAndroid Build Coastguard Worker #include <getopt.h>
39*61046927SAndroid Build Coastguard Worker
40*61046927SAndroid Build Coastguard Worker #include "ast.h"
41*61046927SAndroid Build Coastguard Worker #include "ir_optimization.h"
42*61046927SAndroid Build Coastguard Worker #include "program.h"
43*61046927SAndroid Build Coastguard Worker #include "ir_reader.h"
44*61046927SAndroid Build Coastguard Worker #include "standalone_scaffolding.h"
45*61046927SAndroid Build Coastguard Worker #include "main/mtypes.h"
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker using namespace std;
48*61046927SAndroid Build Coastguard Worker
read_stdin_to_eof()49*61046927SAndroid Build Coastguard Worker static string read_stdin_to_eof()
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker stringbuf sb;
52*61046927SAndroid Build Coastguard Worker cin.get(sb, '\0');
53*61046927SAndroid Build Coastguard Worker return sb.str();
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker
56*61046927SAndroid Build Coastguard Worker static GLboolean
do_optimization(struct exec_list * ir,const char * optimization,const struct gl_shader_compiler_options * options)57*61046927SAndroid Build Coastguard Worker do_optimization(struct exec_list *ir, const char *optimization,
58*61046927SAndroid Build Coastguard Worker const struct gl_shader_compiler_options *options)
59*61046927SAndroid Build Coastguard Worker {
60*61046927SAndroid Build Coastguard Worker int int_0;
61*61046927SAndroid Build Coastguard Worker int int_1;
62*61046927SAndroid Build Coastguard Worker int int_2;
63*61046927SAndroid Build Coastguard Worker int int_3;
64*61046927SAndroid Build Coastguard Worker
65*61046927SAndroid Build Coastguard Worker if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) {
66*61046927SAndroid Build Coastguard Worker return do_common_optimization(ir, int_0 != 0, options, true);
67*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_algebraic") == 0) {
68*61046927SAndroid Build Coastguard Worker return do_algebraic(ir, true, options);
69*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_dead_code") == 0) {
70*61046927SAndroid Build Coastguard Worker return do_dead_code(ir);
71*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_dead_code_local") == 0) {
72*61046927SAndroid Build Coastguard Worker return do_dead_code_local(ir);
73*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
74*61046927SAndroid Build Coastguard Worker return do_dead_code_unlinked(ir);
75*61046927SAndroid Build Coastguard Worker } else if (sscanf(optimization,
76*61046927SAndroid Build Coastguard Worker "do_lower_jumps ( %d , %d , %d , %d ) ",
77*61046927SAndroid Build Coastguard Worker &int_0, &int_1, &int_2, &int_3) == 4) {
78*61046927SAndroid Build Coastguard Worker return do_lower_jumps(ir, int_0 != 0, int_1 != 0, int_2 != 0,
79*61046927SAndroid Build Coastguard Worker int_3 != 0);
80*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_if_simplification") == 0) {
81*61046927SAndroid Build Coastguard Worker return do_if_simplification(ir);
82*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
83*61046927SAndroid Build Coastguard Worker return do_mat_op_to_vec(ir);
84*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_tree_grafting") == 0) {
85*61046927SAndroid Build Coastguard Worker return do_tree_grafting(ir);
86*61046927SAndroid Build Coastguard Worker } else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
87*61046927SAndroid Build Coastguard Worker return do_vec_index_to_cond_assign(ir);
88*61046927SAndroid Build Coastguard Worker } else if (sscanf(optimization, "lower_instructions ( %d ) ",
89*61046927SAndroid Build Coastguard Worker &int_0) == 1) {
90*61046927SAndroid Build Coastguard Worker return lower_instructions(ir, false);
91*61046927SAndroid Build Coastguard Worker } else {
92*61046927SAndroid Build Coastguard Worker printf("Unrecognized optimization %s\n", optimization);
93*61046927SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
94*61046927SAndroid Build Coastguard Worker return false;
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker static GLboolean
do_optimization_passes(struct exec_list * ir,char ** optimizations,int num_optimizations,bool quiet,const struct gl_shader_compiler_options * options)99*61046927SAndroid Build Coastguard Worker do_optimization_passes(struct exec_list *ir, char **optimizations,
100*61046927SAndroid Build Coastguard Worker int num_optimizations, bool quiet,
101*61046927SAndroid Build Coastguard Worker const struct gl_shader_compiler_options *options)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker GLboolean overall_progress = false;
104*61046927SAndroid Build Coastguard Worker
105*61046927SAndroid Build Coastguard Worker for (int i = 0; i < num_optimizations; ++i) {
106*61046927SAndroid Build Coastguard Worker const char *optimization = optimizations[i];
107*61046927SAndroid Build Coastguard Worker if (!quiet) {
108*61046927SAndroid Build Coastguard Worker printf("*** Running optimization %s...", optimization);
109*61046927SAndroid Build Coastguard Worker }
110*61046927SAndroid Build Coastguard Worker GLboolean progress = do_optimization(ir, optimization, options);
111*61046927SAndroid Build Coastguard Worker if (!quiet) {
112*61046927SAndroid Build Coastguard Worker printf("%s\n", progress ? "progress" : "no progress");
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker validate_ir_tree(ir);
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker overall_progress = overall_progress || progress;
117*61046927SAndroid Build Coastguard Worker }
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker return overall_progress;
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker
test_optpass(int argc,char ** argv)122*61046927SAndroid Build Coastguard Worker int test_optpass(int argc, char **argv)
123*61046927SAndroid Build Coastguard Worker {
124*61046927SAndroid Build Coastguard Worker int input_format_ir = 0; /* 0=glsl, 1=ir */
125*61046927SAndroid Build Coastguard Worker int loop = 0;
126*61046927SAndroid Build Coastguard Worker int shader_type = GL_VERTEX_SHADER;
127*61046927SAndroid Build Coastguard Worker int quiet = 0;
128*61046927SAndroid Build Coastguard Worker int error;
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker const struct option optpass_opts[] = {
131*61046927SAndroid Build Coastguard Worker { "input-ir", no_argument, &input_format_ir, 1 },
132*61046927SAndroid Build Coastguard Worker { "input-glsl", no_argument, &input_format_ir, 0 },
133*61046927SAndroid Build Coastguard Worker { "loop", no_argument, &loop, 1 },
134*61046927SAndroid Build Coastguard Worker { "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
135*61046927SAndroid Build Coastguard Worker { "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
136*61046927SAndroid Build Coastguard Worker { "quiet", no_argument, &quiet, 1 },
137*61046927SAndroid Build Coastguard Worker { NULL, 0, NULL, 0 }
138*61046927SAndroid Build Coastguard Worker };
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker int idx = 0;
141*61046927SAndroid Build Coastguard Worker int c;
142*61046927SAndroid Build Coastguard Worker while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
143*61046927SAndroid Build Coastguard Worker if (c != 0) {
144*61046927SAndroid Build Coastguard Worker printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
145*61046927SAndroid Build Coastguard Worker printf("\n");
146*61046927SAndroid Build Coastguard Worker printf("Possible options are:\n");
147*61046927SAndroid Build Coastguard Worker printf(" --input-ir: input format is IR\n");
148*61046927SAndroid Build Coastguard Worker printf(" --input-glsl: input format is GLSL (the default)\n");
149*61046927SAndroid Build Coastguard Worker printf(" --loop: run optimizations repeatedly until no progress\n");
150*61046927SAndroid Build Coastguard Worker printf(" --vertex-shader: test with a vertex shader (the default)\n");
151*61046927SAndroid Build Coastguard Worker printf(" --fragment-shader: test with a fragment shader\n");
152*61046927SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker }
155*61046927SAndroid Build Coastguard Worker
156*61046927SAndroid Build Coastguard Worker glsl_type_singleton_init_or_ref();
157*61046927SAndroid Build Coastguard Worker
158*61046927SAndroid Build Coastguard Worker struct gl_context local_ctx;
159*61046927SAndroid Build Coastguard Worker struct gl_context *ctx = &local_ctx;
160*61046927SAndroid Build Coastguard Worker initialize_context_to_defaults(ctx, API_OPENGL_COMPAT);
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker ir_variable::temporaries_allocate_names = true;
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
165*61046927SAndroid Build Coastguard Worker shader->Type = shader_type;
166*61046927SAndroid Build Coastguard Worker shader->Stage = _mesa_shader_enum_to_shader_stage(shader_type);
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker string input = read_stdin_to_eof();
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state
171*61046927SAndroid Build Coastguard Worker = new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
172*61046927SAndroid Build Coastguard Worker
173*61046927SAndroid Build Coastguard Worker if (input_format_ir) {
174*61046927SAndroid Build Coastguard Worker shader->ir = new(shader) exec_list;
175*61046927SAndroid Build Coastguard Worker _mesa_glsl_initialize_types(state);
176*61046927SAndroid Build Coastguard Worker _mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
177*61046927SAndroid Build Coastguard Worker } else {
178*61046927SAndroid Build Coastguard Worker shader->Source = input.c_str();
179*61046927SAndroid Build Coastguard Worker const char *source = shader->Source;
180*61046927SAndroid Build Coastguard Worker state->error = glcpp_preprocess(state, &source, &state->info_log,
181*61046927SAndroid Build Coastguard Worker NULL, NULL, ctx) != 0;
182*61046927SAndroid Build Coastguard Worker
183*61046927SAndroid Build Coastguard Worker if (!state->error) {
184*61046927SAndroid Build Coastguard Worker _mesa_glsl_lexer_ctor(state, source);
185*61046927SAndroid Build Coastguard Worker _mesa_glsl_parse(state);
186*61046927SAndroid Build Coastguard Worker _mesa_glsl_lexer_dtor(state);
187*61046927SAndroid Build Coastguard Worker }
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker shader->ir = new(shader) exec_list;
190*61046927SAndroid Build Coastguard Worker if (!state->error && !state->translation_unit.is_empty())
191*61046927SAndroid Build Coastguard Worker _mesa_ast_to_hir(shader->ir, state);
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker /* Print out the initial IR */
195*61046927SAndroid Build Coastguard Worker if (!state->error && !quiet) {
196*61046927SAndroid Build Coastguard Worker printf("*** pre-optimization IR:\n");
197*61046927SAndroid Build Coastguard Worker _mesa_print_ir(stdout, shader->ir, state);
198*61046927SAndroid Build Coastguard Worker printf("\n--\n");
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker /* Optimization passes */
202*61046927SAndroid Build Coastguard Worker if (!state->error) {
203*61046927SAndroid Build Coastguard Worker GLboolean progress;
204*61046927SAndroid Build Coastguard Worker const struct gl_shader_compiler_options *options =
205*61046927SAndroid Build Coastguard Worker &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader_type)];
206*61046927SAndroid Build Coastguard Worker do {
207*61046927SAndroid Build Coastguard Worker progress = do_optimization_passes(shader->ir, &argv[optind],
208*61046927SAndroid Build Coastguard Worker argc - optind, quiet != 0, options);
209*61046927SAndroid Build Coastguard Worker } while (loop && progress);
210*61046927SAndroid Build Coastguard Worker }
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker /* Print out the resulting IR */
213*61046927SAndroid Build Coastguard Worker if (!state->error) {
214*61046927SAndroid Build Coastguard Worker if (!quiet) {
215*61046927SAndroid Build Coastguard Worker printf("*** resulting IR:\n");
216*61046927SAndroid Build Coastguard Worker }
217*61046927SAndroid Build Coastguard Worker _mesa_print_ir(stdout, shader->ir, state);
218*61046927SAndroid Build Coastguard Worker if (!quiet) {
219*61046927SAndroid Build Coastguard Worker printf("\n--\n");
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker }
222*61046927SAndroid Build Coastguard Worker
223*61046927SAndroid Build Coastguard Worker if (state->error) {
224*61046927SAndroid Build Coastguard Worker printf("*** error(s) occurred:\n");
225*61046927SAndroid Build Coastguard Worker printf("%s\n", state->info_log);
226*61046927SAndroid Build Coastguard Worker printf("--\n");
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker error = state->error;
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker ralloc_free(state);
232*61046927SAndroid Build Coastguard Worker ralloc_free(shader);
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker glsl_type_singleton_decref();
235*61046927SAndroid Build Coastguard Worker
236*61046927SAndroid Build Coastguard Worker return error;
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker
239