]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Move unique name generation to syntax.cpp
[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         bool remap_names;
47         bool deps_only;
48         RefPtr<Statement> r_inlined_statement;
49         std::set<Node *> dependencies;
50         std::string r_result_name;
51
52 public:
53         InlineContentInjector();
54
55         const std::string &apply(Stage &, FunctionDeclaration &, Block &, const NodeList<Statement>::iterator &, FunctionDeclaration &);
56
57 private:
58         virtual void visit(VariableReference &);
59         virtual void visit(InterfaceBlockReference &);
60         virtual void visit(FunctionCall &);
61         virtual void visit(VariableDeclaration &);
62         virtual void visit(Return &);
63 };
64
65 /** Inlines functions.  Internally uses InlineableFunctionLocator to find
66 candidate functions.  Only functions which consist of a single return statement
67 are inlined. */
68 class FunctionInliner: private TraversingVisitor
69 {
70 private:
71         Stage *stage;
72         std::set<FunctionDeclaration *> inlineable;
73         FunctionDeclaration *current_function;
74         NodeList<Statement>::iterator insert_point;
75         RefPtr<Expression> r_inline_result;
76         bool r_any_inlined;
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 /** Removes conditional statements and loops where the condition can be
139 determined as constant at compile time. */
140 class ConstantConditionEliminator: private TraversingVisitor
141 {
142 private:
143         NodeList<Statement>::iterator insert_point;
144         std::set<Node *> nodes_to_remove;
145
146 public:
147         void apply(Stage &);
148
149 private:
150         virtual void visit(Block &);
151         virtual void visit(Conditional &);
152         virtual void visit(Iteration &);
153 };
154
155 /** Removes types which are not used anywhere. */
156 class UnusedTypeRemover: private TraversingVisitor
157 {
158 private:
159         std::set<Node *> unused_nodes;
160
161 public:
162         bool apply(Stage &);
163
164 private:
165         virtual void visit(Literal &);
166         virtual void visit(UnaryExpression &);
167         virtual void visit(BinaryExpression &);
168         virtual void visit(TernaryExpression &);
169         virtual void visit(FunctionCall &);
170         virtual void visit(BasicTypeDeclaration &);
171         virtual void visit(ImageTypeDeclaration &);
172         virtual void visit(StructDeclaration &);
173         virtual void visit(VariableDeclaration &);
174         virtual void visit(InterfaceBlock &);
175         virtual void visit(FunctionDeclaration &);
176 };
177
178 /** Removes variable declarations with no references to them.  Assignment
179 statements where the result is not used are also removed. */
180 class UnusedVariableRemover: private TraversingVisitor
181 {
182 private:
183         struct AssignmentInfo
184         {
185                 Node *node;
186                 Assignment::Target target;
187                 std::vector<Node *> used_by;
188
189                 AssignmentInfo(): node(0) { }
190         };
191
192         struct VariableInfo
193         {
194                 InterfaceBlock *interface_block;
195                 std::vector<AssignmentInfo *> assignments;
196                 bool initialized;
197                 bool output;
198                 bool referenced;
199
200                 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
201         };
202
203         typedef std::map<Statement *, VariableInfo> BlockVariableMap;
204
205         Stage *stage;
206         BlockVariableMap variables;
207         std::list<AssignmentInfo> assignments;
208         InterfaceBlock *interface_block;
209         Assignment *r_assignment;
210         bool assignment_target;
211         bool r_side_effects;
212         std::set<Node *> unused_nodes;
213
214 public:
215         UnusedVariableRemover();
216
217         bool apply(Stage &);
218
219 private:
220         void referenced(const Assignment::Target &, Node &);
221         virtual void visit(VariableReference &);
222         virtual void visit(InterfaceBlockReference &);
223         virtual void visit(UnaryExpression &);
224         virtual void visit(BinaryExpression &);
225         virtual void visit(Assignment &);
226         virtual void visit(FunctionCall &);
227         void record_assignment(const Assignment::Target &, Node &);
228         virtual void visit(ExpressionStatement &);
229         // Ignore structs because their members can't be accessed directly.
230         virtual void visit(StructDeclaration &) { }
231         virtual void visit(VariableDeclaration &);
232         virtual void visit(InterfaceBlock &);
233         void merge_variables(const BlockVariableMap &);
234         virtual void visit(FunctionDeclaration &);
235         virtual void visit(Conditional &);
236         virtual void visit(Iteration &);
237 };
238
239 /** Removes function declarations with no references to them. */
240 class UnusedFunctionRemover: private TraversingVisitor
241 {
242 private:
243         std::set<Node *> unused_nodes;
244         std::set<FunctionDeclaration *> used_definitions;
245
246 public:
247         bool apply(Stage &s);
248
249 private:
250         virtual void visit(FunctionCall &);
251         virtual void visit(FunctionDeclaration &);
252 };
253
254 } // namespace SL
255 } // namespace GL
256 } // namespace Msp
257
258 #endif