lp_bld_init.c revision b363dd43d6f7f63bfe5261a46f8bdb2024f85db1
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 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: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 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. 25 * 26 **************************************************************************/ 27 28 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" 36 37#include <llvm-c/Transforms/Scalar.h> 38 39 40#ifdef DEBUG 41unsigned gallivm_debug = 0; 42 43static 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 }, 51 DEBUG_NAMED_VALUE_END 52}; 53 54DEBUG_GET_ONCE_FLAGS_OPTION(gallivm_debug, "GALLIVM_DEBUG", lp_bld_debug_flags, 0) 55#endif 56 57 58static boolean gallivm_initialized = FALSE; 59 60 61/* 62 * Optimization values are: 63 * - 0: None (-O0) 64 * - 1: Less (-O1) 65 * - 2: Default (-O2, -Os) 66 * - 3: Aggressive (-O3) 67 * 68 * See also CodeGenOpt::Level in llvm/Target/TargetMachine.h 69 */ 70enum LLVM_CodeGenOpt_Level { 71#if HAVE_LLVM >= 0x207 72 None, // -O0 73 Less, // -O1 74 Default, // -O2, -Os 75 Aggressive // -O3 76#else 77 Default, 78 None, 79 Aggressive 80#endif 81}; 82 83 84/** 85 * LLVM 2.6 permits only one ExecutionEngine to be created. This is it. 86 */ 87static LLVMExecutionEngineRef GlobalEngine = NULL; 88 89/** 90 * Same gallivm state shared by all contexts. 91 */ 92static struct gallivm_state *GlobalGallivm = NULL; 93 94 95 96 97extern void 98lp_register_oprofile_jit_event_listener(LLVMExecutionEngineRef EE); 99 100extern void 101lp_set_target_options(void); 102 103 104 105/** 106 * Create the LLVM (optimization) pass manager and install 107 * relevant optimization passes. 108 * \return TRUE for success, FALSE for failure 109 */ 110static boolean 111create_pass_manager(struct gallivm_state *gallivm) 112{ 113 assert(!gallivm->passmgr); 114 115 gallivm->passmgr = LLVMCreateFunctionPassManager(gallivm->provider); 116 if (!gallivm->passmgr) 117 return FALSE; 118 119 LLVMAddTargetData(gallivm->target, gallivm->passmgr); 120 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. 125 */ 126 LLVMAddCFGSimplificationPass(gallivm->passmgr); 127 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. 132 */ 133 LLVMAddConstantPropagationPass(gallivm->passmgr); 134 LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr); 135 } 136 else { 137 LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr); 138 LLVMAddConstantPropagationPass(gallivm->passmgr); 139 } 140 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. 145 */ 146 LLVMAddInstructionCombiningPass(gallivm->passmgr); 147 } 148 LLVMAddGVNPass(gallivm->passmgr); 149 } 150 else { 151 /* We need at least this pass to prevent the backends to fail in 152 * unexpected ways. 153 */ 154 LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr); 155 } 156 157 return TRUE; 158} 159 160 161/** 162 * Free gallivm object's LLVM allocations, but not the gallivm object itself. 163 */ 164static void 165free_gallivm_state(struct gallivm_state *gallivm) 166{ 167#if HAVE_LLVM >= 0x207 /* XXX or 0x208? */ 168 /* This leads to crashes w/ some versions of LLVM */ 169 LLVMModuleRef mod; 170 char *error; 171 172 if (gallivm->engine && gallivm->provider) 173 LLVMRemoveModuleProvider(gallivm->engine, gallivm->provider, 174 &mod, &error); 175#endif 176 177#if 0 178 /* XXX this seems to crash with all versions of LLVM */ 179 if (gallivm->provider) 180 LLVMDisposeModuleProvider(gallivm->provider); 181#endif 182 183 if (gallivm->passmgr) 184 LLVMDisposePassManager(gallivm->passmgr); 185 186#if HAVE_LLVM >= 0x207 187 if (gallivm->module) 188 LLVMDisposeModule(gallivm->module); 189#endif 190 191#if 0 192 /* Don't free the exec engine, it's a global/singleton */ 193 if (gallivm->engine) 194 LLVMDisposeExecutionEngine(gallivm->engine); 195#endif 196 197#if 0 198 /* Don't free the TargetData, it's owned by the exec engine */ 199 LLVMDisposeTargetData(gallivm->target); 200#endif 201 202 if (gallivm->context) 203 LLVMContextDispose(gallivm->context); 204 205 if (gallivm->builder) 206 LLVMDisposeBuilder(gallivm->builder); 207 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; 215} 216 217 218/** 219 * Allocate gallivm LLVM objects. 220 * \return TRUE for success, FALSE for failure 221 */ 222static boolean 223init_gallivm_state(struct gallivm_state *gallivm) 224{ 225 assert(gallivm_initialized); 226 assert(!gallivm->context); 227 assert(!gallivm->module); 228 assert(!gallivm->provider); 229 230 gallivm->context = LLVMContextCreate(); 231 if (!gallivm->context) 232 goto fail; 233 234 gallivm->module = LLVMModuleCreateWithNameInContext("gallivm", 235 gallivm->context); 236 if (!gallivm->module) 237 goto fail; 238 239 gallivm->provider = 240 LLVMCreateModuleProviderForExistingModule(gallivm->module); 241 if (!gallivm->provider) 242 goto fail; 243 244 if (!GlobalEngine) { 245 /* We can only create one LLVMExecutionEngine (w/ LLVM 2.6 anyway) */ 246 enum LLVM_CodeGenOpt_Level optlevel; 247 char *error = NULL; 248 249 if (gallivm_debug & GALLIVM_DEBUG_NO_OPT) { 250 optlevel = None; 251 } 252 else { 253 optlevel = Default; 254 } 255 256 if (LLVMCreateJITCompiler(&GlobalEngine, gallivm->provider, 257 (unsigned) optlevel, &error)) { 258 _debug_printf("%s\n", error); 259 LLVMDisposeMessage(error); 260 goto fail; 261 } 262 263#if defined(DEBUG) || defined(PROFILE) 264 lp_register_oprofile_jit_event_listener(GlobalEngine); 265#endif 266 } 267 268 gallivm->engine = GlobalEngine; 269 270 LLVMAddModuleProvider(gallivm->engine, gallivm->provider);//new 271 272 gallivm->target = LLVMGetExecutionEngineTargetData(gallivm->engine); 273 if (!gallivm->target) 274 goto fail; 275 276 if (!create_pass_manager(gallivm)) 277 goto fail; 278 279 gallivm->builder = LLVMCreateBuilderInContext(gallivm->context); 280 if (!gallivm->builder) 281 goto fail; 282 283 return TRUE; 284 285fail: 286 free_gallivm_state(gallivm); 287 return FALSE; 288} 289 290 291struct callback 292{ 293 garbage_collect_callback_func func; 294 void *cb_data; 295 struct callback *prev, *next; 296}; 297 298 299/** list of all garbage collector callbacks */ 300static struct callback callback_list = {NULL, NULL, NULL, NULL}; 301 302 303/** 304 * Register a function with gallivm which will be called when we 305 * do garbage collection. 306 */ 307void 308gallivm_register_garbage_collector_callback(garbage_collect_callback_func func, 309 void *cb_data) 310{ 311 struct callback *cb; 312 313 if (!callback_list.prev) { 314 make_empty_list(&callback_list); 315 } 316 317 /* see if already in list */ 318 foreach(cb, &callback_list) { 319 if (cb->func == func && cb->cb_data == cb_data) 320 return; 321 } 322 323 /* add to list */ 324 cb = CALLOC_STRUCT(callback); 325 if (cb) { 326 cb->func = func; 327 cb->cb_data = cb_data; 328 insert_at_head(&callback_list, cb); 329 } 330} 331 332 333/** 334 * Remove a callback. 335 */ 336void 337gallivm_remove_garbage_collector_callback(garbage_collect_callback_func func, 338 void *cb_data) 339{ 340 struct callback *cb; 341 342 /* search list */ 343 foreach(cb, &callback_list) { 344 if (cb->func == func && cb->cb_data == cb_data) { 345 /* found, remove it */ 346 remove_from_list(cb); 347 return; 348 } 349 } 350} 351 352 353/** 354 * Call the callback functions (which are typically in the 355 * draw module and llvmpipe driver. 356 */ 357static void 358call_garbage_collector_callbacks(void) 359{ 360 struct callback *cb; 361 foreach(cb, &callback_list) { 362 cb->func(cb->cb_data); 363 } 364} 365 366 367 368/** 369 * Other gallium components using gallivm should call this periodically 370 * to let us do garbage collection (or at least try to free memory 371 * accumulated by the LLVM libraries). 372 */ 373void 374gallivm_garbage_collect(struct gallivm_state *gallivm) 375{ 376 if (gallivm->context) { 377 if (gallivm_debug & GALLIVM_DEBUG_GC) 378 debug_printf("***** Doing LLVM garbage collection\n"); 379 380 call_garbage_collector_callbacks(); 381 free_gallivm_state(gallivm); 382 init_gallivm_state(gallivm); 383 } 384} 385 386 387void 388lp_build_init(void) 389{ 390#ifdef DEBUG 391 gallivm_debug = debug_get_option_gallivm_debug(); 392#endif 393 394 lp_set_target_options(); 395 396 LLVMInitializeNativeTarget(); 397 398 LLVMLinkInJIT(); 399 400 util_cpu_detect(); 401 402 gallivm_initialized = TRUE; 403 404#if 0 405 /* For simulating less capable machines */ 406 util_cpu_caps.has_sse3 = 0; 407 util_cpu_caps.has_ssse3 = 0; 408 util_cpu_caps.has_sse4_1 = 0; 409#endif 410} 411 412 413 414/** 415 * Create a new gallivm_state object. 416 * Note that we return a singleton. 417 */ 418struct gallivm_state * 419gallivm_create(void) 420{ 421 if (!GlobalGallivm) { 422 GlobalGallivm = CALLOC_STRUCT(gallivm_state); 423 if (GlobalGallivm) { 424 if (!init_gallivm_state(GlobalGallivm)) { 425 FREE(GlobalGallivm); 426 GlobalGallivm = NULL; 427 } 428 } 429 } 430 return GlobalGallivm; 431} 432 433 434/** 435 * Destroy a gallivm_state object. 436 */ 437void 438gallivm_destroy(struct gallivm_state *gallivm) 439{ 440 /* No-op: don't destroy the singleton */ 441 (void) gallivm; 442} 443 444 445 446/* 447 * Hack to allow the linking of release LLVM static libraries on a debug build. 448 * 449 * See also: 450 * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d 451 */ 452#if defined(_MSC_VER) && defined(_DEBUG) 453#include <crtdefs.h> 454_CRTIMP void __cdecl 455_invalid_parameter_noinfo(void) {} 456#endif 457