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