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