]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Implement the ternary operator 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         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(TernaryExpression &);
139         virtual void visit(FunctionCall &);
140         virtual void visit(VariableDeclaration &);
141         virtual void visit(Iteration &);
142 };
143
144 /** Removes conditional statements and loops where the condition can be
145 determined as constant at compile time. */
146 class ConstantConditionEliminator: private TraversingVisitor
147 {
148 private:
149         NodeList<Statement>::iterator insert_point;
150         std::set<Node *> nodes_to_remove;
151
152 public:
153         void apply(Stage &);
154
155 private:
156         virtual void visit(Block &);
157         virtual void visit(Conditional &);
158         virtual void visit(Iteration &);
159 };
160
161 /** Removes types which are not used anywhere. */
162 class UnusedTypeRemover: private TraversingVisitor
163 {
164 private:
165         std::set<Node *> unused_nodes;
166
167 public:
168         bool apply(Stage &);
169
170 private:
171         virtual void visit(Literal &);
172         virtual void visit(UnaryExpression &);
173         virtual void visit(BinaryExpression &);
174         virtual void visit(TernaryExpression &);
175         virtual void visit(FunctionCall &);
176         virtual void visit(BasicTypeDeclaration &);
177         virtual void visit(ImageTypeDeclaration &);
178         virtual void visit(StructDeclaration &);
179         virtual void visit(VariableDeclaration &);
180         virtual void visit(InterfaceBlock &);
181         virtual void visit(FunctionDeclaration &);
182 };
183
184 /** Removes variable declarations with no references to them.  Assignment
185 statements where the result is not used are also removed. */
186 class UnusedVariableRemover: private TraversingVisitor
187 {
188 private:
189         struct AssignmentInfo
190         {
191                 Node *node;
192                 Assignment::Target target;
193                 std::vector<Node *> used_by;
194
195                 AssignmentInfo(): node(0) { }
196         };
197
198         struct VariableInfo
199         {
200                 InterfaceBlock *interface_block;
201                 std::vector<AssignmentInfo *> assignments;
202                 bool initialized;
203                 bool output;
204                 bool referenced;
205
206                 VariableInfo(): interface_block(0), initialized(false), output(false), referenced(false) { }
207         };
208
209         typedef std::map<Statement *, VariableInfo> BlockVariableMap;
210
211         Stage *stage;
212         BlockVariableMap variables;
213         std::list<AssignmentInfo> assignments;
214         InterfaceBlock *interface_block;
215         Assignment *r_assignment;
216         bool assignment_target;
217         bool r_side_effects;
218         std::set<Node *> unused_nodes;
219
220 public:
221         UnusedVariableRemover();
222
223         bool apply(Stage &);
224
225 private:
226         void referenced(const Assignment::Target &, Node &);
227         virtual void visit(VariableReference &);
228         virtual void visit(InterfaceBlockReference &);
229         virtual void visit(UnaryExpression &);
230         virtual void visit(BinaryExpression &);
231         virtual void visit(Assignment &);
232         virtual void visit(FunctionCall &);
233         void record_assignment(const Assignment::Target &, Node &);
234         virtual void visit(ExpressionStatement &);
235         // Ignore structs because their members can't be accessed directly.
236         virtual void visit(StructDeclaration &) { }
237         virtual void visit(VariableDeclaration &);
238         virtual void visit(InterfaceBlock &);
239         void merge_variables(const BlockVariableMap &);
240         virtual void visit(FunctionDeclaration &);
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