[Bf-blender-cvs] [239570a2780] nodes_playground: do value copying and cleanup

Jacques Lucke noreply at git.blender.org
Sun Jan 6 17:25:51 CET 2019


Commit: 239570a278030845278ceab39cf7010e7dc9350e
Author: Jacques Lucke
Date:   Sun Jan 6 16:29:57 2019 +0100
Branches: nodes_playground
https://developer.blender.org/rB239570a278030845278ceab39cf7010e7dc9350e

do value copying and cleanup

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

M	source/blender/modifiers/intern/ArraySet.hpp
M	source/blender/modifiers/intern/HashMap.hpp
M	source/blender/modifiers/intern/node_compiler.cpp
M	source/blender/modifiers/intern/node_compiler.hpp
M	source/blender/modifiers/intern/node_compiler_testing.cpp

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

diff --git a/source/blender/modifiers/intern/ArraySet.hpp b/source/blender/modifiers/intern/ArraySet.hpp
index 2db9d00739b..9d462176215 100644
--- a/source/blender/modifiers/intern/ArraySet.hpp
+++ b/source/blender/modifiers/intern/ArraySet.hpp
@@ -43,12 +43,28 @@ public:
 		return false;
 	}
 
+	T get_any() const
+	{
+		return this[0];
+	}
+
 	T operator[](const int index) const
 	{
 		assert(index >= 0 && index < this->size());
 		return this->entries[index];
 	}
 
+	ArraySet<T> operator-(ArraySet<T> &other) const
+	{
+		ArraySet<T> new_set;
+		for (T value : this) {
+			if (!other.contains(value)) {
+				new_set.add(value);
+			}
+		}
+		return new_set;
+	}
+
 	uint size() const
 	{
 		return this->entries.size();
diff --git a/source/blender/modifiers/intern/HashMap.hpp b/source/blender/modifiers/intern/HashMap.hpp
index 1e0fb215f9a..f7c4fb374bc 100644
--- a/source/blender/modifiers/intern/HashMap.hpp
+++ b/source/blender/modifiers/intern/HashMap.hpp
@@ -32,6 +32,14 @@ public:
 		return false;
 	}
 
