Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2012, 2013 Advanced Micro Devices, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 *
23
 * Authors: Tom Stellard 
24
 *
25
 */
26
 
27
#include "radeon_llvm_util.h"
28
#include "util/u_memory.h"
29
 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
 
36
LLVMModuleRef radeon_llvm_parse_bitcode(LLVMContextRef ctx,
37
							const char * bitcode, unsigned bitcode_len)
38
{
39
	LLVMMemoryBufferRef buf;
40
	LLVMModuleRef module;
41
 
42
	buf = LLVMCreateMemoryBufferWithMemoryRangeCopy((const char*)bitcode,
43
							bitcode_len, "radeon");
44
	LLVMParseBitcodeInContext(ctx, buf, &module, NULL);
45
	LLVMDisposeMemoryBuffer(buf);
46
	return module;
47
}
48
 
49
unsigned radeon_llvm_get_num_kernels(LLVMContextRef ctx,
50
				const char *bitcode, unsigned bitcode_len)
51
{
52
	LLVMModuleRef mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
53
	return LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
54
}
55
 
56
static void radeon_llvm_optimize(LLVMModuleRef mod)
57
{
58
	const char *data_layout = LLVMGetDataLayout(mod);
59
	LLVMTargetDataRef TD = LLVMCreateTargetData(data_layout);
60
	LLVMPassManagerBuilderRef builder = LLVMPassManagerBuilderCreate();
61
	LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
62
 
63
	/* Functions calls are not supported yet, so we need to inline
64
	 * everything.  The most efficient way to do this is to add
65
	 * the always_inline attribute to all non-kernel functions
66
	 * and then run the Always Inline pass.  The Always Inline
67
	 * pass will automaically inline functions with this attribute
68
	 * and does not perform the expensive cost analysis that the normal
69
	 * inliner does.
70
	 */
71
 
72
	LLVMValueRef fn;
73
	for (fn = LLVMGetFirstFunction(mod); fn; fn = LLVMGetNextFunction(fn)) {
74
		/* All the non-kernel functions have internal linkage */
75
		if (LLVMGetLinkage(fn) == LLVMInternalLinkage) {
76
			LLVMAddFunctionAttr(fn, LLVMAlwaysInlineAttribute);
77
		}
78
	}
79
 
80
	LLVMAddTargetData(TD, pass_manager);
81
	LLVMAddAlwaysInlinerPass(pass_manager);
82
	LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
83
 
84
	LLVMRunPassManager(pass_manager, mod);
85
	LLVMPassManagerBuilderDispose(builder);
86
	LLVMDisposePassManager(pass_manager);
87
	LLVMDisposeTargetData(TD);
88
}
89
 
90
LLVMModuleRef radeon_llvm_get_kernel_module(LLVMContextRef ctx, unsigned index,
91
		const char *bitcode, unsigned bitcode_len)
92
{
93
	LLVMModuleRef mod;
94
	unsigned num_kernels;
95
	LLVMValueRef *kernel_metadata;
96
	unsigned i;
97
 
98
	mod = radeon_llvm_parse_bitcode(ctx, bitcode, bitcode_len);
99
	num_kernels = LLVMGetNamedMetadataNumOperands(mod, "opencl.kernels");
100
	kernel_metadata = MALLOC(num_kernels * sizeof(LLVMValueRef));
101
	LLVMGetNamedMetadataOperands(mod, "opencl.kernels", kernel_metadata);
102
	for (i = 0; i < num_kernels; i++) {
103
		LLVMValueRef kernel_signature, *kernel_function;
104
		unsigned num_kernel_md_operands;
105
		if (i == index) {
106
			continue;
107
		}
108
		kernel_signature = kernel_metadata[i];
109
		num_kernel_md_operands = LLVMGetMDNodeNumOperands(kernel_signature);
110
		kernel_function = MALLOC(num_kernel_md_operands * sizeof (LLVMValueRef));
111
		LLVMGetMDNodeOperands(kernel_signature, kernel_function);
112
		LLVMDeleteFunction(*kernel_function);
113
		FREE(kernel_function);
114
	}
115
	FREE(kernel_metadata);
116
	radeon_llvm_optimize(mod);
117
	return mod;
118
}