]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Handle expression replacement through TraversingVisitor
[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         std::string create_unused_name(const std::string &, bool);
59
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                 const Operator *inner_oper;
105                 const Operator *outer_oper;
106                 bool inline_on_rhs;
107                 bool trivial;
108                 bool available;
109
110                 ExpressionInfo();
111         };
112
113         std::map<Assignment::Target, ExpressionInfo> expressions;
114         ExpressionInfo *r_ref_info;
115         bool r_any_inlined;
116         bool r_trivial;
117         bool mutating;
118         bool iteration_init;
119         Block *iteration_body;
120         const Operator *r_oper;
121
122 public:
123         ExpressionInliner();
124
125         bool apply(Stage &);
126
127 private:
128         void visit_and_record(RefPtr<Expression> &, const Operator *, bool);
129         void inline_expression(Expression &, RefPtr<Expression> &, const Operator *, const Operator *, bool);
130         virtual void visit(Block &);
131         virtual void visit(RefPtr<Expression> &);
132         virtual void visit(VariableReference &);
133         virtual void visit(MemberAccess &);
134         virtual void visit(Swizzle &);
135         virtual void visit(UnaryExpression &);
136         virtual void visit(BinaryExpression &);
137         virtual void visit(Assignment &);
138         virtual void visit(FunctionCall &);
139         virtual void visit(VariableDeclaration &);
140         virtual void visit(Iteration &);
141 };
142
143 /** Removes conditional statements and loops where the condition can be
144 determined as constant at compile time. */
145 class ConstantConditionEliminator: private TraversingVisitor
146 {
147 private:
148         NodeList<Statement>::iterator insert_point;
149         std::set<Node *> nodes_to_remove;
150
151 public:
152         void apply(Stage &);
153
154 private:
155         virtual void visit(Block &);
156         virtual void visit(Conditional &);
157         virtual void visit(Iteration &);
158 };
159
160 /** Removes types which are not used anywhere. */
161 class UnusedTypeRemover: private TraversingVisitor
162 {
163 private:
164         std::set<Node *> unused_nodes;
165
166 public:
167         bool apply(Stage &);
168
169 private:
170         virtual void visit(Literal &);
171         virtual void visit(UnaryExpression &);
172         virtual void visit(BinaryExpression &);
173         virtual void visit(FunctionCall &);
174         virtual void visit(BasicTypeDeclaration &);
175         virtual void visit(ImageTypeDeclaration &);
176         virtual void visit(StructDeclaration &);
177         virtual void visit(VariableDeclaration &);
178         virtual void visit(InterfaceBlock &);
179         virtual void visit(FunctionDeclaration &);
180 };
181
182 /** Removes variable declarations with no references to them.  Assignment
183 statements where the result is not used are also removed. */
184 class UnusedVariableRemover: private TraversingVisitor
185 {
186 private:
187         struct VariableInfo
188         {
189                 std::vector<Node *> assignments;
190                 bool local;
191                 bool output;
192                 bool conditionally_assigned;
193                 bool referenced;
194                 InterfaceBlock *interface_block;
195
196                 VariableInfo();
197         };
198
199         typedef std::map<Assignment::Target, VariableInfo> BlockVariableMap;
200
201         Stage *stage;
202         std::set<Node *> unused_nodes;
203         std::vector<BlockVariableMap> variables;
204         InterfaceBlock *interface_block;
205         Assignment *r_assignment;
206         bool assignment_target;
207         bool r_side_effects;
208
209 public:
210         UnusedVariableRemover();
211
212         bool apply(Stage &);
213
214 private:
215         void reference_used(Statement &);
216         virtual void visit(VariableReference &);
217         virtual void visit(InterfaceBlockReference &);
218         virtual void visit(UnaryExpression &);
219         virtual void visit(BinaryExpression &);
220         virtual void visit(Assignment &);
221         void record_assignment(const Assignment::Target &, Node &, bool);
222         void clear_assignments(VariableInfo &, bool);
223         virtual void visit(FunctionCall &);
224         virtual void visit(ExpressionStatement &);
225         // Ignore structs because their members can't be accessed directly.
226         virtual void visit(StructDeclaration &) { }
227         virtual void visit(VariableDeclaration &);
228         virtual void visit(InterfaceBlock &);
229         virtual void visit(FunctionDeclaration &);
230         void merge_down_variables();
231         virtual void visit(Conditional &);
232         virtual void visit(Iteration &);
233 };
234
235 /** Removes function declarations with no references to them. */
236 class UnusedFunctionRemover: private TraversingVisitor
237 {
238 private:
239         std::set<Node *> unused_nodes;
240         std::set<FunctionDeclaration *> used_definitions;
241
242 public:
243         bool apply(Stage &s);
244
245 private:
246         virtual void visit(FunctionCall &);
247         virtual void visit(FunctionDeclaration &);
248 };
249
250 } // namespace SL
251 } // namespace GL
252 } // namespace Msp
253
254 #endif