+	bool key_has_value(TKey key, TValue value)
+	{
+		if (this->contains(key)) {
+			return this->lookup(key) == value;
+		}
+		return false;
+	}
+
 	TValue lookup(TKey key)
 	{
 		for (Entry entry : this->entries) {
diff --git a/source/blender/modifiers/intern/node_compiler.cpp b/source/blender/modifiers/intern/node_compiler.cpp
index 6cc22a4a458..7d430d310ec 100644
--- a/source/blender/modifiers/intern/node_compiler.cpp
+++ b/source/blender/modifiers/intern/node_compiler.cpp
@@ -1,6 +1,7 @@
 #include "node_compiler.hpp"
 
 #include <sstream>
+#include <iostream>
 
 namespace LLVMNodeCompiler {
 
@@ -13,6 +14,20 @@ llvm::Type *Type::getLLVMType(llvm::LLVMContext &context)
 	return this->typePerContext.lookup(&context);
 }
 
+llvm::Value *Type::buildCopyIR(
+	llvm::IRBuilder<> &UNUSED(builder),
+	llvm::Value *value)
+{
+	return value;
+}
+
+void Type::buildFreeIR(
+	llvm::IRBuilder<> &UNUSED(builder),
+	llvm::Value *UNUSED(value))
+{
+	return;
+}
+
 AnySocket LinkSet::getOriginSocket(AnySocket socket) const
 {
 	assert(socket.is_input());
@@ -31,6 +46,25 @@ AnySocket DataFlowGraph::getOriginSocket(AnySocket socket) const
 	return this->links.getOriginSocket(socket);
 }
 
+SocketSet LinkSet::getTargetSockets(AnySocket socket) const
+{
+	assert(socket.is_output());
+
+	SocketSet targets;
+	for (Link link : this->links) {
+		if (link.from == socket) {
+			targets.add(link.to);
+		}
+	}
+
+	return targets;
+}
+
+SocketSet DataFlowGraph::getTargetSockets(AnySocket socket) const
+{
+	return this->links.getTargetSockets(socket);
+}
+
 const SocketInfo *AnySocket::info() const
 {
 	if (this->is_input()) {
@@ -63,7 +97,7 @@ llvm::CallInst *callPointer(
 	void *pointer, llvm::FunctionType *type, llvm::ArrayRef<llvm::Value *> arguments)
 {
 	auto address_int = builder.getInt64((size_t)pointer);
-	auto address = builder.CreateIntToPtr(address_int, llvm::PointerType::get(type, 0));
+	auto address = builder.CreateIntToPtr(address_int, type->getPointerTo());
 	return builder.CreateCall(address, arguments);
 }
 
@@ -105,6 +139,7 @@ llvm::Module *DataFlowGraph::generateModule(
 	assert(outputs.size() > 0);
 	llvm::Module *module = new llvm::Module(module_name, context);
 	this->generateFunction(module, function_name, inputs, outputs);
+	module->print(llvm::outs(), nullptr);
 	return module;
 }
 
@@ -143,14 +178,13 @@ llvm::Function *DataFlowGraph::generateFunction(
 	}
 
 	std::vector<llvm::Value *> output_values;
-	llvm::IRBuilder<> *next_builder;
-	this->generateCode(&builder, inputs, outputs, input_values, &next_builder, output_values);
+	this->generateCode(builder, inputs, outputs, input_values, output_values);
 
 	llvm::Value *output = llvm::UndefValue::get(return_type);
 	for (uint i = 0; i < outputs.size(); i++) {
-		output = next_builder->CreateInsertValue(output, output_values[i], i);
+		output = builder.CreateInsertValue(output, output_values[i], i);
 	}
-	next_builder->CreateRet(output);
+	builder.CreateRet(output);
 
 	llvm::verifyFunction(*function, &llvm::outs());
 	llvm::verifyModule(*module, &llvm::outs());
@@ -159,70 +193,98 @@ llvm::Function *DataFlowGraph::generateFunction(
 }
 
 void DataFlowGraph::generateCode(
-	llvm::IRBuilder<> *builder,
+	llvm::IRBuilder<> &builder,
 	SocketArraySet &inputs, SocketArraySet &outputs, std::vector<llvm::Value *> &input_values,
-	llvm::IRBuilder<> **r_builder, std::vector<llvm::Value *> &r_output_values)
+	std::vector<llvm::Value *> &r_output_values)
 {
+	assert(outputs.size() > 0);
 	assert(inputs.size() == input_values.size());
 
+	SocketSet required_sockets = this->findRequiredSockets(inputs, outputs);
+
 	SocketValueMap values;
 	for (uint i = 0; i < inputs.size(); i++) {
 		values.add(inputs[i], input_values[i]);
 	}
 
+	SocketSet forwarded_sockets;
 	for (AnySocket socket : outputs) {
-		llvm::IRBuilder<> *next_builder;
-
-		llvm::Value *value = this->generateCodeForSocket(socket, builder, values, &next_builder);
-		r_output_values.push_back(value);
-
-		builder = next_builder;
+		this->generateCodeForSocket(builder, socket, values, required_sockets, forwarded_sockets);
+		r_output_values.push_back(values.lookup(socket));
 	}
-
-	*r_builder = builder;
 }
 
-llvm::Value *DataFlowGraph::generateCodeForSocket(
+void DataFlowGraph::generateCodeForSocket(
+	llvm::IRBuilder<> &builder,
 	AnySocket socket,
-	llvm::IRBuilder<> *builder,
 	SocketValueMap &values,
-	llvm::IRBuilder<> **r_builder)
+	SocketSet &required_sockets,
+	SocketSet &forwarded_sockets)
 {
 	if (values.contains(socket)) {
-		*r_builder = builder;
-		return values.lookup(socket);
+		/* do nothing */
 	}
-
-	if (socket.is_input()) {
+	else if (socket.is_input()) {
 		AnySocket origin = this->getOriginSocket(socket);
-		llvm::Value *value = this->generateCodeForSocket(origin, builder, values, r_builder);
-		values.add(socket, value);
-		return value;
+		this->generateCodeForSocket(builder, origin, values, required_sockets, forwarded_sockets);
+		if (!forwarded_sockets.contains(origin)) {
+			this->forwardOutputToRequiredInputs(builder, origin, values, required_sockets);
+			forwarded_sockets.add(origin);
+		}
 	}
-
-	if (socket.is_output()) {
+	else if (socket.is_output()) {
 		Node *node = socket.node();
 		std::vector<llvm::Value *> input_values;
 		for (uint i = 0; i < node->inputs().size(); i++) {
-			llvm::IRBuilder<> *next_builder;
-
-			llvm::Value *value = this->generateCodeForSocket(node->Input(i), builder, values, &next_builder);
-			input_values.push_back(value);
-
-			builder = next_builder;
+			AnySocket input = node->Input(i);
+			this->generateCodeForSocket(builder, input, values, required_sockets, forwarded_sockets);
+			input_values.push_back(values.lookup(input));
 		}
 
 		std::vector<llvm::Value *> output_values;
-		node->buildLLVMIR(input_values, builder, output_values, r_builder);
+		node->buildLLVMIR(builder, input_values, output_values);
 
 		for (uint i = 0; i < node->outputs().size(); i++) {
 			values.add(node->Output(i), output_values[i]);
 		}
+	}
+	else {
+		assert(!"should never happen");
+	}
 
-		return values.lookup(socket);
+}
+
+void DataFlowGraph::forwardOutputToRequiredInputs(
+	llvm::IRBuilder<> &builder,
+	AnySocket output,
+	SocketValueMap &values,
+	SocketSet &required_sockets)
+{
+	llvm::Value *value_to_forward = values.lookup(output);
+	Type *type = output.type();
+
+	SocketArraySet targets;
+	for (AnySocket target : this->getTargetSockets(output)) {
+		if (required_sockets.contains(target) && !values.contains(target)) {
+			assert(type == target.type());
+			targets.add(target);
+		}
 	}
 
-	assert(!"should never happen");
+	if (targets.size() == 0) {
+		type->buildFreeIR(builder, value_to_forward);
+	}
+	else if (targets.size() == 1) {
+		values.add(targets[0], value_to_forward);
+	}
+	else {
+		values.add(targets[0], value_to_forward);
+		for (uint i = 1; i < targets.size(); i++) {
+			AnySocket target = targets[i];
+			llvm::Value *copied_value = type->buildCopyIR(builder, value_to_forward);
+			values.add(target, copied_value);
+		}
+	}
 }
 
 SocketSet DataFlowGraph::findRequiredSockets(SocketSet &inputs, SocketSet &outputs)
diff --git a/source/blender/modifiers/intern/node_compiler.hpp b/source/blender/modifiers/intern/node_compiler.hpp
index 7ffc501fdc3..e495a0dc06a 100644
--- a/source/blender/modifiers/intern/node_compiler.hpp
+++ b/source/blender/modifiers/intern/node_compiler.hpp
@@ -8,6 +8,8 @@
 #include <functional>
 #include <unordered_set>
 
+#include "BLI_utildefines.h"
+
 #include "ArraySet.hpp"
 #include "HashMap.hpp"
 
@@ -31,8 +33,13 @@ private:
 public:
 	llvm::Type *getLLVMType(llvm::LLVMContext &context);
 
-	// virtual llvm::Value *buildCopyIR(llvm::Value *value);
-	// virtual void buildFreeIR(llvm::Value *value);
+	virtual llvm::Value *buildCopyIR(
+		llvm::IRBuilder<> &builder,
+		llvm::Value *value);
+
+	virtual void buildFreeIR(
+		llvm::IRBuilder<> &builder,
+		llvm::Value *value);
 };
 
 struct AnySocket {
@@ -85,10 +92,6 @@ struct SocketInfo {
 		: debug_name(debug_name), type(type) {}
 };
 
-typedef std::function<void(
-	std::vector<llvm::Value *> &inputs, llvm::IRBuilder<> *builder,
-	std::vector<llvm::Value *> &r_outputs, llvm::IRBuilder<> **r_builder)> IRBuilderFunction;
-
 struct NodeSockets {
 private:
 	using sockets_t = std::vector<SocketInfo>;
@@ -129,8 +132,9 @@ public:
 	virtual std::string debug_id() const;
 
 	virtual void buildLLVMIR(
-		std::vector<llvm::Value *> &inputs, llvm::IRBuilder<> *builder,
-		std::vector<llvm::Value *> &r_outputs, llvm::IRBuilder<> **r_builder) = 0;
+		llvm::IRBuilder<> &builder,
+		std::vector<llvm::Value *> &inputs,
+		std::vector<llvm::Value *> &r_outputs) = 0;
 
 	inline AnySocket Input(const uint index)
 	{ return AnySocket::NewInput(this, index); }
@@ -138,21 +142,6 @@ public:
 	{ return AnySocket::NewOutput(this, index); }
 };
 
-class SingleBuilderNode : public Node {
-	virtual void buildLLVMIR(
-		llvm::IRBuilder<> *builder,
-		std::vector<llvm::Value *> &inputs,
-		std::vector<llvm::Value *> &r_outputs) = 0;
-
-	void buildLLVMIR(
-		std::vector<llvm::Value *> &inputs, llvm::IRBuilder<> *builder,
-		std::vector<llvm::Value *> &r_outputs, llvm::IRBuilder<> **r_builder)
-	{
-		this->buildLLVMIR(builder, inputs, r_outputs);
-		

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list