summaryrefslogtreecommitdiff
path: root/lib/mesa/src/compiler/glsl/tests
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2019-01-29 11:08:07 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2019-01-29 11:08:07 +0000
commit6b139c2063623e9310025247cd966490b9aa57ea (patch)
tree375acfd898ca3d721250aa17291bbb90a8d7250a /lib/mesa/src/compiler/glsl/tests
parentcce99579dcfb1d54c54cff65573be3430e77f2c5 (diff)
Import Mesa 18.3.2
Diffstat (limited to 'lib/mesa/src/compiler/glsl/tests')
-rw-r--r--lib/mesa/src/compiler/glsl/tests/.deps/cache_test-cache_test.Po1
-rw-r--r--lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp1
-rw-r--r--lib/mesa/src/compiler/glsl/tests/lower_jump_cases.py643
-rw-r--r--lib/mesa/src/compiler/glsl/tests/meson.build110
-rw-r--r--lib/mesa/src/compiler/glsl/tests/optimization_test.py96
-rw-r--r--lib/mesa/src/compiler/glsl/tests/sexps.py11
-rw-r--r--lib/mesa/src/compiler/glsl/tests/warnings_test.py73
7 files changed, 891 insertions, 44 deletions
diff --git a/lib/mesa/src/compiler/glsl/tests/.deps/cache_test-cache_test.Po b/lib/mesa/src/compiler/glsl/tests/.deps/cache_test-cache_test.Po
new file mode 100644
index 000000000..9ce06a81e
--- /dev/null
+++ b/lib/mesa/src/compiler/glsl/tests/.deps/cache_test-cache_test.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp b/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
index 0d8f4521c..45c204dc2 100644
--- a/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
+++ b/lib/mesa/src/compiler/glsl/tests/array_refcount_test.cpp
@@ -160,7 +160,6 @@ validate_variables_in_hash_table(struct hash_table *ht,
va_end(args);
- struct hash_entry *entry;
hash_table_foreach(ht, entry) {
const ir_instruction *const ir = (ir_instruction *) entry->key;
const ir_variable *const v = ir->as_variable();
diff --git a/lib/mesa/src/compiler/glsl/tests/lower_jump_cases.py b/lib/mesa/src/compiler/glsl/tests/lower_jump_cases.py
new file mode 100644
index 000000000..1977f3a9b
--- /dev/null
+++ b/lib/mesa/src/compiler/glsl/tests/lower_jump_cases.py
@@ -0,0 +1,643 @@
+# 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,
+ lower_break=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}, {4:d})'.format(
+ pull_out_jumps, lower_sub_return, lower_main_return,
+ lower_continue, lower_break))
+
+ return (test_name, optimization, input_str, expected_output)
+
+def test_lower_returns_main():
+ """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())
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_returns_main_true',
+ lower_main_return=True)
+ yield create_test_case(
+ input_sexp, input_sexp, 'lower_returns_main_false',
+ lower_main_return=False)
+
+def test_lower_returns_sub():
+ """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())
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_returns_sub_true',
+ lower_sub_return=True)
+ yield create_test_case(
+ input_sexp, input_sexp, 'lower_returns_sub_false',
+ lower_sub_return=False)
+
+def test_lower_returns_1():
+ """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))
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_returns_1', lower_main_return=True)
+
+def test_lower_returns_2():
+ """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))
+ ))
+ yield create_test_case(
+ input_sexp, input_sexp, 'lower_returns_2', lower_sub_return=True)
+
+def test_lower_returns_3():
+ """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()
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_returns_3', lower_sub_return=True)
+
+def test_lower_returns_4():
+ """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()
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_returns_4', lower_sub_return=True)
+
+def test_lower_unified_returns():
+ """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())))
+ ))
+ yield create_test_case(
+ 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_return_flag(assign_x('return_flag', const_bool(1)) +
+ assign_x('execute_flag', const_bool(0)),
+ assign_x('d', const_float(1))))
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_pulled_out_jump',
+ lower_main_return=True, pull_out_jumps=True)
+
+def test_lower_breaks_1():
+ """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
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_1', lower_break=True)
+
+def test_lower_breaks_2():
+ """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
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_2', lower_break=True)
+
+def test_lower_breaks_3():
+ """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
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_3', lower_break=True)
+
+def test_lower_breaks_4():
+ """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
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_4', lower_break=True)
+
+def test_lower_breaks_5():
+ """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
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_5', lower_break=True)
+
+def test_lower_breaks_6():
+ """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())
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_breaks_6', lower_break=True,
+ lower_continue=True)
+
+def test_lower_guarded_conditional_break():
+ """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())
+ ))
+ yield create_test_case(
+ input_sexp, expected_sexp, 'lower_guarded_conditional_break',
+ lower_break=True, lower_continue=True)
+
+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')
+
+def test_lower_return_void_at_end_of_loop():
+ """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_execute_flag() +
+ declare_return_flag() +
+ loop(assign_x('a', const_float(1)) +
+ lowered_return_simple() +
+ break_()) +
+ if_return_flag(assign_x('return_flag', const_bool(1)) +
+ assign_x('execute_flag', const_bool(0)),
+ assign_x('b', const_float(2)))
+ ))
+ yield create_test_case(
+ input_sexp, input_sexp, 'return_void_at_end_of_loop_lower_nothing')
+ yield create_test_case(
+ input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return',
+ lower_main_return=True)
+ yield create_test_case(
+ 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():
+ """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_return_flag(assign_x('return_value', '(var_ref return_value)') +
+ assign_x('return_flag', const_bool(1)) +
+ assign_x('execute_flag', const_bool(0)),
+ assign_x('b', const_float(3)) +
+ lowered_return(const_float(4))) +
+ final_return()
+ ))
+ yield create_test_case(
+ input_sexp, input_sexp, 'return_non_void_at_end_of_loop_lower_nothing')
+ yield create_test_case(
+ input_sexp, expected_sexp,
+ 'return_non_void_at_end_of_loop_lower_return', lower_sub_return=True)
+ yield create_test_case(
+ input_sexp, expected_sexp,
+ 'return_non_void_at_end_of_loop_lower_return_and_break',
+ lower_sub_return=True, lower_break=True)
+
+CASES = [
+ 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_lower_pulled_out_jump,
+ test_lower_return_non_void_at_end_of_loop,
+ test_lower_return_void_at_end_of_loop,
+ test_lower_returns_1, test_lower_returns_2, test_lower_returns_3,
+ test_lower_returns_4, test_lower_returns_main, test_lower_returns_sub,
+ test_lower_unified_returns, test_remove_continue_at_end_of_loop,
+]
diff --git a/lib/mesa/src/compiler/glsl/tests/meson.build b/lib/mesa/src/compiler/glsl/tests/meson.build
index 27f34075b..2a41e30a2 100644
--- a/lib/mesa/src/compiler/glsl/tests/meson.build
+++ b/lib/mesa/src/compiler/glsl/tests/meson.build
@@ -18,59 +18,87 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-glsl_blob_test = executable(
+test(
'blob_test',
- 'blob_test.c',
- c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
- include_directories : [inc_common, inc_compiler],
- link_with : [libglsl],
+ executable(
+ 'blob_test',
+ 'blob_test.c',
+ c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
+ include_directories : [inc_common, inc_compiler],
+ link_with : [libglsl],
+ )
)
-glsl_cache_test = executable(
+test(
'cache_test',
- 'cache_test.c',
- c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
- include_directories : [inc_common, inc_glsl],
- link_with : [libglsl],
- dependencies : [dep_clock, dep_thread],
+ executable(
+ 'cache_test',
+ 'cache_test.c',
+ c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl],
+ dependencies : [dep_clock, dep_thread],
+ )
)
-glsl_general_ir_test = executable(
+
+test(
'general_ir_test',
- ['array_refcount_test.cpp', 'builtin_variable_test.cpp',
- 'invalidate_locations_test.cpp', 'general_ir_test.cpp',
- 'lower_int64_test.cpp', 'opt_add_neg_to_sub_test.cpp', 'varyings_test.cpp',
- ir_expression_operation_h],
- cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
- include_directories : [inc_common, inc_glsl],
- link_with : [libglsl, libglsl_standalone, libglsl_util],
- dependencies : [dep_clock, dep_thread, idep_gtest],
+ executable(
+ 'general_ir_test',
+ ['array_refcount_test.cpp', 'builtin_variable_test.cpp',
+ 'invalidate_locations_test.cpp', 'general_ir_test.cpp',
+ 'lower_int64_test.cpp', 'opt_add_neg_to_sub_test.cpp',
+ 'varyings_test.cpp', ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_standalone, libglsl_util],
+ dependencies : [dep_clock, dep_thread, idep_gtest],
+ )
)
-glsl_uniform_initializer_test = executable(
+test(
'uniform_initializer_test',
- ['copy_constant_to_storage_tests.cpp', 'set_uniform_initializer_tests.cpp',
- 'uniform_initializer_utils.cpp', 'uniform_initializer_utils.h',
- ir_expression_operation_h],
- cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
- include_directories : [inc_common, inc_glsl],
- link_with : [libglsl, libglsl_util],
- dependencies : [dep_thread, idep_gtest],
+ executable(
+ 'uniform_initializer_test',
+ ['copy_constant_to_storage_tests.cpp', 'set_uniform_initializer_tests.cpp',
+ 'uniform_initializer_utils.cpp', 'uniform_initializer_utils.h',
+ ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_util],
+ dependencies : [dep_thread, idep_gtest],
+ )
)
-glsl_sampler_types_test = executable(
+test(
'sampler_types_test',
- ['sampler_types_test.cpp', ir_expression_operation_h],
- cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
- include_directories : [inc_common, inc_glsl],
- link_with : [libglsl, libglsl_util],
- dependencies : [dep_thread, idep_gtest],
+ executable(
+ 'sampler_types_test',
+ ['sampler_types_test.cpp', ir_expression_operation_h],
+ cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
+ include_directories : [inc_common, inc_glsl],
+ link_with : [libglsl, libglsl_util],
+ dependencies : [dep_thread, idep_gtest],
+ )
)
-test('blob_test', glsl_blob_test)
-test('cache_test', glsl_cache_test)
-test('general_ir_test', glsl_general_ir_test)
-test('uniform_initializer_test', glsl_uniform_initializer_test)
-test('sampler_types_test', glsl_sampler_types_test)
-
-# TODO: figure out how to get the shell based tests to work?
+test(
+ 'glsl compiler warnings',
+ prog_python,
+ args : [
+ join_paths(meson.current_source_dir(), 'warnings_test.py'),
+ '--glsl-compiler', glsl_compiler,
+ '--test-directory', join_paths(
+ meson.source_root(), 'src', 'compiler', 'glsl', 'tests', 'warnings'
+ ),
+ ],
+)
+test(
+ 'glsl optimization',
+ prog_python,
+ args : [
+ join_paths(meson.current_source_dir(), 'optimization_test.py'),
+ '--test-runner', glsl_test
+ ],
+)
diff --git a/lib/mesa/src/compiler/glsl/tests/optimization_test.py b/lib/mesa/src/compiler/glsl/tests/optimization_test.py
new file mode 100644
index 000000000..15ca3216f
--- /dev/null
+++ b/lib/mesa/src/compiler/glsl/tests/optimization_test.py
@@ -0,0 +1,96 @@
+# 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."""
+
+from __future__ import print_function
+import argparse
+import difflib
+import subprocess
+import sys
+
+import sexps
+import lower_jump_cases
+
+
+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 main():
+ """Generate each test and report pass or fail."""
+ args = arg_parser()
+
+ total = 0
+ passes = 0
+
+ for gen in lower_jump_cases.CASES:
+ for name, opt, source, expected in gen():
+ total += 1
+ print('{}: '.format(name), end='')
+ proc = subprocess.Popen(
+ [args.test_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 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__':
+ main()
diff --git a/lib/mesa/src/compiler/glsl/tests/sexps.py b/lib/mesa/src/compiler/glsl/tests/sexps.py
index a714af8d2..7939b42f9 100644
--- a/lib/mesa/src/compiler/glsl/tests/sexps.py
+++ b/lib/mesa/src/compiler/glsl/tests/sexps.py
@@ -28,6 +28,11 @@
# as ['constant', 'float', ['1.000000']].
import re
+import sys
+if sys.version_info >= (3, 0, 0):
+ STRING_TYPE = str
+else:
+ STRING_TYPE = unicode
def check_sexp(sexp):
"""Verify that the argument is a proper sexp.
@@ -39,7 +44,7 @@ def check_sexp(sexp):
if isinstance(sexp, list):
for s in sexp:
check_sexp(s)
- elif not isinstance(sexp, basestring):
+ elif not isinstance(sexp, (STRING_TYPE, bytes)):
raise Exception('Not a sexp: {0!r}'.format(sexp))
def parse_sexp(sexp):
@@ -70,8 +75,10 @@ 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):
+ if isinstance(sexp, STRING_TYPE):
return sexp
+ if isinstance(sexp, bytes):
+ return sexp.encode('utf-8')
assert isinstance(sexp, list)
result = ''
for s in sexp:
diff --git a/lib/mesa/src/compiler/glsl/tests/warnings_test.py b/lib/mesa/src/compiler/glsl/tests/warnings_test.py
new file mode 100644
index 000000000..2c4fa5a0d
--- /dev/null
+++ b/lib/mesa/src/compiler/glsl/tests/warnings_test.py
@@ -0,0 +1,73 @@
+# encoding=utf-8
+# Copyright © 2017 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.
+
+from __future__ import print_function
+import argparse
+import os
+import subprocess
+
+
+def arg_parser():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--glsl-compiler',
+ required=True,
+ help='Path to the standalone glsl compiler')
+ parser.add_argument(
+ '--test-directory',
+ required=True,
+ help='Directory containing tests to run.')
+ return parser.parse_args()
+
+
+def main():
+ args = arg_parser()
+ files = [f for f in os.listdir(args.test_directory) if f.endswith('.vert')]
+ passed = 0
+
+ if not files:
+ print('Could not find any tests')
+ exit(1)
+
+ print('====== Testing compilation output ======')
+ for file in files:
+ print('Testing {} ...'.format(file), end='')
+ file = os.path.join(args.test_directory, file)
+
+ with open('{}.expected'.format(file), 'rb') as f:
+ expected = f.read().strip()
+
+ actual = subprocess.check_output(
+ [args.glsl_compiler, '--just-log', '--version', '150', file]
+ ).strip()
+
+ if actual == expected:
+ print('PASS')
+ passed += 1
+ else:
+ print('FAIL')
+
+ print('{}/{} tests returned correct results'.format(passed, len(files)))
+ exit(0 if passed == len(files) else 1)
+
+
+if __name__ == '__main__':
+ main()