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