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