[Mesa-dev] [PATCH] radv/ac: enable loop unrolling.

Dave Airlie airlied at gmail.com
Fri Feb 24 03:27:36 UTC 2017


From: Dave Airlie <airlied at redhat.com>

This enables LLVM loop unrolling.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/amd/common/ac_llvm_helper.cpp | 22 ++++++++++++++++++++++
 src/amd/common/ac_llvm_util.h     |  1 +
 src/amd/common/ac_nir_to_llvm.c   | 24 ++++++++++++++++++++++--
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/amd/common/ac_llvm_helper.cpp b/src/amd/common/ac_llvm_helper.cpp
index 594339e..85b0cbf 100644
--- a/src/amd/common/ac_llvm_helper.cpp
+++ b/src/amd/common/ac_llvm_helper.cpp
@@ -36,7 +36,9 @@
 #include <llvm/Target/TargetOptions.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/IR/Attributes.h>
+#include <llvm/IR/LLVMContext.h>
 
+using namespace llvm;
 void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes)
 {
    llvm::Argument *A = llvm::unwrap<llvm::Argument>(val);
@@ -53,3 +55,23 @@ bool ac_is_sgpr_param(LLVMValueRef arg)
 	return AS.hasAttribute(ArgNo + 1, llvm::Attribute::ByVal) ||
 	       AS.hasAttribute(ArgNo + 1, llvm::Attribute::InReg);
 }
+
+// MetadataAsValue uses a canonical format which strips the actual MDNode for
+// MDNode with just a single constant value, storing just a ConstantAsMetadata
+// This undoes this canonicalization, reconstructing the MDNode.
+static MDNode *extractMDNode(MetadataAsValue *MAV) {
+	Metadata *MD = MAV->getMetadata();
+	assert((isa<MDNode>(MD) || isa<ConstantAsMetadata>(MD)) &&
+	       "Expected a metadata node or a canonicalized constant");
+
+	if (MDNode *N = dyn_cast<MDNode>(MD))
+		return N;
+	assert(0);
+	return MDNode::get(MAV->getContext(), MD);
+}
+
+void ac_metadata_point_op0_to_itself(LLVMValueRef v)
+{
+	MDNode *node = extractMDNode(unwrap<MetadataAsValue>(v));
+	node->replaceOperandWith(0, node);
+}
diff --git a/src/amd/common/ac_llvm_util.h b/src/amd/common/ac_llvm_util.h
index 1f37a12..0d6c53c 100644
--- a/src/amd/common/ac_llvm_util.h
+++ b/src/amd/common/ac_llvm_util.h
@@ -48,6 +48,7 @@ LLVMTargetMachineRef ac_create_target_machine(enum radeon_family family, bool su
 
 void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes);
 bool ac_is_sgpr_param(LLVMValueRef param);
+void ac_metadata_point_op0_to_itself(LLVMValueRef v);
 
 void
 ac_add_function_attr(LLVMValueRef function,
diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index 9778581..0e20aa1 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -3950,6 +3950,21 @@ static void visit_if(struct nir_to_llvm_context *ctx, nir_if *if_stmt)
 	LLVMPositionBuilderAtEnd(ctx->builder, merge_block);
 }
 
+static void set_unroll_metadata(struct nir_to_llvm_context *ctx,
+			       LLVMValueRef br)
+{
+	unsigned kind = LLVMGetMDKindIDInContext(ctx->context, "llvm.loop", 9);
+	LLVMValueRef md_unroll;
+	LLVMValueRef full_arg = LLVMMDStringInContext(ctx->context, "llvm.loop.unroll.full", 21);
+	LLVMValueRef full = LLVMMDNodeInContext(ctx->context, &full_arg, 1);
+
+	LLVMValueRef md_args[] = {NULL, full};
+	md_unroll = LLVMMDNodeInContext(ctx->context, md_args, 2);
+	ac_metadata_point_op0_to_itself(md_unroll);
+
+	LLVMSetMetadata(br, kind, md_unroll);
+}
+
 static void visit_loop(struct nir_to_llvm_context *ctx, nir_loop *loop)
 {
 	LLVMBasicBlockRef continue_parent = ctx->continue_block;
@@ -3964,8 +3979,10 @@ static void visit_loop(struct nir_to_llvm_context *ctx, nir_loop *loop)
 	LLVMPositionBuilderAtEnd(ctx->builder, ctx->continue_block);
 	visit_cf_list(ctx, &loop->body);
 
-	if (LLVMGetInsertBlock(ctx->builder))
-		LLVMBuildBr(ctx->builder, ctx->continue_block);
+	if (LLVMGetInsertBlock(ctx->builder)) {
+		LLVMValueRef loop = LLVMBuildBr(ctx->builder, ctx->continue_block);
+		set_unroll_metadata(ctx, loop);
+	}
 	LLVMPositionBuilderAtEnd(ctx->builder, ctx->break_block);
 
 	ctx->continue_block = continue_parent;
@@ -4827,10 +4844,13 @@ static void ac_llvm_finalize_module(struct nir_to_llvm_context * ctx)
 
 	/* Add some optimization passes */
 	LLVMAddScalarReplAggregatesPass(passmgr);
+	LLVMAddLoopRotatePass(passmgr);
 	LLVMAddLICMPass(passmgr);
 	LLVMAddAggressiveDCEPass(passmgr);
 	LLVMAddCFGSimplificationPass(passmgr);
 	LLVMAddInstructionCombiningPass(passmgr);
+	LLVMAddIndVarSimplifyPass(passmgr);
+	LLVMAddLoopUnrollPass(passmgr);
 
 	/* Run the pass */
 	LLVMInitializeFunctionPassManager(passmgr);
-- 
2.9.3



More information about the mesa-dev mailing list