OpenVDB: openvdb_ax/codegen/ConstantFolding.h Source File

OpenVDB 9.1.0

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