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 "util/u_simple_list.h"
34 #include "lp_bld_debug.h"
35 #include "lp_bld_init.h"
37 #include <llvm-c/Transforms/Scalar.h>
41 unsigned gallivm_debug
= 0;
43 static const struct debug_named_value lp_bld_debug_flags
[] = {
44 { "tgsi", GALLIVM_DEBUG_TGSI
, NULL
},
45 { "ir", GALLIVM_DEBUG_IR
, NULL
},
46 { "asm", GALLIVM_DEBUG_ASM
, NULL
},
47 { "nopt", GALLIVM_DEBUG_NO_OPT
, NULL
},
48 { "perf", GALLIVM_DEBUG_PERF
, NULL
},
49 { "no_brilinear", GALLIVM_DEBUG_NO_BRILINEAR
, NULL
},
50 { "gc", GALLIVM_DEBUG_GC
, NULL
},
54 DEBUG_GET_ONCE_FLAGS_OPTION(gallivm_debug
, "GALLIVM_DEBUG", lp_bld_debug_flags
, 0)
58 static boolean gallivm_initialized
= FALSE
;
62 * Optimization values are:
65 * - 2: Default (-O2, -Os)
66 * - 3: Aggressive (-O3)
68 * See also CodeGenOpt::Level in llvm/Target/TargetMachine.h
70 enum LLVM_CodeGenOpt_Level
{
71 #if HAVE_LLVM >= 0x207
85 * LLVM 2.6 permits only one ExecutionEngine to be created. This is it.
87 static LLVMExecutionEngineRef GlobalEngine
= NULL
;
90 * Same gallivm state shared by all contexts.
92 static struct gallivm_state
*GlobalGallivm
= NULL
;
98 lp_register_oprofile_jit_event_listener(LLVMExecutionEngineRef EE
);
101 lp_set_target_options(void);
106 * Create the LLVM (optimization) pass manager and install
107 * relevant optimization passes.
108 * \return TRUE for success, FALSE for failure
111 create_pass_manager(struct gallivm_state
*gallivm
)
113 assert(!gallivm
->passmgr
);
115 gallivm
->passmgr
= LLVMCreateFunctionPassManager(gallivm
->provider
);
116 if (!gallivm
->passmgr
)
119 LLVMAddTargetData(gallivm
->target
, gallivm
->passmgr
);
121 if ((gallivm_debug
& GALLIVM_DEBUG_NO_OPT
) == 0) {
122 /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
123 * but there are more on SVN.
124 * TODO: Add more passes.
126 LLVMAddCFGSimplificationPass(gallivm
->passmgr
);
128 if (HAVE_LLVM
>= 0x207 && sizeof(void*) == 4) {
129 /* For LLVM >= 2.7 and 32-bit build, use this order of passes to
130 * avoid generating bad code.
131 * Test with piglit glsl-vs-sqrt-zero test.
133 LLVMAddConstantPropagationPass(gallivm
->passmgr
);
134 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
137 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
138 LLVMAddConstantPropagationPass(gallivm
->passmgr
);
141 if (util_cpu_caps
.has_sse4_1
) {
142 /* FIXME: There is a bug in this pass, whereby the combination
143 * of fptosi and sitofp (necessary for trunc/floor/ceil/round
144 * implementation) somehow becomes invalid code.
146 LLVMAddInstructionCombiningPass(gallivm
->passmgr
);
148 LLVMAddGVNPass(gallivm
->passmgr
);
151 /* We need at least this pass to prevent the backends to fail in
154 LLVMAddPromoteMemoryToRegisterPass(gallivm
->passmgr
);
162 * Free gallivm object's LLVM allocations, but not the gallivm object itself.
165 free_gallivm_state(struct gallivm_state
*gallivm
)
167 #if HAVE_LLVM >= 0x207 /* XXX or 0x208? */
168 /* This leads to crashes w/ some versions of LLVM */
172 if (gallivm
->engine
&& gallivm
->provider
)
173 LLVMRemoveModuleProvider(gallivm
->engine
, gallivm
->provider
,
178 /* XXX this seems to crash with all versions of LLVM */
179 if (gallivm
->provider
)
180 LLVMDisposeModuleProvider(gallivm
->provider
);
183 if (gallivm
->passmgr
)
184 LLVMDisposePassManager(gallivm
->passmgr
);
186 #if HAVE_LLVM >= 0x207
188 LLVMDisposeModule(gallivm
->module
);
192 /* Don't free the exec engine, it's a global/singleton */
194 LLVMDisposeExecutionEngine(gallivm
->engine
);
198 /* Don't free the TargetData, it's owned by the exec engine */
199 LLVMDisposeTargetData(gallivm
->target
);
202 if (gallivm
->context
)
203 LLVMContextDispose(gallivm
->context
);
205 if (gallivm
->builder
)
206 LLVMDisposeBuilder(gallivm
->builder
);
208 gallivm
->engine
= NULL
;
209 gallivm
->target
= NULL
;
210 gallivm
->module
= NULL
;
211 gallivm
->provider
= NULL
;
212 gallivm
->passmgr
= NULL
;
213 gallivm
->context
= NULL
;
214 gallivm
->builder
= NULL
;
219 * Allocate gallivm LLVM objects.
220 * \return TRUE for success, FALSE for failure
223 init_gallivm_state(struct gallivm_state
*gallivm
)
225 assert(!gallivm
->context
);
226 assert(!gallivm
->module
);
227 assert(!gallivm
->provider
);
231 gallivm
->context
= LLVMContextCreate();
232 if (!gallivm
->context
)
235 gallivm
->module
= LLVMModuleCreateWithNameInContext("gallivm",
237 if (!gallivm
->module
)
241 LLVMCreateModuleProviderForExistingModule(gallivm
->module
);
242 if (!gallivm
->provider
)
246 /* We can only create one LLVMExecutionEngine (w/ LLVM 2.6 anyway) */
247 enum LLVM_CodeGenOpt_Level optlevel
;
250 if (gallivm_debug
& GALLIVM_DEBUG_NO_OPT
) {
257 if (LLVMCreateJITCompiler(&GlobalEngine
, gallivm
->provider
,
258 (unsigned) optlevel
, &error
)) {
259 _debug_printf("%s\n", error
);
260 LLVMDisposeMessage(error
);
264 #if defined(DEBUG) || defined(PROFILE)
265 lp_register_oprofile_jit_event_listener(GlobalEngine
);
269 gallivm
->engine
= GlobalEngine
;
271 LLVMAddModuleProvider(gallivm
->engine
, gallivm
->provider
);//new
273 gallivm
->target
= LLVMGetExecutionEngineTargetData(gallivm
->engine
);
274 if (!gallivm
->target
)
277 if (!create_pass_manager(gallivm
))
280 gallivm
->builder
= LLVMCreateBuilderInContext(gallivm
->context
);
281 if (!gallivm
->builder
)
287 free_gallivm_state(gallivm
);
294 garbage_collect_callback_func func
;
296 struct callback
*prev
, *next
;
300 /** list of all garbage collector callbacks */
301 static struct callback callback_list
= {NULL
, NULL
, NULL
, NULL
};
305 * Register a function with gallivm which will be called when we
306 * do garbage collection.
309 gallivm_register_garbage_collector_callback(garbage_collect_callback_func func
,
314 if (!callback_list
.prev
) {
315 make_empty_list(&callback_list
);
318 /* see if already in list */
319 foreach(cb
, &callback_list
) {
320 if (cb
->func
== func
&& cb
->cb_data
== cb_data
)
325 cb
= CALLOC_STRUCT(callback
);
328 cb
->cb_data
= cb_data
;
329 insert_at_head(&callback_list
, cb
);
338 gallivm_remove_garbage_collector_callback(garbage_collect_callback_func func
,
344 foreach(cb
, &callback_list
) {
345 if (cb
->func
== func
&& cb
->cb_data
== cb_data
) {
346 /* found, remove it */
347 remove_from_list(cb
);
355 * Call the callback functions (which are typically in the
356 * draw module and llvmpipe driver.
359 call_garbage_collector_callbacks(void)
362 foreach(cb
, &callback_list
) {
363 cb
->func(cb
->cb_data
);
370 * Other gallium components using gallivm should call this periodically
371 * to let us do garbage collection (or at least try to free memory
372 * accumulated by the LLVM libraries).
375 gallivm_garbage_collect(struct gallivm_state
*gallivm
)
377 if (gallivm
->context
) {
378 if (gallivm_debug
& GALLIVM_DEBUG_GC
)
379 debug_printf("***** Doing LLVM garbage collection\n");
381 call_garbage_collector_callbacks();
382 free_gallivm_state(gallivm
);
383 init_gallivm_state(gallivm
);
391 if (gallivm_initialized
)
395 gallivm_debug
= debug_get_option_gallivm_debug();
398 lp_set_target_options();
400 LLVMInitializeNativeTarget();
406 gallivm_initialized
= TRUE
;
409 /* For simulating less capable machines */
410 util_cpu_caps
.has_sse3
= 0;
411 util_cpu_caps
.has_ssse3
= 0;
412 util_cpu_caps
.has_sse4_1
= 0;
419 * Create a new gallivm_state object.
420 * Note that we return a singleton.
422 struct gallivm_state
*
425 if (!GlobalGallivm
) {
426 GlobalGallivm
= CALLOC_STRUCT(gallivm_state
);
428 if (!init_gallivm_state(GlobalGallivm
)) {
430 GlobalGallivm
= NULL
;
434 return GlobalGallivm
;
439 * Destroy a gallivm_state object.
442 gallivm_destroy(struct gallivm_state
*gallivm
)
444 /* No-op: don't destroy the singleton */
451 * Hack to allow the linking of release LLVM static libraries on a debug build.
454 * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d
456 #if defined(_MSC_VER) && defined(_DEBUG)
459 _invalid_parameter_noinfo(void) {}