]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Fix an issue where member assignments were incorrectly optimized away
[libs/gl.git] / source / glsl / optimize.h
1 #ifndef MSP_GL_SL_OPTIMIZE_H_
2 #define MSP_GL_SL_OPTIMIZE_H_
3
4 #include <map>
5 #include <set>
6 #include "evaluate.h"
7 #include "visitor.h"
8
9 namespace Msp {
10 namespace GL {
11 namespace SL {
12
13 /** Finds functions which are candidates for inlining.  Currently this means
14 functions which have no parameters, contain no more than one return statement,
15 and are only called once. */
16 class InlineableFunctionLocator: private TraversingVisitor
17 {
18 private:
19         std::map<FunctionDeclaration *, unsigned> refcounts;
20         std::set<FunctionDeclaration *> inlineable;
21         FunctionDeclaration *current_function;
22         unsigned return_count;
23
24 public:
25         InlineableFunctionLocator();
26
27         const std::set<FunctionDeclaration *> &apply(Stage &s) { s.content.visit(*this); return inlineable; }
28
29 private:
30         virtual void visit(FunctionCall &);
31         virtual void visit(FunctionDeclaration &);
32         virtual void visit(Conditional &);
33         virtual void visit(Iteration &);
34         virtual void visit(Return &);
35 };
36
37 /** Injects statements from one function into another.  Local variables are
38 renamed to avoid conflicts.  After inlining, uses NodeReorderer to cause
39 dependencies of the inlined statements to appear before the target function. */
40 class InlineContentInjector: private TraversingVisitor
41 {
42 private:
43         FunctionDeclaration *source_func;
44         Block *target_block;
45         std::map<std::string, VariableDeclaration *> variable_map;
46         bool remap_names;
47         bool deps_only;
48         RefPtr<Statement> r_inlined_statement;
49         std::set<Node *> dependencies;
50         std::string r_result_name;
51
52 public:
53         InlineContentInjector();
54
55         const std::string &apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionDeclaration &);
56
57 private:
58         std::string create_unused_name(const std::string &, bool);
59
60         virtual void visit(VariableReference &);
61         virtual void visit(InterfaceBlockReference &);
62         virtual void visit(FunctionCall &);
63         virtual void visit(VariableDeclaration &);
64         virtual void visit(Return &);
65 };
66
67 /** Inlines functions.  Internally uses InlineableFunctionLocator to find
68 candidate functions.  Only functions which consist of a single return statement
69 are inlined. */
70 class FunctionInliner: private TraversingVisitor
71 {
72 private:
73         Stage *stage;
74         std::set<FunctionDeclaration *> inlineable;
75         FunctionDeclaration *current_function;
76         NodeList<Statement>::iterator insert_point;
77         RefPtr<Expression> r_inline_result;
78         bool r_any_inlined;
79
80 public:
81         FunctionInliner();
82
83         bool apply(Stage &);
84
85 private:
86         void visit_and_inline(RefPtr<Expression> &);
87
88         virtual void visit(Block &);
89         virtual void visit(UnaryExpression &);
90         virtual void visit(BinaryExpression &);
91         virtual void visit(MemberAccess &);
92         virtual void visit(FunctionCall &);
93         virtual void visit(ExpressionStatement &);
94         virtual void visit(VariableDeclaration &);
95         virtual void visit(FunctionDeclaration &);
96         virtual void visit(Conditional &);
97         virtual void visit(Iteration &);
98         virtual void visit(Return &);
99 };
100
101 /** Removes conditional statements and loops where the condition can be
102 determined as constant at compile time. */
103 class ConstantConditionEliminator: private TraversingVisitor
104 {
105 private:
106         bool record_only;
107         ExpressionEvaluator::ValueMap variable_values;
108         NodeList<Statement>::iterator insert_point;
109         std::set<Node *> nodes_to_remove;
110
111 public:
112         ConstantConditionEliminator();
113
114         void apply(Stage &);
115
116 private:
117         virtual void visit(Block &);
118         virtual void visit(UnaryExpression &);
119         virtual void visit(Assignment &);
120         virtual void visit(VariableDeclaration &);
121         virtual void visit(Conditional &);
122         virtual void visit(Iteration &);
123 };
124
125 /** Removes variable declarations with no references to them.  Assignment
126 statements where the result is not used are also removed. */
127 class UnusedVariableRemover: private TraversingVisitor
128 {
129 private:
130         struct VariableInfo
131         {
132                 bool local;
133                 std::vector<Node *> assignments;
134                 bool conditionally_assigned;
135                 bool referenced;
136
137                 VariableInfo();
138         };
139
140         typedef std::map<VariableDeclaration *, VariableInfo> BlockVariableMap;
141
142         std::set<Node *> unused_nodes;
143         std::map<VariableDeclaration *, Node *> aggregates;
144         Node *aggregate;
145         std::vector<BlockVariableMap> variables;
146         Assignment *r_assignment;
147         bool assignment_target;
148         bool r_assign_to_subfield;
149         bool r_side_effects;
150
151 public:
152         UnusedVariableRemover();
153
154         bool apply(Stage &);
155
156 private:
157         virtual void visit(VariableReference &);
158         virtual void visit(InterfaceBlockReference &);
159         virtual void visit(MemberAccess &);
160         virtual void visit(UnaryExpression &);
161         virtual void visit(BinaryExpression &);
162         virtual void visit(Assignment &);
163         void record_assignment(VariableDeclaration &, Node &, bool);
164         void clear_assignments(VariableInfo &, bool);
165         virtual void visit(FunctionCall &);
166         virtual void visit(ExpressionStatement &);
167         virtual void visit(StructDeclaration &);
168         virtual void visit(VariableDeclaration &);
169         virtual void visit(InterfaceBlock &);
170         virtual void visit(FunctionDeclaration &);
171         void merge_down_variables();
172         virtual void visit(Conditional &);
173         virtual void visit(Iteration &);
174 };
175
176 /** Removes function declarations with no references to them. */
177 class UnusedFunctionRemover: private TraversingVisitor
178 {
179 private:
180         std::set<Node *> unused_nodes;
181         std::set<FunctionDeclaration *> used_definitions;
182
183 public:
184         bool apply(Stage &s);
185
186 private:
187         virtual void visit(FunctionCall &);
188         virtual void visit(FunctionDeclaration &);
189 };
190
191 } // namespace SL
192 } // namespace GL
193 } // namespace Msp
194
195 #endif