1 #ifndef MSP_GL_SL_OPTIMIZE_H_
2 #define MSP_GL_SL_OPTIMIZE_H_
12 /** Assigns values to specialization constants, turning them into normal
14 class ConstantSpecializer: private TraversingVisitor
17 const std::map<std::string, int> *values = 0;
20 void apply(Stage &, const std::map<std::string, int> &);
23 virtual void visit(VariableDeclaration &);
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
32 std::map<FunctionDeclaration *, unsigned> refcounts;
33 std::set<FunctionDeclaration *> inlineable;
34 FunctionDeclaration *current_function = 0;
35 unsigned return_count = 0;
38 std::set<FunctionDeclaration *> apply(Stage &s) { s.content.visit(*this); return inlineable; }
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 &);
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
61 FunctionDeclaration *source_func = 0;
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;
70 std::string apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionCall &);
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 &);
80 /** Inlines functions. Internally uses InlineableFunctionLocator to find
81 candidate functions. Only functions which consist of a single return statement
83 class FunctionInliner: private TraversingVisitor
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;
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 &);
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
113 RefPtr<Expression> *reference = 0;
114 Block *ref_scope = 0;
115 bool blocked = false;
118 struct ExpressionInfo
120 Assignment::Target target;
121 RefPtr<Expression> expression;
122 Block *assign_scope = 0;
123 std::vector<ExpressionUse> uses;
124 bool trivial = false;
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;
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 &);
155 Breaks aggregates up into separate variables if only the individual fields are
156 accessed and not the aggregate as a whole.
158 class AggregateDismantler: public TraversingVisitor
161 struct AggregateMember
163 const VariableDeclaration *declaration = 0;
164 RefPtr<Expression> initializer;
165 std::vector<RefPtr<Expression> *> references;
170 VariableDeclaration *declaration = 0;
171 Block *decl_scope = 0;
172 NodeList<Statement>::iterator insert_point;
173 std::vector<AggregateMember> members;
174 bool referenced = false;
175 bool members_referenced = false;
178 NodeList<Statement>::iterator insert_point;
179 std::map<Statement *, Aggregate> aggregates;
180 bool composite_reference = false;
181 Assignment::Target r_reference;
182 Aggregate *r_aggregate_ref = 0;
188 virtual void visit(Block &);
189 virtual void visit(RefPtr<Expression> &);
190 virtual void visit(VariableReference &);
191 void visit_composite(RefPtr<Expression> &);
192 virtual void visit(MemberAccess &);
193 virtual void visit(BinaryExpression &);
194 virtual void visit(StructDeclaration &) { }
195 virtual void visit(VariableDeclaration &);
196 virtual void visit(InterfaceBlock &) { }
199 /** Replaces expressions consisting entirely of literals with the results of
200 evaluating the expression.*/
201 class ConstantFolder: private TraversingVisitor
204 VariableDeclaration *iteration_var = 0;
205 Variant iter_init_value;
206 Variant r_constant_value;
207 bool iteration_init = false;
208 bool r_constant = false;
209 bool r_literal = false;
210 bool r_uses_iter_var = false;
211 bool r_any_folded = false;
214 bool apply(Stage &s) { s.content.visit(*this); return r_any_folded; }
218 static T evaluate_logical(char, T, T);
220 static bool evaluate_relation(const char *, T, T);
222 static T evaluate_arithmetic(char, T, T);
224 static T evaluate_int_special_op(char, T, T);
226 void convert_to_result(const Variant &);
227 void set_result(const Variant &, bool = false);
229 virtual void visit(RefPtr<Expression> &);
230 virtual void visit(Literal &);
231 virtual void visit(VariableReference &);
232 virtual void visit(MemberAccess &);
233 virtual void visit(Swizzle &);
234 virtual void visit(UnaryExpression &);
235 virtual void visit(BinaryExpression &);
236 virtual void visit(Assignment &);
237 virtual void visit(TernaryExpression &);
238 virtual void visit(FunctionCall &);
239 virtual void visit(VariableDeclaration &);
240 virtual void visit(Iteration &);
243 /** Removes conditional statements and loops where the condition can be
244 determined as constant at compile time. Also removes such statements where
245 the body is empty and the condition has no side effects. */
246 class ConstantConditionEliminator: private TraversingVisitor
256 NodeList<Statement>::iterator insert_point;
257 std::set<Node *> nodes_to_remove;
258 RefPtr<Expression> r_ternary_result;
259 bool r_external_side_effects = false;
265 ConstantStatus check_constant_condition(const Expression &);
267 virtual void visit(Block &);
268 virtual void visit(RefPtr<Expression> &);
269 virtual void visit(UnaryExpression &);
270 virtual void visit(Assignment &);
271 virtual void visit(TernaryExpression &);
272 virtual void visit(FunctionCall &);
273 virtual void visit(Conditional &);
274 virtual void visit(Iteration &);
277 class UnreachableCodeRemover: private TraversingVisitor
280 bool reachable = true;
281 std::set<Node *> unreachable_nodes;
284 virtual bool apply(Stage &);
287 virtual void visit(Block &);
288 virtual void visit(FunctionDeclaration &);
289 virtual void visit(Conditional &);
290 virtual void visit(Iteration &);
291 virtual void visit(Return &) { reachable = false; }
292 virtual void visit(Jump &) { reachable = false; }
295 /** Removes types which are not used anywhere. */
296 class UnusedTypeRemover: private TraversingVisitor
299 std::set<Node *> unused_nodes;
305 virtual void visit(RefPtr<Expression> &);
306 virtual void visit(BasicTypeDeclaration &);
307 virtual void visit(ImageTypeDeclaration &);
308 virtual void visit(StructDeclaration &);
309 virtual void visit(VariableDeclaration &);
310 virtual void visit(InterfaceBlock &);
311 virtual void visit(FunctionDeclaration &);
314 /** Removes variable declarations with no references to them. Assignment
315 statements where the result is not used are also removed. */
316 class UnusedVariableRemover: private TraversingVisitor
319 struct AssignmentInfo
322 Assignment::Target target;
323 std::vector<Node *> used_by;
324 unsigned in_loop = 0;
329 InterfaceBlock *interface_block = 0;
330 std::vector<AssignmentInfo *> assignments;
331 bool initialized = false;
333 bool referenced = false;
336 typedef std::map<Statement *, VariableInfo> BlockVariableMap;
339 BlockVariableMap variables;
340 std::list<AssignmentInfo> assignments;
341 InterfaceBlock *interface_block = 0;
342 Assignment *r_assignment = 0;
343 bool assignment_target = false;
344 bool r_side_effects = false;
345 bool in_struct = false;
346 bool composite_reference = false;
347 unsigned in_loop = 0;
348 std::vector<Node *> loop_ext_refs;
349 Assignment::Target r_reference;
350 std::set<Node *> unused_nodes;
356 void referenced(const Assignment::Target &, Node &);
357 virtual void visit(VariableReference &);
358 virtual void visit(InterfaceBlockReference &);
359 void visit_composite(Expression &);
360 virtual void visit(MemberAccess &);
361 virtual void visit(Swizzle &);
362 virtual void visit(UnaryExpression &);
363 virtual void visit(BinaryExpression &);
364 virtual void visit(Assignment &);
365 virtual void visit(TernaryExpression &);
366 virtual void visit(FunctionCall &);
367 void record_assignment(const Assignment::Target &, Node &);
368 virtual void visit(ExpressionStatement &);
369 virtual void visit(StructDeclaration &);
370 virtual void visit(VariableDeclaration &);
371 virtual void visit(InterfaceBlock &);
372 void merge_variables(const BlockVariableMap &);
373 virtual void visit(FunctionDeclaration &);
374 virtual void visit(Conditional &);
375 virtual void visit(Iteration &);
378 /** Removes function declarations with no references to them. */
379 class UnusedFunctionRemover: private TraversingVisitor
382 std::set<Node *> unused_nodes;
383 std::set<FunctionDeclaration *> used_definitions;
386 bool apply(Stage &s);
389 virtual void visit(FunctionCall &);
390 virtual void visit(FunctionDeclaration &);