Move the IR sexp builder helpers and test script creation parts of
tests/lower_jumps/create_test_cases.py into tests/test_case_generator.py
No functional changes.
Signed-off-by: Petri Latvala <petri.latv...@intel.com>
---
src/glsl/tests/lower_jumps/create_test_cases.py | 336 +++---------------------
src/glsl/tests/test_case_generator.py | 293 +++++++++++++++++++++
2 files changed, 334 insertions(+), 295 deletions(-)
create mode 100644 src/glsl/tests/test_case_generator.py
diff --git a/src/glsl/tests/lower_jumps/create_test_cases.py
b/src/glsl/tests/lower_jumps/create_test_cases.py
index 3be1079..9783627 100644
--- a/src/glsl/tests/lower_jumps/create_test_cases.py
+++ b/src/glsl/tests/lower_jumps/create_test_cases.py
@@ -27,278 +27,9 @@ 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
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) # For access
to sexps.py and test_case_generator.py, which are 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('#!/usr/bin/env 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))
+from test_case_generator import *
def test_lower_returns_main():
doc_string = """Test that do_lower_jumps respects the lower_main_return
@@ -314,9 +45,9 @@ def test_lower_returns_main():
complex_if('', lowered_return())
))
create_test_case(doc_string, input_sexp, expected_sexp,
'lower_returns_main_true',
- lower_main_return=True)
+ create_opt_string(lower_main_return=True))
create_test_case(doc_string, input_sexp, input_sexp,
'lower_returns_main_false',
- lower_main_return=False)
+ create_opt_string(lower_main_return=False))
def test_lower_returns_sub():
doc_string = """Test that do_lower_jumps respects the lower_sub_return
flag
@@ -331,9 +62,9 @@ def test_lower_returns_sub():
complex_if('', lowered_return())
))
create_test_case(doc_string, input_sexp, expected_sexp,
'lower_returns_sub_true',
- lower_sub_return=True)
+ create_opt_string(lower_sub_return=True))
create_test_case(doc_string, input_sexp, input_sexp,
'lower_returns_sub_false',
- lower_sub_return=False)
+ create_opt_string(lower_sub_return=False))
def test_lower_returns_1():
doc_string = """Test that a void return at the end of a function is
@@ -347,7 +78,7 @@ def test_lower_returns_1():
assign_x('a', const_float(1))
))
create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_1',
- lower_main_return=True)
+ create_opt_string(lower_main_return=True))
def test_lower_returns_2():
doc_string = """Test that lowering is not performed on a non-void return
at
@@ -358,7 +89,7 @@ def test_lower_returns_2():
return_(const_float(1))
))
create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_2',
- lower_sub_return=True)
+ create_opt_string(lower_sub_return=True))
def test_lower_returns_3():
doc_string = """Test lowering of returns when there is one nested inside a
@@ -381,7 +112,7 @@ def test_lower_returns_3():
final_return()
))
create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_3',
- lower_sub_return=True)
+ create_opt_string(lower_sub_return=True))
def test_lower_returns_4():
doc_string = """Test that returns are properly lowered when they occur in
@@ -400,7 +131,7 @@ def test_lower_returns_4():
final_return()
))
create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_4',
- lower_sub_return=True)
+ create_opt_string(lower_sub_return=True))
def test_lower_unified_returns():
doc_string = """If both branches of an if statement end in a return, and
@@ -423,7 +154,7 @@ def test_lower_unified_returns():
lowered_return())))
))
create_test_case(doc_string, input_sexp, expected_sexp,
'lower_unified_returns',
- lower_main_return=True, pull_out_jumps=True)
+ create_opt_string(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
@@ -455,7 +186,7 @@ def test_lower_pulled_out_jump():
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)
+ create_opt_string(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
@@ -465,7 +196,8 @@ def test_lower_breaks_1():
break_())
))
expected_sexp = input_sexp
- create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1',
lower_break=True)
+ create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1',
+ create_opt_string(lower_break=True))
def test_lower_breaks_2():
doc_string = """If a loop contains a conditional break at the bottom of
it,
@@ -476,7 +208,8 @@ def test_lower_breaks_2():
simple_if('b', break_()))
))
expected_sexp = input_sexp
- create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2',
lower_break=True)
+ create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2',
+ create_opt_string(lower_break=True))
def test_lower_breaks_3():
doc_string = """If a loop contains a conditional break at the bottom of
it,
@@ -489,7 +222,8 @@ def test_lower_breaks_3():
break_())))
))
expected_sexp = input_sexp
- create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3',
lower_break=True)
+ create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3',
+ create_opt_string(lower_break=True))
def test_lower_breaks_4():
doc_string = """If a loop contains a conditional break at the bottom of
it,
@@ -500,7 +234,8 @@ def test_lower_breaks_4():
simple_if('b', [], break_()))
))
expected_sexp = input_sexp
- create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4',
lower_break=True)
+ create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4',
+ create_opt_string(lower_break=True))
def test_lower_breaks_5():
doc_string = """If a loop contains a conditional break at the bottom of
it,
@@ -513,7 +248,8 @@ def test_lower_breaks_5():
break_())))
))
expected_sexp = input_sexp
- create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5',
lower_break=True)
+ create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5',
+ create_opt_string(lower_break=True))
def test_lower_breaks_6():
doc_string = """If a loop contains conditional breaks and continues, and
@@ -538,7 +274,7 @@ def test_lower_breaks_6():
final_break())
))
create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_6',
- lower_break=True, lower_continue=True)
+ create_opt_string(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
@@ -558,7 +294,7 @@ def test_lower_guarded_conditional_break():
final_break())
))
create_test_case(doc_string, input_sexp, expected_sexp,
'lower_guarded_conditional_break',
- lower_break=True, lower_continue=True)
+ create_opt_string(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
@@ -571,7 +307,8 @@ def test_remove_continue_at_end_of_loop():
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')
+ create_test_case(doc_string, input_sexp, expected_sexp,
'remove_continue_at_end_of_loop',
+ create_opt_string())
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
@@ -589,11 +326,12 @@ def test_lower_return_void_at_end_of_loop():
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, input_sexp,
'return_void_at_end_of_loop_lower_nothing',
+ create_opt_string())
create_test_case(doc_string, input_sexp, expected_sexp,
'return_void_at_end_of_loop_lower_return',
- lower_main_return=True)
+ create_opt_string(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)
+ create_opt_string(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
@@ -616,11 +354,19 @@ def test_lower_return_non_void_at_end_of_loop():
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, input_sexp,
'return_non_void_at_end_of_loop_lower_nothing',
+ create_opt_string())
create_test_case(doc_string, input_sexp, expected_sexp,
'return_non_void_at_end_of_loop_lower_return',
- lower_sub_return=True)
+ create_opt_string(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)
+ create_opt_string(lower_sub_return=True,
lower_break=True))
+
+def create_opt_string(pull_out_jumps=False, lower_sub_return=False,
+ lower_main_return=False, lower_continue=False,
+ lower_break=False):
+ return ('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))
if __name__ == '__main__':
test_lower_returns_main()
diff --git a/src/glsl/tests/test_case_generator.py
b/src/glsl/tests/test_case_generator.py
new file mode 100644
index 0000000..d6754fc8
--- /dev/null
+++ b/src/glsl/tests/test_case_generator.py
@@ -0,0 +1,293 @@
+# coding=utf-8
+#
+# Copyright © 2011 Intel Corporation