Commit: 14bb065f13ac11d8dfea283198bf896e14637f67
Author: Jacques Lucke
Date:   Wed Jul 31 14:54:28 2019 +0200
Branches: functions
https://developer.blender.org/rB14bb065f13ac11d8dfea283198bf896e14637f67

support for compiling particle functions down to machine code

===================================================================

M       source/blender/functions/backends/llvm/build_ir_body.cpp
M       source/blender/functions/backends/llvm/build_ir_body.hpp
M       source/blender/functions/functions/array_execution.cpp
M       source/blender/functions/functions/array_execution.hpp
M       source/blender/simulations/CMakeLists.txt
M       source/blender/simulations/bparticles/particle_function.cpp
M       source/blender/simulations/bparticles/particle_function.hpp
M       source/blender/simulations/bparticles/particle_function_builder.cpp

===================================================================

diff --git a/source/blender/functions/backends/llvm/build_ir_body.cpp 
b/source/blender/functions/backends/llvm/build_ir_body.cpp
index a1888201087..64a40c30962 100644
--- a/source/blender/functions/backends/llvm/build_ir_body.cpp
+++ b/source/blender/functions/backends/llvm/build_ir_body.cpp
@@ -1,5 +1,62 @@
-#include "build_ir_body.hpp"
+#include "FN_llvm.hpp"
 
 namespace FN {
 
+llvm::Function *LLVMBuildIRBody::build_function(llvm::Module *module,
+                                                StringRef name,
+                                                BuildIRSettings &settings,
+                                                FunctionIRCache 
&function_cache)
+{
+  Function *owner_fn = this->owner();
+  llvm::LLVMContext &context = module->getContext();
+
+  uint input_amount = owner_fn->input_amount();
+  uint output_amount = owner_fn->output_amount();
+
+  Vector<LLVMTypeInfo *> input_type_infos(input_amount);
+  Vector<LLVMTypeInfo *> output_type_infos(output_amount);
+  Vector<llvm::Type *> input_types(input_amount);
+  Vector<llvm::Type *> output_types(output_amount);
+
+  for (uint i = 0; i < input_amount; i++) {
+    LLVMTypeInfo &type_info = 
owner_fn->input_type(i)->extension<LLVMTypeInfo>();
+    input_type_infos[i] = &type_info;
+    input_types[i] = type_info.get_type(context);
+  }
+
+  for (uint i = 0; i < output_amount; i++) {
+    LLVMTypeInfo &type_info = 
owner_fn->output_type(i)->extension<LLVMTypeInfo>();
+    output_type_infos[i] = &type_info;
+    output_types[i] = type_info.get_type(context);
+  }
+
+  Vector<llvm::Type *> arg_types = input_types;
+  arg_types.append(llvm::Type::getInt8PtrTy(context));
+  llvm::Type *return_type = llvm::StructType::get(context, 
to_llvm(output_types));
+
+  llvm::FunctionType *ftype = llvm::FunctionType::get(return_type, 
to_llvm(arg_types), false);
+  llvm::Function *function = llvm::Function::Create(
+      ftype, llvm::GlobalValue::LinkageTypes::ExternalLinkage, to_llvm(name), 
module);
+  llvm::BasicBlock *bb = llvm::BasicBlock::Create(context, "entry", function);
+  CodeBuilder builder(bb);
+
+  Vector<llvm::Value *> input_values(input_amount);
+  for (uint i = 0; i < input_amount; i++) {
+    input_values[i] = builder.take_function_input(i, owner_fn->input_name(i));
+  }
+  llvm::Value *context_ptr = builder.take_function_input(input_amount, 
"context_ptr");
+  Vector<llvm::Value *> output_values(output_amount);
+
+  CodeInterface interface(input_values, output_values, context_ptr, 
function_cache);
+  this->build_ir(builder, interface, settings);
+
+  llvm::Value *output_value_struct = builder.getUndef(return_type);
+  for (uint i = 0; i < output_amount; i++) {
+    output_value_struct = builder.CreateInsertValue(output_value_struct, 
output_values[i], i);
+  }
+
+  builder.CreateRet(output_value_struct);
+  return function;
+}
+
 } /* namespace FN */
