Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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_if_simplification.cpp
26
 *
27
 * Moves constant branches of if statements out to the surrounding
28
 * instruction stream, and inverts if conditionals to avoid empty
29
 * "then" blocks.
30
 */
31
 
32
#include "ir.h"
33
 
34
namespace {
35
 
36
class ir_if_simplification_visitor : public ir_hierarchical_visitor {
37
public:
38
   ir_if_simplification_visitor()
39
   {
40
      this->made_progress = false;
41
   }
42
 
43
   ir_visitor_status visit_leave(ir_if *);
44
   ir_visitor_status visit_enter(ir_assignment *);
45
 
46
   bool made_progress;
47
};
48
 
49
} /* unnamed namespace */
50
 
51
/* We only care about the top level "if" instructions, so don't
52
 * descend into expressions.
53
 */
54
ir_visitor_status
55
ir_if_simplification_visitor::visit_enter(ir_assignment *ir)
56
{
57
   (void) ir;
58
   return visit_continue_with_parent;
59
}
60
 
61
bool
62
do_if_simplification(exec_list *instructions)
63
{
64
   ir_if_simplification_visitor v;
65
 
66
   v.run(instructions);
67
   return v.made_progress;
68
}
69
 
70
 
71
ir_visitor_status
72
ir_if_simplification_visitor::visit_leave(ir_if *ir)
73
{
74
   /* If the if statement has nothing on either side, remove it. */
75
   if (ir->then_instructions.is_empty() &&
76
       ir->else_instructions.is_empty()) {
77
      ir->remove();
78
      this->made_progress = true;
79
      return visit_continue;
80
   }
81
 
82
   /* FINISHME: Ideally there would be a way to note that the condition results
83
    * FINISHME: in a constant before processing both of the other subtrees.
84
    * FINISHME: This can probably be done with some flags, but it would take
85
    * FINISHME: some work to get right.
86
    */
87
   ir_constant *condition_constant = ir->condition->constant_expression_value();
88
   if (condition_constant) {
89
      /* Move the contents of the one branch of the conditional
90
       * that matters out.
91
       */
92
      if (condition_constant->value.b[0]) {
93
	 foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
94
	    ir_instruction *then_ir = (ir_instruction *)then_iter.get();
95
	    ir->insert_before(then_ir);
96
	 }
97
      } else {
98
	 foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
99
	    ir_instruction *else_ir = (ir_instruction *)else_iter.get();
100
	    ir->insert_before(else_ir);
101
	 }
102
      }
103
      ir->remove();
104
      this->made_progress = true;
105
      return visit_continue;
106
   }
107
 
108
   /* Turn:
109
    *
110
    *     if (cond) {
111
    *     } else {
112
    *         do_work();
113
    *     }
114
    *
115
    * into :
116
    *
117
    *     if (!cond)
118
    *         do_work();
119
    *
120
    * which avoids control flow for "else" (which is usually more
121
    * expensive than normal operations), and the "not" can usually be
122
    * folded into the generation of "cond" anyway.
123
    */
124
   if (ir->then_instructions.is_empty()) {
125
      ir->condition = new(ralloc_parent(ir->condition))
126
	 ir_expression(ir_unop_logic_not, ir->condition);
127
      ir->else_instructions.move_nodes_to(&ir->then_instructions);
128
      this->made_progress = true;
129
   }
130
 
131
   return visit_continue;
132
}