• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 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 propagate_invariance.cpp
26  * Propagate the "invariant" and "precise" qualifiers to variables used to
27  * compute invariant or precise values.
28  *
29  * The GLSL spec (depending on what version you read) says, among the
30  * conditions for getting bit-for-bit the same values on an invariant output:
31  *
32  *    "All operations in the consuming expressions and any intermediate
33  *    expressions must be the same, with the same order of operands and same
34  *    associativity, to give the same order of evaluation."
35  *
36  * This effectively means that if a variable is used to compute an invariant
37  * value then that variable becomes invariant.  The same should apply to the
38  * "precise" qualifier.
39  */
40 
41 #include "ir.h"
42 #include "ir_visitor.h"
43 #include "ir_rvalue_visitor.h"
44 #include "ir_optimization.h"
45 #include "compiler/glsl_types.h"
46 
47 namespace {
48 
49 class ir_invariance_propagation_visitor : public ir_hierarchical_visitor {
50 public:
ir_invariance_propagation_visitor()51    ir_invariance_propagation_visitor()
52    {
53       this->progress = false;
54       this->dst_var = NULL;
55    }
56 
~ir_invariance_propagation_visitor()57    virtual ~ir_invariance_propagation_visitor()
58    {
59       /* empty */
60    }
61 
62    virtual ir_visitor_status visit_enter(ir_assignment *ir);
63    virtual ir_visitor_status visit_leave(ir_assignment *ir);
64    virtual ir_visitor_status visit(ir_dereference_variable *ir);
65 
66    ir_variable *dst_var;
67    bool progress;
68 };
69 
70 } /* unnamed namespace */
71 
72 ir_visitor_status
visit_enter(ir_assignment * ir)73 ir_invariance_propagation_visitor::visit_enter(ir_assignment *ir)
74 {
75    assert(this->dst_var == NULL);
76    ir_variable *var = ir->lhs->variable_referenced();
77    if (var->data.invariant || var->data.precise) {
78       this->dst_var = var;
79       return visit_continue;
80    } else {
81       return visit_continue_with_parent;
82    }
83 }
84 
85 ir_visitor_status
visit_leave(ir_assignment *)86 ir_invariance_propagation_visitor::visit_leave(ir_assignment *)
87 {
88    this->dst_var = NULL;
89 
90    return visit_continue;
91 }
92 
93 ir_visitor_status
visit(ir_dereference_variable * ir)94 ir_invariance_propagation_visitor::visit(ir_dereference_variable *ir)
95 {
96    if (this->dst_var == NULL)
97       return visit_continue;
98 
99    if (this->dst_var->data.invariant) {
100       if (!ir->var->data.invariant)
101          this->progress = true;
102 
103       ir->var->data.invariant = true;
104    }
105 
106    if (this->dst_var->data.precise) {
107       if (!ir->var->data.precise)
108          this->progress = true;
109 
110       ir->var->data.precise = true;
111    }
112 
113    return visit_continue;
114 }
115 
116 bool
propagate_invariance(exec_list * instructions)117 propagate_invariance(exec_list *instructions)
118 {
119    ir_invariance_propagation_visitor visitor;
120    bool progress = false;
121 
122    do {
123       visitor.progress = false;
124       visit_list_elements(&visitor, instructions);
125       progress = progress || visitor.progress;
126    } while (visitor.progress);
127 
128    return progress;
129 }
130