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