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