OpenVDB 12.1.0
Loading...
Searching...
No Matches
LegacyIR.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @file codegen/LegacyIR.h
5///
6/// @authors Nick Avramoussis
7///
8/// @brief Legacy IR utilities for LLVM_VERSION_MAJOR <= 15
9///
10
11#ifndef OPENVDB_AX_CODEGEN_LEGACY_IR_HAS_BEEN_INCLUDED
12#define OPENVDB_AX_CODEGEN_LEGACY_IR_HAS_BEEN_INCLUDED
13
14#include <llvm/Config/llvm-config.h>
15
16#if LLVM_VERSION_MAJOR <= 15
17
18#include "Types.h"
19#include "Utils.h"
20#include <openvdb/version.h>
21#include <openvdb/util/Assert.h>
22#include <llvm/IR/IRBuilder.h>
23
24namespace openvdb {
26namespace OPENVDB_VERSION_NAME {
27
28namespace ax {
29namespace codegen {
30
32inline auto ir_load(llvm::IRBuilder<>& B, llvm::Value* ptr, const char* Name = "")
33{
34 OPENVDB_ASSERT(ptr);
35 OPENVDB_ASSERT(ptr->getType()->isPointerTy());
36 return B.CreateLoad(ptr->getType()->getPointerElementType(), ptr, Name);
37}
38
40inline auto ir_gep(llvm::IRBuilder<>& B,
41 llvm::Value* ptr, llvm::ArrayRef<llvm::Value*> IdxList, const char* Name = "")
42{
43 OPENVDB_ASSERT(ptr);
44 OPENVDB_ASSERT(ptr->getType()->getScalarType());
45 OPENVDB_ASSERT(ptr->getType()->getScalarType()->isPointerTy());
46 return B.CreateGEP(ptr->getType()->getScalarType()->getPointerElementType(),
47 ptr, IdxList, Name);
48#
49}
50
52inline auto ir_constgep2_64(llvm::IRBuilder<>& B,
53 llvm::Value* ptr, uint64_t Idx0, uint64_t Idx1, const char* Name = "")
54{
55 OPENVDB_ASSERT(ptr);
56 OPENVDB_ASSERT(ptr->getType()->getScalarType());
57 OPENVDB_ASSERT(ptr->getType()->getScalarType()->isPointerTy());
58 return B.CreateConstGEP2_64(
59 ptr->getType()->getScalarType()->getPointerElementType(), ptr, Idx0,
60 Idx1, Name);
61}
62
64inline auto ir_constinboundsgep2_64(llvm::IRBuilder<>& B,
65 llvm::Value* ptr, uint64_t Idx0, uint64_t Idx1, const char* Name = "")
66{
67 OPENVDB_ASSERT(ptr);
68 OPENVDB_ASSERT(ptr->getType()->getScalarType());
69 OPENVDB_ASSERT(ptr->getType()->getScalarType()->isPointerTy());
70 return B.CreateConstInBoundsGEP2_64(
71 ptr->getType()->getScalarType()->getPointerElementType(), ptr, Idx0,
72 Idx1, Name);
73}
74
75/// @brief Return the base llvm value which is being pointed to through
76/// any number of layered pointers.
77/// @note This function does not check for cyclical pointer dependencies
78///
79/// @param type A llvm pointer type to traverse
80///
82inline llvm::Type*
83getBaseContainedType(llvm::Type* const type)
84{
85 llvm::Type* elementType = type;
86 while (elementType->isPointerTy()) {
87 elementType = elementType->getContainedType(0);
88 }
89 return elementType;
90}
91
92/// @brief Casts an array to another array of equal size but of a different element
93/// type. Both source and target array element types must be scalar types.
94/// The source array llvm Value should be a pointer to the array to cast.
95///
96/// @param ptrToArray A llvm value which is a pointer to a llvm array
97/// @param targetElementType The target llvm scalar type to convert each element
98/// of the input array
99/// @param builder The current llvm IRBuilder
100///
102inline llvm::Value*
103arrayCast(llvm::Value* ptrToArray,
104 llvm::Type* targetElementType,
105 llvm::IRBuilder<>& builder)
106{
107 OPENVDB_ASSERT(targetElementType && (targetElementType->isIntegerTy() ||
108 targetElementType->isFloatingPointTy()) &&
109 "Target element type is not a scalar type");
110 OPENVDB_ASSERT(ptrToArray && ptrToArray->getType()->isPointerTy() &&
111 "Input to arrayCast is not a pointer type.");
112
113 llvm::Type* arrayType = ptrToArray->getType()->getContainedType(0);
114 OPENVDB_ASSERT(arrayType && llvm::isa<llvm::ArrayType>(arrayType));
115
116 // getArrayElementType() calls getContainedType(0)
117 llvm::Type* sourceElementType = arrayType->getArrayElementType();
118 OPENVDB_ASSERT(sourceElementType && (sourceElementType->isIntegerTy() ||
119 sourceElementType->isFloatingPointTy()) &&
120 "Source element type is not a scalar type");
121
122 if (sourceElementType == targetElementType) return ptrToArray;
123
124 CastFunction llvmCastFunction = llvmArithmeticConversion(sourceElementType, targetElementType);
125
126 const size_t elementSize = arrayType->getArrayNumElements();
127 llvm::Value* targetArray =
128 insertStaticAlloca(builder,
129 llvm::ArrayType::get(targetElementType, elementSize));
130
131 for (size_t i = 0; i < elementSize; ++i) {
132 llvm::Value* target = builder.CreateConstGEP2_64(targetArray->getType()->getScalarType()->getPointerElementType(), targetArray, 0, i);
133 llvm::Value* source = builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, i);
134 source = builder.CreateLoad(source->getType()->getPointerElementType(), source);
135 source = llvmCastFunction(builder, source, targetElementType);
136 builder.CreateStore(source, target);
137 }
138
139 return targetArray;
140}
141
142/// @brief Unpack a particular element of an array and return a pointer to that element
143/// The provided llvm Value is expected to be a pointer to an array
144///
145/// @param ptrToArray A llvm value which is a pointer to a llvm array
146/// @param index The index at which to access the array
147/// @param builder The current llvm IRBuilder
148///
150inline llvm::Value*
151arrayIndexUnpack(llvm::Value* ptrToArray,
152 const int16_t index,
153 llvm::IRBuilder<>& builder)
154{
155 return builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, index);
156}
157
158/// @brief Unpack an array type into llvm Values which represent all its elements
159/// The provided llvm Value is expected to be a pointer to an array
160/// If loadElements is true, values will store loaded llvm values instead
161/// of pointers to the array elements
162///
163/// @param ptrToArray A llvm value which is a pointer to a llvm array
164/// @param values A vector of llvm values where to store the array elements
165/// @param builder The current llvm IRBuilder
166/// @param loadElements Whether or not to load each array element into a register
167///
169inline void
170arrayUnpack(llvm::Value* ptrToArray,
171 std::vector<llvm::Value*>& values,
172 llvm::IRBuilder<>& builder,
173 const bool loadElements = false)
174{
175 const size_t elements =
176 ptrToArray->getType()->getContainedType(0)->getArrayNumElements();
177
178 values.reserve(elements);
179 for (size_t i = 0; i < elements; ++i) {
180 llvm::Value* value = builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, i);
181 if (loadElements) value = builder.CreateLoad(value->getType()->getPointerElementType(), value);
182 values.push_back(value);
183 }
184}
185
186/// @brief Unpack the first three elements of an array.
187/// The provided llvm Value is expected to be a pointer to an array
188/// @note The elements are note loaded
189///
190/// @param ptrToArray A llvm value which is a pointer to a llvm array
191/// @param value1 The first array value
192/// @param value2 The second array value
193/// @param value3 The third array value
194/// @param builder The current llvm IRBuilder
195///
197inline void
198array3Unpack(llvm::Value* ptrToArray,
199 llvm::Value*& value1,
200 llvm::Value*& value2,
201 llvm::Value*& value3,
202 llvm::IRBuilder<>& builder)
203{
204 OPENVDB_ASSERT(ptrToArray && ptrToArray->getType()->isPointerTy() &&
205 "Input to array3Unpack is not a pointer type.");
206
207 value1 = builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, 0);
208 value2 = builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, 1);
209 value3 = builder.CreateConstGEP2_64(ptrToArray->getType()->getScalarType()->getPointerElementType(), ptrToArray, 0, 2);
210}
211
212/// @brief Pack three values into a new array and return a pointer to the
213/// newly allocated array. If the values are of a mismatching type,
214/// the highets order type is uses, as defined by typePrecedence. All
215/// llvm values are expected to a be a loaded scalar type
216///
217/// @param value1 The first array value
218/// @param value2 The second array value
219/// @param value3 The third array value
220/// @param builder The current llvm IRBuilder
221///
223inline llvm::Value*
224array3Pack(llvm::Value* value1,
225 llvm::Value* value2,
226 llvm::Value* value3,
227 llvm::IRBuilder<>& builder)
228{
229 llvm::Type* type = typePrecedence(value1->getType(), value2->getType());
230 type = typePrecedence(type, value3->getType());
231
232 value1 = arithmeticConversion(value1, type, builder);
233 value2 = arithmeticConversion(value2, type, builder);
234 value3 = arithmeticConversion(value3, type, builder);
235
236 llvm::Type* vectorType = llvm::ArrayType::get(type, 3);
237 llvm::Value* vector = insertStaticAlloca(builder, vectorType);
238
239 llvm::Value* e1 = builder.CreateConstGEP2_64(vector->getType()->getScalarType()->getPointerElementType(), vector, 0, 0);
240 llvm::Value* e2 = builder.CreateConstGEP2_64(vector->getType()->getScalarType()->getPointerElementType(), vector, 0, 1);
241 llvm::Value* e3 = builder.CreateConstGEP2_64(vector->getType()->getScalarType()->getPointerElementType(), vector, 0, 2);
242
243 builder.CreateStore(value1, e1);
244 builder.CreateStore(value2, e2);
245 builder.CreateStore(value3, e3);
246
247 return vector;
248}
249
250/// @brief Pack a loaded llvm scalar value into a new array of a specified
251/// size and return a pointer to the newly allocated array. Each element
252/// of the new array will have the value of the given scalar
253///
254/// @param value The uniform scalar llvm value to pack into the array
255/// @param builder The current llvm IRBuilder
256/// @param size The size of the newly allocated array
257///
259inline llvm::Value*
260arrayPack(llvm::Value* value,
261 llvm::IRBuilder<>& builder,
262 const size_t size = 3)
263{
264 OPENVDB_ASSERT(value && (value->getType()->isIntegerTy() ||
265 value->getType()->isFloatingPointTy()) &&
266 "value type is not a scalar type");
267
268 llvm::Type* type = value->getType();
269 llvm::Value* array =
270 insertStaticAlloca(builder,
271 llvm::ArrayType::get(type, size));
272
273 for (size_t i = 0; i < size; ++i) {
274 llvm::Value* element = builder.CreateConstGEP2_64(array->getType()->getScalarType()->getPointerElementType(), array, 0, i);
275 builder.CreateStore(value, element);
276 }
277
278 return array;
279}
280
281/// @brief Pack a vector of loaded llvm scalar values into a new array of
282/// equal size and return a pointer to the newly allocated array.
283///
284/// @param values A vector of loaded llvm scalar values to pack
285/// @param builder The current llvm IRBuilder
286///
288inline llvm::Value*
289arrayPack(const std::vector<llvm::Value*>& values,
290 llvm::IRBuilder<>& builder)
291{
292 llvm::Type* type = values.front()->getType();
293 llvm::Value* array = insertStaticAlloca(builder,
294 llvm::ArrayType::get(type, values.size()));
295
296 size_t idx = 0;
297 for (llvm::Value* const& value : values) {
298 llvm::Value* element = builder.CreateConstGEP2_64(array->getType()->getScalarType()->getPointerElementType(), array, 0, idx++);
299 builder.CreateStore(value, element);
300 }
301
302 return array;
303}
304
305/// @brief Pack a vector of loaded llvm scalar values into a new array of
306/// equal size and return a pointer to the newly allocated array.
307/// arrayPackCast first checks all the contained types in values
308/// and casts all types to the highest order type present. All llvm
309/// values in values are expected to be loaded scalar types
310///
311/// @param values A vector of loaded llvm scalar values to pack
312/// @param builder The current llvm IRBuilder
313///
315inline llvm::Value*
316arrayPackCast(std::vector<llvm::Value*>& values,
317 llvm::IRBuilder<>& builder)
318{
319 // get the highest order type present
320
321 llvm::Type* type = LLVMType<bool>::get(builder.getContext());
322 for (llvm::Value* const& value : values) {
323 type = typePrecedence(type, value->getType());
324 }
325
326 // convert all to this type
327
328 for (llvm::Value*& value : values) {
329 value = arithmeticConversion(value, type, builder);
330 }
331
332 return arrayPack(values, builder);
333}
334
336inline llvm::Value*
337scalarToMatrix(llvm::Value* scalar,
338 llvm::IRBuilder<>& builder,
339 const size_t dim = 3)
340{
341 OPENVDB_ASSERT(scalar && (scalar->getType()->isIntegerTy() ||
342 scalar->getType()->isFloatingPointTy()) &&
343 "value type is not a scalar type");
344
345 llvm::Type* type = scalar->getType();
346 llvm::Value* array =
347 insertStaticAlloca(builder,
348 llvm::ArrayType::get(type, dim*dim));
349
350 llvm::Value* zero = llvmConstant(0, type);
351 for (size_t i = 0; i < dim*dim; ++i) {
352 llvm::Value* m = ((i % (dim+1) == 0) ? scalar : zero);
353 llvm::Value* element = builder.CreateConstGEP2_64(array->getType()->getScalarType()->getPointerElementType(), array, 0, i);
354 builder.CreateStore(m, element);
355 }
356
357 return array;
358}
359
360} // namespace codegen
361} // namespace ax
362} // namespace OPENVDB_VERSION_NAME
363} // namespace openvdb
364
365#endif // LLVM_VERSION_MAJOR <= 15
366
367#endif // OPENVDB_AX_CODEGEN_LEGACY_IR_HAS_BEEN_INCLUDED
368
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
#define OPENVDB_DEPRECATED
Definition Platform.h:170
Consolidated llvm types for most supported types.
auto ir_gep(llvm::IRBuilder<> &B, llvm::Value *ptr, llvm::ArrayRef< llvm::Value * > IdxList, const char *Name="")
Definition LegacyIR.h:40
llvm::Value * arithmeticConversion(llvm::Value *value, llvm::Type *targetType, llvm::IRBuilder<> &builder)
Casts a scalar llvm Value to a target scalar llvm Type. Returns the cast scalar value of type targetT...
Definition Utils.h:484
llvm::Value * insertStaticAlloca(llvm::IRBuilder<> &B, llvm::Type *type, llvm::Value *size=nullptr)
Insert a stack allocation at the beginning of the current function of the provided type and size....
Definition Utils.h:117
llvm::Value * arrayIndexUnpack(llvm::Value *ptrToArray, const int16_t index, llvm::IRBuilder<> &builder)
Unpack a particular element of an array and return a pointer to that element The provided llvm Value ...
Definition LegacyIR.h:151
void array3Unpack(llvm::Value *ptrToArray, llvm::Value *&value1, llvm::Value *&value2, llvm::Value *&value3, llvm::IRBuilder<> &builder)
Unpack the first three elements of an array. The provided llvm Value is expected to be a pointer to a...
Definition LegacyIR.h:198
llvm::Value * array3Pack(llvm::Value *value1, llvm::Value *value2, llvm::Value *value3, llvm::IRBuilder<> &builder)
Pack three values into a new array and return a pointer to the newly allocated array....
Definition LegacyIR.h:224
auto ir_load(llvm::IRBuilder<> &B, llvm::Value *ptr, const char *Name="")
Definition LegacyIR.h:32
llvm::Value * scalarToMatrix(llvm::Value *scalar, llvm::IRBuilder<> &builder, const size_t dim=3)
Definition LegacyIR.h:337
std::function< llvm::Value *(llvm::IRBuilder<> &, llvm::Value *, llvm::Type *)> CastFunction
Definition Utils.h:37
void arrayUnpack(llvm::Value *ptrToArray, std::vector< llvm::Value * > &values, llvm::IRBuilder<> &builder, const bool loadElements=false)
Unpack an array type into llvm Values which represent all its elements The provided llvm Value is exp...
Definition LegacyIR.h:170
llvm::Value * arrayCast(llvm::Value *ptrToArray, llvm::Type *targetElementType, llvm::IRBuilder<> &builder)
Casts an array to another array of equal size but of a different element type. Both source and target...
Definition LegacyIR.h:103
llvm::Type * typePrecedence(llvm::Type *const typeA, llvm::Type *const typeB)
Returns the highest order type from two LLVM Scalar types.
Definition Utils.h:173
llvm::Constant * llvmConstant(const T t, llvm::Type *type)
Returns an llvm Constant holding a scalar value.
Definition Types.h:360
auto ir_constinboundsgep2_64(llvm::IRBuilder<> &B, llvm::Value *ptr, uint64_t Idx0, uint64_t Idx1, const char *Name="")
Definition LegacyIR.h:64
llvm::Value * arrayPackCast(std::vector< llvm::Value * > &values, llvm::IRBuilder<> &builder)
Pack a vector of loaded llvm scalar values into a new array of equal size and return a pointer to the...
Definition LegacyIR.h:316
auto ir_constgep2_64(llvm::IRBuilder<> &B, llvm::Value *ptr, uint64_t Idx0, uint64_t Idx1, const char *Name="")
Definition LegacyIR.h:52
llvm::Type * getBaseContainedType(llvm::Type *const type)
Return the base llvm value which is being pointed to through any number of layered pointers.
Definition LegacyIR.h:83
CastFunction llvmArithmeticConversion(const llvm::Type *const sourceType, const llvm::Type *const targetType, const std::string &twine="")
Returns a CastFunction which represents the corresponding instruction to convert a source llvm Type t...
Definition Utils.h:220
llvm::Value * arrayPack(llvm::Value *value, llvm::IRBuilder<> &builder, const size_t size=3)
Pack a loaded llvm scalar value into a new array of a specified size and return a pointer to the newl...
Definition LegacyIR.h:260
std::string Name
Definition Name.h:19
Definition Exceptions.h:13
Utility code generation methods for performing various llvm operations.
static llvm::Type * get(llvm::LLVMContext &C)
Return an LLVM type which represents T.
Definition Types.h:81
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218