1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 #include "pipe/p_compiler.h"
30 #include "util/u_cpu_detect.h"
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
33 #include "lp_bld_debug.h"
34 #include "lp_bld_init.h"
36 #include <llvm-c/Transforms/Scalar.h>
40 unsigned gallivm_debug
= 0;
42 static const struct debug_named_value lp_bld_debug_flags
[] = {
43 { "tgsi", GALLIVM_DEBUG_TGSI
, NULL
},
44 { "ir", GALLIVM_DEBUG_IR
, NULL
},
45 { "asm", GALLIVM_DEBUG_ASM
, NULL
},
46 { "nopt", GALLIVM_DEBUG_NO_OPT
, NULL
},
47 { "perf", GALLIVM_DEBUG_PERF
, NULL
},
48 { "no_brilinear", GALLIVM_DEBUG_NO_BRILINEAR
, NULL
},
49 { "gc", GALLIVM_DEBUG_GC
, NULL
},
53 DEBUG_GET_ONCE_FLAGS_OPTION(gallivm_debug
, "GALLIVM_DEBUG", lp_bld_debug_flags
, 0)
57 static boolean gallivm_initialized
= FALSE
;
61 * Optimization values are:
64 * - 2: Default (-O2, -Os)
65 * - 3: Aggressive (-O3)
67 * See also CodeGenOpt::Level in llvm/Target/TargetMachine.h
69 enum LLVM_CodeGenOpt_Level
{
70 #if HAVE_LLVM >= 0x207
84 * LLVM 2.6 permits only one ExecutionEngine to be created. This is it.
86 static LLVMExecutionEngineRef GlobalEngine
= NULL
;
89 * Same gallivm state shared by all contexts.
91 static struct gallivm_state
*GlobalGallivm
= NULL
;
97 lp_register_oprofile_jit_event_listener(LLVMExecutionEngineRef EE
);
100 lp_set_target_options(void);
105 * Create the LLVM (optimization) pass manager and install
106 * relevant optimization passes.
107 * \return TRUE for success, FALSE for failure
110 create_pass_manager(struct gallivm_state
*gallivm
)
112 assert(!gallivm
->passmgr
);
114 gallivm
->passmgr
= LLVMCreateFunctionPassManager(gallivm
->provider
);
115 if (!gallivm
->passmgr
)
118 LLVMAddTargetData(gallivm
->target
, gallivm
->passmgr
);
120 if ((gallivm_debug
& GALLIVM_DEBUG_NO_OPT
) == 0) {
121 /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
122 * but there are more on SVN.
123 * TODO: Add more passes.
125 LLVMAddCFGSimplificationPass(gallivm
->passmgr
);
127 if (HAVE_LLVM
>= 0x207 && sizeof(void*) == 4) {
128 /* For LLVM >= 2.7 and 32-bit build, use this order of passes to
129 * avoid generating bad code.
130 * Test with piglit glsl-vs-sqrt-zero test.
132 LLVMAddConstantPropagationPass(gallivm
->passmgr
);
133 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
136 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
137 LLVMAddConstantPropagationPass(gallivm
->passmgr
);
140 if (util_cpu_caps
.has_sse4_1
) {
141 /* FIXME: There is a bug in this pass, whereby the combination
142 * of fptosi and sitofp (necessary for trunc/floor/ceil/round
143 * implementation) somehow becomes invalid code.
145 LLVMAddInstructionCombiningPass(gallivm
->passmgr
);
147 LLVMAddGVNPass(gallivm
->passmgr
);
150 /* We need at least this pass to prevent the backends to fail in
153 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
161 * Free gallivm object's LLVM allocations, but not the gallivm object itself.
164 free_gallivm_state(struct gallivm_state
*gallivm
)
166 #if HAVE_LLVM >= 0x207 /* XXX or 0x208? */
167 /* This leads to crashes w/ some versions of LLVM */
171 if (gallivm
->engine
&& gallivm
->provider
)
172 LLVMRemoveModuleProvider(gallivm
->engine
, gallivm
->provider
,
177 /* XXX this seems to crash with all versions of LLVM */
178 if (gallivm
->provider
)
179 LLVMDisposeModuleProvider(gallivm
->provider
);
182 if (gallivm
->passmgr
)
183 LLVMDisposePassManager(gallivm
->passmgr
);
185 #if HAVE_LLVM >= 0x207
187 LLVMDisposeModule(gallivm
->module
);
191 /* Don't free the exec engine, it's a global/singleton */
193 LLVMDisposeExecutionEngine(gallivm
->engine
);
197 /* Don't free the TargetData, it's owned by the exec engine */
198 LLVMDisposeTargetData(gallivm
->target
);
201 if (gallivm
->context
)
202 LLVMContextDispose(gallivm
->context
);
204 if (gallivm
->builder
)
205 LLVMDisposeBuilder(gallivm
->builder
);
207 gallivm
->engine
= NULL
;
208 gallivm
->target
= NULL
;
209 gallivm
->module
= NULL
;
210 gallivm
->provider
= NULL
;
211 gallivm
->passmgr
= NULL
;
212 gallivm
->context
= NULL
;
213 gallivm
->builder
= NULL
;
218 * Allocate gallivm LLVM objects.
219 * \return TRUE for success, FALSE for failure
222 init_gallivm_state(struct gallivm_state
*gallivm
)
224 assert(gallivm_initialized
);
225 assert(!gallivm
->context
);
226 assert(!gallivm
->module
);
227 assert(!gallivm
->provider
);
229 gallivm
->context
= LLVMContextCreate();
230 if (!gallivm
->context
)
233 gallivm
->module
= LLVMModuleCreateWithNameInContext("gallivm",
235 if (!gallivm
->module
)
239 LLVMCreateModuleProviderForExistingModule(gallivm
->module
);
240 if (!gallivm
->provider
)
244 /* We can only create one LLVMExecutionEngine (w/ LLVM 2.6 anyway) */
245 enum LLVM_CodeGenOpt_Level optlevel
;
248 if (gallivm_debug
& GALLIVM_DEBUG_NO_OPT
) {
255 if (LLVMCreateJITCompiler(&GlobalEngine
, gallivm
->provider
,
256 (unsigned) optlevel
, &error
)) {
257 _debug_printf("%s\n", error
);
258 LLVMDisposeMessage(error
);
262 #if defined(DEBUG) || defined(PROFILE)
263 lp_register_oprofile_jit_event_listener(GlobalEngine
);
267 gallivm
->engine
= GlobalEngine
;
269 LLVMAddModuleProvider(gallivm
->engine
, gallivm
->provider
);//new
271 gallivm
->target
= LLVMGetExecutionEngineTargetData(gallivm
->engine
);
272 if (!gallivm
->target
)
275 if (!create_pass_manager(gallivm
))
278 gallivm
->builder
= LLVMCreateBuilderInContext(gallivm
->context
);
279 if (!gallivm
->builder
)
285 free_gallivm_state(gallivm
);
292 garbage_collect_callback_func func
;
297 #define MAX_CALLBACKS 32
298 static struct callback Callbacks
[MAX_CALLBACKS
];
299 static unsigned NumCallbacks
= 0;
303 * Register a function with gallivm which will be called when we
304 * do garbage collection.
307 gallivm_register_garbage_collector_callback(garbage_collect_callback_func func
,
312 for (i
= 0; i
< NumCallbacks
; i
++) {
313 if (Callbacks
[i
].func
== func
&& Callbacks
[i
].cb_data
== cb_data
) {
314 /* already in list: no-op */
319 assert(NumCallbacks
< MAX_CALLBACKS
);
320 if (NumCallbacks
< MAX_CALLBACKS
) {
321 Callbacks
[NumCallbacks
].func
= func
;
322 Callbacks
[NumCallbacks
].cb_data
= cb_data
;
332 gallivm_remove_garbage_collector_callback(garbage_collect_callback_func func
,
337 for (i
= 0; i
< NumCallbacks
; i
++) {
338 if (Callbacks
[i
].func
== func
&& Callbacks
[i
].cb_data
== cb_data
) {
339 /* found, now remove it */
341 for ( ; i
< NumCallbacks
; i
++) {
342 Callbacks
[i
] = Callbacks
[i
+ 1];
351 * Call the callback functions (which are typically in the
352 * draw module and llvmpipe driver.
355 call_garbage_collector_callbacks(void)
359 for (i
= 0; i
< NumCallbacks
; i
++) {
360 Callbacks
[i
].func(Callbacks
[i
].cb_data
);
367 * Other gallium components using gallivm should call this periodically
368 * to let us do garbage collection (or at least try to free memory
369 * accumulated by the LLVM libraries).
372 gallivm_garbage_collect(struct gallivm_state
*gallivm
)
374 if (gallivm
->context
) {
375 if (gallivm_debug
& GALLIVM_DEBUG_GC
)
376 debug_printf("***** Doing LLVM garbage collection\n");
378 call_garbage_collector_callbacks();
379 free_gallivm_state(gallivm
);
380 init_gallivm_state(gallivm
);
389 gallivm_debug
= debug_get_option_gallivm_debug();
392 lp_set_target_options();
394 LLVMInitializeNativeTarget();
400 gallivm_initialized
= TRUE
;
403 /* For simulating less capable machines */
404 util_cpu_caps
.has_sse3
= 0;
405 util_cpu_caps
.has_ssse3
= 0;
406 util_cpu_caps
.has_sse4_1
= 0;
413 * Create a new gallivm_state object.
414 * Note that we return a singleton.
416 struct gallivm_state
*
419 if (!GlobalGallivm
) {
420 GlobalGallivm
= CALLOC_STRUCT(gallivm_state
);
422 if (!init_gallivm_state(GlobalGallivm
)) {
424 GlobalGallivm
= NULL
;
428 return GlobalGallivm
;
433 * Destroy a gallivm_state object.
436 gallivm_destroy(struct gallivm_state
*gallivm
)
438 /* No-op: don't destroy the singleton */
445 * Hack to allow the linking of release LLVM static libraries on a debug build.
448 * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d
450 #if defined(_MSC_VER) && defined(_DEBUG)
453 _invalid_parameter_noinfo(void) {}