• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2010 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /**
25  * \file opt_redundant_jumps.cpp
26  * Remove certain types of redundant jumps
27  */
28 
29 #include "ir.h"
30 
31 class redundant_jumps_visitor : public ir_hierarchical_visitor {
32 public:
redundant_jumps_visitor()33    redundant_jumps_visitor()
34    {
35       this->progress = false;
36    }
37 
38    virtual ir_visitor_status visit_leave(ir_if *);
39    virtual ir_visitor_status visit_leave(ir_loop *);
40 
41    bool progress;
42 };
43 
44 
45 ir_visitor_status
visit_leave(ir_if * ir)46 redundant_jumps_visitor::visit_leave(ir_if *ir)
47 {
48    /* If the last instruction in both branches is a 'break' or a 'continue',
49     * pull it out of the branches and insert it after the if-statment.  Note
50     * that both must be the same type (either 'break' or 'continue').
51     */
52    ir_instruction *const last_then =
53       (ir_instruction *) ir->then_instructions.get_tail();
54    ir_instruction *const last_else =
55       (ir_instruction *) ir->else_instructions.get_tail();
56 
57    if ((last_then == NULL) || (last_else == NULL))
58       return visit_continue;
59 
60    if ((last_then->ir_type != ir_type_loop_jump)
61        || (last_else->ir_type != ir_type_loop_jump))
62       return visit_continue;
63 
64    ir_loop_jump *const then_jump = (ir_loop_jump *) last_then;
65    ir_loop_jump *const else_jump = (ir_loop_jump *) last_else;
66 
67    if (then_jump->mode != else_jump->mode)
68       return visit_continue;
69 
70    then_jump->remove();
71    else_jump->remove();
72    this->progress = true;
73 
74    ir->insert_after(then_jump);
75 
76    /* If both branchs of the if-statement are now empty, remove the
77     * if-statement.
78     */
79    if (ir->then_instructions.is_empty() && ir->else_instructions.is_empty())
80       ir->remove();
81 
82    return visit_continue;
83 }
84 
85 
86 ir_visitor_status
visit_leave(ir_loop * ir)87 redundant_jumps_visitor::visit_leave(ir_loop *ir)
88 {
89    /* If the last instruction of a loop body is a 'continue', remove it.
90     */
91    ir_instruction *const last =
92       (ir_instruction *) ir->body_instructions.get_tail();
93 
94    if (last && (last->ir_type == ir_type_loop_jump)
95        && (((ir_loop_jump *) last)->mode == ir_loop_jump::jump_continue)) {
96       last->remove();
97       this->progress = true;
98    }
99 
100    return visit_continue;
101 }
102 
103 
104 bool
optimize_redundant_jumps(exec_list * instructions)105 optimize_redundant_jumps(exec_list *instructions)
106 {
107    redundant_jumps_visitor v;
108 
109    v.run(instructions);
110    return v.progress;
111 }
112