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