[Bf-blender-cvs] [2a8c7b82308] functions: use cache to avoid building the same function ir twice
Jacques Lucke
noreply at git.blender.org
Wed Apr 3 11:56:25 CEST 2019
Commit: 2a8c7b8230839ec2376d1def658adfc3289d1d27
Author: Jacques Lucke
Date: Wed Apr 3 11:55:11 2019 +0200
Branches: functions
https://developer.blender.org/rB2a8c7b8230839ec2376d1def658adfc3289d1d27
use cache to avoid building the same function ir twice
===================================================================
M source/blender/functions/backends/llvm/build_ir_body.hpp
M source/blender/functions/backends/llvm/builder.hpp
M source/blender/functions/backends/llvm/fgraph_ir_generation.cpp
M source/blender/functions/backends/llvm/ir_for_tuple_call.cpp
M source/blender/functions/backends/llvm/ir_to_tuple_call.cpp
===================================================================
diff --git a/source/blender/functions/backends/llvm/build_ir_body.hpp b/source/blender/functions/backends/llvm/build_ir_body.hpp
index 53f00443cfe..d4017e79a70 100644
--- a/source/blender/functions/backends/llvm/build_ir_body.hpp
+++ b/source/blender/functions/backends/llvm/build_ir_body.hpp
@@ -15,20 +15,25 @@ namespace FN {
}
};
+ using FunctionIRCache = SmallMap<void *, llvm::Function *>;
+
class CodeInterface {
private:
LLVMValues &m_inputs;
LLVMValues &m_outputs;
llvm::Value *m_context_ptr;
+ FunctionIRCache &m_function_ir_cache;
public:
CodeInterface(
LLVMValues &inputs,
LLVMValues &outputs,
- llvm::Value *context_ptr = nullptr)
+ llvm::Value *context_ptr,
+ FunctionIRCache &function_ir_cache)
: m_inputs(inputs),
m_outputs(outputs),
- m_context_ptr(context_ptr) {}
+ m_context_ptr(context_ptr),
+ m_function_ir_cache(function_ir_cache) {}
llvm::Value *get_input(uint index)
{
@@ -49,6 +54,11 @@ namespace FN {
{
return m_context_ptr;
}
+
+ FunctionIRCache &function_ir_cache()
+ {
+ return m_function_ir_cache;
+ }
};
class LLVMBuildIRBody : public FunctionBody {
diff --git a/source/blender/functions/backends/llvm/builder.hpp b/source/blender/functions/backends/llvm/builder.hpp
index a377a61a0b9..ecd49d6158b 100644
--- a/source/blender/functions/backends/llvm/builder.hpp
+++ b/source/blender/functions/backends/llvm/builder.hpp
@@ -65,6 +65,17 @@ namespace FN {
return llvm::ArrayType::get(m_builder.getInt8Ty(), size);
}
+ llvm::Type *getStructType(LLVMTypes &types)
+ {
+ return llvm::StructType::get(this->getContext(), to_array_ref(types));
+ }
+
+ llvm::FunctionType *getFunctionType(llvm::Type *ret_type, LLVMTypes &arg_types)
+ {
+ return llvm::FunctionType::get(
+ ret_type, to_array_ref(arg_types), false);
+ }
+
/* Value Builders
**************************************/
diff --git a/source/blender/functions/backends/llvm/fgraph_ir_generation.cpp b/source/blender/functions/backends/llvm/fgraph_ir_generation.cpp
index 2f0a539a042..d847c484a79 100644
--- a/source/blender/functions/backends/llvm/fgraph_ir_generation.cpp
+++ b/source/blender/functions/backends/llvm/fgraph_ir_generation.cpp
@@ -46,7 +46,7 @@ namespace FN {
for (uint i = 0; i < m_outputs.size(); i++) {
Socket socket = m_outputs[i];
this->generate_for_socket(
- builder, interface.context_ptr(), settings, socket, values, forwarded_sockets);
+ builder, interface, settings, socket, values, forwarded_sockets);
interface.set_output(i, values.lookup(socket));
}
@@ -55,7 +55,7 @@ namespace FN {
private:
void generate_for_socket(
CodeBuilder &builder,
- llvm::Value *context_ptr,
+ CodeInterface &interface,
const BuildIRSettings &settings,
Socket socket,
SocketValueMap &values,
@@ -67,7 +67,7 @@ namespace FN {
else if (socket.is_input()) {
Socket origin = socket.origin();
this->generate_for_socket(
- builder, context_ptr, settings, origin, values, forwarded_sockets);
+ builder, interface, settings, origin, values, forwarded_sockets);
this->forward_output_if_necessary(builder, origin, values, forwarded_sockets);
}
else if (socket.is_output()) {
@@ -75,12 +75,12 @@ namespace FN {
LLVMValues input_values;
for (Socket input : node->inputs()) {
this->generate_for_socket(
- builder, context_ptr, settings, input, values, forwarded_sockets);
+ builder, interface, settings, input, values, forwarded_sockets);
input_values.append(values.lookup(input));
}
LLVMValues output_values = this->build_node_ir(
- builder, context_ptr, settings, node, input_values);
+ builder, interface, settings, node, input_values);
for (uint i = 0; i < output_values.size(); i++) {
Socket output = node->output(i);
@@ -143,25 +143,27 @@ namespace FN {
LLVMValues build_node_ir(
CodeBuilder &builder,
- llvm::Value *context_ptr,
+ CodeInterface &interface,
const BuildIRSettings &settings,
Node *node,
LLVMValues &input_values) const
{
if (settings.maintain_stack()) {
- this->push_stack_frames_for_node(builder, context_ptr, node);
+ this->push_stack_frames_for_node(builder, interface.context_ptr(), node);
}
SharedFunction &fn = node->function();
LLVMValues output_values(node->output_amount());
- CodeInterface sub_interface(input_values, output_values, context_ptr);
+ CodeInterface sub_interface(
+ input_values, output_values,
+ interface.context_ptr(), interface.function_ir_cache());
BLI_assert(fn->has_body<LLVMBuildIRBody>());
auto *body = fn->body<LLVMBuildIRBody>();
body->build_ir(builder, sub_interface, settings);
if (settings.maintain_stack()) {
- this->pop_stack_frames_for_node(builder, context_ptr);
+ this->pop_stack_frames_for_node(builder, interface.context_ptr());
}
return output_values;
diff --git a/source/blender/functions/backends/llvm/ir_for_tuple_call.cpp b/source/blender/functions/backends/llvm/ir_for_tuple_call.cpp
index 950f7f16c48..a9b71afbcc5 100644
--- a/source/blender/functions/backends/llvm/ir_for_tuple_call.cpp
+++ b/source/blender/functions/backends/llvm/ir_for_tuple_call.cpp
@@ -59,41 +59,21 @@ namespace FN {
CodeInterface &interface,
const BuildIRSettings &settings) const override
{
- Function *fn = m_tuple_call->owner();
+
llvm::LLVMContext &context = builder.getContext();
+ Function *fn = m_tuple_call->owner();
/* Find relevant type information. */
auto input_type_infos = fn->signature().input_extensions<LLVMTypeInfo>();
auto output_type_infos = fn->signature().output_extensions<LLVMTypeInfo>();
- LLVMTypes input_types = builder.types_of_values(interface.inputs());
- if (settings.maintain_stack()) {
- input_types.append(builder.getVoidPtrTy());
- }
-
- LLVMTypes output_types;
- for (auto type_info : output_type_infos) {
- output_types.append(type_info->get_type(context));
- }
-
/* Build wrapper function. */
- llvm::Type *wrapper_output_type = llvm::StructType::get(context, to_array_ref(output_types));
-
- llvm::FunctionType *wrapper_function_type = llvm::FunctionType::get(
- wrapper_output_type, to_array_ref(input_types), false);
-
- llvm::Function *wrapper_function = llvm::Function::Create(
- wrapper_function_type,
- llvm::GlobalValue::LinkageTypes::InternalLinkage,
- fn->name() + " Wrapper",
- builder.getModule());
-
- this->build_wrapper_function(
+ llvm::Function *wrapper_function = this->get_wrapper_function(
+ builder,
+ interface,
settings,
- wrapper_function,
input_type_infos,
- output_type_infos,
- wrapper_output_type);
+ output_type_infos);
/* Call wrapper function. */
LLVMValues call_inputs = interface.inputs();
@@ -110,6 +90,54 @@ namespace FN {
}
private:
+ llvm::Function *get_wrapper_function(
+ CodeBuilder &builder,
+ CodeInterface &interface,
+ const BuildIRSettings &settings,
+ SmallVector<LLVMTypeInfo *> input_type_infos,
+ SmallVector<LLVMTypeInfo *> output_type_infos) const
+ {
+ Function *fn = m_tuple_call->owner();
+
+ LLVMTypes input_types = builder.types_of_values(interface.inputs());
+ if (settings.maintain_stack()) {
+ input_types.append(builder.getVoidPtrTy());
+ }
+
+ LLVMTypes output_types;
+ for (auto type_info : output_type_infos) {
+ output_types.append(type_info->get_type(builder.getContext()));
+ }
+
+ llvm::Function *wrapper_function;
+ FunctionIRCache &function_cache = interface.function_ir_cache();
+ if (function_cache.contains((void *)this)) {
+ wrapper_function = function_cache.lookup((void *)this);
+ }
+ else {
+ llvm::Type *wrapper_output_type = builder.getStructType(output_types);
+
+ llvm::FunctionType *wrapper_function_type = builder.getFunctionType(
+ wrapper_output_type, input_types);
+
+ wrapper_function = llvm::Function::Create(
+ wrapper_function_type,
+ llvm::GlobalValue::LinkageTypes::InternalLinkage,
+ fn->name() + " Wrapper",
+ builder.getModule());
+
+ this->build_wrapper_function(
+ settings,
+ wrapper_function,
+ input_type_infos,
+ output_type_infos,
+ wrapper_output_type);
+
+ function_cache.add((void *)this, wrapper_function);
+ }
+ return wrapper_function;
+ }
+
void build_wrapper_function(
const BuildIRSettings &settings,
llvm::Function *function,
diff --git a/source/blender/functions/backends/llvm/ir_to_tuple_call.cpp b/source/blender/functions/backends/llvm/ir_to_tuple_call.cpp
index 4fa8d529cb6..74e9364c667 100644
--- a/source/blender/functions/backends/llvm/ir_to_tuple_call.cpp
+++ b/source/blender/functions/backends/llvm/ir_to_tuple_call.cpp
@@ -82,7 +82,8 @@ namespace FN {
LLVMValues output_values(fn->signature().outputs().size());
BuildIRSettings settings;
- CodeInterface interface(input_values, output_values, context_ptr);
+ FunctionIRCache function_cache;
+ CodeInterface interface(input_values, output_values, context_ptr, function_cache);
body->build_ir(builder, interface, settings);
for (uint i = 0; i < output_values.size(); i++) {
More information about the Bf-blender-cvs
mailing list