]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
e7592c00a29956e7ad4ab09384cf9798b3d1aacf
[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 "visitor.h"
7
8 namespace Msp {
9 namespace GL {
10 namespace SL {
11
12 /** Finds functions which are candidates for inlining.  Currently this means
13 functions which have no flow control statements, no more than one return
14 statement, and are only called once. */
15 class InlineableFunctionLocator: private TraversingVisitor
16 {
17 private:
18         std::map<FunctionDeclaration *, unsigned> refcounts;
19         std::set<FunctionDeclaration *> inlineable;
20         FunctionDeclaration *current_function;
21         unsigned return_count;
22
23 public:
24         InlineableFunctionLocator();
25
26         const std::set<FunctionDeclaration *> &apply(Stage &s) { s.content.visit(*this); return inlineable; }
27
28 private:
29         virtual void visit(FunctionCall &);
30         virtual void visit(FunctionDeclaration &);
31         virtual void visit(Conditional &);
32         virtual void visit(Iteration &);
33         virtual void visit(Return &);
34 };
35
36 /** Injects statements from one function into another.  Local variables are
37 renamed to avoid conflicts.  After inlining, uses NodeReorderer to cause
38 dependencies of the inlined statements to appear before the target function. */
39 class InlineContentInjector: private TraversingVisitor
40 {
41 private:
42         enum Pass
43         {
44                 DEPENDS,
45                 REFERENCED,
46                 INLINE,
47                 RENAME
48         };
49
50         FunctionDeclaration *source_func;
51         Block staging_block;
52         Pass pass;
53         RefPtr<Statement> r_inlined_statement;
54         std::set<Node *> dependencies;
55         std::set<std::string> referenced_names;
56         std::string r_result_name;
57
58 public:
59         InlineContentInjector();
60
61         const std::string &apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionCall &);
62
63 private:
64         virtual void visit(VariableReference &);
65         virtual void visit(InterfaceBlockReference &);
66         virtual void visit(FunctionCall &);
67         virtual void visit(VariableDeclaration &);
68         virtual void visit(Return &);
69 };
70
71 /** Inlines functions.  Internally uses InlineableFunctionLocator to find
72 candidate functions.  Only functions which consist of a single return statement
73 are inlined. */
74 class FunctionInliner: private TraversingVisitor
75 {
76 private:
77         Stage *stage;
78         std::set<FunctionDeclaration *> inlineable;
79         FunctionDeclaration *current_function;
80         NodeList<Statement>::iterator insert_point;
81         RefPtr<Expression> r_inline_result;
82         bool r_any_inlined;
83         bool r_inlined_here;
84
85 public:
86         FunctionInliner();
87
88         bool apply(Stage &);
89
90 private:
91         virtual void visit(RefPtr<Expression> &);
92         virtual void visit(Block &);
93         virtual void visit(FunctionCall &);
94         virtual void visit(FunctionDeclaration &);
95         virtual void visit(Iteration &);
96 };
97
98 /** Inlines variables into expressions.  Variables with trivial values (those
99 consisting of a single literal or variable reference) are always inlined.
100 Variables which are only referenced once are also inlined. */
101 class ExpressionInliner: private TraversingVisitor
102 {
103 private:
104         struct ExpressionInfo
105         {
106                 Expression *expression;
107                 Block *assign_scope;
108                 RefPtr<Expression> *inline_point;
109                 bool trivial;
110                 bool available;
111
112                 ExpressionInfo();
113         };
114
115         std::map<Assignment::Target, ExpressionInfo> expressions;
116         ExpressionInfo *r_ref_info;
117         bool r_any_inlined;
118         bool r_trivial;
119         bool mutating;
120         bool iteration_init;
121         Block *iteration_body;
122         const Operator *r_oper;
123
124 public:
125         ExpressionInliner();
126
127         bool apply(Stage &);
128
129 private:
130         void inline_expression(Expression &, RefPtr<Expression> &);
131         virtual void visit(Block &);
132         virtual void visit(RefPtr<Expression> &);
133         virtual void visit(VariableReference &);
134         virtual void visit(MemberAccess &);
135         virtual void visit(Swizzle &);
136         virtual void visit(UnaryExpression &);
137         virtual void visit(BinaryExpression &);
138         virtual void visit(Assignment &);
139         virtual void visit(TernaryExpression &);
140         virtual void visit(FunctionCall &);
141         virtual void visit(VariableDeclaration &);
142         virtual void visit(Iteration &);
143 };
144
145 /** Replaces expressions consisting entirely of literals with the results of
146 evaluating the expression.*/
147 class ConstantFolder: private TraversingVisitor
148 {
149 private:
150         VariableDeclaration *iteration_var;
151         Variant iter_init_value;
152         Variant r_constant_value;
153         bool iteration_init;
154         bool r_constant;
155         bool r_literal;
156         bool r_uses_iter_var;
157         bool r_any_folded;
158
159 public:
160         bool apply(Stage &s) { s.content.visit(*this); return r_any_folded; }
161
162 private:
163         static BasicTypeDeclaration::Kind get_value_kind(const Variant &);
164         template<typename T>
165         static T evaluate_logical(char, T, T);
166         template<typename T>
167         static bool evaluate_relation(const char *, T, T);
168         template<typename T>
169         static T evaluate_arithmetic(char, T, T);
170         void set_result(const Variant &, bool = false);
171
172         virtual void visit(RefPtr<Expression> &);
173         virtual void visit(Literal &);
174         virtual void visit(VariableReference &);
175         virtual void visit(MemberAccess &);
176         virtual void visit(Swizzle &);
177         virtual void visit(UnaryExpression &);
178         virtual void visit(BinaryExpression &);
179         virtual void visit(Assignment &);
180         virtual void visit(TernaryExpression &);
181         virtual void visit(FunctionCall &);
182         virtual void visit(VariableDeclaration &);
183         virtual void visit(Iteration &);
184 };
185
186 /** Removes conditional statements and loops where the condition can be
187 determined as constant at compile time. */
188 class ConstantConditionEliminator: private TraversingVisitor
189 {
190 private:
191         enum ConstantStatus
192         {
193                 CONSTANT_FALSE,
194                 CONSTANT_TRUE,
195                 NOT_CONSTANT
196         };
197
198         NodeList<Statement>::iterator insert_point;
199         std::set<Node *> nodes_to_remove;
200         RefPtr<Expression> r_ternary_result;
201
202 public:
203         void apply(Stage &);
204
205 private:
206         ConstantStatus check_constant_condition(const Expression &);
207
208         virtual void visit(Block &);
209         virtual void visit(RefPtr<Expression> &);
210         virtual void visit(TernaryExpression &);
211         virtual void visit(Conditional &);
212         virtual void visit(Iteration &);
213 };
214
215 /** Removes types which are not used anywhere. */
216 class UnusedTypeRemover: private TraversingVisitor
217 {
218 private:
219         std::set<Node *> unused_nodes;
220
221 public:
222         bool apply(Stage &);
223
224 private:
225         virtual void visit(Literal &);
226         virtual void visit(UnaryExpression &);
227         virtual void visit(BinaryExpression &);
228         virtual void visit(TernaryExpression &);
229         virtual void visit(FunctionCall &);
230         virtual void visit(BasicTypeDeclaration &);
231         virtual void visit(ImageTypeDeclaration &);
232         virtual void visit(StructDeclaration &);
233         virtual void visit(VariableDeclaration &);
234         virtual void visit(InterfaceBlock &);
235         virtual void visit(FunctionDeclaration &);
236 };
237
238 /** Removes variable declarations with no references to them.  Assignment
239 statements where the result is not used are also removed. */
240 class UnusedVariableRemover: private TraversingVisitor
241 {
242 private:
243         struct AssignmentInfo
244         {
245                 Node *node;
246                 Assignment::Target target;
247                 std::vector<Node *> used_by;
248
249                 AssignmentInfo(): node(0) { }
250         };
251
252         struct VariableInfo
253         {
254                 InterfaceBlock *interface_block;
255                 std::vector<AssignmentInfo *> assignments;
256                 bool initialized;
257                 bool output;
258                 bool referenced;
259
260                 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
261         };
262
263         typedef std::map<Statement *, VariableInfo> BlockVariableMap;
264
265         Stage *stage;
266         BlockVariableMap variables;
267         std::list<AssignmentInfo> assignments;
268         InterfaceBlock *interface_block;
269         Assignment *r_assignment;
270         bool assignment_target;
271         bool r_side_effects;
272         std::set<Node *> unused_nodes;
273
274 public:
275         UnusedVariableRemover();
276
277         bool apply(Stage &);
278
279 private:
280         void referenced(const Assignment::Target &, Node &);
281         virtual void visit(VariableReference &);
282         virtual void visit(InterfaceBlockReference &);
283         virtual void visit(UnaryExpression &);
284         virtual void visit(BinaryExpression &);
285         virtual void visit(Assignment &);
286         virtual void visit(FunctionCall &);
287         void record_assignment(const Assignment::Target &, Node &);
288         virtual void visit(ExpressionStatement &);
289         // Ignore structs because their members can't be accessed directly.
290         virtual void visit(StructDeclaration &) { }
291         virtual void visit(VariableDeclaration &);
292         virtual void visit(InterfaceBlock &);
293         void merge_variables(const BlockVariableMap &);
294         virtual void visit(FunctionDeclaration &);
295         virtual void visit(Conditional &);
296         virtual void visit(Iteration &);
297 };
298
299 /** Removes function declarations with no references to them. */
300 class UnusedFunctionRemover: private TraversingVisitor
301 {
302 private:
303         std::set<Node *> unused_nodes;
304         std::set<FunctionDeclaration *> used_definitions;
305
306 public:
307         bool apply(Stage &s);
308
309 private:
310         virtual void visit(FunctionCall &);
311         virtual void visit(FunctionDeclaration &);
312 };
313
314 } // namespace SL
315 } // namespace GL
316 } // namespace Msp
317
318 #endif