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