| 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 |