Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file codegen/VolumeComputeGenerator.cc | ||
5 | |||
6 | #include "VolumeComputeGenerator.h" | ||
7 | #include "FunctionRegistry.h" | ||
8 | #include "FunctionTypes.h" | ||
9 | #include "Types.h" | ||
10 | #include "Utils.h" | ||
11 | |||
12 | #include "../Exceptions.h" | ||
13 | #include "../ast/Scanners.h" | ||
14 | |||
15 | namespace openvdb { | ||
16 | OPENVDB_USE_VERSION_NAMESPACE | ||
17 | namespace OPENVDB_VERSION_NAME { | ||
18 | |||
19 | namespace ax { | ||
20 | namespace codegen { | ||
21 | |||
22 | const std::array<std::string, VolumeKernelValue::N_ARGS>& | ||
23 | 763 | VolumeKernelValue::argumentKeys() | |
24 | { | ||
25 | static const std::array<std::string, VolumeKernelValue::N_ARGS> arguments = {{ | ||
26 | "custom_data", | ||
27 | "origin", | ||
28 | "value", | ||
29 | "active", | ||
30 | "offset", | ||
31 | "accessors", | ||
32 | "transforms", | ||
33 | "write_index" | ||
34 |
11/20✓ Branch 0 taken 1 times.
✓ Branch 1 taken 762 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
|
763 | }}; |
35 | |||
36 | 763 | return arguments; | |
37 | } | ||
38 | |||
39 | 763 | const char* VolumeKernelValue::getDefaultName() { return "ax.compute.voxel.k1"; } | |
40 | |||
41 | // | ||
42 | |||
43 | const std::array<std::string, VolumeKernelBuffer::N_ARGS>& | ||
44 | ✗ | VolumeKernelBuffer::argumentKeys() | |
45 | { | ||
46 | static const std::array<std::string, VolumeKernelBuffer::N_ARGS> arguments = {{ | ||
47 | "custom_data", | ||
48 | "origin", | ||
49 | "value_buffer", | ||
50 | "active_buffer", | ||
51 | "buffer_size", | ||
52 | "mode", | ||
53 | "accessors", | ||
54 | "transforms", | ||
55 | "write_index" | ||
56 | ✗ | }}; | |
57 | |||
58 | ✗ | return arguments; | |
59 | } | ||
60 | |||
61 | 3007 | const char* VolumeKernelBuffer::getDefaultName() { return "ax.compute.voxel.k2"; } | |
62 | |||
63 | // | ||
64 | |||
65 | const std::array<std::string, VolumeKernelNode::N_ARGS>& | ||
66 | ✗ | VolumeKernelNode::argumentKeys() | |
67 | { | ||
68 | static const std::array<std::string, VolumeKernelNode::N_ARGS> arguments = {{ | ||
69 | "custom_data", | ||
70 | "coord_is", | ||
71 | "accessors", | ||
72 | "transforms", | ||
73 | "write_index", | ||
74 | "write_acccessor" | ||
75 | ✗ | }}; | |
76 | |||
77 | ✗ | return arguments; | |
78 | } | ||
79 | |||
80 | 3007 | const char* VolumeKernelNode::getDefaultName() { return "ax.compute.voxel.k3"; } | |
81 | |||
82 | |||
83 | /////////////////////////////////////////////////////////////////////////// | ||
84 | /////////////////////////////////////////////////////////////////////////// | ||
85 | |||
86 | namespace codegen_internal { | ||
87 | |||
88 | 751 | inline void VolumeComputeGenerator::computek2(llvm::Function* compute, const AttributeRegistry&) | |
89 | { | ||
90 | auto generate = | ||
91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | [&](const std::vector<llvm::Value*>& args, |
92 | llvm::IRBuilder<>& B) -> llvm::Value* | ||
93 | { | ||
94 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(args.size() == 9); |
95 | 751 | llvm::Value* vbuff = args[2]; //extractArgument(rangeFunction, "value_buffer"); | |
96 | 751 | llvm::Value* abuff = args[3]; //extractArgument(rangeFunction, "active_buffer"); | |
97 | 751 | llvm::Value* buffSize = args[4]; //extractArgument(rangeFunction, "buffer_size"); | |
98 | 751 | llvm::Value* mode = args[5]; //extractArgument(rangeFunction, "mode"); | |
99 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(buffSize); |
100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(vbuff); |
101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(abuff); |
102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(mode); |
103 | |||
104 | llvm::Function* base = B.GetInsertBlock()->getParent(); | ||
105 | llvm::LLVMContext& C = B.getContext(); | ||
106 | |||
107 | 751 | llvm::BasicBlock* conditionBlock = llvm::BasicBlock::Create(C, "k2.condition", base); | |
108 | 751 | llvm::BasicBlock* bodyBlock = llvm::BasicBlock::Create(C, "k2.body", base); | |
109 | 751 | llvm::BasicBlock* iterBlock = llvm::BasicBlock::Create(C, "k2.iter", base); | |
110 | |||
111 | // init var - loops from 0 -> buffSize | ||
112 | 751 | llvm::Value* incr = insertStaticAlloca(B, LLVMType<int64_t>::get(C)); | |
113 | 751 | B.CreateStore(B.getInt64(0), incr); | |
114 | 751 | B.CreateBr(conditionBlock); | |
115 | |||
116 | // increment | ||
117 | B.SetInsertPoint(iterBlock); | ||
118 | 751 | llvm::Value* new_incr = B.CreateAdd(B.CreateLoad(incr), B.getInt64(1)); | |
119 | 751 | B.CreateStore(new_incr, incr); | |
120 | 751 | B.CreateBr(conditionBlock); | |
121 | |||
122 | // generate loop body | ||
123 | B.SetInsertPoint(bodyBlock); | ||
124 | 751 | llvm::Value* lincr = B.CreateLoad(incr); | |
125 | |||
126 | // Extract mask bit from array of words | ||
127 | // NodeMask::isOn() = (0 != (mWords[n >> 6] & (Word(1) << (n & 63)))); | ||
128 |
3/6✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 751 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 751 times.
✗ Branch 8 not taken.
|
751 | llvm::Value* mask = binaryOperator(B.getInt64(1), |
129 | 1502 | binaryOperator(lincr, B.getInt64(63), ast::tokens::BITAND, B), | |
130 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | ast::tokens::SHIFTLEFT, B); |
131 | 751 | llvm::Value* word_idx = binaryOperator(lincr, B.getInt64(6), ast::tokens::SHIFTRIGHT, B); | |
132 | 751 | llvm::Value* word = B.CreateGEP(abuff, word_idx); | |
133 | 751 | word = B.CreateLoad(word); | |
134 | 751 | word = binaryOperator(word, mask, ast::tokens::BITAND, B); | |
135 | 751 | llvm::Value* ison = B.CreateICmpNE(word, B.getInt64(0)); | |
136 | |||
137 | // Check if we should run the kernel depending on the mode. | ||
138 | // mode == 0, inactive values | ||
139 | // mode == 1, active values | ||
140 | // mode == 2, all values | ||
141 | 751 | llvm::Value* matches_mode = B.CreateICmpEQ(B.CreateZExt(ison, mode->getType()), mode); | |
142 | 751 | llvm::Value* mode_is_all = B.CreateICmpEQ(mode, B.getInt64(2)); | |
143 | 751 | llvm::Value* process = binaryOperator(matches_mode, mode_is_all, ast::tokens::OR, B); | |
144 | 751 | llvm::BasicBlock* then = llvm::BasicBlock::Create(C, "k2.invoke_k1", base); | |
145 | |||
146 | 751 | B.CreateCondBr(process, then, iterBlock); | |
147 | B.SetInsertPoint(then); | ||
148 | { | ||
149 | // invoke the volume kernel for this value | ||
150 | const std::array<llvm::Value*, 8> input { | ||
151 | args[0], // ax::CustomData | ||
152 | args[1], // index space coordinate | ||
153 | vbuff, // value buffer | ||
154 | ison, // active/inactive | ||
155 | 751 | B.CreateLoad(incr), // offset in the value buffer | |
156 | args[6], // read accessors | ||
157 | args[7], // transforms | ||
158 | args[8] // write index | ||
159 | 1502 | }; | |
160 | 751 | B.CreateCall(compute, input); | |
161 | 751 | B.CreateBr(iterBlock); | |
162 | } | ||
163 | |||
164 | B.SetInsertPoint(conditionBlock); | ||
165 | 751 | llvm::Value* endCondition = B.CreateICmpULT(B.CreateLoad(incr), buffSize); | |
166 | |||
167 | 751 | llvm::BasicBlock* postBlock = llvm::BasicBlock::Create(C, "k2.end", base); | |
168 | 751 | B.CreateCondBr(endCondition, bodyBlock, postBlock); | |
169 | B.SetInsertPoint(postBlock); | ||
170 | 751 | return B.CreateRetVoid(); | |
171 | 751 | }; | |
172 | |||
173 | // Use the function builder to generate the correct prototype and body for K2 | ||
174 |
1/2✓ Branch 3 taken 751 times.
✗ Branch 4 not taken.
|
1502 | auto k2 = FunctionBuilder(VolumeKernelBuffer::getDefaultName()) |
175 |
2/4✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 751 times.
✗ Branch 6 not taken.
|
1502 | .addSignature<VolumeKernelBuffer::Signature>(generate, VolumeKernelBuffer::getDefaultName()) |
176 | .setConstantFold(false) | ||
177 | .setEmbedIR(false) | ||
178 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::ReadOnly) |
179 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::NoCapture) |
180 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::NoAlias) |
181 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::ReadOnly) |
182 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::NoCapture) |
183 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::NoAlias) |
184 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(2, llvm::Attribute::NoCapture) |
185 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(2, llvm::Attribute::NoAlias) |
186 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(3, llvm::Attribute::NoCapture) |
187 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(3, llvm::Attribute::NoAlias) |
188 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(6, llvm::Attribute::NoCapture) |
189 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(6, llvm::Attribute::NoAlias) |
190 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(7, llvm::Attribute::NoCapture) |
191 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(7, llvm::Attribute::NoAlias) |
192 | 751 | .addFunctionAttribute(llvm::Attribute::NoRecurse) | |
193 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
1502 | .get(); |
194 | |||
195 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | k2->list()[0]->create(mContext, &mModule); |
196 | 751 | } | |
197 | |||
198 | 751 | inline void VolumeComputeGenerator::computek3(llvm::Function* compute, const AttributeRegistry& reg) | |
199 | { | ||
200 | 751 | const SymbolTable& localTable = *(this->mSymbolTables.get(1)); | |
201 | |||
202 | auto generate = | ||
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | [&, this](const std::vector<llvm::Value*>& args, |
204 | 15511 | llvm::IRBuilder<>& B) -> llvm::Value* | |
205 | { | ||
206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(args.size() == 6); |
207 | 751 | llvm::Value* isc = args[1]; // index space coord | |
208 | 751 | llvm::Value* wi = args[4]; // write index | |
209 | 751 | llvm::Value* wa = args[5]; // write_accessor | |
210 | |||
211 | llvm::Function* base = B.GetInsertBlock()->getParent(); | ||
212 | llvm::LLVMContext& C = B.getContext(); | ||
213 | |||
214 |
2/2✓ Branch 0 taken 5060 times.
✓ Branch 1 taken 751 times.
|
5811 | for (const AttributeRegistry::AccessData& access : reg.data()) { |
215 |
2/2✓ Branch 0 taken 140 times.
✓ Branch 1 taken 4920 times.
|
5060 | if (!access.writes()) continue; |
216 | |||
217 | const std::string token = access.tokenname(); | ||
218 | 4920 | llvm::Type* type = localTable.get(token)->getType(); | |
219 | type = type->getPointerElementType(); | ||
220 | |||
221 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | llvm::Value* registeredIndex = this->mModule.getGlobalVariable(token); |
222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4920 times.
|
4920 | assert(registeredIndex); |
223 |
1/2✓ Branch 2 taken 4920 times.
✗ Branch 3 not taken.
|
4920 | registeredIndex = B.CreateLoad(registeredIndex); |
224 | 4920 | llvm::Value* result = B.CreateICmpEQ(wi, registeredIndex); | |
225 | |||
226 |
2/4✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4920 times.
✗ Branch 6 not taken.
|
4920 | llvm::BasicBlock* thenBlock = llvm::BasicBlock::Create(C, "k3.invoke_k1_" + token, base); |
227 |
1/2✓ Branch 2 taken 4920 times.
✗ Branch 3 not taken.
|
4920 | llvm::BasicBlock* continueBlock = llvm::BasicBlock::Create(C, "k3.next", base); |
228 | |||
229 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | B.CreateCondBr(result, thenBlock, continueBlock); |
230 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | B.SetInsertPoint(thenBlock); |
231 | |||
232 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | llvm::Value* location = insertStaticAlloca(B, type); |
233 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | llvm::Value* ison = insertStaticAlloca(B, B.getInt1Ty()); |
234 | |||
235 |
2/4✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4920 times.
✗ Branch 5 not taken.
|
4920 | const FunctionGroup* const F = this->getFunction("probevalue", true); |
236 |
2/4✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4920 times.
✗ Branch 5 not taken.
|
4920 | F->execute({wa, isc, ison, location}, B); |
237 |
1/2✓ Branch 2 taken 4920 times.
✗ Branch 3 not taken.
|
4920 | ison = B.CreateLoad(ison); |
238 | |||
239 |
3/6✓ Branch 2 taken 4920 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4920 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4920 times.
✗ Branch 9 not taken.
|
4920 | llvm::Value* vptr = B.CreatePointerCast(location, LLVMType<void*>::get(C)); |
240 | |||
241 | const std::array<llvm::Value*, 8> input { | ||
242 | args[0], // ax::CustomData | ||
243 | args[1], // index space coordinate | ||
244 | vptr, // value buffer (in this case, a pointer to a single value) | ||
245 | ison, // active/inactive | ||
246 | 4920 | B.getInt64(0), // offset in the value buffer, always zero | |
247 | args[2], // read accessors | ||
248 | args[3], // transforms | ||
249 | wi // write index | ||
250 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | }; |
251 |
3/4✓ Branch 2 taken 4920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3234 times.
✓ Branch 5 taken 1686 times.
|
4920 | B.CreateCall(compute, input); |
252 | |||
253 | // set the voxel - load the result (if its a scalar) | ||
254 |
2/2✓ Branch 0 taken 3234 times.
✓ Branch 1 taken 1686 times.
|
4920 | if (type->isIntegerTy() || type->isFloatingPointTy()) { |
255 |
1/2✓ Branch 2 taken 3030 times.
✗ Branch 3 not taken.
|
3030 | location = B.CreateLoad(location); |
256 | } | ||
257 | |||
258 |
2/4✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4920 times.
✗ Branch 5 not taken.
|
4920 | const FunctionGroup* const function = this->getFunction("setvoxel", true); |
259 |
3/6✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4920 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4920 times.
✗ Branch 8 not taken.
|
4920 | function->execute({wa, isc, /*level=unknown*/B.getInt32(-1), ison, location}, B); |
260 | |||
261 |
1/2✓ Branch 1 taken 4920 times.
✗ Branch 2 not taken.
|
4920 | B.CreateBr(continueBlock); |
262 | B.SetInsertPoint(continueBlock); | ||
263 | } | ||
264 | |||
265 | 751 | llvm::Value* ret = B.CreateRetVoid(); | |
266 | // insert string frees for k3 which can allocate them | ||
267 | 751 | this->createFreeSymbolStrings(B); | |
268 | 751 | return ret; | |
269 | 751 | }; | |
270 | |||
271 |
1/2✓ Branch 3 taken 751 times.
✗ Branch 4 not taken.
|
1502 | auto k3 = FunctionBuilder(VolumeKernelNode::getDefaultName()) |
272 |
3/6✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 751 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 751 times.
✗ Branch 8 not taken.
|
1502 | .addSignature<VolumeKernelNode::Signature>(generate, VolumeKernelNode::getDefaultName()) |
273 | .setConstantFold(false) | ||
274 | .setEmbedIR(false) | ||
275 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::ReadOnly) |
276 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::NoCapture) |
277 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(0, llvm::Attribute::NoAlias) |
278 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::ReadOnly) |
279 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::NoCapture) |
280 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(1, llvm::Attribute::NoAlias) |
281 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(2, llvm::Attribute::NoCapture) |
282 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(2, llvm::Attribute::NoAlias) |
283 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(3, llvm::Attribute::NoCapture) |
284 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(3, llvm::Attribute::NoAlias) |
285 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(5, llvm::Attribute::NoCapture) |
286 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | .addParameterAttribute(5, llvm::Attribute::NoAlias) |
287 | 751 | .addFunctionAttribute(llvm::Attribute::NoRecurse) | |
288 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
1502 | .get(); |
289 | |||
290 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | k3->list()[0]->create(mContext, &mModule); |
291 | 751 | } | |
292 | |||
293 | 763 | VolumeComputeGenerator::VolumeComputeGenerator(llvm::Module& module, | |
294 | const FunctionOptions& options, | ||
295 | FunctionRegistry& functionRegistry, | ||
296 | 763 | Logger& logger) | |
297 | 763 | : ComputeGenerator(module, options, functionRegistry, logger) {} | |
298 | |||
299 | 763 | AttributeRegistry::Ptr VolumeComputeGenerator::generate(const ast::Tree& tree) | |
300 | { | ||
301 | llvm::FunctionType* type = | ||
302 | 763 | llvmFunctionTypeFromSignature<VolumeKernelValue::Signature>(mContext); | |
303 | |||
304 |
1/2✓ Branch 2 taken 763 times.
✗ Branch 3 not taken.
|
763 | mFunction = llvm::Function::Create(type, |
305 | llvm::Function::ExternalLinkage, | ||
306 | VolumeKernelValue::getDefaultName(), | ||
307 | 763 | &mModule); | |
308 | |||
309 | // Set up arguments for initial entry | ||
310 | |||
311 | llvm::Function::arg_iterator argIter = mFunction->arg_begin(); | ||
312 | 763 | const auto arguments = VolumeKernelValue::argumentKeys(); | |
313 | auto keyIter = arguments.cbegin(); | ||
314 | |||
315 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 6867 times.
✓ Branch 2 taken 6104 times.
✓ Branch 3 taken 763 times.
|
6867 | for (; argIter != mFunction->arg_end(); ++argIter, ++keyIter) { |
316 |
1/2✓ Branch 2 taken 6104 times.
✗ Branch 3 not taken.
|
6104 | argIter->setName(*keyIter); |
317 | } | ||
318 | |||
319 |
4/6✓ Branch 2 taken 763 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 763 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
✓ Branch 8 taken 4 times.
|
799 | llvm::BasicBlock* entry = llvm::BasicBlock::Create(mContext, "k1.entry", mFunction); |
320 | mBuilder.SetInsertPoint(entry); | ||
321 | |||
322 | // build the attribute registry | ||
323 | |||
324 |
1/2✓ Branch 1 taken 763 times.
✗ Branch 2 not taken.
|
763 | AttributeRegistry::Ptr registry = AttributeRegistry::create(tree); |
325 | |||
326 | // Visit all attributes and allocate them in local IR memory - assumes attributes | ||
327 | // have been verified by the ax compiler | ||
328 | // @note Call all attribute allocs at the start of this block so that llvm folds | ||
329 | // them into the function prologue (as a static allocation) | ||
330 | |||
331 | 763 | SymbolTable* localTable = this->mSymbolTables.getOrInsert(1); | |
332 | |||
333 | // run allocations and update the symbol table | ||
334 | |||
335 |
2/2✓ Branch 0 taken 5062 times.
✓ Branch 1 taken 763 times.
|
5825 | for (const AttributeRegistry::AccessData& data : registry->data()) { |
336 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | llvm::Type* type = llvmTypeFromToken(data.type(), mContext); |
337 | { | ||
338 |
3/6✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5062 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5062 times.
✗ Branch 9 not taken.
|
5062 | llvm::Value* vptr = mBuilder.CreateAlloca(type->getPointerTo(0)); |
339 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
10124 | localTable->insert(data.tokenname() + "_vptr", vptr); |
340 |
2/4✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5062 times.
|
5062 | assert(llvm::cast<llvm::AllocaInst>(vptr)->isStaticAlloca()); |
341 | } | ||
342 | |||
343 | // @warning This method will insert the alloc before the above alloc. | ||
344 | // This is fine, but is worth noting | ||
345 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | llvm::Value* value = insertStaticAlloca(mBuilder, type); |
346 |
2/4✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5062 times.
|
5062 | assert(llvm::cast<llvm::AllocaInst>(value)->isStaticAlloca()); |
347 | |||
348 | // @note this technically doesn't need to live in the local table | ||
349 | // (only the pointer to this value (_vptr) needs to) but it's | ||
350 | // re-accessed by the subsequent loop. could remove this. | ||
351 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
10128 | localTable->insert(data.tokenname(), value); |
352 | } | ||
353 | |||
354 | // insert getters for read variables | ||
355 | |||
356 |
2/2✓ Branch 0 taken 5062 times.
✓ Branch 1 taken 763 times.
|
5825 | for (const AttributeRegistry::AccessData& data : registry->data()) { |
357 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | if (!data.reads()) continue; |
358 | const std::string token = data.tokenname(); | ||
359 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | this->getAccessorValue(token, localTable->get(token)); |
360 | } | ||
361 | |||
362 | // full code generation | ||
363 | // errors can stop traversal, but dont always, so check the log | ||
364 | |||
365 |
2/2✓ Branch 1 taken 759 times.
✓ Branch 2 taken 4 times.
|
763 | const size_t err = mLog.errors(); |
366 |
3/4✓ Branch 0 taken 759 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 751 times.
|
759 | if (!this->traverse(&tree) || (mLog.errors() > err)) return nullptr; |
367 | |||
368 | // insert free calls for any strings | ||
369 | |||
370 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | this->createFreeSymbolStrings(mBuilder); |
371 | |||
372 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | this->computek2(mFunction, *registry); |
373 |
1/2✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
|
751 | this->computek3(mFunction, *registry); |
374 | |||
375 | return registry; | ||
376 | } | ||
377 | |||
378 | 6009 | bool VolumeComputeGenerator::visit(const ast::Attribute* node) | |
379 | { | ||
380 | 6009 | SymbolTable* localTable = this->mSymbolTables.getOrInsert(1); | |
381 | const std::string globalName = node->tokenname(); | ||
382 | llvm::Value* value; | ||
383 |
1/2✓ Branch 1 taken 6009 times.
✗ Branch 2 not taken.
|
6009 | value = localTable->get(globalName + "_vptr"); |
384 |
1/2✓ Branch 2 taken 6009 times.
✗ Branch 3 not taken.
|
6009 | value = mBuilder.CreateLoad(value); |
385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6009 times.
|
6009 | assert(value); |
386 | mValues.push(value); | ||
387 | 6009 | return true; | |
388 | } | ||
389 | |||
390 | |||
391 | /////////////////////////////////////////////////////////////////////////// | ||
392 | /////////////////////////////////////////////////////////////////////////// | ||
393 | |||
394 | |||
395 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | void VolumeComputeGenerator::getAccessorValue(const std::string& globalName, llvm::Value* location) |
396 | { | ||
397 | std::string name, type; | ||
398 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | ast::Attribute::nametypeFromToken(globalName, &name, &type); |
399 | |||
400 | llvm::Value* registeredIndex = llvm::cast<llvm::GlobalVariable> | ||
401 |
3/6✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5062 times.
✗ Branch 9 not taken.
|
5062 | (mModule.getOrInsertGlobal(globalName, LLVMType<int64_t>::get(mContext))); |
402 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | this->globals().insert(globalName, registeredIndex); |
403 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | registeredIndex = mBuilder.CreateLoad(registeredIndex); |
404 | |||
405 | // first see if pre cached node exists. | ||
406 | |||
407 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* accessIndex = extractArgument(mFunction, "write_index"); |
408 | 5062 | llvm::Value* result = mBuilder.CreateICmpEQ(accessIndex, registeredIndex); | |
409 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | result = boolComparison(result, mBuilder); |
410 | |||
411 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | llvm::BasicBlock* then = llvm::BasicBlock::Create(mContext, "then", mFunction); |
412 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | llvm::BasicBlock* els = llvm::BasicBlock::Create(mContext, "else", mFunction); |
413 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | llvm::BasicBlock* post = llvm::BasicBlock::Create(mContext, "post", mFunction); |
414 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | mBuilder.CreateCondBr(result, then, els); |
415 | |||
416 | mBuilder.SetInsertPoint(then); | ||
417 | { | ||
418 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* valueptr = extractArgument(mFunction, "value"); |
419 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* offset = extractArgument(mFunction, "offset"); |
420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(valueptr); |
421 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(offset); |
422 | |||
423 | llvm::Type* type = location->getType(); // ValueType* | ||
424 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | valueptr = mBuilder.CreatePointerCast(valueptr, type); |
425 | 10124 | llvm::Value* value = mBuilder.CreateGEP(valueptr, offset); | |
426 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5062 times.
✗ Branch 6 not taken.
|
5062 | mBuilder.CreateStore(value, this->mSymbolTables.get(1)->get(globalName + "_vptr")); |
427 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | mBuilder.CreateBr(post); |
428 | } | ||
429 | |||
430 | mBuilder.SetInsertPoint(els); | ||
431 | { | ||
432 | // If no node, index into the void* array of handles and load the value | ||
433 | // through an accessor | ||
434 | |||
435 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* accessorPtr = extractArgument(mFunction, "accessors"); |
436 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* transformPtr = extractArgument(mFunction, "transforms"); |
437 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* origin = extractArgument(mFunction, "origin"); |
438 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | llvm::Value* offset = extractArgument(mFunction, "offset"); |
439 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(accessorPtr); |
440 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(transformPtr); |
441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(origin); |
442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
|
5062 | assert(offset); |
443 | |||
444 | 5062 | accessorPtr = mBuilder.CreateGEP(accessorPtr, registeredIndex); | |
445 | 5062 | llvm::Value* targetTransform = mBuilder.CreateGEP(transformPtr, registeredIndex); | |
446 | 5062 | llvm::Value* sourceTransform = mBuilder.CreateGEP(transformPtr, accessIndex); | |
447 | |||
448 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | llvm::Value* accessor = mBuilder.CreateLoad(accessorPtr); |
449 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | targetTransform = mBuilder.CreateLoad(targetTransform); |
450 |
1/2✓ Branch 2 taken 5062 times.
✗ Branch 3 not taken.
|
5062 | sourceTransform = mBuilder.CreateLoad(sourceTransform); |
451 | |||
452 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
5062 | const FunctionGroup* const F = this->getFunction("getvoxel", true); |
453 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5062 times.
✗ Branch 5 not taken.
|
10124 | F->execute({accessor, sourceTransform, targetTransform, origin, offset, location}, mBuilder); |
454 |
2/4✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5062 times.
✗ Branch 6 not taken.
|
5062 | mBuilder.CreateStore(location, this->mSymbolTables.get(1)->get(globalName + "_vptr")); |
455 |
1/2✓ Branch 1 taken 5062 times.
✗ Branch 2 not taken.
|
5062 | mBuilder.CreateBr(post); |
456 | } | ||
457 | |||
458 | mBuilder.SetInsertPoint(post); | ||
459 | 5062 | } | |
460 | |||
461 | ✗ | llvm::Value* VolumeComputeGenerator::accessorHandleFromToken(const std::string& globalName) | |
462 | { | ||
463 | // Visiting an "attribute" - get the volume accessor out of a vector of void pointers | ||
464 | // mAttributeHandles is a void pointer to a vector of void pointers (void**) | ||
465 | |||
466 | llvm::Value* registeredIndex = llvm::cast<llvm::GlobalVariable> | ||
467 | ✗ | (mModule.getOrInsertGlobal(globalName, LLVMType<int64_t>::get(mContext))); | |
468 | ✗ | this->globals().insert(globalName, registeredIndex); | |
469 | |||
470 | ✗ | registeredIndex = mBuilder.CreateLoad(registeredIndex); | |
471 | |||
472 | // index into the void* array of handles and load the value. | ||
473 | // The result is a loaded void* value | ||
474 | |||
475 | ✗ | llvm::Value* accessorPtr = extractArgument(mFunction, "accessors"); | |
476 | ✗ | assert(accessorPtr); | |
477 | ✗ | accessorPtr = mBuilder.CreateGEP(accessorPtr, registeredIndex); | |
478 | |||
479 | // return loaded void** = void* | ||
480 | ✗ | return mBuilder.CreateLoad(accessorPtr); | |
481 | } | ||
482 | |||
483 | /////////////////////////////////////////////////////////////////////////// | ||
484 | /////////////////////////////////////////////////////////////////////////// | ||
485 | |||
486 | } // namespace codegen_internal | ||
487 | |||
488 | } // namespace codegen | ||
489 | } // namespace ax | ||
490 | } // namespace OPENVDB_VERSION_NAME | ||
491 | } // namespace openvdb | ||
492 | |||
493 |