GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/codegen/PointComputeGenerator.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 356 358 99.4%
Functions: 20 21 95.2%
Branches: 247 454 54.4%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file codegen/PointComputeGenerator.cc
5
6 #include "PointComputeGenerator.h"
7
8 #include "FunctionRegistry.h"
9 #include "FunctionTypes.h"
10 #include "Types.h"
11 #include "Utils.h"
12 #include "Codecs.h"
13
14 #include "openvdb_ax/Exceptions.h"
15 #include "openvdb_ax/ast/Scanners.h"
16
17 #include <llvm/ADT/SmallVector.h>
18 #include <llvm/IR/BasicBlock.h>
19 #include <llvm/IR/CallingConv.h>
20 #include <llvm/IR/Constants.h>
21 #include <llvm/IR/DerivedTypes.h>
22 #include <llvm/IR/Function.h>
23 #include <llvm/IR/GlobalVariable.h>
24 #include <llvm/IR/InlineAsm.h>
25 #include <llvm/IR/Instructions.h>
26 #include <llvm/IR/Intrinsics.h>
27 #include <llvm/IR/IRBuilder.h>
28 #include <llvm/IR/LLVMContext.h>
29 #include <llvm/Pass.h>
30 #include <llvm/Support/MathExtras.h>
31
32 namespace openvdb {
33 OPENVDB_USE_VERSION_NAMESPACE
34 namespace OPENVDB_VERSION_NAME {
35
36 namespace ax {
37 namespace codegen {
38
39 const std::array<const char*, PointKernelValue::N_ARGS>&
40 772 PointKernelValue::argumentKeys()
41 {
42 static const std::array<const char*, PointKernelValue::N_ARGS> arguments = {{
43 "custom_data",
44 "origin",
45 "value_buffer",
46 "isactive",
47 "point_index",
48 "transforms",
49 "values",
50 "flags",
51 "attribute_set",
52 "group_handles",
53 "leaf_data"
54 }};
55
56 772 return arguments;
57 }
58
59 2284 const char* PointKernelValue::getDefaultName() { return "ax.compute.point.PKV"; }
60
61 //
62
63 const std::array<const char*, PointKernelBufferRange::N_ARGS>&
64 PointKernelBufferRange::argumentKeys()
65 {
66 static const std::array<const char*, PointKernelBufferRange::N_ARGS> arguments = {{
67 "custom_data",
68 "origin",
69 "value_buffer",
70 "active_buffer",
71 "buffer_size",
72 "mode",
73 "transforms",
74 "buffers",
75 "flags",
76 "attribute_set",
77 "group_handles",
78 "leaf_data"
79 }};
80
81 return arguments;
82 }
83
84 3037 const char* PointKernelBufferRange::getDefaultName() { return "ax.compute.point.PKBR"; }
85
86 //
87
88 const std::array<const char*, PointKernelBuffer::N_ARGS>&
89 756 PointKernelBuffer::argumentKeys()
90 {
91 static const std::array<const char*, PointKernelBuffer::N_ARGS> arguments = {{
92 "custom_data",
93 "origin",
94 "value_buffer",
95 "isactive",
96 "point_index",
97 "transforms",
98 "buffers",
99 "flags",
100 "attribute_set",
101 "group_handles",
102 "leaf_data"
103 }};
104
105 756 return arguments;
106 }
107
108 2268 const char* PointKernelBuffer::getDefaultName() { return "ax.compute.point.PKB"; }
109
110 //
111
112 const std::array<const char*, PointKernelAttributeArray::N_ARGS>&
113 756 PointKernelAttributeArray::argumentKeys()
114 {
115 static const std::array<const char*, PointKernelAttributeArray::N_ARGS> arguments = {{
116 "custom_data",
117 "origin",
118 "value_buffer",
119 "isactive",
120 "point_index",
121 "transforms",
122 "attribute_arrays",
123 "flags",
124 "attribute_set",
125 "group_handles",
126 "leaf_data"
127 }};
128
129 756 return arguments;
130 }
131
132 3037 const char* PointKernelAttributeArray::getDefaultName() { return "ax.compute.point.PKAA"; }
133
134 ///////////////////////////////////////////////////////////////////////////
135 ///////////////////////////////////////////////////////////////////////////
136
137 namespace codegen_internal {
138
139 756 inline void PointComputeGenerator::computePKBR(const AttributeRegistry&)
140 {
141 1512 llvm::Function* compute = mModule.getFunction(PointKernelBuffer::getDefaultName());
142
143 auto generate =
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 [&](const std::vector<llvm::Value*>& args,
145 llvm::IRBuilder<>& B) -> llvm::Value*
146 {
147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(args.size() == 12);
148 756 llvm::Value* vbuff = args[2]; //extractArgument(rangeFunction, "value_buffer");
149 756 llvm::Value* abuff = args[3]; //extractArgument(rangeFunction, "active_buffer");
150 756 llvm::Value* buffSize = args[4]; //extractArgument(rangeFunction, "buffer_size");
151 756 llvm::Value* mode = args[5]; //extractArgument(rangeFunction, "mode");
152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(buffSize);
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(vbuff);
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(abuff);
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(mode);
156
157 llvm::Function* base = B.GetInsertBlock()->getParent();
158 llvm::LLVMContext& C = B.getContext();
159
160 756 llvm::BasicBlock* conditionBlock = llvm::BasicBlock::Create(C, "k2.condition", base);
161 756 llvm::BasicBlock* bodyBlock = llvm::BasicBlock::Create(C, "k2.body", base);
162 756 llvm::BasicBlock* iterBlock = llvm::BasicBlock::Create(C, "k2.buffiter", base);
163
164 // init var - loops from 0 -> buffSize
165 756 llvm::Value* incr = insertStaticAlloca(B, LLVMType<int64_t>::get(C));
166 756 B.CreateStore(B.getInt64(0), incr);
167 756 B.CreateBr(conditionBlock);
168
169 // increment
170 B.SetInsertPoint(iterBlock);
171 {
172 756 llvm::Value* new_incr = B.CreateAdd(B.CreateLoad(incr), B.getInt64(1));
173 756 B.CreateStore(new_incr, incr);
174 756 B.CreateBr(conditionBlock);
175 }
176
177 // generate loop body
178 B.SetInsertPoint(bodyBlock);
179 {
180 756 llvm::Value* lincr = B.CreateLoad(incr);
181
182 // Extract mask bit from array of words
183 // NodeMask::isOn() = (0 != (mWords[n >> 6] & (Word(1) << (n & 63))));
184
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 756 times.
✗ Branch 8 not taken.
756 llvm::Value* mask = binaryOperator(B.getInt64(1),
185 1512 binaryOperator(lincr, B.getInt64(63), ast::tokens::BITAND, B),
186
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 ast::tokens::SHIFTLEFT, B);
187 756 llvm::Value* word_idx = binaryOperator(lincr, B.getInt64(6), ast::tokens::SHIFTRIGHT, B);
188 756 llvm::Value* word = B.CreateGEP(abuff, word_idx);
189 756 word = B.CreateLoad(word);
190 756 word = binaryOperator(word, mask, ast::tokens::BITAND, B);
191 756 llvm::Value* ison = B.CreateICmpNE(word, B.getInt64(0));
192
193 // Check if we should run the kernel depending on the mode.
194 // mode == 0, inactive values
195 // mode == 1, active values
196 // mode == 2, all values
197 756 llvm::Value* matches_mode = B.CreateICmpEQ(B.CreateZExt(ison, mode->getType()), mode);
198 756 llvm::Value* mode_is_all = B.CreateICmpEQ(mode, B.getInt64(2));
199 756 llvm::Value* process = binaryOperator(matches_mode, mode_is_all, ast::tokens::OR, B);
200 756 llvm::BasicBlock* then = llvm::BasicBlock::Create(C, "k2.do_points", base);
201
202 756 B.CreateCondBr(process, then, iterBlock);
203 B.SetInsertPoint(then);
204 {
205 // branches for getting the end point index
206 756 llvm::BasicBlock* pthen = llvm::BasicBlock::Create(C, "k2.get_0_end", base);
207 756 llvm::BasicBlock* pelse = llvm::BasicBlock::Create(C, "k2.get_p_end", base);
208
209 // loop branches
210 756 llvm::BasicBlock* pcondition = llvm::BasicBlock::Create(C, "k2.pcond", base);
211 756 llvm::BasicBlock* pbody = llvm::BasicBlock::Create(C, "k2.pbody", base);
212 756 llvm::BasicBlock* piter = llvm::BasicBlock::Create(C, "k2.piter", base);
213
214 // loops from pindex->pindexend (point grids have 32bit buffers)
215 756 llvm::Value* pindex = insertStaticAlloca(B, B.getInt32Ty());
216 756 llvm::Value* pindexend = B.CreateGEP(vbuff, lincr);
217 756 pindexend = B.CreateLoad(pindexend);
218
219 756 llvm::Value* firstvoxel = binaryOperator(lincr, B.getInt64(0), ast::tokens::EQUALSEQUALS, B);
220 756 B.CreateCondBr(firstvoxel, pthen, pelse);
221 B.SetInsertPoint(pthen);
222 {
223 756 B.CreateStore(B.getInt32(0), pindex);
224 756 B.CreateBr(pcondition);
225 }
226
227 B.SetInsertPoint(pelse);
228 {
229 756 llvm::Value* prevv = binaryOperator(lincr, B.getInt64(1), ast::tokens::MINUS, B);
230 756 llvm::Value* pindexcount = B.CreateGEP(vbuff, prevv);
231 756 B.CreateStore(B.CreateLoad(pindexcount), pindex);
232 756 B.CreateBr(pcondition);
233 }
234
235 B.SetInsertPoint(pcondition);
236 {
237 756 llvm::Value* end = B.CreateICmpULT(B.CreateLoad(pindex), pindexend);
238 756 B.CreateCondBr(end, pbody, iterBlock);
239 }
240
241 B.SetInsertPoint(piter);
242 {
243 756 llvm::Value* pnext = B.CreateAdd(B.CreateLoad(pindex), B.getInt32(1));
244 756 B.CreateStore(pnext, pindex);
245 756 B.CreateBr(pcondition);
246 }
247
248 B.SetInsertPoint(pbody);
249 {
250 // invoke the point kernel for this value
251 const std::array<llvm::Value*, 11> input {
252 args[0], // ax::CustomData
253 args[1], // index space coordinate
254 vbuff, // value buffer
255 ison, // active/inactive
256 756 arithmeticConversion(B.CreateLoad(pindex), B.getInt64Ty(), B), // offset in the point array
257 args[6], // transforms
258 args[7], // buffers
259 args[8], // flags
260 args[9], // attr set
261 args[10], // groups
262 args[11] // leafdata
263 1512 };
264
265 756 B.CreateCall(compute, input);
266 756 B.CreateBr(piter);
267 }
268 }
269 }
270
271 B.SetInsertPoint(conditionBlock);
272 756 llvm::Value* endCondition = B.CreateICmpULT(B.CreateLoad(incr), buffSize);
273
274 756 llvm::BasicBlock* postBlock = llvm::BasicBlock::Create(C, "k2.end", base);
275 756 B.CreateCondBr(endCondition, bodyBlock, postBlock);
276 B.SetInsertPoint(postBlock);
277 756 return B.CreateRetVoid();
278 756 };
279
280 // Use the function builder to generate the correct prototype and body for K2
281
1/2
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
1512 auto k = FunctionBuilder(PointKernelBufferRange::getDefaultName())
282
2/4
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 756 times.
✗ Branch 6 not taken.
1512 .addSignature<PointKernelBufferRange::Signature>(generate, PointKernelBufferRange::getDefaultName())
283 .setConstantFold(false)
284 .setEmbedIR(false)
285
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
286
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoCapture)
287
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoAlias)
288
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
289
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoCapture)
290
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoAlias)
291
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoCapture)
292
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoAlias)
293
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(3, llvm::Attribute::NoCapture)
294
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(3, llvm::Attribute::NoAlias)
295
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoCapture)
296
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoAlias)
297
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoCapture)
298
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoAlias)
299 756 .addFunctionAttribute(llvm::Attribute::NoRecurse)
300
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
1512 .get();
301
302
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 k->list()[0]->create(mContext, &mModule);
303 756 }
304
305 /// @brief Decode the value held by buffer[pid] based on the flag type.
306 /// @details Certain types either cannot be encoded or can only be encoded with
307 /// certain encoders, so we use the type information to filter out what
308 /// encoders we need to loop over in IR.
309 /// @return Either returns buffer[pid] if no decoding was necessary or a
310 /// pointer to the newly allocated var of the decoded type which will have
311 /// been allocated in the function prologue
312 inline llvm::Value*
313 10170 decode(llvm::Value* buffer,
314 llvm::Value* pid,
315 llvm::Value* flag,
316 llvm::Value* store,
317 ast::tokens::CoreType decodedType,
318 llvm::IRBuilder<>& B)
319 {
320 llvm::LLVMContext& C = B.getContext();
321 10170 llvm::Type* type = llvmTypeFromToken(decodedType, C);
322
323 // see if this type might be encoded. If not, just return the original value
324 10170 const auto* codecs = getTypeSupportedCodecs(decodedType);
325
2/2
✓ Branch 0 taken 8530 times.
✓ Branch 1 taken 1640 times.
10170 if (!codecs) {
326 // Value can't be encoded so the buffer is guaranteed to be the decoded type
327 8530 buffer = B.CreatePointerCast(buffer, type->getPointerTo());
328 17060 return B.CreateGEP(buffer, pid);
329 }
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1640 times.
1640 assert(!codecs->empty());
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1640 times.
1640 assert(store);
332
333 llvm::Function* self = B.GetInsertBlock()->getParent();
334 1640 llvm::BasicBlock* post = llvm::BasicBlock::Create(C, "k1.get_buffer.decode", self);
335
336
2/2
✓ Branch 0 taken 5912 times.
✓ Branch 1 taken 1640 times.
7552 for (const auto& codecNamePair : *codecs) {
337 5912 const std::string& name = codecNamePair.first;
338 5912 const Codec* codec = codecNamePair.second;
339
340
1/2
✓ Branch 3 taken 5912 times.
✗ Branch 4 not taken.
5912 llvm::BasicBlock* then = llvm::BasicBlock::Create(C, "k1.get_buffer." + name, self);
341 5912 llvm::BasicBlock* els = llvm::BasicBlock::Create(C, "", self);
342
343 llvm::Value* usescodec =
344 5912 B.CreateAnd(flag, LLVMType<uint64_t>::get(C, codec->flag()));
345 5912 usescodec = boolComparison(usescodec, B);
346 5912 B.CreateCondBr(usescodec, then, els);
347
348 B.SetInsertPoint(then);
349 {
350 // If this is the codec in use, get the appropriate function, cast
351 // the input value and decode the value.
352 const FunctionGroup* const F = codec->decoder();
353 5912 llvm::Type* encodedType = codec->decodedToEncoded(decodedType, C);
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5912 times.
5912 assert(encodedType);
355 5912 encodedType = encodedType->getPointerTo();
356
357 // guranteed to be castable
358 5912 llvm::Value* typedBuffer = B.CreatePointerCast(buffer, encodedType);
359
1/2
✓ Branch 2 taken 5912 times.
✗ Branch 3 not taken.
11824 llvm::Value* encoded = B.CreateGEP(typedBuffer, pid);
360
3/6
✓ Branch 1 taken 5912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5912 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5912 times.
5912 assert(F->match({store->getType(), encoded->getType()}, C));
361
2/4
✓ Branch 1 taken 5912 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5912 times.
✗ Branch 5 not taken.
5912 F->execute({store, encoded}, B);
362 5912 B.CreateBr(post);
363 }
364
365 B.SetInsertPoint(els);
366 }
367
368 // if we're here (the final else), the value is not encoded
369 // @todo We could instead register all vaid nullcodecs which would give
370 // guarantees should a codec not exist
371 1640 llvm::Value* typedBuffer = B.CreatePointerCast(buffer, type->getPointerTo());
372 1640 llvm::Value* value = B.CreateGEP(typedBuffer, pid);
373 1640 B.CreateStore(B.CreateLoad(value), store);
374 1640 B.CreateBr(post);
375
376 B.SetInsertPoint(post);
377 1640 return store;
378 }
379
380 /// @brief Encode the value held by "in" based on the flag type, to the
381 /// location pointed to by buffer[pid].
382 /// @details Certain types either cannot be encoded or can only be encoded with
383 /// certain codec, so we use the type information to filter out what
384 /// codec we need to loop over in IR.
385 /// @return Either returns immediately if no encoding was necessary or stores
386 /// the encoded version of "in" at the location pointed to by buffer[pid]
387 inline void
388 4940 encode(llvm::Value* in,
389 llvm::Value* buffer,
390 llvm::Value* pid,
391 llvm::Value* flag,
392 ast::tokens::CoreType decodedType,
393 llvm::IRBuilder<>& B)
394 {
395 llvm::LLVMContext& C = B.getContext();
396 4940 llvm::Type* type = llvmTypeFromToken(decodedType, C);
397
398 // see if this type might be encoded. If not, just store the original value
399 4940 const auto* codecs = getTypeSupportedCodecs(decodedType);
400
2/2
✓ Branch 0 taken 4149 times.
✓ Branch 1 taken 791 times.
4940 if (!codecs) {
401 // Value can't be encoded so the buffer is guaranteed to be the decoded type
402 4149 buffer = B.CreatePointerCast(buffer, type->getPointerTo());
403 8298 B.CreateStore(B.CreateLoad(in), B.CreateGEP(buffer, pid));
404 4149 return;
405 }
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 791 times.
791 assert(!codecs->empty());
407
408 llvm::Function* self = B.GetInsertBlock()->getParent();
409 791 llvm::BasicBlock* post = llvm::BasicBlock::Create(C, "k1.set_buffer.encode", self);
410
411
2/2
✓ Branch 0 taken 2847 times.
✓ Branch 1 taken 791 times.
3638 for (const auto& codecNamePair : *codecs) {
412 2847 const std::string& name = codecNamePair.first;
413 2847 const Codec* codec = codecNamePair.second;
414
415
1/2
✓ Branch 3 taken 2847 times.
✗ Branch 4 not taken.
2847 llvm::BasicBlock* then = llvm::BasicBlock::Create(C, "k1.set_buffer." + name, self);
416 2847 llvm::BasicBlock* els = llvm::BasicBlock::Create(C, "", self);
417
418 llvm::Value* usescodec =
419 2847 B.CreateAnd(flag, LLVMType<uint64_t>::get(C, codec->flag()));
420 2847 usescodec = boolComparison(usescodec, B);
421 2847 B.CreateCondBr(usescodec, then, els);
422
423 B.SetInsertPoint(then);
424 {
425 const FunctionGroup* const F = codec->encoder();
426 2847 llvm::Type* encodedType = codec->decodedToEncoded(decodedType, C);
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2847 times.
2847 assert(encodedType);
428 2847 encodedType = encodedType->getPointerTo();
429 2847 llvm::Value* typedBuffer = B.CreatePointerCast(buffer, encodedType);
430
1/2
✓ Branch 2 taken 2847 times.
✗ Branch 3 not taken.
5694 llvm::Value* loc = B.CreateGEP(typedBuffer, pid);
431
3/6
✓ Branch 1 taken 2847 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2847 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2847 times.
2847 assert(F->match({loc->getType(),in->getType()}, C));
432
2/4
✓ Branch 1 taken 2847 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2847 times.
✗ Branch 5 not taken.
2847 F->execute({loc, in}, B);
433 2847 B.CreateBr(post);
434 }
435
436 B.SetInsertPoint(els);
437 }
438
439 // if we're here (the final else), the value is not encodable
440 // @todo We could instead register all vaid nullcodecs which would give
441 // guarantees should a codec not exist
442 791 llvm::Value* typedBuffer = B.CreatePointerCast(buffer, type->getPointerTo());
443 791 llvm::Value* loc = B.CreateGEP(typedBuffer, pid);
444 791 B.CreateStore(B.CreateLoad(in), loc);
445 791 B.CreateBr(post);
446
447 B.SetInsertPoint(post);
448 }
449
450 756 inline void PointComputeGenerator::computePKB(const AttributeRegistry& registry)
451 {
452 1512 llvm::Function* compute = mModule.getFunction(PointKernelValue::getDefaultName());
453
454 auto generate =
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 [&](const std::vector<llvm::Value*>& args,
456 llvm::IRBuilder<>& B) -> llvm::Value*
457 {
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(args.size() == 11);
459 auto& C = B.getContext();
460 llvm::Function* self = B.GetInsertBlock()->getParent();
461
2/4
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
756 llvm::Value* pindex = extractArgument(self, "point_index");
462
2/4
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
756 llvm::Value* flags = extractArgument(self, "flags");
463
2/4
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
756 llvm::Value* buffers = extractArgument(self, "buffers");
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(buffers);
465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(pindex);
466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(flags);
467
468 // create array of void*. each pointer will encode an address to a stored typed value
469 1512 llvm::Type* locType = llvm::ArrayType::get(LLVMType<void*>::get(C), registry.data().size()); // [SIZE x i8*]
470 756 llvm::Value* loc = insertStaticAlloca(B, locType);
471
472 size_t i = 0;
473
2/2
✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 756 times.
5841 for (const AttributeRegistry::AccessData& data : registry.data())
474 {
475 const std::string token = data.tokenname();
476
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 llvm::Type* type = llvmTypeFromToken(data.type(), C);
477
478
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 llvm::Value* decodedPtrs = B.CreateConstInBoundsGEP2_64(loc, 0, i++); // void**, location to hold the typed ptr
479
3/6
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5085 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5085 times.
✗ Branch 9 not taken.
5085 decodedPtrs = B.CreatePointerCast(decodedPtrs, type->getPointerTo()->getPointerTo()); // ValueType**
480
481
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 llvm::Value* index = mModule.getGlobalVariable(token);
482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5085 times.
5085 assert(index);
483
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 index = B.CreateLoad(index);
484 5085 llvm::Value* buffer = B.CreateGEP(buffers, index);
485
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 buffer = B.CreateLoad(buffer); // void** = void*
486
487
1/2
✓ Branch 3 taken 5085 times.
✗ Branch 4 not taken.
10170 llvm::Value* flag = B.CreateLoad(B.CreateGEP(flags, index));
488
489 // @todo write handles shouldn't need to do this check
490
2/4
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5085 times.
✗ Branch 6 not taken.
5085 llvm::Value* isuniform = B.CreateAnd(flag, LLVMType<uint64_t>::get(C, (uint64_t(1) << 63)));
491
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 isuniform = boolComparison(isuniform, B);
492
493 // If the value type has supported codecs we have to allocate the
494 // expected decoded type that will be stored. Otherwise, decode()
495 // will simply extract the value ptr directly from the buffer.
496 llvm::Value* decodedStore = nullptr;
497
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 const auto* codecs = getTypeSupportedCodecs(data.type());
498
4/6
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 4265 times.
✓ Branch 3 taken 820 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 820 times.
✗ Branch 7 not taken.
5085 if (codecs) decodedStore = insertStaticAlloca(B, llvmTypeFromToken(data.type(), C)); // allocated to prologue
499
500
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 llvm::BasicBlock* then = llvm::BasicBlock::Create(C, "k1.get_buffer.uniform", self);
501
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 llvm::BasicBlock* els = llvm::BasicBlock::Create(C, "k1.get_buffer.nuniform", self);
502
1/2
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
5085 llvm::BasicBlock* cont = llvm::BasicBlock::Create(C, "k1.get_buffer.continue", self);
503
504
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateCondBr(isuniform, then, els);
505
506
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.SetInsertPoint(then);
507 {
508
2/4
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5085 times.
✗ Branch 5 not taken.
5085 llvm::Value* ptr = decode(buffer, B.getInt64(0), flag, decodedStore, data.type(), B);
509
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateStore(ptr, decodedPtrs);
510
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateBr(cont);
511 }
512
513 B.SetInsertPoint(els);
514 {
515
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 llvm::Value* ptr = decode(buffer, pindex, flag, decodedStore, data.type(), B);
516
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateStore(ptr, decodedPtrs);
517
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateBr(cont);
518 }
519
520 B.SetInsertPoint(cont);
521 }
522
523 756 llvm::BasicBlock* post = llvm::BasicBlock::Create(C, "k1.run_compute", self);
524 756 B.CreateBr(post);
525 B.SetInsertPoint(post);
526
527 // invoke the point kernel for this value
528 std::array<llvm::Value*, 11> input;
529 756 std::copy_n(args.begin(), 11, input.begin());
530 756 input[6] = B.CreateConstInBoundsGEP2_64(loc, 0, 0); // void**, replace the buffers with the extracted values
531
532 756 B.CreateCall(compute, input);
533
534 // insert writes to any attributes that were potentially compressed
535 i = 0;
536
2/2
✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 756 times.
5841 for (const AttributeRegistry::AccessData& data : registry.data())
537 {
538
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 4940 times.
5085 if (!data.writes()) {
539 145 i++;
540 145 continue;
541 }
542
543 const std::string token = data.tokenname();
544
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 llvm::Type* type = llvmTypeFromToken(data.type(), C);
545
546
1/2
✓ Branch 2 taken 4940 times.
✗ Branch 3 not taken.
4940 llvm::Value* store = B.CreateConstInBoundsGEP2_64(loc, 0, i++); // void**, location to hold the typed ptr
547
1/2
✓ Branch 2 taken 4940 times.
✗ Branch 3 not taken.
4940 store = B.CreateLoad(store); // void*
548
2/4
✓ Branch 2 taken 4940 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4940 times.
✗ Branch 6 not taken.
4940 store = B.CreatePointerCast(store, type->getPointerTo()); // ValueType*
549
550
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 llvm::Value* index = mModule.getGlobalVariable(token);
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4940 times.
4940 assert(index);
552
1/2
✓ Branch 2 taken 4940 times.
✗ Branch 3 not taken.
4940 index = B.CreateLoad(index);
553
1/2
✓ Branch 3 taken 4940 times.
✗ Branch 4 not taken.
9880 llvm::Value* flag = B.CreateLoad(B.CreateGEP(flags, index));
554
555 4940 llvm::Value* buffer = B.CreateGEP(buffers, index);
556
2/4
✓ Branch 2 taken 4940 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4940 times.
✗ Branch 6 not taken.
4940 buffer = B.CreateLoad(buffer); // void** = void*
557
558 // The buffer should not be uniform if we're writing to it, so no
559 // need to branch for this case (this should be guaranteed by the
560 // PointExectuable)
561
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 encode(store, buffer, pindex, flag, data.type(), B);
562 }
563
564 756 return B.CreateRetVoid();
565 756 };
566
567 756 const auto& keys = PointKernelBuffer::argumentKeys();
568
569 // Use the function builder to generate the correct prototype and body for K2
570
1/2
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
1512 auto k = FunctionBuilder(PointKernelBuffer::getDefaultName())
571
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 756 times.
✗ Branch 8 not taken.
1512 .addSignature<PointKernelBuffer::Signature>(generate, PointKernelBuffer::getDefaultName())
572 .setConstantFold(false)
573 .setEmbedIR(false)
574
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 756 times.
✗ Branch 7 not taken.
1512 .setArgumentNames(std::vector<const char*>(keys.begin(), keys.end()))
575
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
576
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoCapture)
577
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoAlias)
578
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
579
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoCapture)
580
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoAlias)
581
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoCapture)
582
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoAlias)
583
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(5, llvm::Attribute::NoCapture)
584
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(5, llvm::Attribute::NoAlias)
585
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoCapture)
586
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoAlias)
587
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoCapture)
588
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoAlias)
589
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(8, llvm::Attribute::NoCapture)
590
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(8, llvm::Attribute::NoAlias)
591 756 .addFunctionAttribute(llvm::Attribute::NoRecurse)
592
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
1512 .get();
593
594
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 k->list()[0]->create(mContext, &mModule);
595 756 }
596
597 756 inline void PointComputeGenerator::computePKAA(const AttributeRegistry& registry)
598 {
599 1512 llvm::Function* compute = mModule.getFunction(PointKernelValue::getDefaultName());
600
601 /// @brief PKAA function for getting a point value from an attribute array
602 5085 auto getAttributeValue = [this](const std::string& token,
603 llvm::Value* pindex,
604 llvm::Value* store,
605 5085 llvm::IRBuilder<>& B)
606 {
607 llvm::Function* self = B.GetInsertBlock()->getParent();
608 llvm::Module* M = self->getParent();
609 llvm::LLVMContext& C = B.getContext();
610
611 llvm::Type* type = store->getType();
612
613 // insert the attribute into the map of global variables and get a unique global representing
614 // the location which will hold the attribute handle offset.
615 5085 llvm::Value* index = M->getGlobalVariable(token);
616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5085 times.
5085 assert(index);
617 5085 index = B.CreateLoad(index);
618
619
2/4
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5085 times.
✗ Branch 5 not taken.
5085 llvm::Value* arrays = extractArgument(self, "attribute_arrays");
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5085 times.
5085 assert(arrays);
621 5085 llvm::Value* array = B.CreateGEP(arrays, index);
622 5085 array = B.CreateLoad(array); // void** = void*
623
624 // invoke C binding
625 const bool usingString =
626 type == LLVMType<codegen::String*>::get(C);
627
628 std::vector<llvm::Value*> args {
629 array,
630 pindex,
631 store
632 5085 };
633
634
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 4995 times.
5085 if (usingString) {
635
3/6
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 90 times.
✗ Branch 8 not taken.
90 args.emplace_back(extractArgument(self, "leaf_data"));
636 }
637
638
2/4
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5085 times.
✗ Branch 5 not taken.
5085 const FunctionGroup* const F = this->getFunction("getattribute", true);
639
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 F->execute(args, B);
640 5085 };
641
642 /// @brief PKAA function for setting a point value on an attribute array
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4940 times.
4940 auto setAttributeValue = [this](const std::string& token,
644 llvm::Value* pindex,
645 llvm::Value* load,
646 4940 llvm::IRBuilder<>& B)
647 {
648 llvm::Function* self = B.GetInsertBlock()->getParent();
649 llvm::Module* M = self->getParent();
650 llvm::LLVMContext& C = B.getContext();
651
652 llvm::Type* type = load->getType()->getPointerElementType();
653
654 // insert the attribute into the map of global variables and get a unique global representing
655 // the location which will hold the attribute handle offset.
656 4940 llvm::Value* index = M->getGlobalVariable(token);
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4940 times.
4940 assert(index);
658 4940 index = B.CreateLoad(index);
659
660
2/4
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4940 times.
✗ Branch 5 not taken.
4940 llvm::Value* arrays = extractArgument(self, "attribute_arrays");
661
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4940 times.
4940 assert(arrays);
662 4940 llvm::Value* array = B.CreateGEP(arrays, index);
663
2/2
✓ Branch 2 taken 3239 times.
✓ Branch 3 taken 1701 times.
4940 array = B.CreateLoad(array); // void** = void*
664
665 // load the result (if its a scalar)
666
2/2
✓ Branch 0 taken 3239 times.
✓ Branch 1 taken 1701 times.
4940 if (type->isIntegerTy() || type->isFloatingPointTy()) {
667 3039 load = B.CreateLoad(load);
668 }
669 //llvm::errs() << "storing: " << *(load->getType()) << '\n';
670
671 // construct function arguments
672 std::vector<llvm::Value*> args {
673 array, // handle
674 pindex, // point index
675 load // set value
676 4940 };
677
678
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 llvm::Type* strType = LLVMType<codegen::String>::get(C);
679 const bool usingString = type == strType;
680
681
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 4856 times.
4940 if (usingString) {
682
2/4
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 5 not taken.
84 llvm::Value* leafdata = extractArgument(self, "leaf_data");
683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 assert(leafdata);
684
1/2
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
84 args.emplace_back(leafdata);
685 }
686
687
2/4
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4940 times.
✗ Branch 5 not taken.
4940 const FunctionGroup* const function = this->getFunction("setattribute", true);
688
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 function->execute(args, B);
689 4940 };
690
691 //
692
693 auto generate =
694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 [&](const std::vector<llvm::Value*>& args,
695 llvm::IRBuilder<>& B) -> llvm::Value*
696 {
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
756 assert(args.size() == 11);
698 auto& C = B.getContext();
699 llvm::Function* self = B.GetInsertBlock()->getParent();
700
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 756 times.
✗ Branch 8 not taken.
1512 llvm::Value* pindex = extractArgument(self, "point_index");
701
702 SymbolTable table;
703
704 // create array of void*. each element will hold the attribute values
705
2/4
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
2268 llvm::Type* locType = llvm::ArrayType::get(LLVMType<void*>::get(C), registry.data().size()); // [SIZE x i8*]
706
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 llvm::Value* loc = insertStaticAlloca(B, locType);
707
708 // run allocations
709 size_t i = 0;
710
2/2
✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 756 times.
5841 for (const AttributeRegistry::AccessData& access : registry.data()) {
711
2/4
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5085 times.
✗ Branch 5 not taken.
5085 llvm::Value* value = insertStaticAlloca(B, llvmTypeFromToken(access.type(), C));
712
2/4
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5085 times.
5085 assert(llvm::cast<llvm::AllocaInst>(value)->isStaticAlloca());
713
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 table.insert(access.tokenname(), value);
714
715 // store the allocated ptr in the array of void*
716 5085 llvm::Value* store = B.CreateConstInBoundsGEP2_64(loc, 0, i); // void**, location to hold the typed ptr
717
2/4
✓ Branch 2 taken 5085 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5085 times.
✗ Branch 6 not taken.
5085 value = B.CreatePointerCast(value, LLVMType<void*>::get(C));
718
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 B.CreateStore(value, store);
719
720 5085 ++i;
721 }
722
723 // get attributes
724
2/2
✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 756 times.
5841 for (const AttributeRegistry::AccessData& data : registry.data()) {
725 const std::string token = data.tokenname();
726 5085 llvm::Value* store = table.get(token);
727
1/2
✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
5085 getAttributeValue(token, pindex, store, B);
728 }
729
730 // invoke the point kernel for this value
731 std::array<llvm::Value*, 11> input;
732 756 std::copy_n(args.begin(), 11, input.begin());
733 756 input[6] = B.CreateConstInBoundsGEP2_64(loc, 0, 0); // void**, replace the buffers with the extracted values
734
1/2
✓ Branch 2 taken 756 times.
✗ Branch 3 not taken.
756 B.CreateCall(compute, input);
735
736 // insert set code and deallocations
737
2/2
✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 756 times.
5841 for (const AttributeRegistry::AccessData& data : registry.data()) {
738
2/2
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 4940 times.
5085 if (!data.writes()) continue;
739
740 const std::string token = data.tokenname();
741 4940 llvm::Value* value = table.get(token);
742 // // Expected to be used more than one (i.e. should never be zero)
743 // assert(value->hasNUsesOrMore(1));
744 // // Check to see if this value is still being used - it may have
745 // // been cleaned up due to returns. If there's only one use, it's
746 // // the original get of this attribute.
747 // if (value->hasOneUse()) {
748 // // @todo The original get can also be optimized out in this case
749 // // this->globals().remove(variable.first);
750 // // mModule.getGlobalVariable(variable.first)->eraseFromParent();
751 // continue;
752 // }
753
1/2
✓ Branch 1 taken 4940 times.
✗ Branch 2 not taken.
4940 setAttributeValue(token, pindex, value, B);
754 }
755
756
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 llvm::Value* last = B.CreateRetVoid();
757
758 // insert free calls for any strings
759
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 this->createFreeSymbolStrings(B);
760
761 756 return last;
762 756 };
763
764 756 const auto& keys = PointKernelAttributeArray::argumentKeys();
765
766 // Use the function builder to generate the correct prototype and body for K2
767
1/2
✓ Branch 3 taken 756 times.
✗ Branch 4 not taken.
1512 auto k = FunctionBuilder(PointKernelAttributeArray::getDefaultName())
768
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 756 times.
✗ Branch 8 not taken.
1512 .addSignature<PointKernelAttributeArray::Signature>(generate, PointKernelAttributeArray::getDefaultName())
769 .setConstantFold(false)
770 .setEmbedIR(false)
771
3/6
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 756 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 756 times.
✗ Branch 7 not taken.
1512 .setArgumentNames(std::vector<const char*>(keys.begin(), keys.end()))
772
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::ReadOnly)
773
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoCapture)
774
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(0, llvm::Attribute::NoAlias)
775
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::ReadOnly)
776
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoCapture)
777
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(1, llvm::Attribute::NoAlias)
778
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoCapture)
779
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(2, llvm::Attribute::NoAlias)
780
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(5, llvm::Attribute::NoCapture)
781
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(5, llvm::Attribute::NoAlias)
782
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoCapture)
783
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(6, llvm::Attribute::NoAlias)
784
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoCapture)
785
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(7, llvm::Attribute::NoAlias)
786
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(8, llvm::Attribute::NoCapture)
787
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 .addParameterAttribute(8, llvm::Attribute::NoAlias)
788 756 .addFunctionAttribute(llvm::Attribute::NoRecurse)
789
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
1512 .get();
790
791
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 k->list()[0]->create(mContext, &mModule);
792 756 }
793
794 772 PointComputeGenerator::PointComputeGenerator(llvm::Module& module,
795 const FunctionOptions& options,
796 FunctionRegistry& functionRegistry,
797 772 Logger& logger)
798 772 : ComputeGenerator(module, options, functionRegistry, logger) {}
799
800
801 772 AttributeRegistry::Ptr PointComputeGenerator::generate(const ast::Tree& tree)
802 {
803 llvm::FunctionType* type =
804 772 llvmFunctionTypeFromSignature<PointKernelValue::Signature>(mContext);
805
806
1/2
✓ Branch 2 taken 772 times.
✗ Branch 3 not taken.
772 mFunction = llvm::Function::Create(type,
807 llvm::Function::ExternalLinkage,
808 PointKernelValue::getDefaultName(),
809 772 &mModule);
810
811 // @note Might be worth always inlining the value kernel into the buffer kernel
812 //mFunction->addFnAttr(llvm::Attribute::AlwaysInline);
813
814 // Set up arguments for initial entry
815
816 llvm::Function::arg_iterator argIter = mFunction->arg_begin();
817 772 const auto arguments = PointKernelValue::argumentKeys();
818 auto keyIter = arguments.cbegin();
819
820
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9264 times.
✓ Branch 2 taken 8492 times.
✓ Branch 3 taken 772 times.
9264 for (; argIter != mFunction->arg_end(); ++argIter, ++keyIter) {
821 8492 argIter->setName(*keyIter);
822 }
823
824 772 llvm::BasicBlock* entry = llvm::BasicBlock::Create(mContext, "k1.entry", mFunction);
825 mBuilder.SetInsertPoint(entry);
826
827 // build the attribute registry
828
829 772 AttributeRegistry::Ptr registry = AttributeRegistry::create(tree);
830
831 // intialise the global indices - do this here so it's only done once
832
833
2/2
✓ Branch 0 taken 5087 times.
✓ Branch 1 taken 772 times.
5859 for (const AttributeRegistry::AccessData& access : registry->data()) {
834 const std::string token = access.tokenname();
835 llvm::Value* index = llvm::cast<llvm::GlobalVariable>
836
3/6
✓ Branch 1 taken 5087 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5087 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5087 times.
✗ Branch 9 not taken.
5087 (mModule.getOrInsertGlobal(token, LLVMType<int64_t>::get(mContext)));
837
1/2
✓ Branch 1 taken 5087 times.
✗ Branch 2 not taken.
5087 this->globals().insert(token, index);
838 }
839
840 // full code generation
841 // errors can stop traversal, but dont always, so check the log
842
843
2/2
✓ Branch 1 taken 767 times.
✓ Branch 2 taken 5 times.
772 const size_t err = mLog.errors();
844
3/4
✓ Branch 0 taken 767 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 756 times.
767 if (!this->traverse(&tree) || (mLog.errors() > err)) return nullptr;
845
846 // insert free calls for any strings
847
848
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 this->createFreeSymbolStrings(mBuilder);
849
850 // compute extra kernels (order here is important)
851
852
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 this->computePKB(*registry);
853
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 this->computePKAA(*registry);
854 // must come after PKB
855
1/2
✓ Branch 1 taken 756 times.
✗ Branch 2 not taken.
756 this->computePKBR(*registry);
856
857 return registry;
858 }
859
860 6082 bool PointComputeGenerator::visit(const ast::Attribute* node)
861 {
862 12164 llvm::Value* index = mModule.getGlobalVariable(node->tokenname());
863 6082 llvm::Type* type = llvmTypeFromToken(node->type(), mContext);
864
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6082 times.
6082 assert(index);
866 // index into the void* array of handles and load the value.
867 6082 index = mBuilder.CreateLoad(index);
868
2/4
✓ Branch 1 taken 6082 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6082 times.
✗ Branch 5 not taken.
6082 llvm::Value* value = extractArgument(mFunction, "values"); // void**
869 6082 value = mBuilder.CreateGEP(value, index); // void**
870 6082 value = mBuilder.CreateLoad(value); // void*
871 6082 value = mBuilder.CreatePointerCast(value, type->getPointerTo()); // void* = ValueType*
872
873 mValues.push(value);
874 6082 return true;
875 }
876
877 } // namespace codegen_internal
878
879 } // namespace codegen
880 } // namespace ax
881 } // namespace OPENVDB_VERSION_NAME
882 } // namespace openvdb
883
884