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