mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-11 06:28:09 +02:00
glsl: drop last remaining lower jump test
This test only tests that a redundant continue is removed. This test is not very useful and there are hundreds of lines of supporting test infrastructure that can be removed if we drop it. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32364>
This commit is contained in:
parent
cf188a0efb
commit
722f939614
8 changed files with 0 additions and 903 deletions
|
|
@ -259,20 +259,6 @@ glsl_compiler = executable(
|
|||
install : with_tools.contains('glsl'),
|
||||
)
|
||||
|
||||
glsl_test = executable(
|
||||
'glsl_test',
|
||||
['test.cpp', 'test_optpass.cpp', 'test_optpass.h',
|
||||
ir_expression_operation_h],
|
||||
c_args : [c_msvc_compat_args, no_override_init_args],
|
||||
cpp_args : [cpp_msvc_compat_args],
|
||||
gnu_symbol_visibility : 'hidden',
|
||||
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
|
||||
dependencies : [dep_clock, dep_thread, idep_getopt, idep_mesautil, idep_compiler],
|
||||
link_with : [libglsl, libglsl_standalone, libglsl_util],
|
||||
build_by_default : with_tools.contains('glsl'),
|
||||
install : with_tools.contains('glsl'),
|
||||
)
|
||||
|
||||
if with_any_opengl and with_tests
|
||||
subdir('tests')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file test.cpp
|
||||
*
|
||||
* Standalone tests for the GLSL compiler.
|
||||
*
|
||||
* This file provides a standalone executable which can be used to
|
||||
* test components of the GLSL.
|
||||
*
|
||||
* Each test is a function with the same signature as main(). The
|
||||
* main function interprets its first argument as the name of the test
|
||||
* to run, strips out that argument, and then calls the test function.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "test_optpass.h"
|
||||
|
||||
/**
|
||||
* Print proper usage and exit with failure.
|
||||
*/
|
||||
static void
|
||||
usage_fail(const char *name)
|
||||
{
|
||||
printf("*** usage: %s <command> <options>\n", name);
|
||||
printf("\n");
|
||||
printf("Possible commands are:\n");
|
||||
printf(" optpass: test an optimization pass in isolation\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static const char *extract_command_from_argv(int *argc, char **argv)
|
||||
{
|
||||
if (*argc < 2) {
|
||||
usage_fail(argv[0]);
|
||||
}
|
||||
const char *command = argv[1];
|
||||
--*argc;
|
||||
memmove(&argv[1], &argv[2], (*argc) * sizeof(argv[1]));
|
||||
return command;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *command = extract_command_from_argv(&argc, argv);
|
||||
if (strcmp(command, "optpass") == 0) {
|
||||
return test_optpass(argc, argv);
|
||||
} else {
|
||||
usage_fail(argv[0]);
|
||||
}
|
||||
|
||||
/* Execution should never reach here. */
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file test_optpass.cpp
|
||||
*
|
||||
* Standalone test for optimization passes.
|
||||
*
|
||||
* This file provides the "optpass" command for the standalone
|
||||
* glsl_test app. It accepts either GLSL or high-level IR as input,
|
||||
* and performs the optimiation passes specified on the command line.
|
||||
* It outputs the IR, both before and after optimiations.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "ast.h"
|
||||
#include "ir_optimization.h"
|
||||
#include "program.h"
|
||||
#include "ir_reader.h"
|
||||
#include "standalone_scaffolding.h"
|
||||
#include "main/mtypes.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static string read_stdin_to_eof()
|
||||
{
|
||||
stringbuf sb;
|
||||
cin.get(sb, '\0');
|
||||
return sb.str();
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
do_optimization(struct exec_list *ir, const char *optimization,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
{
|
||||
int int_0;
|
||||
int int_1;
|
||||
int int_2;
|
||||
int int_3;
|
||||
|
||||
if (sscanf(optimization, "do_common_optimization ( %d ) ", &int_0) == 1) {
|
||||
return do_common_optimization(ir, int_0 != 0, options, true);
|
||||
} else if (strcmp(optimization, "do_algebraic") == 0) {
|
||||
return do_algebraic(ir, true, options);
|
||||
} else if (strcmp(optimization, "do_dead_code") == 0) {
|
||||
return do_dead_code(ir);
|
||||
} else if (strcmp(optimization, "do_dead_code_local") == 0) {
|
||||
return do_dead_code_local(ir);
|
||||
} else if (strcmp(optimization, "do_dead_code_unlinked") == 0) {
|
||||
return do_dead_code_unlinked(ir);
|
||||
} else if (sscanf(optimization,
|
||||
"do_lower_jumps ( %d , %d , %d , %d ) ",
|
||||
&int_0, &int_1, &int_2, &int_3) == 4) {
|
||||
return do_lower_jumps(ir, int_0 != 0, int_3 != 0);
|
||||
} else if (strcmp(optimization, "do_if_simplification") == 0) {
|
||||
return do_if_simplification(ir);
|
||||
} else if (strcmp(optimization, "do_mat_op_to_vec") == 0) {
|
||||
return do_mat_op_to_vec(ir);
|
||||
} else if (strcmp(optimization, "do_tree_grafting") == 0) {
|
||||
return do_tree_grafting(ir);
|
||||
} else if (strcmp(optimization, "do_vec_index_to_cond_assign") == 0) {
|
||||
return do_vec_index_to_cond_assign(ir);
|
||||
} else if (sscanf(optimization, "lower_instructions ( %d ) ",
|
||||
&int_0) == 1) {
|
||||
return lower_instructions(ir, false, false);
|
||||
} else {
|
||||
printf("Unrecognized optimization %s\n", optimization);
|
||||
exit(EXIT_FAILURE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
do_optimization_passes(struct exec_list *ir, char **optimizations,
|
||||
int num_optimizations, bool quiet,
|
||||
const struct gl_shader_compiler_options *options)
|
||||
{
|
||||
GLboolean overall_progress = false;
|
||||
|
||||
for (int i = 0; i < num_optimizations; ++i) {
|
||||
const char *optimization = optimizations[i];
|
||||
if (!quiet) {
|
||||
printf("*** Running optimization %s...", optimization);
|
||||
}
|
||||
GLboolean progress = do_optimization(ir, optimization, options);
|
||||
if (!quiet) {
|
||||
printf("%s\n", progress ? "progress" : "no progress");
|
||||
}
|
||||
validate_ir_tree(ir);
|
||||
|
||||
overall_progress = overall_progress || progress;
|
||||
}
|
||||
|
||||
return overall_progress;
|
||||
}
|
||||
|
||||
int test_optpass(int argc, char **argv)
|
||||
{
|
||||
int input_format_ir = 0; /* 0=glsl, 1=ir */
|
||||
int loop = 0;
|
||||
int shader_type = GL_VERTEX_SHADER;
|
||||
int quiet = 0;
|
||||
int error;
|
||||
|
||||
const struct option optpass_opts[] = {
|
||||
{ "input-ir", no_argument, &input_format_ir, 1 },
|
||||
{ "input-glsl", no_argument, &input_format_ir, 0 },
|
||||
{ "loop", no_argument, &loop, 1 },
|
||||
{ "vertex-shader", no_argument, &shader_type, GL_VERTEX_SHADER },
|
||||
{ "fragment-shader", no_argument, &shader_type, GL_FRAGMENT_SHADER },
|
||||
{ "quiet", no_argument, &quiet, 1 },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int idx = 0;
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "", optpass_opts, &idx)) != -1) {
|
||||
if (c != 0) {
|
||||
printf("*** usage: %s optpass <optimizations> <options>\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("Possible options are:\n");
|
||||
printf(" --input-ir: input format is IR\n");
|
||||
printf(" --input-glsl: input format is GLSL (the default)\n");
|
||||
printf(" --loop: run optimizations repeatedly until no progress\n");
|
||||
printf(" --vertex-shader: test with a vertex shader (the default)\n");
|
||||
printf(" --fragment-shader: test with a fragment shader\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
glsl_type_singleton_init_or_ref();
|
||||
|
||||
struct gl_context local_ctx;
|
||||
struct gl_context *ctx = &local_ctx;
|
||||
initialize_context_to_defaults(ctx, API_OPENGL_COMPAT);
|
||||
|
||||
ir_variable::temporaries_allocate_names = true;
|
||||
|
||||
struct gl_shader *shader = rzalloc(NULL, struct gl_shader);
|
||||
shader->Type = shader_type;
|
||||
shader->Stage = _mesa_shader_enum_to_shader_stage(shader_type);
|
||||
|
||||
string input = read_stdin_to_eof();
|
||||
|
||||
struct _mesa_glsl_parse_state *state
|
||||
= new(shader) _mesa_glsl_parse_state(ctx, shader->Stage, shader);
|
||||
|
||||
if (input_format_ir) {
|
||||
shader->ir = new(shader) exec_list;
|
||||
_mesa_glsl_initialize_types(state);
|
||||
_mesa_glsl_read_ir(state, shader->ir, input.c_str(), true);
|
||||
} else {
|
||||
shader->Source = input.c_str();
|
||||
const char *source = shader->Source;
|
||||
state->error = glcpp_preprocess(state, &source, &state->info_log,
|
||||
NULL, NULL, ctx) != 0;
|
||||
|
||||
if (!state->error) {
|
||||
_mesa_glsl_lexer_ctor(state, source);
|
||||
_mesa_glsl_parse(state);
|
||||
_mesa_glsl_lexer_dtor(state);
|
||||
}
|
||||
|
||||
shader->ir = new(shader) exec_list;
|
||||
if (!state->error && !state->translation_unit.is_empty())
|
||||
_mesa_ast_to_hir(shader->ir, state);
|
||||
}
|
||||
|
||||
/* Print out the initial IR */
|
||||
if (!state->error && !quiet) {
|
||||
printf("*** pre-optimization IR:\n");
|
||||
_mesa_print_ir(stdout, shader->ir, state);
|
||||
printf("\n--\n");
|
||||
}
|
||||
|
||||
/* Optimization passes */
|
||||
if (!state->error) {
|
||||
GLboolean progress;
|
||||
const struct gl_shader_compiler_options *options =
|
||||
&ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader_type)];
|
||||
do {
|
||||
progress = do_optimization_passes(shader->ir, &argv[optind],
|
||||
argc - optind, quiet != 0, options);
|
||||
} while (loop && progress);
|
||||
}
|
||||
|
||||
/* Print out the resulting IR */
|
||||
if (!state->error) {
|
||||
if (!quiet) {
|
||||
printf("*** resulting IR:\n");
|
||||
}
|
||||
_mesa_print_ir(stdout, shader->ir, state);
|
||||
if (!quiet) {
|
||||
printf("\n--\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (state->error) {
|
||||
printf("*** error(s) occurred:\n");
|
||||
printf("%s\n", state->info_log);
|
||||
printf("--\n");
|
||||
}
|
||||
|
||||
error = state->error;
|
||||
|
||||
ralloc_free(state);
|
||||
ralloc_free(shader);
|
||||
|
||||
glsl_type_singleton_decref();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TEST_OPTPASS_H
|
||||
#define TEST_OPTPASS_H
|
||||
|
||||
int test_optpass(int argc, char **argv);
|
||||
|
||||
#endif /* TEST_OPTPASS_H */
|
||||
|
|
@ -1,307 +0,0 @@
|
|||
# coding=utf-8
|
||||
#
|
||||
# Copyright © 2011, 2018 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from sexps import *
|
||||
|
||||
def make_test_case(f_name, ret_type, body):
|
||||
"""Create a simple optimization test case consisting of a single
|
||||
function with the given name, return type, and body.
|
||||
|
||||
Global declarations are automatically created for any undeclared
|
||||
variables that are referenced by the function. All undeclared
|
||||
variables are assumed to be floats.
|
||||
"""
|
||||
check_sexp(body)
|
||||
declarations = {}
|
||||
def make_declarations(sexp, already_declared = ()):
|
||||
if isinstance(sexp, list):
|
||||
if len(sexp) == 2 and sexp[0] == 'var_ref':
|
||||
if sexp[1] not in already_declared:
|
||||
declarations[sexp[1]] = [
|
||||
'declare', ['in'], 'float', sexp[1]]
|
||||
elif len(sexp) == 4 and sexp[0] == 'assign':
|
||||
assert sexp[2][0] == 'var_ref'
|
||||
if sexp[2][1] not in already_declared:
|
||||
declarations[sexp[2][1]] = [
|
||||
'declare', ['out'], 'float', sexp[2][1]]
|
||||
make_declarations(sexp[3], already_declared)
|
||||
else:
|
||||
already_declared = set(already_declared)
|
||||
for s in sexp:
|
||||
if isinstance(s, list) and len(s) >= 4 and \
|
||||
s[0] == 'declare':
|
||||
already_declared.add(s[3])
|
||||
else:
|
||||
make_declarations(s, already_declared)
|
||||
make_declarations(body)
|
||||
return list(declarations.values()) + \
|
||||
[['function', f_name, ['signature', ret_type, ['parameters'], body]]]
|
||||
|
||||
|
||||
# The following functions can be used to build expressions.
|
||||
|
||||
def const_float(value):
|
||||
"""Create an expression representing the given floating point value."""
|
||||
return ['constant', 'float', ['{0:.6f}'.format(value)]]
|
||||
|
||||
def const_bool(value):
|
||||
"""Create an expression representing the given boolean value.
|
||||
|
||||
If value is not a boolean, it is converted to a boolean. So, for
|
||||
instance, const_bool(1) is equivalent to const_bool(True).
|
||||
"""
|
||||
return ['constant', 'bool', ['{0}'.format(1 if value else 0)]]
|
||||
|
||||
def gt_zero(var_name):
|
||||
"""Create Construct the expression var_name > 0"""
|
||||
return ['expression', 'bool', '<', const_float(0), ['var_ref', var_name]]
|
||||
|
||||
|
||||
# The following functions can be used to build complex control flow
|
||||
# statements. All of these functions return statement lists (even
|
||||
# those which only create a single statement), so that statements can
|
||||
# be sequenced together using the '+' operator.
|
||||
|
||||
def return_(value = None):
|
||||
"""Create a return statement."""
|
||||
if value is not None:
|
||||
return [['return', value]]
|
||||
else:
|
||||
return [['return']]
|
||||
|
||||
def break_():
|
||||
"""Create a break statement."""
|
||||
return ['break']
|
||||
|
||||
def continue_():
|
||||
"""Create a continue statement."""
|
||||
return ['continue']
|
||||
|
||||
def simple_if(var_name, then_statements, else_statements = None):
|
||||
"""Create a statement of the form
|
||||
|
||||
if (var_name > 0.0) {
|
||||
<then_statements>
|
||||
} else {
|
||||
<else_statements>
|
||||
}
|
||||
|
||||
else_statements may be omitted.
|
||||
"""
|
||||
if else_statements is None:
|
||||
else_statements = []
|
||||
check_sexp(then_statements)
|
||||
check_sexp(else_statements)
|
||||
return [['if', gt_zero(var_name), then_statements, else_statements]]
|
||||
|
||||
def loop(statements):
|
||||
"""Create a loop containing the given statements as its loop
|
||||
body.
|
||||
"""
|
||||
check_sexp(statements)
|
||||
return [['loop', statements]]
|
||||
|
||||
def declare_temp(var_type, var_name):
|
||||
"""Create a declaration of the form
|
||||
|
||||
(declare (temporary) <var_type> <var_name)
|
||||
"""
|
||||
return [['declare', ['temporary'], var_type, var_name]]
|
||||
|
||||
def assign_x(var_name, value):
|
||||
"""Create a statement that assigns <value> to the variable
|
||||
<var_name>. The assignment uses the mask (x).
|
||||
"""
|
||||
check_sexp(value)
|
||||
return [['assign', ['x'], ['var_ref', var_name], value]]
|
||||
|
||||
def complex_if(var_prefix, statements):
|
||||
"""Create a statement of the form
|
||||
|
||||
if (<var_prefix>a > 0.0) {
|
||||
if (<var_prefix>b > 0.0) {
|
||||
<statements>
|
||||
}
|
||||
}
|
||||
|
||||
This is useful in testing jump lowering, because if <statements>
|
||||
ends in a jump, lower_jumps.cpp won't try to combine this
|
||||
construct with the code that follows it, as it might do for a
|
||||
simple if.
|
||||
|
||||
All variables used in the if statement are prefixed with
|
||||
var_prefix. This can be used to ensure uniqueness.
|
||||
"""
|
||||
check_sexp(statements)
|
||||
return simple_if(var_prefix + 'a', simple_if(var_prefix + 'b', statements))
|
||||
|
||||
def declare_execute_flag():
|
||||
"""Create the statements that lower_jumps.cpp uses to declare and
|
||||
initialize the temporary boolean execute_flag.
|
||||
"""
|
||||
return declare_temp('bool', 'execute_flag') + \
|
||||
assign_x('execute_flag', const_bool(True))
|
||||
|
||||
def declare_return_flag():
|
||||
"""Create the statements that lower_jumps.cpp uses to declare and
|
||||
initialize the temporary boolean return_flag.
|
||||
"""
|
||||
return declare_temp('bool', 'return_flag') + \
|
||||
assign_x('return_flag', const_bool(False))
|
||||
|
||||
def declare_return_value():
|
||||
"""Create the statements that lower_jumps.cpp uses to declare and
|
||||
initialize the temporary variable return_value. Assume that
|
||||
return_value is a float.
|
||||
"""
|
||||
return declare_temp('float', 'return_value')
|
||||
|
||||
def declare_break_flag():
|
||||
"""Create the statements that lower_jumps.cpp uses to declare and
|
||||
initialize the temporary boolean break_flag.
|
||||
"""
|
||||
return declare_temp('bool', 'break_flag') + \
|
||||
assign_x('break_flag', const_bool(False))
|
||||
|
||||
def lowered_return_simple(value = None):
|
||||
"""Create the statements that lower_jumps.cpp lowers a return
|
||||
statement to, in situations where it does not need to clear the
|
||||
execute flag.
|
||||
"""
|
||||
if value:
|
||||
result = assign_x('return_value', value)
|
||||
else:
|
||||
result = []
|
||||
return result + assign_x('return_flag', const_bool(True))
|
||||
|
||||
def lowered_return(value = None):
|
||||
"""Create the statements that lower_jumps.cpp lowers a return
|
||||
statement to, in situations where it needs to clear the execute
|
||||
flag.
|
||||
"""
|
||||
return lowered_return_simple(value) + \
|
||||
assign_x('execute_flag', const_bool(False))
|
||||
|
||||
def lowered_continue():
|
||||
"""Create the statement that lower_jumps.cpp lowers a continue
|
||||
statement to.
|
||||
"""
|
||||
return assign_x('execute_flag', const_bool(False))
|
||||
|
||||
def lowered_break_simple():
|
||||
"""Create the statement that lower_jumps.cpp lowers a break
|
||||
statement to, in situations where it does not need to clear the
|
||||
execute flag.
|
||||
"""
|
||||
return assign_x('break_flag', const_bool(True))
|
||||
|
||||
def lowered_break():
|
||||
"""Create the statement that lower_jumps.cpp lowers a break
|
||||
statement to, in situations where it needs to clear the execute
|
||||
flag.
|
||||
"""
|
||||
return lowered_break_simple() + assign_x('execute_flag', const_bool(False))
|
||||
|
||||
def if_execute_flag(statements):
|
||||
"""Wrap statements in an if test so that they will only execute if
|
||||
execute_flag is True.
|
||||
"""
|
||||
check_sexp(statements)
|
||||
return [['if', ['var_ref', 'execute_flag'], statements, []]]
|
||||
|
||||
def if_return_flag(then_statements, else_statements):
|
||||
"""Wrap statements in an if test with return_flag as the condition.
|
||||
"""
|
||||
check_sexp(then_statements)
|
||||
check_sexp(else_statements)
|
||||
return [['if', ['var_ref', 'return_flag'], then_statements, else_statements]]
|
||||
|
||||
def if_not_return_flag(statements):
|
||||
"""Wrap statements in an if test so that they will only execute if
|
||||
return_flag is False.
|
||||
"""
|
||||
check_sexp(statements)
|
||||
return [['if', ['var_ref', 'return_flag'], [], statements]]
|
||||
|
||||
def final_return():
|
||||
"""Create the return statement that lower_jumps.cpp places at the
|
||||
end of a function when lowering returns.
|
||||
"""
|
||||
return [['return', ['var_ref', 'return_value']]]
|
||||
|
||||
def final_break():
|
||||
"""Create the conditional break statement that lower_jumps.cpp
|
||||
places at the end of a function when lowering breaks.
|
||||
"""
|
||||
return [['if', ['var_ref', 'break_flag'], break_(), []]]
|
||||
|
||||
def bash_quote(*args):
|
||||
"""Quote the arguments appropriately so that bash will understand
|
||||
each argument as a single word.
|
||||
"""
|
||||
def quote_word(word):
|
||||
for c in word:
|
||||
if not (c.isalpha() or c.isdigit() or c in '@%_-+=:,./'):
|
||||
break
|
||||
else:
|
||||
if not word:
|
||||
return "''"
|
||||
return word
|
||||
return "'{0}'".format(word.replace("'", "'\"'\"'"))
|
||||
return ' '.join(quote_word(word) for word in args)
|
||||
|
||||
def create_test_case(input_sexp, expected_sexp, test_name,
|
||||
pull_out_jumps=False, lower_sub_return=False,
|
||||
lower_main_return=False, lower_continue=False):
|
||||
"""Create a test case that verifies that do_lower_jumps transforms
|
||||
the given code in the expected way.
|
||||
"""
|
||||
check_sexp(input_sexp)
|
||||
check_sexp(expected_sexp)
|
||||
input_str = sexp_to_string(sort_decls(input_sexp))
|
||||
expected_output = sexp_to_string(sort_decls(expected_sexp)) # XXX: don't stringify this
|
||||
optimization = (
|
||||
'do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d})'.format(
|
||||
pull_out_jumps, lower_sub_return, lower_main_return,
|
||||
lower_continue))
|
||||
|
||||
return (test_name, optimization, input_str, expected_output)
|
||||
|
||||
|
||||
def test_remove_continue_at_end_of_loop():
|
||||
"""Test that a redundant continue-statement at the end of a loop is
|
||||
removed.
|
||||
"""
|
||||
input_sexp = make_test_case('main', 'void', (
|
||||
loop(assign_x('a', const_float(1)) +
|
||||
continue_())
|
||||
))
|
||||
expected_sexp = make_test_case('main', 'void', (
|
||||
loop(assign_x('a', const_float(1)))
|
||||
))
|
||||
yield create_test_case(input_sexp, expected_sexp, 'remove_continue_at_end_of_loop')
|
||||
|
||||
|
||||
CASES = [
|
||||
test_remove_continue_at_end_of_loop,
|
||||
]
|
||||
|
|
@ -72,16 +72,6 @@ if meson.can_run_host_binaries()
|
|||
suite : ['compiler', 'glsl'],
|
||||
timeout: 60,
|
||||
)
|
||||
|
||||
test(
|
||||
'glsl optimization',
|
||||
prog_python,
|
||||
args : [
|
||||
files('optimization_test.py'),
|
||||
'--test-runner', glsl_test
|
||||
],
|
||||
suite : ['compiler', 'glsl'],
|
||||
)
|
||||
endif
|
||||
|
||||
if with_tools.contains('glsl')
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
# encoding=utf-8
|
||||
# Copyright © 2018 Intel Corporation
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
"""Script to generate and run glsl optimization tests."""
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
import errno
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import sexps
|
||||
import lower_jump_cases
|
||||
|
||||
# The meson version handles windows paths better, but if it's not available
|
||||
# fall back to shlex
|
||||
try:
|
||||
from meson.mesonlib import split_args
|
||||
except ImportError:
|
||||
from shlex import split as split_args
|
||||
|
||||
|
||||
def arg_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--test-runner',
|
||||
required=True,
|
||||
help='The glsl_test binary.')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def compare(actual, expected):
|
||||
"""Compare the s-expresions and return a diff if they are different."""
|
||||
actual = sexps.sort_decls(sexps.parse_sexp(actual))
|
||||
expected = sexps.sort_decls(sexps.parse_sexp(expected))
|
||||
|
||||
if actual == expected:
|
||||
return None
|
||||
|
||||
actual = sexps.sexp_to_string(actual)
|
||||
expected = sexps.sexp_to_string(expected)
|
||||
|
||||
return difflib.unified_diff(expected.splitlines(), actual.splitlines())
|
||||
|
||||
|
||||
def get_test_runner(runner):
|
||||
"""Wrap the test runner in the exe wrapper if necessary."""
|
||||
wrapper = os.environ.get('MESON_EXE_WRAPPER', None)
|
||||
if wrapper is None:
|
||||
return [runner]
|
||||
return split_args(wrapper) + [runner]
|
||||
|
||||
|
||||
def main():
|
||||
"""Generate each test and report pass or fail."""
|
||||
args = arg_parser()
|
||||
|
||||
total = 0
|
||||
passes = 0
|
||||
|
||||
runner = get_test_runner(args.test_runner)
|
||||
|
||||
for gen in lower_jump_cases.CASES:
|
||||
for name, opt, source, expected in gen():
|
||||
total += 1
|
||||
print('{}: '.format(name), end='')
|
||||
proc = subprocess.Popen(
|
||||
runner + ['optpass', '--quiet', '--input-ir', opt],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE)
|
||||
out, err = proc.communicate(source.encode('utf-8'))
|
||||
out = out.decode('utf-8')
|
||||
err = err.decode('utf-8')
|
||||
|
||||
if proc.returncode == 255:
|
||||
print("Test returned general error, possibly missing linker")
|
||||
sys.exit(77)
|
||||
|
||||
if err:
|
||||
print('FAIL')
|
||||
print('Unexpected output on stderr: {}'.format(err),
|
||||
file=sys.stdout)
|
||||
continue
|
||||
|
||||
result = compare(out, expected)
|
||||
if result is not None:
|
||||
print('FAIL')
|
||||
for l in result:
|
||||
print(l, file=sys.stderr)
|
||||
else:
|
||||
print('PASS')
|
||||
passes += 1
|
||||
|
||||
print('{}/{} tests returned correct results'.format(passes, total))
|
||||
exit(0 if passes == total else 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOEXEC:
|
||||
print('Skipping due to inability to run host binaries', file=sys.stderr)
|
||||
sys.exit(77)
|
||||
raise
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
# coding=utf-8
|
||||
#
|
||||
# Copyright © 2011 Intel Corporation
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the next
|
||||
# paragraph) shall be included in all copies or substantial portions of the
|
||||
# Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# This file contains helper functions for manipulating sexps in Python.
|
||||
#
|
||||
# We represent a sexp in Python using nested lists containing strings.
|
||||
# So, for example, the sexp (constant float (1.000000)) is represented
|
||||
# as ['constant', 'float', ['1.000000']].
|
||||
|
||||
import re
|
||||
|
||||
def check_sexp(sexp):
|
||||
"""Verify that the argument is a proper sexp.
|
||||
|
||||
That is, raise an exception if the argument is not a string or a
|
||||
list, or if it contains anything that is not a string or a list at
|
||||
any nesting level.
|
||||
"""
|
||||
if isinstance(sexp, list):
|
||||
for s in sexp:
|
||||
check_sexp(s)
|
||||
elif not isinstance(sexp, str):
|
||||
raise Exception('Not a sexp: {0!r}'.format(sexp))
|
||||
|
||||
def parse_sexp(sexp):
|
||||
"""Convert a string, of the form that would be output by mesa,
|
||||
into a sexp represented as nested lists containing strings.
|
||||
"""
|
||||
sexp_token_regexp = re.compile(
|
||||
'[a-zA-Z_]+(@[0-9]+)?|[0-9]+(\\.[0-9]+)?|[^ \r?\n]')
|
||||
stack = [[]]
|
||||
for match in sexp_token_regexp.finditer(sexp):
|
||||
token = match.group(0)
|
||||
if token == '(':
|
||||
stack.append([])
|
||||
elif token == ')':
|
||||
if len(stack) == 1:
|
||||
raise Exception('Unmatched )')
|
||||
sexp = stack.pop()
|
||||
stack[-1].append(sexp)
|
||||
else:
|
||||
stack[-1].append(token)
|
||||
if len(stack) != 1:
|
||||
raise Exception('Unmatched (')
|
||||
if len(stack[0]) != 1:
|
||||
raise Exception('Multiple sexps')
|
||||
return stack[0][0]
|
||||
|
||||
def sexp_to_string(sexp):
|
||||
"""Convert a sexp, represented as nested lists containing strings,
|
||||
into a single string of the form parseable by mesa.
|
||||
"""
|
||||
if isinstance(sexp, str):
|
||||
return sexp
|
||||
assert isinstance(sexp, list)
|
||||
result = ''
|
||||
for s in sexp:
|
||||
sub_result = sexp_to_string(s)
|
||||
if result == '':
|
||||
result = sub_result
|
||||
elif '\n' not in result and '\n' not in sub_result and \
|
||||
len(result) + len(sub_result) + 1 <= 70:
|
||||
result += ' ' + sub_result
|
||||
else:
|
||||
result += '\n' + sub_result
|
||||
return '({0})'.format(result.replace('\n', '\n '))
|
||||
|
||||
def sort_decls(sexp):
|
||||
"""Sort all toplevel variable declarations in sexp.
|
||||
|
||||
This is used to work around the fact that
|
||||
ir_reader::read_instructions reorders declarations.
|
||||
"""
|
||||
assert isinstance(sexp, list)
|
||||
decls = []
|
||||
other_code = []
|
||||
for s in sexp:
|
||||
if isinstance(s, list) and len(s) >= 4 and s[0] == 'declare':
|
||||
decls.append(s)
|
||||
else:
|
||||
other_code.append(s)
|
||||
return sorted(decls) + other_code
|
||||
|
||||
Loading…
Add table
Reference in a new issue