radeon/compute: Stop leaking LLVMContexts in radeon_llvm_parse_bitcode
authorAaron Watry <awatry@gmail.com>
Thu, 12 Dec 2013 22:34:09 +0000 (16:34 -0600)
committerAaron Watry <awatry@gmail.com>
Mon, 23 Dec 2013 13:24:50 +0000 (07:24 -0600)
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@amd.com>
CC: "10.0" <mesa-stable@lists.freedesktop.org>
src/gallium/drivers/r600/evergreen_compute.c
src/gallium/drivers/r600/evergreen_compute_internal.h
src/gallium/drivers/radeon/radeon_llvm_util.c
src/gallium/drivers/radeon/radeon_llvm_util.h
src/gallium/drivers/radeonsi/radeonsi_compute.c

index dc17c058e2cd574140357d49eb44f48b49e275ae..0d722b6cad6b2a9856a8ec66de19abb7c268b622 100644 (file)
@@ -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);
 }
 
index c524da2b84dda054207225a5ecea8bd1e77e4ec8..0929d8dcf270eb1620f31f1a3bcbd4aebfbdc0b5 100644 (file)
@@ -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);
index 3ba0acc55bc925aeab7de2d482f7e1353a7f290f..cf6d21ed71fe7aa21aaba9d6941d96eb73bdba00 100644 (file)
 #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);
index b85164885ddb81309e505367ab18501c3f695662..733c329e99e903d330402e06d75c8ec067d7675a 100644 (file)
 
 #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
index 2d53f2d9864d85f6790c4d4c02a730c607bc7d6e..214ea3c25525feba541b37482e22c75c2b0c3e42 100644 (file)
@@ -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);
 }