1 #ifndef MSP_GL_SL_OPTIMIZE_H_
2 #define MSP_GL_SL_OPTIMIZE_H_
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
18 std::map<FunctionDeclaration *, unsigned> refcounts;
19 std::set<FunctionDeclaration *> inlineable;
20 FunctionDeclaration *current_function;
21 unsigned return_count;
24 InlineableFunctionLocator();
26 const std::set<FunctionDeclaration *> &apply(Stage &s) { s.content.visit(*this); return inlineable; }
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 &);
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
42 FunctionDeclaration *source_func;
44 std::map<std::string, VariableDeclaration *> variable_map;
45 std::string remap_prefix;
48 RefPtr<Statement> r_inlined_statement;
49 std::set<Node *> dependencies;
50 std::set<std::string> referenced_names;
51 std::string r_result_name;
54 InlineContentInjector();
56 const std::string &apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionDeclaration &);
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 &);
66 /** Inlines functions. Internally uses InlineableFunctionLocator to find
67 candidate functions. Only functions which consist of a single return statement
69 class FunctionInliner: private TraversingVisitor
73 std::set<FunctionDeclaration *> inlineable;
74 FunctionDeclaration *current_function;
75 NodeList<Statement>::iterator insert_point;
76 RefPtr<Expression> r_inline_result;
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 &);
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
100 Expression *expression;
102 RefPtr<Expression> *inline_point;
109 std::map<Assignment::Target, ExpressionInfo> expressions;
110 ExpressionInfo *r_ref_info;
115 Block *iteration_body;
116 const Operator *r_oper;
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 &);
139 /** Replaces expressions consisting entirely of literals with the results of
140 evaluating the expression.*/
141 class ConstantFolder: private TraversingVisitor
144 VariableDeclaration *iteration_var;
145 Variant iter_init_value;
146 Variant r_constant_value;
150 bool r_uses_iter_var;
154 bool apply(Stage &s) { s.content.visit(*this); return r_any_folded; }
157 static BasicTypeDeclaration::Kind get_value_kind(const Variant &);
159 static T evaluate_logical(char, T, T);
161 static bool evaluate_relation(const char *, T, T);
163 static T evaluate_arithmetic(char, T, T);
164 void set_result(const Variant &, bool = false);
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 &);
180 /** Removes conditional statements and loops where the condition can be
181 determined as constant at compile time. */
182 class ConstantConditionEliminator: private TraversingVisitor
192 NodeList<Statement>::iterator insert_point;
193 std::set<Node *> nodes_to_remove;
199 ConstantStatus check_constant_condition(const Expression &);
201 virtual void visit(Block &);
202 virtual void visit(Conditional &);
203 virtual void visit(Iteration &);
206 /** Removes types which are not used anywhere. */
207 class UnusedTypeRemover: private TraversingVisitor
210 std::set<Node *> unused_nodes;
216 virtual void visit(Literal &);
217 virtual void visit(UnaryExpression &);
218 virtual void visit(BinaryExpression &);
219 virtual void visit(TernaryExpression &);
220 virtual void visit(FunctionCall &);
221 virtual void visit(BasicTypeDeclaration &);
222 virtual void visit(ImageTypeDeclaration &);
223 virtual void visit(StructDeclaration &);
224 virtual void visit(VariableDeclaration &);
225 virtual void visit(InterfaceBlock &);
226 virtual void visit(FunctionDeclaration &);
229 /** Removes variable declarations with no references to them. Assignment
230 statements where the result is not used are also removed. */
231 class UnusedVariableRemover: private TraversingVisitor
234 struct AssignmentInfo
237 Assignment::Target target;
238 std::vector<Node *> used_by;
240 AssignmentInfo(): node(0) { }
245 InterfaceBlock *interface_block;
246 std::vector<AssignmentInfo *> assignments;
251 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
254 typedef std::map<Statement *, VariableInfo> BlockVariableMap;
257 BlockVariableMap variables;
258 std::list<AssignmentInfo> assignments;
259 InterfaceBlock *interface_block;
260 Assignment *r_assignment;
261 bool assignment_target;
263 std::set<Node *> unused_nodes;
266 UnusedVariableRemover();
271 void referenced(const Assignment::Target &, Node &);
272 virtual void visit(VariableReference &);
273 virtual void visit(InterfaceBlockReference &);
274 virtual void visit(UnaryExpression &);
275 virtual void visit(BinaryExpression &);
276 virtual void visit(Assignment &);
277 virtual void visit(FunctionCall &);
278 void record_assignment(const Assignment::Target &, Node &);
279 virtual void visit(ExpressionStatement &);
280 // Ignore structs because their members can't be accessed directly.
281 virtual void visit(StructDeclaration &) { }
282 virtual void visit(VariableDeclaration &);
283 virtual void visit(InterfaceBlock &);
284 void merge_variables(const BlockVariableMap &);
285 virtual void visit(FunctionDeclaration &);
286 virtual void visit(Conditional &);
287 virtual void visit(Iteration &);
290 /** Removes function declarations with no references to them. */
291 class UnusedFunctionRemover: private TraversingVisitor
294 std::set<Node *> unused_nodes;
295 std::set<FunctionDeclaration *> used_definitions;
298 bool apply(Stage &s);
301 virtual void visit(FunctionCall &);
302 virtual void visit(FunctionDeclaration &);