[Mesa-dev] [PATCH 3/8] radeon/compute: Stop leaking LLVMContexts in radeon_llvm_parse_bitcode

Aaron Watry awatry at gmail.com
Tue Dec 17 14:34:36 PST 2013


Previously we were creating a new LLVMContext every time that we called
radeon_llvm_parse_bitcode, which caused us to leak the context every time
that we compiled a CL program.

Sadly, we can't dispose of the LLVMContext at the point that it was being
created because evergreen_launch_grid (and possibly the SI equivalent) was
assuming that the context used to compile the kernels was still available.

Now, we'll create a new LLVMContext when creating EG/SI compute state, store
it there, and pass it to all of the places that need it.

The LLVM Context gets destroyed when we delete the EG/SI compute state.

Reviewed-by: Tom Stellard <thomas.stellard at amd.com>

CC: "10.0" <mesa-stable at lists.freedesktop.org>
---
 src/gallium/drivers/r600/evergreen_compute.c          | 18 +++++++++++++++---
 src/gallium/drivers/r600/evergreen_compute_internal.h |  4 ++++
 src/gallium/drivers/radeon/radeon_llvm_util.c         | 15 +++++++--------
 src/gallium/drivers/radeon/radeon_llvm_util.h         |  9 +++++----
 src/gallium/drivers/radeonsi/radeonsi_compute.c       | 13 ++++++++++---
 5 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_compute.c b/src/gallium/drivers/r600/evergreen_compute.c
