Commit 659cdedb authored by Paul Berry's avatar Paul Berry

glsl: Add unit tests for lower_jumps.cpp

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.
Acked-by: chadversary's avatarChad Versace <chad@chad-versace.us>
parent f1f76e15
......@@ -21,6 +21,10 @@ all: default
doxygen:
cd doxygen && $(MAKE)
check:
cd src/glsl/tests/ && ./optimization-test
@echo "All tests passed."
clean:
-@touch $(TOP)/configs/current
-@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:
......
#!/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)
This diff is collapsed.
#!/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
((declare (out) float a)
(function main
(signature void (parameters)
((loop () () () ()
((assign (x) (var_ref a) (constant float (1.000000))) break))))))
#!/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
((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)
())))))))
#!/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
((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)
())))))))
#!/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
((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))))))))
#!/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
((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))))))))
#!/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
((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) ())))))))
#!/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
((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) ())))))))
#!/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
((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))))))
())))))
#!/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
((declare (out) float a)
(function main
(signature void (parameters)
((assign (x) (var_ref a) (constant float (1.000000)))))))
#!/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
((declare (out) float a)
(function sub
(signature float (parameters)
((assign (x) (var_ref a) (constant float (1.000000)))
(return (constant float (1.000000)))))))
#!/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
((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))))))
#!/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
((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))))))
#!/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
((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))
()))
())))))
#!/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
((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))))
()))
())))))
#!/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
((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))
()))
())))))
#!/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
((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))))
()))
())))))
#!/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
((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))))
()))
())))))
#!/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
((declare (out) float a)
(function main
(signature void (parameters)
((loop () () () ()
((assign (x) (var_ref a) (constant float (1.000000)))))))))
#!/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