[Mesa-dev] [PATCH 4/4] glsl: Add unit tests for lower_jumps.cpp
Ian Romanick
idr at freedesktop.org
Tue Jul 19 13:20:55 PDT 2011
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/18/2011 11:37 AM, Paul Berry wrote:
> These tests invoke do_lower_jumps() in isolation (using the glsl_test
> executable) and verify that it transforms the IR in the expected way.
>
> The unit tests may be run from the top level directory using "make
> check".
>
> For reference, I've also checked in the Python script
> create_test_cases.py, which was used to generate these tests. It is
> not necessary to run this script in order to run the tests.
This is quite a bit better. Now I can at least see what is being
tested. I do share Eric's concern about maintaining the tests requiring
an exact transformation. For this set of tests that shouldn't be much
of a problem, but we'll want to be careful in more complex tests.
> ---
> Makefile | 6 +-
> src/glsl/tests/compare_ir | 59 ++
> src/glsl/tests/lower_jumps/.gitignore | 1 +
> src/glsl/tests/lower_jumps/create_test_cases.py | 643 ++++++++++++++++++++
> src/glsl/tests/lower_jumps/lower_breaks_1.opt_test | 13 +
> .../lower_jumps/lower_breaks_1.opt_test.expected | 5 +
> src/glsl/tests/lower_jumps/lower_breaks_2.opt_test | 15 +
> .../lower_jumps/lower_breaks_2.opt_test.expected | 7 +
> src/glsl/tests/lower_jumps/lower_breaks_3.opt_test | 17 +
> .../lower_jumps/lower_breaks_3.opt_test.expected | 8 +
> src/glsl/tests/lower_jumps/lower_breaks_4.opt_test | 15 +
> .../lower_jumps/lower_breaks_4.opt_test.expected | 7 +
> src/glsl/tests/lower_jumps/lower_breaks_5.opt_test | 16 +
> .../lower_jumps/lower_breaks_5.opt_test.expected | 7 +
> src/glsl/tests/lower_jumps/lower_breaks_6.opt_test | 29 +
> .../lower_jumps/lower_breaks_6.opt_test.expected | 29 +
> .../lower_guarded_conditional_break.opt_test | 21 +
> ...wer_guarded_conditional_break.opt_test.expected | 20 +
> .../lower_jumps/lower_pulled_out_jump.opt_test | 28 +
> .../lower_pulled_out_jump.opt_test.expected | 25 +
> .../tests/lower_jumps/lower_returns_1.opt_test | 12 +
> .../lower_jumps/lower_returns_1.opt_test.expected | 4 +
> .../tests/lower_jumps/lower_returns_2.opt_test | 13 +
> .../lower_jumps/lower_returns_2.opt_test.expected | 5 +
> .../tests/lower_jumps/lower_returns_3.opt_test | 20 +
> .../lower_jumps/lower_returns_3.opt_test.expected | 21 +
> .../tests/lower_jumps/lower_returns_4.opt_test | 14 +
> .../lower_jumps/lower_returns_4.opt_test.expected | 16 +
> .../lower_jumps/lower_returns_main_false.opt_test | 17 +
> .../lower_returns_main_false.opt_test.expected | 8 +
> .../lower_jumps/lower_returns_main_true.opt_test | 17 +
> .../lower_returns_main_true.opt_test.expected | 13 +
> .../lower_jumps/lower_returns_sub_false.opt_test | 16 +
> .../lower_returns_sub_false.opt_test.expected | 8 +
> .../lower_jumps/lower_returns_sub_true.opt_test | 16 +
> .../lower_returns_sub_true.opt_test.expected | 13 +
> .../lower_jumps/lower_unified_returns.opt_test | 26 +
> .../lower_unified_returns.opt_test.expected | 21 +
> .../remove_continue_at_end_of_loop.opt_test | 13 +
> ...emove_continue_at_end_of_loop.opt_test.expected | 5 +
> ..._non_void_at_end_of_loop_lower_nothing.opt_test | 16 +
> ..._at_end_of_loop_lower_nothing.opt_test.expected | 8 +
> ...n_non_void_at_end_of_loop_lower_return.opt_test | 16 +
> ...d_at_end_of_loop_lower_return.opt_test.expected | 19 +
> ..._at_end_of_loop_lower_return_and_break.opt_test | 16 +
> ...f_loop_lower_return_and_break.opt_test.expected | 19 +
> ...turn_void_at_end_of_loop_lower_nothing.opt_test | 14 +
> ..._at_end_of_loop_lower_nothing.opt_test.expected | 6 +
> ...eturn_void_at_end_of_loop_lower_return.opt_test | 14 +
> ...d_at_end_of_loop_lower_return.opt_test.expected | 11 +
> ..._at_end_of_loop_lower_return_and_break.opt_test | 14 +
> ...f_loop_lower_return_and_break.opt_test.expected | 11 +
> src/glsl/tests/optimization-test | 28 +
> src/glsl/tests/sexps.py | 103 ++++
> 54 files changed, 1543 insertions(+), 1 deletions(-)
> create mode 100755 src/glsl/tests/compare_ir
> create mode 100644 src/glsl/tests/lower_jumps/.gitignore
> create mode 100644 src/glsl/tests/lower_jumps/create_test_cases.py
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_1.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_2.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_3.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_4.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_5.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_breaks_6.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_1.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_1.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_2.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_2.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_3.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_4.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/lower_unified_returns.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected
> create mode 100755 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test
> create mode 100644 src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> create mode 100755 src/glsl/tests/optimization-test
> create mode 100644 src/glsl/tests/sexps.py
>
> diff --git a/Makefile b/Makefile
> index b0a2d80..8b7adce 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -21,6 +21,10 @@ all: default
> doxygen:
> cd doxygen && $(MAKE)
>
> +check:
> + cd src/glsl/tests/ && ./optimization-test
> + @echo "All tests passed."
> +
> clean:
> - at touch $(TOP)/configs/current
> - at for dir in $(SUBDIRS) ; do \
> @@ -51,7 +55,7 @@ install:
> done
>
>
> -.PHONY: default doxygen clean realclean distclean install
> +.PHONY: default doxygen clean realclean distclean install check
>
> # If there's no current configuration file
> $(TOP)/configs/current:
> diff --git a/src/glsl/tests/compare_ir b/src/glsl/tests/compare_ir
> new file mode 100755
> index 0000000..a40fc81
> --- /dev/null
> +++ b/src/glsl/tests/compare_ir
> @@ -0,0 +1,59 @@
> +#!/usr/bin/env python
> +# 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.
> +
> +# Compare two files containing IR code. Ignore formatting differences
> +# and declaration order.
> +
> +import os
> +import os.path
> +import subprocess
> +import sys
> +import tempfile
> +
> +from sexps import *
> +
> +if len(sys.argv) != 3:
> + print 'Usage: compare_ir <file1> <file2>'
> + exit(1)
> +
> +with open(sys.argv[1]) as f:
> + ir1 = sort_decls(parse_sexp(f.read()))
> +with open(sys.argv[2]) as f:
> + ir2 = sort_decls(parse_sexp(f.read()))
> +
> +if ir1 == ir2:
> + exit(0)
> +else:
> + file1, path1 = tempfile.mkstemp(os.path.basename(sys.argv[1]))
> + file2, path2 = tempfile.mkstemp(os.path.basename(sys.argv[2]))
> + try:
> + os.write(file1, '{0}\n'.format(sexp_to_string(ir1)))
> + os.close(file1)
> + os.write(file2, '{0}\n'.format(sexp_to_string(ir2)))
> + os.close(file2)
> + subprocess.call(['diff', '-u', path1, path2])
> + finally:
> + os.remove(path1)
> + os.remove(path2)
> + exit(1)
> diff --git a/src/glsl/tests/lower_jumps/.gitignore b/src/glsl/tests/lower_jumps/.gitignore
> new file mode 100644
> index 0000000..f47cb20
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/.gitignore
> @@ -0,0 +1 @@
> +*.out
> diff --git a/src/glsl/tests/lower_jumps/create_test_cases.py b/src/glsl/tests/lower_jumps/create_test_cases.py
> new file mode 100644
> index 0000000..fbc6f0a
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/create_test_cases.py
> @@ -0,0 +1,643 @@
> +# 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.
> +
> +import os
> +import os.path
> +import re
> +import subprocess
> +import sys
> +
> +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) # For access to sexps.py, which is in parent dir
> +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 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', '>', ['var_ref', var_name], const_float(0)]
> +
> +
> +# 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_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(doc_string, input_sexp, expected_sexp, test_name,
> + pull_out_jumps=False, lower_sub_return=False,
> + lower_main_return=False, lower_continue=False,
> + lower_break=False):
> + """Create a test case that verifies that do_lower_jumps transforms
> + the given code in the expected way.
> + """
> + doc_lines = [line.strip() for line in doc_string.splitlines()]
> + doc_string = ''.join('# {0}\n'.format(line) for line in doc_lines if line != '')
> + 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))
> +
> + optimization = (
> + 'do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d}, {4:d})'.format(
> + pull_out_jumps, lower_sub_return, lower_main_return,
> + lower_continue, lower_break))
> + args = ['../../glsl_test', 'optpass', '--quiet', '--input-ir', optimization]
> + test_file = '{0}.opt_test'.format(test_name)
> + with open(test_file, 'w') as f:
> + f.write('#!/bin/bash\n#\n# This file was generated by create_test_cases.py.\n#\n')
> + f.write(doc_string)
> + f.write('{0} <<EOF\n'.format(bash_quote(*args)))
> + f.write('{0}\nEOF\n'.format(input_str))
> + os.chmod(test_file, 0774)
> + expected_file = '{0}.opt_test.expected'.format(test_name)
> + with open(expected_file, 'w') as f:
> + f.write('{0}\n'.format(expected_output))
> +
> +def test_lower_returns_main():
> + doc_string = """Test that do_lower_jumps respects the lower_main_return
> + flag in deciding whether to lower returns in the main
> + function.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + complex_if('', return_())
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + declare_execute_flag() +
> + declare_return_flag() +
> + complex_if('', lowered_return())
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_main_true',
> + lower_main_return=True)
> + create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_main_false',
> + lower_main_return=False)
> +
> +def test_lower_returns_sub():
> + doc_string = """Test that do_lower_jumps respects the lower_sub_return flag
> + in deciding whether to lower returns in subroutines.
> + """
> + input_sexp = make_test_case('sub', 'void', (
> + complex_if('', return_())
> + ))
> + expected_sexp = make_test_case('sub', 'void', (
> + declare_execute_flag() +
> + declare_return_flag() +
> + complex_if('', lowered_return())
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_sub_true',
> + lower_sub_return=True)
> + create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_sub_false',
> + lower_sub_return=False)
> +
> +def test_lower_returns_1():
> + doc_string = """Test that a void return at the end of a function is
> + eliminated.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + assign_x('a', const_float(1)) +
> + return_()
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + assign_x('a', const_float(1))
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_1',
> + lower_main_return=True)
> +
> +def test_lower_returns_2():
> + doc_string = """Test that lowering is not performed on a non-void return at
> + the end of subroutine.
> + """
> + input_sexp = make_test_case('sub', 'float', (
> + assign_x('a', const_float(1)) +
> + return_(const_float(1))
> + ))
> + create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_2',
> + lower_sub_return=True)
> +
> +def test_lower_returns_3():
> + doc_string = """Test lowering of returns when there is one nested inside a
> + complex structure of ifs, and one at the end of a function.
> +
> + In this case, the latter return needs to be lowered because it
> + will not be at the end of the function once the final return
> + is inserted.
> + """
> + input_sexp = make_test_case('sub', 'float', (
> + complex_if('', return_(const_float(1))) +
> + return_(const_float(2))
> + ))
> + expected_sexp = make_test_case('sub', 'float', (
> + declare_execute_flag() +
> + declare_return_value() +
> + declare_return_flag() +
> + complex_if('', lowered_return(const_float(1))) +
> + if_execute_flag(lowered_return(const_float(2))) +
> + final_return()
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_3',
> + lower_sub_return=True)
> +
> +def test_lower_returns_4():
> + doc_string = """Test that returns are properly lowered when they occur in
> + both branches of an if-statement.
> + """
> + input_sexp = make_test_case('sub', 'float', (
> + simple_if('a', return_(const_float(1)),
> + return_(const_float(2)))
> + ))
> + expected_sexp = make_test_case('sub', 'float', (
> + declare_execute_flag() +
> + declare_return_value() +
> + declare_return_flag() +
> + simple_if('a', lowered_return(const_float(1)),
> + lowered_return(const_float(2))) +
> + final_return()
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_4',
> + lower_sub_return=True)
> +
> +def test_lower_unified_returns():
> + doc_string = """If both branches of an if statement end in a return, and
> + pull_out_jumps is True, then those returns should be lifted
> + outside the if and then properly lowered.
> +
> + Verify that this lowering occurs during the same pass as the
> + lowering of other returns by checking that extra temporary
> + variables aren't generated.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + complex_if('a', return_()) +
> + simple_if('b', simple_if('c', return_(), return_()))
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + declare_execute_flag() +
> + declare_return_flag() +
> + complex_if('a', lowered_return()) +
> + if_execute_flag(simple_if('b', (simple_if('c', [], []) +
> + lowered_return())))
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_unified_returns',
> + lower_main_return=True, pull_out_jumps=True)
> +
> +def test_lower_pulled_out_jump():
> + doc_string = """If one branch of an if ends in a jump, and control cannot
> + fall out the bottom of the other branch, and pull_out_jumps is
> + True, then the jump is lifted outside the if.
> +
> + Verify that this lowering occurs during the same pass as the
> + lowering of other jumps by checking that extra temporary
> + variables aren't generated.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + complex_if('a', return_()) +
> + loop(simple_if('b', simple_if('c', break_(), continue_()),
> + return_())) +
> + assign_x('d', const_float(1))
> + ))
> + # Note: optimization produces two other effects: the break
> + # gets lifted out of the if statements, and the code after the
> + # loop gets guarded so that it only executes if the return
> + # flag is clear.
> + expected_sexp = make_test_case('main', 'void', (
> + declare_execute_flag() +
> + declare_return_flag() +
> + complex_if('a', lowered_return()) +
> + if_execute_flag(
> + loop(simple_if('b', simple_if('c', [], continue_()),
> + lowered_return_simple()) +
> + break_()) +
> + if_not_return_flag(assign_x('d', const_float(1))))
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_pulled_out_jump',
> + lower_main_return=True, pull_out_jumps=True)
> +
> +def test_lower_breaks_1():
> + doc_string = """If a loop contains an unconditional break at the bottom of
> + it, it should not be lowered."""
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + break_())
> + ))
> + expected_sexp = input_sexp
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1', lower_break=True)
> +
> +def test_lower_breaks_2():
> + doc_string = """If a loop contains a conditional break at the bottom of it,
> + it should not be lowered if it is in the then-clause.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + simple_if('b', break_()))
> + ))
> + expected_sexp = input_sexp
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2', lower_break=True)
> +
> +def test_lower_breaks_3():
> + doc_string = """If a loop contains a conditional break at the bottom of it,
> + it should not be lowered if it is in the then-clause, even if
> + there are statements preceding the break.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + simple_if('b', (assign_x('c', const_float(1)) +
> + break_())))
> + ))
> + expected_sexp = input_sexp
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3', lower_break=True)
> +
> +def test_lower_breaks_4():
> + doc_string = """If a loop contains a conditional break at the bottom of it,
> + it should not be lowered if it is in the else-clause.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + simple_if('b', [], break_()))
> + ))
> + expected_sexp = input_sexp
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4', lower_break=True)
> +
> +def test_lower_breaks_5():
> + doc_string = """If a loop contains a conditional break at the bottom of it,
> + it should not be lowered if it is in the else-clause, even if
> + there are statements preceding the break.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + simple_if('b', [], (assign_x('c', const_float(1)) +
> + break_())))
> + ))
> + expected_sexp = input_sexp
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5', lower_break=True)
> +
> +def test_lower_breaks_6():
> + doc_string = """If a loop contains conditional breaks and continues, and
> + ends in an unconditional break, then the unconditional break
> + needs to be lowered, because it will no longer be at the end
> + of the loop after the final break is added.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(simple_if('a', (complex_if('b', continue_()) +
> + complex_if('c', break_()))) +
> + break_())
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + declare_break_flag() +
> + loop(declare_execute_flag() +
> + simple_if(
> + 'a',
> + (complex_if('b', lowered_continue()) +
> + if_execute_flag(
> + complex_if('c', lowered_break())))) +
> + if_execute_flag(lowered_break_simple()) +
> + final_break())
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_6',
> + lower_break=True, lower_continue=True)
> +
> +def test_lower_guarded_conditional_break():
> + doc_string = """Normally a conditional break at the end of a loop isn't
> + lowered, however if the conditional break gets placed inside
> + an if(execute_flag) because of earlier lowering of continues,
> + then the break needs to be lowered.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(complex_if('a', continue_()) +
> + simple_if('b', break_()))
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + declare_break_flag() +
> + loop(declare_execute_flag() +
> + complex_if('a', lowered_continue()) +
> + if_execute_flag(simple_if('b', lowered_break())) +
> + final_break())
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'lower_guarded_conditional_break',
> + lower_break=True, lower_continue=True)
> +
> +def test_remove_continue_at_end_of_loop():
> + doc_string = """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)))
> + ))
> + create_test_case(doc_string, input_sexp, expected_sexp, 'remove_continue_at_end_of_loop')
> +
> +def test_lower_return_void_at_end_of_loop():
> + doc_string = """Test that a return of void at the end of a loop is properly
> + lowered.
> + """
> + input_sexp = make_test_case('main', 'void', (
> + loop(assign_x('a', const_float(1)) +
> + return_()) +
> + assign_x('b', const_float(2))
> + ))
> + expected_sexp = make_test_case('main', 'void', (
> + declare_return_flag() +
> + loop(assign_x('a', const_float(1)) +
> + lowered_return_simple() +
> + break_()) +
> + if_not_return_flag(assign_x('b', const_float(2)))
> + ))
> + create_test_case(doc_string, input_sexp, input_sexp, 'return_void_at_end_of_loop_lower_nothing')
> + create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return',
> + lower_main_return=True)
> + create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return_and_break',
> + lower_main_return=True, lower_break=True)
> +
> +def test_lower_return_non_void_at_end_of_loop():
> + doc_string = """Test that a non-void return at the end of a loop is
> + properly lowered.
> + """
> + input_sexp = make_test_case('sub', 'float', (
> + loop(assign_x('a', const_float(1)) +
> + return_(const_float(2))) +
> + assign_x('b', const_float(3)) +
> + return_(const_float(4))
> + ))
> + expected_sexp = make_test_case('sub', 'float', (
> + declare_execute_flag() +
> + declare_return_value() +
> + declare_return_flag() +
> + loop(assign_x('a', const_float(1)) +
> + lowered_return_simple(const_float(2)) +
> + break_()) +
> + if_not_return_flag(assign_x('b', const_float(3)) +
> + lowered_return(const_float(4))) +
> + final_return()
> + ))
> + create_test_case(doc_string, input_sexp, input_sexp, 'return_non_void_at_end_of_loop_lower_nothing')
> + create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return',
> + lower_sub_return=True)
> + create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return_and_break',
> + lower_sub_return=True, lower_break=True)
> +
> +if __name__ == '__main__':
> + test_lower_returns_main()
> + test_lower_returns_sub()
> + test_lower_returns_1()
> + test_lower_returns_2()
> + test_lower_returns_3()
> + test_lower_returns_4()
> + test_lower_unified_returns()
> + test_lower_pulled_out_jump()
> + test_lower_breaks_1()
> + test_lower_breaks_2()
> + test_lower_breaks_3()
> + test_lower_breaks_4()
> + test_lower_breaks_5()
> + test_lower_breaks_6()
> + test_lower_guarded_conditional_break()
> + test_remove_continue_at_end_of_loop()
> + test_lower_return_void_at_end_of_loop()
> + test_lower_return_non_void_at_end_of_loop()
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test
> new file mode 100755
> index 0000000..01ad708
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test
> @@ -0,0 +1,13 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains an unconditional break at the bottom of
> +# it, it should not be lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 1)' <<EOF
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) break))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected
> new file mode 100644
> index 0000000..d4bb6fc
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_1.opt_test.expected
> @@ -0,0 +1,5 @@
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) break))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test
> new file mode 100755
> index 0000000..0be22f9
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test
> @@ -0,0 +1,15 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains a conditional break at the bottom of it,
> +# it should not be lowered if it is in the then-clause.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 1)' <<EOF
> +((declare (in) float b) (declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) (break)
> + ())))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected
> new file mode 100644
> index 0000000..a4cb2d6
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_2.opt_test.expected
> @@ -0,0 +1,7 @@
> +((declare (in) float b) (declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) (break)
> + ())))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test
> new file mode 100755
> index 0000000..4149360
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test
> @@ -0,0 +1,17 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains a conditional break at the bottom of it,
> +# it should not be lowered if it is in the then-clause, even if
> +# there are statements preceding the break.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 1)' <<EOF
> +((declare (in) float b) (declare (out) float a) (declare (out) float c)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref c) (constant float (1.000000))) break)
> + ())))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected
> new file mode 100644
> index 0000000..325f7b4
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_3.opt_test.expected
> @@ -0,0 +1,8 @@
> +((declare (in) float b) (declare (out) float a) (declare (out) float c)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref c) (constant float (1.000000))) break)
> + ())))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test
> new file mode 100755
> index 0000000..70458bb
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test
> @@ -0,0 +1,15 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains a conditional break at the bottom of it,
> +# it should not be lowered if it is in the else-clause.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 1)' <<EOF
> +((declare (in) float b) (declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) ()
> + (break))))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected
> new file mode 100644
> index 0000000..a773545
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_4.opt_test.expected
> @@ -0,0 +1,7 @@
> +((declare (in) float b) (declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) ()
> + (break))))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test
> new file mode 100755
> index 0000000..da9eef1
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains a conditional break at the bottom of it,
> +# it should not be lowered if it is in the else-clause, even if
> +# there are statements preceding the break.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 1)' <<EOF
> +((declare (in) float b) (declare (out) float a) (declare (out) float c)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) ()
> + ((assign (x) (var_ref c) (constant float (1.000000))) break))))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected
> new file mode 100644
> index 0000000..0dd4a52
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_5.opt_test.expected
> @@ -0,0 +1,7 @@
> +((declare (in) float b) (declare (out) float a) (declare (out) float c)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (if (expression bool > (var_ref b) (constant float (0.000000))) ()
> + ((assign (x) (var_ref c) (constant float (1.000000))) break))))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test b/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test
> new file mode 100755
> index 0000000..9440dfe
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test
> @@ -0,0 +1,29 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If a loop contains conditional breaks and continues, and
> +# ends in an unconditional break, then the unconditional break
> +# needs to be lowered, because it will no longer be at the end
> +# of the loop after the final break is added.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 1, 1)' <<EOF
> +((declare (in) float a) (declare (in) float ba) (declare (in) float bb)
> + (declare (in) float ca)
> + (declare (in) float cb)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ba) (constant float (0.000000)))
> + ((if (expression bool > (var_ref bb) (constant float (0.000000)))
> + (continue)
> + ()))
> + ())
> + (if (expression bool > (var_ref ca) (constant float (0.000000)))
> + ((if (expression bool > (var_ref cb) (constant float (0.000000)))
> + (break)
> + ()))
> + ()))
> + ())
> + break))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected b/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected
> new file mode 100644
> index 0000000..8222328
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_breaks_6.opt_test.expected
> @@ -0,0 +1,29 @@
> +((declare (in) float a) (declare (in) float ba) (declare (in) float bb)
> + (declare (in) float ca)
> + (declare (in) float cb)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool break_flag)
> + (assign (x) (var_ref break_flag) (constant bool (0)))
> + (loop () () () ()
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ba) (constant float (0.000000)))
> + ((if (expression bool > (var_ref bb) (constant float (0.000000)))
> + ((assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((if (expression bool > (var_ref ca) (constant float (0.000000)))
> + ((if (expression bool > (var_ref cb) (constant float (0.000000)))
> + ((assign (x) (var_ref break_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ()))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((assign (x) (var_ref break_flag) (constant bool (1))))
> + ())
> + (if (var_ref break_flag) (break) ())))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test b/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test
> new file mode 100755
> index 0000000..379aa59
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test
> @@ -0,0 +1,21 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Normally a conditional break at the end of a loop isn't
> +# lowered, however if the conditional break gets placed inside
> +# an if(execute_flag) because of earlier lowering of continues,
> +# then the break needs to be lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 1, 1)' <<EOF
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + (continue)
> + ()))
> + ())
> + (if (expression bool > (var_ref b) (constant float (0.000000))) (break)
> + ())))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected b/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected
> new file mode 100644
> index 0000000..7c6e73f
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_guarded_conditional_break.opt_test.expected
> @@ -0,0 +1,20 @@
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool break_flag)
> + (assign (x) (var_ref break_flag) (constant bool (0)))
> + (loop () () () ()
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + ((assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref break_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref break_flag) (break) ())))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test b/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test
> new file mode 100755
> index 0000000..15f3c41
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test
> @@ -0,0 +1,28 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If one branch of an if ends in a jump, and control cannot
> +# fall out the bottom of the other branch, and pull_out_jumps is
> +# True, then the jump is lifted outside the if.
> +# Verify that this lowering occurs during the same pass as the
> +# lowering of other jumps by checking that extra temporary
> +# variables aren't generated.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(1, 0, 1, 0, 0)' <<EOF
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (declare (in) float c)
> + (declare (out) float d)
> + (function main
> + (signature void (parameters)
> + ((if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())
> + (loop () () () ()
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((if (expression bool > (var_ref c) (constant float (0.000000))) (break)
> + (continue)))
> + ((return)))))
> + (assign (x) (var_ref d) (constant float (1.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected b/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected
> new file mode 100644
> index 0000000..bf45c2c
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_pulled_out_jump.opt_test.expected
> @@ -0,0 +1,25 @@
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (declare (in) float c)
> + (declare (out) float d)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + ((assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((loop () () () ()
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((if (expression bool > (var_ref c) (constant float (0.000000))) ()
> + (continue)))
> + ((assign (x) (var_ref return_flag) (constant bool (1)))))
> + break))
> + (if (var_ref return_flag) ()
> + ((assign (x) (var_ref d) (constant float (1.000000))))))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_1.opt_test b/src/glsl/tests/lower_jumps/lower_returns_1.opt_test
> new file mode 100755
> index 0000000..a1f895b
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_1.opt_test
> @@ -0,0 +1,12 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a void return at the end of a function is
> +# eliminated.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 1, 0, 0)' <<EOF
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((assign (x) (var_ref a) (constant float (1.000000))) (return)))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_1.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_1.opt_test.expected
> new file mode 100644
> index 0000000..7c3919c
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_1.opt_test.expected
> @@ -0,0 +1,4 @@
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((assign (x) (var_ref a) (constant float (1.000000)))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_2.opt_test b/src/glsl/tests/lower_jumps/lower_returns_2.opt_test
> new file mode 100755
> index 0000000..61673d4
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_2.opt_test
> @@ -0,0 +1,13 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that lowering is not performed on a non-void return at
> +# the end of subroutine.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 0)' <<EOF
> +((declare (out) float a)
> + (function sub
> + (signature float (parameters)
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (1.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_2.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_2.opt_test.expected
> new file mode 100644
> index 0000000..7777927
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_2.opt_test.expected
> @@ -0,0 +1,5 @@
> +((declare (out) float a)
> + (function sub
> + (signature float (parameters)
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (1.000000)))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_3.opt_test b/src/glsl/tests/lower_jumps/lower_returns_3.opt_test
> new file mode 100755
> index 0000000..9881e24
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_3.opt_test
> @@ -0,0 +1,20 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test lowering of returns when there is one nested inside a
> +# complex structure of ifs, and one at the end of a function.
> +# In this case, the latter return needs to be lowered because it
> +# will not be at the end of the function once the final return
> +# is inserted.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 0)' <<EOF
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature float (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return (constant float (1.000000))))
> + ()))
> + ())
> + (return (constant float (2.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected
> new file mode 100644
> index 0000000..d4835e9
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_3.opt_test.expected
> @@ -0,0 +1,21 @@
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature float (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) float return_value)
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref return_value) (constant float (1.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((assign (x) (var_ref return_value) (constant float (2.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ())
> + (return (var_ref return_value))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_4.opt_test b/src/glsl/tests/lower_jumps/lower_returns_4.opt_test
> new file mode 100755
> index 0000000..9f54c67
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_4.opt_test
> @@ -0,0 +1,14 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that returns are properly lowered when they occur in
> +# both branches of an if-statement.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 0)' <<EOF
> +((declare (in) float a)
> + (function sub
> + (signature float (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((return (constant float (1.000000))))
> + ((return (constant float (2.000000)))))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected
> new file mode 100644
> index 0000000..b551a06
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_4.opt_test.expected
> @@ -0,0 +1,16 @@
> +((declare (in) float a)
> + (function sub
> + (signature float (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) float return_value)
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((assign (x) (var_ref return_value) (constant float (1.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ((assign (x) (var_ref return_value) (constant float (2.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0)))))
> + (return (var_ref return_value))))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test b/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test
> new file mode 100755
> index 0000000..5f97bfd
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test
> @@ -0,0 +1,17 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that do_lower_jumps respects the lower_main_return
> +# flag in deciding whether to lower returns in the main
> +# function.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 0)' <<EOF
> +((declare (in) float a) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected
> new file mode 100644
> index 0000000..e8b36f1
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_main_false.opt_test.expected
> @@ -0,0 +1,8 @@
> +((declare (in) float a) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test b/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test
> new file mode 100755
> index 0000000..59c7ba1
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test
> @@ -0,0 +1,17 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that do_lower_jumps respects the lower_main_return
> +# flag in deciding whether to lower returns in the main
> +# function.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 1, 0, 0)' <<EOF
> +((declare (in) float a) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected
> new file mode 100644
> index 0000000..e15a97d
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_main_true.opt_test.expected
> @@ -0,0 +1,13 @@
> +((declare (in) float a) (declare (in) float b)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test b/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test
> new file mode 100755
> index 0000000..40e784e
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that do_lower_jumps respects the lower_sub_return flag
> +# in deciding whether to lower returns in subroutines.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 0)' <<EOF
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected
> new file mode 100644
> index 0000000..07db6e7
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_sub_false.opt_test.expected
> @@ -0,0 +1,8 @@
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test b/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test
> new file mode 100755
> index 0000000..9fe6b90
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that do_lower_jumps respects the lower_sub_return flag
> +# in deciding whether to lower returns in subroutines.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 0)' <<EOF
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature void (parameters)
> + ((if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected b/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected
> new file mode 100644
> index 0000000..3110980
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_returns_sub_true.opt_test.expected
> @@ -0,0 +1,13 @@
> +((declare (in) float a) (declare (in) float b)
> + (function sub
> + (signature void (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref a) (constant float (0.000000)))
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test b/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test
> new file mode 100755
> index 0000000..e716813
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test
> @@ -0,0 +1,26 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# If both branches of an if statement end in a return, and
> +# pull_out_jumps is True, then those returns should be lifted
> +# outside the if and then properly lowered.
> +# Verify that this lowering occurs during the same pass as the
> +# lowering of other returns by checking that extra temporary
> +# variables aren't generated.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(1, 0, 1, 0, 0)' <<EOF
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (declare (in) float c)
> + (function main
> + (signature void (parameters)
> + ((if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + ((return))
> + ()))
> + ())
> + (if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((if (expression bool > (var_ref c) (constant float (0.000000)))
> + ((return))
> + ((return))))
> + ())))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected b/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected
> new file mode 100644
> index 0000000..271cd3b
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/lower_unified_returns.opt_test.expected
> @@ -0,0 +1,21 @@
> +((declare (in) float aa) (declare (in) float ab) (declare (in) float b)
> + (declare (in) float c)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (if (expression bool > (var_ref aa) (constant float (0.000000)))
> + ((if (expression bool > (var_ref ab) (constant float (0.000000)))
> + ((assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())
> + (if (var_ref execute_flag)
> + ((if (expression bool > (var_ref b) (constant float (0.000000)))
> + ((if (expression bool > (var_ref c) (constant float (0.000000))) () ())
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0))))
> + ()))
> + ())))))
> diff --git a/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test b/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test
> new file mode 100755
> index 0000000..18efc37
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test
> @@ -0,0 +1,13 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a redundant continue-statement at the end of a
> +# loop is removed.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 0)' <<EOF
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) continue))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected b/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected
> new file mode 100644
> index 0000000..d2a02c6
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/remove_continue_at_end_of_loop.opt_test.expected
> @@ -0,0 +1,5 @@
> +((declare (out) float a)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))))))))
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test
> new file mode 100755
> index 0000000..79c0e82
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a non-void return at the end of a loop is
> +# properly lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 0)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (2.000000)))))
> + (assign (x) (var_ref b) (constant float (3.000000)))
> + (return (constant float (4.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected
> new file mode 100644
> index 0000000..2cf117a
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_nothing.opt_test.expected
> @@ -0,0 +1,8 @@
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (2.000000)))))
> + (assign (x) (var_ref b) (constant float (3.000000)))
> + (return (constant float (4.000000)))))))
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test
> new file mode 100755
> index 0000000..920d2ad
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a non-void return at the end of a loop is
> +# properly lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 0)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (2.000000)))))
> + (assign (x) (var_ref b) (constant float (3.000000)))
> + (return (constant float (4.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected
> new file mode 100644
> index 0000000..0bab8f1
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return.opt_test.expected
> @@ -0,0 +1,19 @@
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) float return_value)
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (assign (x) (var_ref return_value) (constant float (2.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + break))
> + (if (var_ref return_flag) ()
> + ((assign (x) (var_ref b) (constant float (3.000000)))
> + (assign (x) (var_ref return_value) (constant float (4.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0)))))
> + (return (var_ref return_value))))))
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test
> new file mode 100755
> index 0000000..99f1f86
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test
> @@ -0,0 +1,16 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a non-void return at the end of a loop is
> +# properly lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 1, 0, 0, 1)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (return (constant float (2.000000)))))
> + (assign (x) (var_ref b) (constant float (3.000000)))
> + (return (constant float (4.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> new file mode 100644
> index 0000000..0bab8f1
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_non_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> @@ -0,0 +1,19 @@
> +((declare (out) float a) (declare (out) float b)
> + (function sub
> + (signature float (parameters)
> + ((declare (temporary) bool execute_flag)
> + (assign (x) (var_ref execute_flag) (constant bool (1)))
> + (declare (temporary) float return_value)
> + (declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (assign (x) (var_ref return_value) (constant float (2.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + break))
> + (if (var_ref return_flag) ()
> + ((assign (x) (var_ref b) (constant float (3.000000)))
> + (assign (x) (var_ref return_value) (constant float (4.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + (assign (x) (var_ref execute_flag) (constant bool (0)))))
> + (return (var_ref return_value))))))
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test
> new file mode 100755
> index 0000000..63487d3
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test
> @@ -0,0 +1,14 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a return of void at the end of a loop is properly
> +# lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 0, 0, 0)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) (return)))
> + (assign (x) (var_ref b) (constant float (2.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected
> new file mode 100644
> index 0000000..0bd8037
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_nothing.opt_test.expected
> @@ -0,0 +1,6 @@
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) (return)))
> + (assign (x) (var_ref b) (constant float (2.000000)))))))
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test
> new file mode 100755
> index 0000000..523c92a
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test
> @@ -0,0 +1,14 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a return of void at the end of a loop is properly
> +# lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 1, 0, 0)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) (return)))
> + (assign (x) (var_ref b) (constant float (2.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected
> new file mode 100644
> index 0000000..53814ea
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return.opt_test.expected
> @@ -0,0 +1,11 @@
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + break))
> + (if (var_ref return_flag) ()
> + ((assign (x) (var_ref b) (constant float (2.000000)))))))))
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test
> new file mode 100755
> index 0000000..22b5581
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test
> @@ -0,0 +1,14 @@
> +#!/bin/bash
> +#
> +# This file was generated by create_test_cases.py.
> +#
> +# Test that a return of void at the end of a loop is properly
> +# lowered.
> +../../glsl_test optpass --quiet --input-ir 'do_lower_jumps(0, 0, 1, 0, 1)' <<EOF
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000))) (return)))
> + (assign (x) (var_ref b) (constant float (2.000000)))))))
> +EOF
> diff --git a/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> new file mode 100644
> index 0000000..53814ea
> --- /dev/null
> +++ b/src/glsl/tests/lower_jumps/return_void_at_end_of_loop_lower_return_and_break.opt_test.expected
> @@ -0,0 +1,11 @@
> +((declare (out) float a) (declare (out) float b)
> + (function main
> + (signature void (parameters)
> + ((declare (temporary) bool return_flag)
> + (assign (x) (var_ref return_flag) (constant bool (0)))
> + (loop () () () ()
> + ((assign (x) (var_ref a) (constant float (1.000000)))
> + (assign (x) (var_ref return_flag) (constant bool (1)))
> + break))
> + (if (var_ref return_flag) ()
> + ((assign (x) (var_ref b) (constant float (2.000000)))))))))
> diff --git a/src/glsl/tests/optimization-test b/src/glsl/tests/optimization-test
> new file mode 100755
> index 0000000..0c130be
> --- /dev/null
> +++ b/src/glsl/tests/optimization-test
> @@ -0,0 +1,28 @@
> +#!/bin/bash
> +
> +total=0
> +pass=0
> +
> +echo "====== Testing optimization passes ======"
> +for test in `find . -iname '*.opt_test'`; do
> + echo -n "Testing $test..."
> + (cd `dirname "$test"`; ./`basename "$test"`) > "$test.out" 2>&1
> + total=$((total+1))
> + if ./compare_ir "$test.expected" "$test.out" >/dev/null 2>&1; then
> + echo "PASS"
> + pass=$((pass+1))
> + else
> + echo "FAIL"
> + ./compare_ir "$test.expected" "$test.out"
> + fi
> +done
> +
> +echo ""
> +echo "$pass/$total tests returned correct results"
> +echo ""
> +
> +if [[ $pass == $total ]]; then
> + exit 0
> +else
> + exit 1
> +fi
> diff --git a/src/glsl/tests/sexps.py b/src/glsl/tests/sexps.py
> new file mode 100644
> index 0000000..a714af8
> --- /dev/null
> +++ b/src/glsl/tests/sexps.py
> @@ -0,0 +1,103 @@
> +# 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, basestring):
> + 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]+)?|[^ \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, basestring):
> + 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
> +
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAk4l5yYACgkQX1gOwKyEAw/bhgCghcKWzfsI6LZCG/imzWVJK1d2
ag0AoJID/DtoxGv+tp2ZFbAW40oUZHj5
=s8Ue
-----END PGP SIGNATURE-----
More information about the mesa-dev
mailing list