diff --git a/source/blender/functions/backends/llvm/build_ir_body.hpp 
b/source/blender/functions/backends/llvm/build_ir_body.hpp
index 03428e6900c..e42912f76a9 100644
--- a/source/blender/functions/backends/llvm/build_ir_body.hpp
+++ b/source/blender/functions/backends/llvm/build_ir_body.hpp
@@ -71,6 +71,11 @@ class LLVMBuildIRBody : public FunctionBody {
   virtual void build_ir(CodeBuilder &builder,
                         CodeInterface &interface,
                         const BuildIRSettings &settings) const = 0;
+
+  llvm::Function *build_function(llvm::Module *module,
+                                 StringRef name,
+                                 BuildIRSettings &settings,
+                                 FunctionIRCache &function_cache);
 };
 
 }  // namespace FN
diff --git a/source/blender/functions/functions/array_execution.cpp 
b/source/blender/functions/functions/array_execution.cpp
index 8495447a3a9..76c324087ab 100644
--- a/source/blender/functions/functions/array_execution.cpp
+++ b/source/blender/functions/functions/array_execution.cpp
@@ -1,3 +1,5 @@
+#include <llvm/IR/TypeBuilder.h>
+
 #include "FN_tuple_call.hpp"
 
 #include "array_execution.hpp"
