]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/optimize.h
Further improve inlining of GLSL functions
[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> inlined_statement;
49         std::set<Node *> dependencies;
50         std::string 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> inline_result;
78         bool 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(Return &);
97 };
98
99 /** Removes conditional statements and loops where the condition can be
100 determined as constant at compile time. */
101 class ConstantConditionEliminator: private TraversingVisitor
102 {
103 private:
104         bool record_only;
105         ExpressionEvaluator::ValueMap variable_values;
106         NodeList<Statement>::iterator insert_point;
107         std::set<Node *> nodes_to_remove;
108
109 public:
110         ConstantConditionEliminator();
111
112         void apply(Stage &);
113
114 private:
115         virtual void visit(Block &);
116         virtual void visit(UnaryExpression &);
117         virtual void visit(Assignment &);
118         virtual void visit(VariableDeclaration &);
119         virtual void visit(Conditional &);
120         virtual void visit(Iteration &);
121 };
122
123 /** Removes variable declarations with no references to them.  Assignment
124 statements where the result is not used are also removed. */
125 class UnusedVariableRemover: private TraversingVisitor
126 {
127 private:
128         struct VariableInfo
129         {
130                 bool local;
131                 std::vector<Node *> assignments;
132                 bool conditionally_assigned;
133                 bool referenced;
134
135                 VariableInfo();
136         };
137
138         typedef std::map<VariableDeclaration *, VariableInfo> BlockVariableMap;
139
140         std::set<Node *> unused_nodes;
141         std::map<VariableDeclaration *, Node *> aggregates;
142         Node *aggregate;
143         std::vector<BlockVariableMap> variables;
144         Assignment *assignment;
145         bool assignment_target;
146         bool assign_to_subscript;
147         bool side_effects;
148
149 public:
150         UnusedVariableRemover();
151
152         bool apply(Stage &);
153
154 private:
155         virtual void visit(VariableReference &);
156         virtual void visit(InterfaceBlockReference &);
157         virtual void visit(MemberAccess &);
158         virtual void visit(UnaryExpression &);
159         virtual void visit(BinaryExpression &);
160         virtual void visit(Assignment &);
161         void record_assignment(VariableDeclaration &, Node &, bool);
162         void clear_assignments(VariableInfo &, bool);
163         virtual void visit(FunctionCall &);
164         virtual void visit(ExpressionStatement &);
165         virtual void visit(StructDeclaration &);
166         virtual void visit(VariableDeclaration &);
167         virtual void visit(InterfaceBlock &);
168         virtual void visit(FunctionDeclaration &);
169         void merge_down_variables();
170         virtual void visit(Conditional &);
171         virtual void visit(Iteration &);
172 };
173
174 /** Removes function declarations with no references to them. */
175 class UnusedFunctionRemover: private TraversingVisitor
176 {
177 private:
178         std::set<Node *> unused_nodes;
179         std::set<FunctionDeclaration *> used_definitions;
180
181 public:
182         bool apply(Stage &s);
183
184 private:
185         virtual void visit(FunctionCall &);
186         virtual void visit(FunctionDeclaration &);
187 };
188
189 } // namespace SL
190 } // namespace GL
191 } // namespace Msp
192
193 #endif