]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Some rearranging and comments
[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 AssignmentInfo
188         {
189                 Node *node;
190                 Assignment::Target target;
191                 std::vector<Node *> used_by;
192
193                 AssignmentInfo(): node(0) { }
194         };
195
196         struct VariableInfo
197         {
198                 InterfaceBlock *interface_block;
199                 std::vector<AssignmentInfo *> assignments;
200                 bool initialized;
201                 bool output;
202                 bool referenced;
203
204                 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
205         };
206
207         typedef std::map<Statement *, VariableInfo> BlockVariableMap;
208
209         Stage *stage;
210         BlockVariableMap variables;
211         std::list<AssignmentInfo> assignments;
212         InterfaceBlock *interface_block;
213         Assignment *r_assignment;
214         bool assignment_target;
215         bool r_side_effects;
216         std::set<Node *> unused_nodes;
217
218 public:
219         UnusedVariableRemover();
220
221         bool apply(Stage &);
222
223 private:
224         void referenced(const Assignment::Target &, Node &);
225         virtual void visit(VariableReference &);
226         virtual void visit(InterfaceBlockReference &);
227         virtual void visit(UnaryExpression &);
228         virtual void visit(BinaryExpression &);
229         virtual void visit(Assignment &);
230         virtual void visit(FunctionCall &);
231         void record_assignment(const Assignment::Target &, Node &);
232         virtual void visit(ExpressionStatement &);
233         // Ignore structs because their members can't be accessed directly.
234         virtual void visit(StructDeclaration &) { }
235         virtual void visit(VariableDeclaration &);
236         virtual void visit(InterfaceBlock &);
237         void merge_variables(const BlockVariableMap &);
238         virtual void visit(FunctionDeclaration &);
239         virtual void visit(Conditional &);
240         virtual void visit(Iteration &);
241 };
242
243 /** Removes function declarations with no references to them. */
244 class UnusedFunctionRemover: private TraversingVisitor
245 {
246 private:
247         std::set<Node *> unused_nodes;
248         std::set<FunctionDeclaration *> used_definitions;
249
250 public:
251         bool apply(Stage &s);
252
253 private:
254         virtual void visit(FunctionCall &);
255         virtual void visit(FunctionDeclaration &);
256 };
257
258 } // namespace SL
259 } // namespace GL
260 } // namespace Msp
261
262 #endif