OpenVDB 12.1.0

Loading...
Searching...
No Matches
ConstantFolding.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/ConstantFolding.h
5///
6/// @authors Nick Avramoussis
7///
8/// @brief Constant folding for C++ bindings.
9///
10
11#ifndef OPENVDB_AX_CODEGEN_CONSTANT_FOLDING_HAS_BEEN_INCLUDED
12#define OPENVDB_AX_CODEGEN_CONSTANT_FOLDING_HAS_BEEN_INCLUDED
13
14#include "Types.h"
15
16#include <openvdb/version.h>
17#include <openvdb/util/Assert.h>
18
19#include <llvm/IR/Constants.h>
20
21#include <type_traits>
22#include <vector>
23
24 namespace openvdb {
25 OPENVDB_USE_VERSION_NAMESPACE
26 namespace OPENVDB_VERSION_NAME {
27
28 namespace ax {
29 namespace codegen {
30
31/// @brief Constant folding support structure
32///
33 template <typename SignatureT,
34 size_t I = FunctionTraits<SignatureT>::N_ARGS>
35 struct ConstantFolder
36{
37 using ArgT = typename FunctionTraits<SignatureT>::template Arg<I-1>;
38 using ArgumentValueType = typename ArgT::Type;
39
40 // @brief Attempts evaluate a given function with a provided set of constant llvm
41 // values. If successful, the function is invoked and the result is stored
42 // and returned in an llvm::Value.
43 // @details Currently only scalar constant folding is supported due to the way
44 // vectors and matrices are alloced. Functions which return void are also
45 // not supported for constant folding.
46 // @param args The vector of llvm constants that comprise the function arguments.
47 // Note that the size of this vector is expected to match the size of
48 // the required function arguments and the templated parameter I
49 // @param function The function to invoke if all arguments have a valid mapping.
50 // @param C The llvm Context
51 // @param ts The list of evaluated C types from the provided llvm constants. This
52 // is expected to be empty (not provided) on the first call to fold and
53 // is used on subsequent recursive calls.
54 template <typename ...Tys>
55 static llvm::Constant*
56 fold(const llvm::ArrayRef<llvm::Constant*>& args,
57 const SignatureT& function,
58 llvm::LLVMContext& C,
59 Tys&&... ts)
60 {
61 OPENVDB_ASSERT(I-1 < args.size());
62 llvm::Constant* constant = args[I-1];
63 const llvm::Type* type = constant->getType();
64 if (type->isIntegerTy()) {
65 OPENVDB_ASSERT(llvm::isa<llvm::ConstantInt>(constant));
66 llvm::ConstantInt* cint =
67 llvm::cast<llvm::ConstantInt>(constant);
68 const uint64_t val = cint->getLimitedValue();
69 return call<uint64_t, ArgumentValueType>(args, function, C, val, ts...);
70 }
71 else if (type->isFloatTy() || type->isDoubleTy()) {
72 OPENVDB_ASSERT(llvm::isa<llvm::ConstantFP>(constant));
73 llvm::ConstantFP* cfp =
74 llvm::cast<llvm::ConstantFP>(constant);
75 const llvm::APFloat& apf = cfp->getValueAPF();
76 if (type->isFloatTy()) {
77 const float val = apf.convertToFloat();
78 return call<float, ArgumentValueType>(args, function, C, val, ts...);
79 }
80 if (type->isDoubleTy()) {
81 const double val = apf.convertToDouble();
82 return call<double, ArgumentValueType>(args, function, C, val, ts...);
83 }
84 }
85 else if (type->isArrayTy()) {
86 // @todo currently all arrays are alloced anyway which
87 // needs to be handled or changed
88 return nullptr;
89 }
90 // fallback
91 return nullptr;
92 }
93 private:
94 // @brief Specialization for supported implicit casting matching AX's supported
95 // scalar casting. Continues to traverse the constant argument list.
96 template <typename In, typename Out, typename ...Tys>
97 static typename std::enable_if<std::is_convertible<In, Out>::value, llvm::Constant*>::type
98 call(const llvm::ArrayRef<llvm::Constant*>& args,
99 const SignatureT& function,
100 llvm::LLVMContext& C,
101 const In& arg,
102 Tys&&... ts)
103 {
104 using Next = ConstantFolder<SignatureT, I-1>;
105 return Next::fold(args, function, C, Out(arg), ts...);
106 }
107
108 // @brief Specialization for unsupported implicit casting. Bails out with a
109 // nullptr return.
110 template <typename In, typename Out, typename ...Tys>
111 static typename std::enable_if<!std::is_convertible<In, Out>::value, llvm::Constant*>::type
112 call(const llvm::ArrayRef<llvm::Constant*>&,
113 const SignatureT&,
114 llvm::LLVMContext&,
115 const In&, Tys&&...)
116 {
117 return nullptr;
118 }
119};
120
121 template <typename SignatureT>
122 struct ConstantFolder<SignatureT, 0>
123{
124 // @brief The final call to fold when all arguments have been evaluated (or no
125 // arguments exist).
126 template <typename ...Tys>
127 static llvm::Constant*
128 fold(const llvm::ArrayRef<llvm::Constant*>& args,
129 const SignatureT& function,
130 llvm::LLVMContext& C,
131 Tys&&... ts)
132 {
133 using ReturnT = typename FunctionTraits<SignatureT>::ReturnType;
134 return call<ReturnT>(args, function, C, ts...);
135 }
136
137 private:
138
139 // @brief Specialization for the invoking of the provided function if the return
140 // type is not void or a pointer
141 template <typename ReturnT, typename ...Tys>
142 static typename std::enable_if<!std::is_pointer<ReturnT>::value &&
143 !std::is_same<ReturnT, void>::value, llvm::Constant*>::type
144 call(const llvm::ArrayRef<llvm::Constant*>&,
145 const SignatureT& function,
146 llvm::LLVMContext& C,
147 Tys&&... ts)
148 {
149 const ReturnT result = function(ts...);
150 return LLVMType<ReturnT>::get(C, result);
151 }
152
153 // @brief Specialization if the return type is void or a pointer. No folding is
154 // supported.
155 template <typename ReturnT, typename ...Tys>
156 static typename std::enable_if<std::is_pointer<ReturnT>::value ||
157 std::is_same<ReturnT, void>::value, llvm::Constant*>::type
158 call(const llvm::ArrayRef<llvm::Constant*>&,
159 const SignatureT&,
160 llvm::LLVMContext&,
161 Tys&&...)
162 {
163 return nullptr;
164 }
165};
166
167} // namespace codegen
168} // namespace ax
169} // namespace OPENVDB_VERSION_NAME
170} // namespace openvdb
171
172#endif // OPENVDB_AX_CODEGEN_CONSTANT_FOLDING_HAS_BEEN_INCLUDED
173
Assert.h
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Types.h
Consolidated llvm types for most supported types.
openvdb
Definition Exceptions.h:13
openvdb::v12_1::ax::codegen::ConstantFolder< SignatureT, 0 >::fold
static llvm::Constant * fold(const llvm::ArrayRef< llvm::Constant * > &args, const SignatureT &function, llvm::LLVMContext &C, Tys &&... ts)
Definition ConstantFolding.h:128
openvdb::v12_1::ax::codegen::ConstantFolder
Constant folding support structure.
Definition ConstantFolding.h:36
openvdb::v12_1::ax::codegen::ConstantFolder::fold
static llvm::Constant * fold(const llvm::ArrayRef< llvm::Constant * > &args, const SignatureT &function, llvm::LLVMContext &C, Tys &&... ts)
Definition ConstantFolding.h:56
openvdb::v12_1::ax::codegen::ConstantFolder::ArgT
typename FunctionTraits< SignatureT >::template Arg< I-1 > ArgT
Definition ConstantFolding.h:37
openvdb::v12_1::ax::codegen::ConstantFolder::ArgumentValueType
typename ArgT::Type ArgumentValueType
Definition ConstantFolding.h:38
openvdb::v12_1::ax::codegen::FunctionTraits
Templated function traits which provides compile-time index access to the types of the function signa...
Definition Types.h:311
openvdb::v12_1::ax::codegen::LLVMType::get
static llvm::Type * get(llvm::LLVMContext &C)
Return an LLVM type which represents T.
Definition Types.h:81
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218