]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Make variable renaming while inlining more robust
[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 "evaluate.h"
7 #include "visitor.h"
8
9 namespace Msp {
10 namespace GL {
11 namespace SL {
12
13 /** Finds functions which are candidates for inlining.  Currently this means
14 functions which have no parameters, contain no more than one return statement,
15 and are only called once. */
16 class InlineableFunctionLocator: private TraversingVisitor
17 {
18 private:
19         std::map<FunctionDeclaration *, unsigned> refcounts;
20         std::set<FunctionDeclaration *> inlineable;
21         FunctionDeclaration *current_function;
22         unsigned return_count;
23
24 public:
25         InlineableFunctionLocator();
26
27         const std::set<FunctionDeclaration *> &apply(Stage &s) { s.content.visit(*this); return inlineable; }
28
29 private:
30         virtual void visit(FunctionCall &);
31         virtual void visit(FunctionDeclaration &);
32         virtual void visit(Conditional &);
33         virtual void visit(Iteration &);
34         virtual void visit(Return &);
35 };
36
37 /** Injects statements from one function into another.  Local variables are
38 renamed to avoid conflicts.  After inlining, uses NodeReorderer to cause
39 dependencies of the inlined statements to appear before the target function. */
40 class InlineContentInjector: private TraversingVisitor
41 {
42 private:
43         FunctionDeclaration *source_func;
44         Block *target_block;
45         std::map<std::string, VariableDeclaration *> variable_map;
46         std::string remap_prefix;
47         unsigned remap_names;
48         bool deps_only;
49         RefPtr<Statement> r_inlined_statement;
50         std::set<Node *> dependencies;
51         std::set<std::string> referenced_names;
52         std::string r_result_name;
53
54 public:
55         InlineContentInjector();
56
57         const std::string &apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionDeclaration &);
58
59 private:
60         virtual void visit(VariableReference &);
61         virtual void visit(InterfaceBlockReference &);
62         virtual void visit(FunctionCall &);
63         virtual void visit(VariableDeclaration &);
64         virtual void visit(Return &);
65 };
66
67 /** Inlines functions.  Internally uses InlineableFunctionLocator to find
68 candidate functions.  Only functions which consist of a single return statement
69 are inlined. */
70 class FunctionInliner: private TraversingVisitor
71 {
72 private:
73         Stage *stage;
74         std::set<FunctionDeclaration *> inlineable;
75         FunctionDeclaration *current_function;
76         NodeList<Statement>::iterator insert_point;
77         RefPtr<Expression> r_inline_result;
78         bool r_any_inlined;
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 /** Removes conditional statements and loops where the condition can be
141 determined as constant at compile time. */
142 class ConstantConditionEliminator: private TraversingVisitor
143 {
144 private:
145         NodeList<Statement>::iterator insert_point;
146         std::set<Node *> nodes_to_remove;
147
148 public:
149         void apply(Stage &);
150
151 private:
152         virtual void visit(Block &);
153         virtual void visit(Conditional &);
154         virtual void visit(Iteration &);
155 };
156
157 /** Removes types which are not used anywhere. */
158 class UnusedTypeRemover: private TraversingVisitor
159 {
160 private:
161         std::set<Node *> unused_nodes;
162
163 public:
164         bool apply(Stage &);
165
166 private:
167         virtual void visit(Literal &);
168         virtual void visit(UnaryExpression &);
169         virtual void visit(BinaryExpression &);
170         virtual void visit(TernaryExpression &);
171         virtual void visit(FunctionCall &);
172         virtual void visit(BasicTypeDeclaration &);
173         virtual void visit(ImageTypeDeclaration &);
174         virtual void visit(StructDeclaration &);
175         virtual void visit(VariableDeclaration &);
176         virtual void visit(InterfaceBlock &);
177         virtual void visit(FunctionDeclaration &);
178 };
179
180 /** Removes variable declarations with no references to them.  Assignment
181 statements where the result is not used are also removed. */
182 class UnusedVariableRemover: private TraversingVisitor
183 {
184 private:
185         struct AssignmentInfo
186         {
187                 Node *node;
188                 Assignment::Target target;
189                 std::vector<Node *> used_by;
190
191                 AssignmentInfo(): node(0) { }
192         };
193
194         struct VariableInfo
195         {
196                 InterfaceBlock *interface_block;
197                 std::vector<AssignmentInfo *> assignments;
198                 bool initialized;
199                 bool output;
200                 bool referenced;
201
202                 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
203         };
204
205         typedef std::map<Statement *, VariableInfo> BlockVariableMap;
206
207         Stage *stage;
208         BlockVariableMap variables;
209         std::list<AssignmentInfo> assignments;
210         InterfaceBlock *interface_block;
211         Assignment *r_assignment;
212         bool assignment_target;
213         bool r_side_effects;
214         std::set<Node *> unused_nodes;
215
216 public:
217         UnusedVariableRemover();
218
219         bool apply(Stage &);
220
221 private:
222         void referenced(const Assignment::Target &, Node &);
223         virtual void visit(VariableReference &);
224         virtual void visit(InterfaceBlockReference &);
225         virtual void visit(UnaryExpression &);
226         virtual void visit(BinaryExpression &);
227         virtual void visit(Assignment &);
228         virtual void visit(FunctionCall &);
229         void record_assignment(const Assignment::Target &, Node &);
230         virtual void visit(ExpressionStatement &);
231         // Ignore structs because their members can't be accessed directly.
232         virtual void visit(StructDeclaration &) { }
233         virtual void visit(VariableDeclaration &);
234         virtual void visit(InterfaceBlock &);
235         void merge_variables(const BlockVariableMap &);
236         virtual void visit(FunctionDeclaration &);
237         virtual void visit(Conditional &);
238         virtual void visit(Iteration &);
239 };
240
241 /** Removes function declarations with no references to them. */
242 class UnusedFunctionRemover: private TraversingVisitor
243 {
244 private:
245         std::set<Node *> unused_nodes;
246         std::set<FunctionDeclaration *> used_definitions;
247
248 public:
249         bool apply(Stage &s);
250
251 private:
252         virtual void visit(FunctionCall &);
253         virtual void visit(FunctionDeclaration &);
254 };
255
256 } // namespace SL
257 } // namespace GL
258 } // namespace Msp
259
260 #endif