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