1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# coding=utf-8
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Copyright © 2011 Intel Corporation
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Permission is hereby granted, free of charge, to any person obtaining a
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# copy of this software and associated documentation files (the "Software"),
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# to deal in the Software without restriction, including without limitation
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# and/or sell copies of the Software, and to permit persons to whom the
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Software is furnished to do so, subject to the following conditions:
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The above copyright notice and this permission notice (including the next
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# paragraph) shall be included in all copies or substantial portions of the
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Software.
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# DEALINGS IN THE SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport os
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport os.path
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport re
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport subprocess
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport sys
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) # For access to sexps.py, which is in parent dir
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfrom sexps import *
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef make_test_case(f_name, ret_type, body):
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a simple optimization test case consisting of a single
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    function with the given name, return type, and body.
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Global declarations are automatically created for any undeclared
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    variables that are referenced by the function.  All undeclared
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    variables are assumed to be floats.
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(body)
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    declarations = {}
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def make_declarations(sexp, already_declared = ()):
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if isinstance(sexp, list):
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if len(sexp) == 2 and sexp[0] == 'var_ref':
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if sexp[1] not in already_declared:
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    declarations[sexp[1]] = [
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        'declare', ['in'], 'float', sexp[1]]
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            elif len(sexp) == 4 and sexp[0] == 'assign':
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                assert sexp[2][0] == 'var_ref'
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if sexp[2][1] not in already_declared:
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    declarations[sexp[2][1]] = [
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        'declare', ['out'], 'float', sexp[2][1]]
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                make_declarations(sexp[3], already_declared)
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            else:
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                already_declared = set(already_declared)
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                for s in sexp:
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    if isinstance(s, list) and len(s) >= 4 and \
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            s[0] == 'declare':
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        already_declared.add(s[3])
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    else:
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        make_declarations(s, already_declared)
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    make_declarations(body)
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return declarations.values() + \
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        [['function', f_name, ['signature', ret_type, ['parameters'], body]]]
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The following functions can be used to build expressions.
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef const_float(value):
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create an expression representing the given floating point value."""
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ['constant', 'float', ['{0:.6f}'.format(value)]]
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef const_bool(value):
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create an expression representing the given boolean value.
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    If value is not a boolean, it is converted to a boolean.  So, for
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    instance, const_bool(1) is equivalent to const_bool(True).
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ['constant', 'bool', ['{0}'.format(1 if value else 0)]]
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef gt_zero(var_name):
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create Construct the expression var_name > 0"""
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ['expression', 'bool', '>', ['var_ref', var_name], const_float(0)]
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The following functions can be used to build complex control flow
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# statements.  All of these functions return statement lists (even
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# those which only create a single statement), so that statements can
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# be sequenced together using the '+' operator.
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef return_(value = None):
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a return statement."""
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if value is not None:
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return [['return', value]]
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else:
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return [['return']]
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef break_():
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a break statement."""
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ['break']
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef continue_():
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a continue statement."""
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ['continue']
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef simple_if(var_name, then_statements, else_statements = None):
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a statement of the form
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (var_name > 0.0) {
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       <then_statements>
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else {
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       <else_statements>
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else_statements may be omitted.
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if else_statements is None:
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else_statements = []
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(then_statements)
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(else_statements)
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['if', gt_zero(var_name), then_statements, else_statements]]
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef loop(statements):
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a loop containing the given statements as its loop
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    body.
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(statements)
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['loop', [], [], [], [], statements]]
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef declare_temp(var_type, var_name):
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a declaration of the form
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    (declare (temporary) <var_type> <var_name)
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['declare', ['temporary'], var_type, var_name]]
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef assign_x(var_name, value):
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a statement that assigns <value> to the variable
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    <var_name>.  The assignment uses the mask (x).
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(value)
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['assign', ['x'], ['var_ref', var_name], value]]
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef complex_if(var_prefix, statements):
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a statement of the form
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (<var_prefix>a > 0.0) {
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       if (<var_prefix>b > 0.0) {
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          <statements>
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       }
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    This is useful in testing jump lowering, because if <statements>
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ends in a jump, lower_jumps.cpp won't try to combine this
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    construct with the code that follows it, as it might do for a
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    simple if.
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    All variables used in the if statement are prefixed with
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    var_prefix.  This can be used to ensure uniqueness.
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(statements)
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return simple_if(var_prefix + 'a', simple_if(var_prefix + 'b', statements))
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef declare_execute_flag():
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp uses to declare and
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initialize the temporary boolean execute_flag.
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return declare_temp('bool', 'execute_flag') + \
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        assign_x('execute_flag', const_bool(True))
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef declare_return_flag():
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp uses to declare and
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initialize the temporary boolean return_flag.
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return declare_temp('bool', 'return_flag') + \
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        assign_x('return_flag', const_bool(False))
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef declare_return_value():
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp uses to declare and
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initialize the temporary variable return_value.  Assume that
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return_value is a float.
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return declare_temp('float', 'return_value')
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef declare_break_flag():
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp uses to declare and
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initialize the temporary boolean break_flag.
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return declare_temp('bool', 'break_flag') + \
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        assign_x('break_flag', const_bool(False))
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef lowered_return_simple(value = None):
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp lowers a return
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    statement to, in situations where it does not need to clear the
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    execute flag.
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if value:
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        result = assign_x('return_value', value)
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else:
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        result = []
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return result + assign_x('return_flag', const_bool(True))
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef lowered_return(value = None):
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statements that lower_jumps.cpp lowers a return
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    statement to, in situations where it needs to clear the execute
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    flag.
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return lowered_return_simple(value) + \
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        assign_x('execute_flag', const_bool(False))
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef lowered_continue():
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statement that lower_jumps.cpp lowers a continue
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    statement to.
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return assign_x('execute_flag', const_bool(False))
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef lowered_break_simple():
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statement that lower_jumps.cpp lowers a break
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    statement to, in situations where it does not need to clear the
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    execute flag.
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return assign_x('break_flag', const_bool(True))
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef lowered_break():
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the statement that lower_jumps.cpp lowers a break
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    statement to, in situations where it needs to clear the execute
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    flag.
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return lowered_break_simple() + assign_x('execute_flag', const_bool(False))
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef if_execute_flag(statements):
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Wrap statements in an if test so that they will only execute if
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    execute_flag is True.
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(statements)
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['if', ['var_ref', 'execute_flag'], statements, []]]
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef if_not_return_flag(statements):
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Wrap statements in an if test so that they will only execute if
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return_flag is False.
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(statements)
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['if', ['var_ref', 'return_flag'], [], statements]]
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef final_return():
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the return statement that lower_jumps.cpp places at the
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    end of a function when lowering returns.
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['return', ['var_ref', 'return_value']]]
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef final_break():
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create the conditional break statement that lower_jumps.cpp
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    places at the end of a function when lowering breaks.
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return [['if', ['var_ref', 'break_flag'], break_(), []]]
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef bash_quote(*args):
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Quote the arguments appropriately so that bash will understand
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    each argument as a single word.
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    def quote_word(word):
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for c in word:
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if not (c.isalpha() or c.isdigit() or c in '@%_-+=:,./'):
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        else:
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if not word:
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                return "''"
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return word
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return "'{0}'".format(word.replace("'", "'\"'\"'"))
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ' '.join(quote_word(word) for word in args)
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef create_test_case(doc_string, input_sexp, expected_sexp, test_name,
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     pull_out_jumps=False, lower_sub_return=False,
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=False, lower_continue=False,
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_break=False):
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Create a test case that verifies that do_lower_jumps transforms
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    the given code in the expected way.
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_lines = [line.strip() for line in doc_string.splitlines()]
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = ''.join('# {0}\n'.format(line) for line in doc_lines if line != '')
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(input_sexp)
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    check_sexp(expected_sexp)
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_str = sexp_to_string(sort_decls(input_sexp))
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_output = sexp_to_string(sort_decls(expected_sexp))
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    optimization = (
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        'do_lower_jumps({0:d}, {1:d}, {2:d}, {3:d}, {4:d})'.format(
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            pull_out_jumps, lower_sub_return, lower_main_return,
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            lower_continue, lower_break))
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    args = ['../../glsl_test', 'optpass', '--quiet', '--input-ir', optimization]
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_file = '{0}.opt_test'.format(test_name)
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    with open(test_file, 'w') as f:
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        f.write('#!/bin/bash\n#\n# This file was generated by create_test_cases.py.\n#\n')
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        f.write(doc_string)
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        f.write('{0} <<EOF\n'.format(bash_quote(*args)))
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        f.write('{0}\nEOF\n'.format(input_str))
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    os.chmod(test_file, 0774)
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_file = '{0}.opt_test.expected'.format(test_name)
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    with open(expected_file, 'w') as f:
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        f.write('{0}\n'.format(expected_output))
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_main():
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that do_lower_jumps respects the lower_main_return
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    flag in deciding whether to lower returns in the main
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    function.
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', return_())
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', lowered_return())
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_main_true',
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True)
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_main_false',
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=False)
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_sub():
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that do_lower_jumps respects the lower_sub_return flag
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    in deciding whether to lower returns in subroutines.
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('sub', 'void', (
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', return_())
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('sub', 'void', (
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', lowered_return())
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_sub_true',
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True)
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_sub_false',
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=False)
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_1():
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that a void return at the end of a function is
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    eliminated.
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('a', const_float(1)) +
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return_()
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('a', const_float(1))
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_1',
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True)
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_2():
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that lowering is not performed on a non-void return at
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    the end of subroutine.
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('sub', 'float', (
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('a', const_float(1)) +
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return_(const_float(1))
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, input_sexp, 'lower_returns_2',
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True)
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_3():
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test lowering of returns when there is one nested inside a
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    complex structure of ifs, and one at the end of a function.
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    In this case, the latter return needs to be lowered because it
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    will not be at the end of the function once the final return
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    is inserted.
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('sub', 'float', (
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', return_(const_float(1))) +
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return_(const_float(2))
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('sub', 'float', (
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_value() +
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('', lowered_return(const_float(1))) +
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if_execute_flag(lowered_return(const_float(2))) +
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            final_return()
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_3',
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True)
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_returns_4():
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that returns are properly lowered when they occur in
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    both branches of an if-statement.
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('sub', 'float', (
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            simple_if('a', return_(const_float(1)),
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      return_(const_float(2)))
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('sub', 'float', (
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_value() +
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            simple_if('a', lowered_return(const_float(1)),
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      lowered_return(const_float(2))) +
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            final_return()
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_returns_4',
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True)
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_unified_returns():
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If both branches of an if statement end in a return, and
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    pull_out_jumps is True, then those returns should be lifted
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    outside the if and then properly lowered.
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Verify that this lowering occurs during the same pass as the
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    lowering of other returns by checking that extra temporary
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    variables aren't generated.
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('a', return_()) +
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            simple_if('b', simple_if('c', return_(), return_()))
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('a', lowered_return()) +
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if_execute_flag(simple_if('b', (simple_if('c', [], []) +
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                            lowered_return())))
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_unified_returns',
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True, pull_out_jumps=True)
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_pulled_out_jump():
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If one branch of an if ends in a jump, and control cannot
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    fall out the bottom of the other branch, and pull_out_jumps is
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    True, then the jump is lifted outside the if.
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Verify that this lowering occurs during the same pass as the
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    lowering of other jumps by checking that extra temporary
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    variables aren't generated.
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('a', return_()) +
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(simple_if('b', simple_if('c', break_(), continue_()),
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           return_())) +
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('d', const_float(1))
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Note: optimization produces two other effects: the break
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # gets lifted out of the if statements, and the code after the
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # loop gets guarded so that it only executes if the return
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # flag is clear.
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            complex_if('a', lowered_return()) +
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if_execute_flag(
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                loop(simple_if('b', simple_if('c', [], continue_()),
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               lowered_return_simple()) +
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     break_()) +
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if_not_return_flag(assign_x('d', const_float(1))))
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_pulled_out_jump',
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True, pull_out_jumps=True)
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_1():
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains an unconditional break at the bottom of
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    it, it should not be lowered."""
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 break_())
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = input_sexp
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_1', lower_break=True)
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_2():
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains a conditional break at the bottom of it,
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    it should not be lowered if it is in the then-clause.
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if('b', break_()))
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = input_sexp
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_2', lower_break=True)
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_3():
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains a conditional break at the bottom of it,
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    it should not be lowered if it is in the then-clause, even if
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    there are statements preceding the break.
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if('b', (assign_x('c', const_float(1)) +
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 break_())))
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = input_sexp
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_3', lower_break=True)
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_4():
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains a conditional break at the bottom of it,
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    it should not be lowered if it is in the else-clause.
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if('b', [], break_()))
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = input_sexp
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_4', lower_break=True)
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_5():
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains a conditional break at the bottom of it,
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    it should not be lowered if it is in the else-clause, even if
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    there are statements preceding the break.
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if('b', [], (assign_x('c', const_float(1)) +
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     break_())))
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = input_sexp
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_5', lower_break=True)
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_breaks_6():
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """If a loop contains conditional breaks and continues, and
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ends in an unconditional break, then the unconditional break
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    needs to be lowered, because it will no longer be at the end
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    of the loop after the final break is added.
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(simple_if('a', (complex_if('b', continue_()) +
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 complex_if('c', break_()))) +
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 break_())
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_break_flag() +
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(declare_execute_flag() +
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if(
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    'a',
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    (complex_if('b', lowered_continue()) +
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     if_execute_flag(
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            complex_if('c', lowered_break())))) +
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 if_execute_flag(lowered_break_simple()) +
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 final_break())
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_breaks_6',
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_break=True, lower_continue=True)
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_guarded_conditional_break():
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Normally a conditional break at the end of a loop isn't
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    lowered, however if the conditional break gets placed inside
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    an if(execute_flag) because of earlier lowering of continues,
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    then the break needs to be lowered.
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(complex_if('a', continue_()) +
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 simple_if('b', break_()))
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_break_flag() +
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(declare_execute_flag() +
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 complex_if('a', lowered_continue()) +
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 if_execute_flag(simple_if('b', lowered_break())) +
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 final_break())
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'lower_guarded_conditional_break',
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_break=True, lower_continue=True)
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_remove_continue_at_end_of_loop():
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that a redundant continue-statement at the end of a
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    loop is removed.
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 continue_())
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)))
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'remove_continue_at_end_of_loop')
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_return_void_at_end_of_loop():
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that a return of void at the end of a loop is properly
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    lowered.
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('main', 'void', (
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 return_()) +
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('b', const_float(2))
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('main', 'void', (
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 lowered_return_simple() +
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 break_()) +
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if_not_return_flag(assign_x('b', const_float(2)))
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, input_sexp, 'return_void_at_end_of_loop_lower_nothing')
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return',
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True)
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'return_void_at_end_of_loop_lower_return_and_break',
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_main_return=True, lower_break=True)
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef test_lower_return_non_void_at_end_of_loop():
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    doc_string = """Test that a non-void return at the end of a loop is
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    properly lowered.
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    input_sexp = make_test_case('sub', 'float', (
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 return_(const_float(2))) +
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assign_x('b', const_float(3)) +
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return_(const_float(4))
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    expected_sexp = make_test_case('sub', 'float', (
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_execute_flag() +
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_value() +
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            declare_return_flag() +
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            loop(assign_x('a', const_float(1)) +
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 lowered_return_simple(const_float(2)) +
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                 break_()) +
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if_not_return_flag(assign_x('b', const_float(3)) +
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               lowered_return(const_float(4))) +
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            final_return()
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ))
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, input_sexp, 'return_non_void_at_end_of_loop_lower_nothing')
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return',
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True)
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    create_test_case(doc_string, input_sexp, expected_sexp, 'return_non_void_at_end_of_loop_lower_return_and_break',
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     lower_sub_return=True, lower_break=True)
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgif __name__ == '__main__':
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_main()
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_sub()
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_1()
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_2()
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_3()
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_returns_4()
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_unified_returns()
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_pulled_out_jump()
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_1()
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_2()
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_3()
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_4()
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_5()
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_breaks_6()
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_guarded_conditional_break()
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_remove_continue_at_end_of_loop()
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_return_void_at_end_of_loop()
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    test_lower_return_non_void_at_end_of_loop()
644