[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