index d668c8e..f0f537c 100644
--- a/src/gallium/drivers/r600/evergreen_compute.c
+++ b/src/gallium/drivers/r600/evergreen_compute.c
@@ -204,6 +204,8 @@ void *evergreen_create_compute_state(
 	const unsigned char * code;
 	unsigned i;
 
+	shader->llvm_ctx = LLVMContextCreate();
+
 	COMPUTE_DBG(ctx->screen, "*** evergreen_create_compute_state\n");
 
 	header = cso->prog;
@@ -216,13 +218,14 @@ void *evergreen_create_compute_state(
 	shader->input_size = cso->req_input_mem;
 
 #ifdef HAVE_OPENCL 
-	shader->num_kernels = radeon_llvm_get_num_kernels(code, header->num_bytes);
+	shader->num_kernels = radeon_llvm_get_num_kernels(shader->llvm_ctx, code,
+							header->num_bytes);
 	shader->kernels = CALLOC(sizeof(struct r600_kernel), shader->num_kernels);
 
 	for (i = 0; i < shader->num_kernels; i++) {
 		struct r600_kernel *kernel = &shader->kernels[i];
-		kernel->llvm_module = radeon_llvm_get_kernel_module(i, code,
-							header->num_bytes);
+		kernel->llvm_module = radeon_llvm_get_kernel_module(shader->llvm_ctx, i,
+							code, header->num_bytes);
 	}
 #endif
 	return shader;
@@ -232,6 +235,15 @@ void evergreen_delete_compute_state(struct pipe_context *ctx, void* state)
 {
 	struct r600_pipe_compute *shader = (struct r600_pipe_compute *)state;
 
+	if (!shader)
+		return;
+
+#ifdef HAVE_OPENCL
+	if (shader->llvm_ctx){
+		LLVMContextDispose(shader->llvm_ctx);
+	}
+#endif
+
 	free(shader);
 }
 
diff --git a/src/gallium/drivers/r600/evergreen_compute_internal.h b/src/gallium/drivers/r600/evergreen_compute_internal.h
index c524da2..0929d8d 100644
--- a/src/gallium/drivers/r600/evergreen_compute_internal.h
+++ b/src/gallium/drivers/r600/evergreen_compute_internal.h
@@ -47,6 +47,10 @@ struct r600_pipe_compute {
 	unsigned private_size;
 	unsigned input_size;
 	struct r600_resource *kernel_param;
+
+#ifdef HAVE_OPENCL
+	LLVMContextRef llvm_ctx;
+#endif
 };
 
 struct r600_resource* r600_compute_buffer_alloc_vram(struct r600_screen *screen, unsigned size);
diff --git a/src/gallium/drivers/radeon/radeon_llvm_util.c b/src/gallium/drivers/radeon/radeon_llvm_util.c
index 3ba0acc..cf6d21e 100644
--- a/src/gallium/drivers/radeon/radeon_llvm_util.c
+++ b/src/gallium/drivers/radeon/radeon_llvm_util.c
@@ -33,11 +33,10 @@
 #include <llvm-c/Transforms/IPO.h>
 #include <llvm-c/Transforms/PassManagerBuilder.h>
 
-LLVMModuleRef radeon_llvm_parse_bitcode(const unsigned char * bitcode,
-							unsigned bitcode_len)
+LLVMModuleRef radeon_llvm_parse_bitcode(LLVMContextRef ctx,
+							const unsigned char * bitcode, unsigned bitcode_len)
 {
 	LLVMMemoryBufferRef buf;
-	LLVMContextRef ctx = LLVMContextCreate();
 	LLVMModuleRef module;
 
 	buf = LLVMCreateMemoryBufferWithMemoryRangeCopy((const char*)bitcode,
@@ -47,10 +46,10 @@ LLVMModuleRef radeon_llvm_parse_bitcode(const unsigned char * bitcode,
 	return module;
 }
 
-unsigned radeon_llvm_get_num_kernels(const unsigned char *bitcode,
-				unsigned bitcode_len)
+unsigned radeon_llvm_get_num_kernels(LLVMContextRef ctx,
+				const unsigned char *bitcode, unsigned bitcode_len)
 {
-	LLVMModuleRef mod = radeon_llvm_parse_bitcode(bitcode, bitcode_len);
+	LLVMModuleRef mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
 	return LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
 }
 
@@ -87,7 +86,7 @@ static void radeon_llvm_optimize(LLVMModuleRef mod)
 	LLVMDisposePassManager(pass_manager);
 }
 
-LLVMModuleRef radeon_llvm_get_kernel_module(unsigned index,
+LLVMModuleRef radeon_llvm_get_kernel_module(LLVMContextRef ctx, unsigned index,
 		const unsigned char *bitcode, unsigned bitcode_len)
 {
 	LLVMModuleRef mod;
@@ -95,7 +94,7 @@ LLVMModuleRef radeon_llvm_get_kernel_module(unsigned index,
 	LLVMValueRef *kernel_metadata;
 	unsigned i;
 
-	mod = radeon_llvm_parse_bitcode(bitcode, bitcode_len);
+	mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
 	num_kernels = LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
 	kernel_metadata = MALLOC(num_kernels * sizeof(LLVMValueRef));
 	LLVMGetNamedMetadataOperands(mod, "opencl.kernels", kernel_metadata);
diff --git a/src/gallium/drivers/radeon/radeon_llvm_util.h b/src/gallium/drivers/radeon/radeon_llvm_util.h
index b851648..733c329 100644
--- a/src/gallium/drivers/radeon/radeon_llvm_util.h
+++ b/src/gallium/drivers/radeon/radeon_llvm_util.h
@@ -29,10 +29,11 @@
 
 #include <llvm-c/Core.h>
 
-LLVMModuleRef radeon_llvm_parse_bitcode(const unsigned char * bitcode,
-							unsigned bitcode_len);
-unsigned radeon_llvm_get_num_kernels(const unsigned char *bitcode, unsigned bitcode_len);
-LLVMModuleRef radeon_llvm_get_kernel_module(unsigned index,
+LLVMModuleRef radeon_llvm_parse_bitcode(LLVMContextRef ctx,
+			const unsigned char * bitcode, unsigned bitcode_len);
+unsigned radeon_llvm_get_num_kernels(LLVMContextRef ctx,
+			const unsigned char *bitcode, unsigned bitcode_len);
+LLVMModuleRef radeon_llvm_get_kernel_module(LLVMContextRef ctx, unsigned index,
 			const unsigned char *bitcode, unsigned bitcode_len);
 
 #endif
diff --git a/src/gallium/drivers/radeonsi/radeonsi_compute.c b/src/gallium/drivers/radeonsi/radeonsi_compute.c
index 2d53f2d..214ea3c 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_compute.c
+++ b/src/gallium/drivers/radeonsi/radeonsi_compute.c
@@ -20,6 +20,7 @@ struct si_pipe_compute {
 
         struct pipe_resource *global_buffers[MAX_GLOBAL_BUFFERS];
 
+	LLVMContextRef llvm_ctx;
 };
 
 static void *radeonsi_create_compute_state(
@@ -33,6 +34,8 @@ static void *radeonsi_create_compute_state(
 	const unsigned char *code;
 	unsigned i;
 
+	program->llvm_ctx = LLVMContextCreate();
+
 	header = cso->prog;
 	code = cso->prog + sizeof(struct pipe_llvm_program_header);
 
@@ -41,13 +44,13 @@ static void *radeonsi_create_compute_state(
 	program->private_size = cso->req_private_mem;
 	program->input_size = cso->req_input_mem;
 
-	program->num_kernels = radeon_llvm_get_num_kernels(code,
+	program->num_kernels = radeon_llvm_get_num_kernels(program->llvm_ctx, code,
 							header->num_bytes);
 	program->kernels = CALLOC(sizeof(struct si_pipe_shader),
 							program->num_kernels);
 	for (i = 0; i < program->num_kernels; i++) {
-		LLVMModuleRef mod = radeon_llvm_get_kernel_module(i, code,
-							header->num_bytes);
+		LLVMModuleRef mod = radeon_llvm_get_kernel_module(program->llvm_ctx, i,
+							code, header->num_bytes);
 		si_compile_llvm(rctx, &program->kernels[i], mod);
 		LLVMDisposeModule(mod);
 	}
@@ -272,6 +275,10 @@ static void si_delete_compute_state(struct pipe_context *ctx, void* state){
 		FREE(program->kernels);
 	}
 
+	if (program->llvm_ctx){
+		LLVMContextDispose(program->llvm_ctx);
+	}
+
 	//And then free the program itself.
 	FREE(program);
 }
-- 
1.8.3.2



More information about the mesa-dev mailing list