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++) {

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

Reply via email to