OpenVDB  9.0.1
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 
23 namespace openvdb {
25 namespace OPENVDB_VERSION_NAME {
26 
27 namespace ax {
28 namespace codegen {
29 
30 /// @brief Constant folding support structure
31 ///
32 template <typename SignatureT,
33  size_t I = FunctionTraits<SignatureT>::N_ARGS>
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  }
92 private:
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 
120 template <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 
136 private:
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>
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>
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 
typename ArgT::Type ArgumentValueType
Definition: ConstantFolding.h:37
static llvm::Value * fold(const std::vector< llvm::Constant * > &args, const SignatureT &function, llvm::LLVMContext &C, Tys &&...ts)
Definition: ConstantFolding.h:127
Consolidated llvm types for most supported types.
Constant folding support structure.
Definition: ConstantFolding.h:34
Templated function traits which provides compile-time index access to the types of the function signa...
Definition: Types.h:259
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
LLVM type mapping from pod types.
Definition: Types.h:54
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
static llvm::Value * fold(const std::vector< llvm::Constant * > &args, const SignatureT &function, llvm::LLVMContext &C, Tys &&...ts)
Definition: ConstantFolding.h:55
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
typename FunctionTraits< SignatureT >::template Arg< I-1 > ArgT
Definition: ConstantFolding.h:36