@@ -5,10 +7,12 @@
 namespace FN {
 namespace Functions {
 
-TupleCallArrayExecution::TupleCallArrayExecution(SharedFunction function)
-    : m_function(std::move(function))
+ArrayExecution::~ArrayExecution()
+{
+}
+
+ArrayExecution::ArrayExecution(SharedFunction function) : 
m_function(std::move(function))
 {
-  BLI_assert(m_function->has_body<TupleCallBody>());
   for (SharedType &type : m_function->input_types()) {
     m_input_sizes.append(type->extension<CPPTypeInfo>().size());
   }
@@ -17,6 +21,15 @@ 
TupleCallArrayExecution::TupleCallArrayExecution(SharedFunction function)
   }
 }
 
+/* Tuple Call Array Execution
+ **********************************************/
+
+TupleCallArrayExecution::TupleCallArrayExecution(SharedFunction function)
+    : ArrayExecution(std::move(function))
+{
+  BLI_assert(m_function->has_body<TupleCallBody>());
+}
+
 void TupleCallArrayExecution::call(ArrayRef<uint> indices,
                                    ArrayRef<void *> input_buffers,
                                    ArrayRef<void *> output_buffers,
@@ -46,5 +59,114 @@ void TupleCallArrayExecution::call(ArrayRef<uint> indices,
   }
 }
 
+/* LLVM Array Execution
+ ********************************************/
+
+LLVMArrayExecution::LLVMArrayExecution(SharedFunction function)
+    : ArrayExecution(std::move(function))
+{
+  BLI_assert(m_function->has_body<LLVMBuildIRBody>());
+  this->compile();
+}
+
+void LLVMArrayExecution::compile()
+{
+  llvm::LLVMContext *context = aquire_llvm_context();
+  llvm::Module *module = new llvm::Module(m_function->name() + " (Array 
Execution)", *context);
+  llvm::Function *function = this->build_function_ir(module);
+  m_compiled_function = CompiledLLVM::FromIR(module, function);
+  release_llvm_context(context);
+}
+
+typedef void(CompiledFunctionSignature)(
+    uint size, uint *indices, void **input_buffers, void **output_buffers, 
void *context_ptr);
+
+llvm::Function *LLVMArrayExecution::build_function_ir(llvm::Module *module)
+{
+  Vector<LLVMTypeInfo *> input_type_infos = 
m_function->input_extensions<LLVMTypeInfo>();
+  Vector<LLVMTypeInfo *> output_type_infos = 
m_function->output_extensions<LLVMTypeInfo>();
+
+  llvm::LLVMContext &context = module->getContext();
+  LLVMBuildIRBody &body = m_function->body<LLVMBuildIRBody>();
+  llvm::FunctionType *ftype = llvm::TypeBuilder<CompiledFunctionSignature, 
false>::get(context);
+
+  llvm::Function *function = llvm::Function::Create(
+      ftype, llvm::GlobalValue::LinkageTypes::ExternalLinkage, 
module->getName(), module);
+
+  llvm::BasicBlock *bb = llvm::BasicBlock::Create(context, "entry", function);
+  CodeBuilder builder(bb);
+
+  llvm::Value *size = builder.take_function_input(0, "indices_amount");
+  llvm::Value *indices = builder.take_function_input(1, "indices");
+  llvm::Value *input_buffers_arg = builder.take_function_input(2, 
"input_buffers");
+  llvm::Value *output_buffers_arg = builder.take_function_input(3, 
"output_buffers");
+  llvm::Value *context_ptr = builder.take_function_input(4, "context_ptr");
+
+  Vector<llvm::Value *> input_buffers;
+  for (uint i = 0; i < m_function->input_amount(); i++) {
+    uint element_size = m_input_sizes[i];
+    llvm::Value *input_buffer = builder.CreateLoadAtIndex(input_buffers_arg, 
i);
+    llvm::Value *typed_input_buffer = 
builder.CastToPointerWithStride(input_buffer, element_size);
+    typed_input_buffer->setName(to_llvm(m_function->input_name(i) + " Array"));
+    input_buffers.append(typed_input_buffer);
+  }
+  Vector<llvm::Value *> output_buffers;
+  for (uint i = 0; i < m_function->output_amount(); i++) {
+    uint element_size = m_output_sizes[i];
+    llvm::Value *output_buffer = builder.CreateLoadAtIndex(output_buffers_arg, 
i);
+    llvm::Value *typed_output_buffer = 
builder.CastToPointerWithStride(output_buffer,
+                                                                       
element_size);
+    output_buffers.append(typed_output_buffer);
+  }
+
+  IRConstruct_IterationsLoop loop = builder.CreateNIterationsLoop(size, 
"Loop");
+  CodeBuilder body_builder = loop.body_builder();
+  llvm::Value *iteration = loop.current_iteration();
+  llvm::Value *index_to_process = body_builder.CreateLoadAtIndex(indices, 
iteration);
+  Vector<llvm::Value *> input_values;
+  for (uint i = 0; i < m_function->input_amount(); i++) {
+    llvm::Value *addr = body_builder.CreateGEP(input_buffers[i], 
index_to_process);
+    llvm::Value *value = 
input_type_infos[i]->build_load_ir__copy(body_builder, addr);
+    value->setName(to_llvm(m_function->input_name(i)));
+    input_values.append(value);
+  }
+  input_values.append(context_ptr);
+
+  FunctionIRCache function_cache;
+  BuildIRSettings settings;
+  llvm::Function *actual_function = body.build_function(
+      module, m_function->name(), settings, function_cache);
+
+  llvm::Value *result = body_builder.CreateCall(actual_function, input_values);
+
+  for (uint i = 0; i < m_function->output_amount(); i++) {
+    llvm::Value *addr = body_builder.CreateGEP(output_buffers[i], 
index_to_process);
+    llvm::Value *value = body_builder.CreateExtractValue(result, i);
+    value->setName(to_llvm(m_function->output_name(i)));
+    output_type_infos[i]->build_store_ir__relocate(body_builder, value, addr);
+  }
+
+  /* TODO(jacques): check if input values have to be freed. */
+
+  loop.finalize(builder);
+  builder.CreateRetVoid();
+
+  return function;
+}
+
+void LLVMArrayExecution::call(ArrayRef<uint> indices,
+                              ArrayRef<void *> input_buffers,
+                              ArrayRef<void *> output_buffers,
+                              ExecutionContext &execution_context)
+{
+  CompiledFunctionSignature *function = (CompiledFunctionSignature *)
+                                            
m_compiled_function->function_ptr();
+  function(indices.size(),
+           indices.begin(),
+           input_buffers.begin(),
+           output_buffers.begin(),
+           (void *)&execution_context);
+}
+
 }  // namespace Functions
 }  // namespace FN
diff --git a/source/blender/functions/functions/array_execution.hpp 
b/source/blender/functions/functions/array_execution.hpp
index 2d8e310cb

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to