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