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