1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "pipe/p_config.h" 30bf215546Sopenharmony_ci#include "pipe/p_compiler.h" 31bf215546Sopenharmony_ci#include "util/u_cpu_detect.h" 32bf215546Sopenharmony_ci#include "util/u_debug.h" 33bf215546Sopenharmony_ci#include "util/u_memory.h" 34bf215546Sopenharmony_ci#include "util/os_time.h" 35bf215546Sopenharmony_ci#include "lp_bld.h" 36bf215546Sopenharmony_ci#include "lp_bld_debug.h" 37bf215546Sopenharmony_ci#include "lp_bld_misc.h" 38bf215546Sopenharmony_ci#include "lp_bld_init.h" 39bf215546Sopenharmony_ci#include "lp_bld_coro.h" 40bf215546Sopenharmony_ci#include "lp_bld_printf.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include <llvm/Config/llvm-config.h> 43bf215546Sopenharmony_ci#include <llvm-c/Analysis.h> 44bf215546Sopenharmony_ci#include <llvm-c/Transforms/Scalar.h> 45bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR >= 7 46bf215546Sopenharmony_ci#include <llvm-c/Transforms/Utils.h> 47bf215546Sopenharmony_ci#endif 48bf215546Sopenharmony_ci#include <llvm-c/BitWriter.h> 49bf215546Sopenharmony_ci#if GALLIVM_USE_NEW_PASS == 1 50bf215546Sopenharmony_ci#include <llvm-c/Transforms/PassBuilder.h> 51bf215546Sopenharmony_ci#elif GALLIVM_HAVE_CORO == 1 52bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR <= 8 && (defined(PIPE_ARCH_AARCH64) || defined (PIPE_ARCH_ARM) || defined(PIPE_ARCH_S390) || defined(PIPE_ARCH_MIPS64)) 53bf215546Sopenharmony_ci#include <llvm-c/Transforms/IPO.h> 54bf215546Sopenharmony_ci#endif 55bf215546Sopenharmony_ci#include <llvm-c/Transforms/Coroutines.h> 56bf215546Sopenharmony_ci#endif 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ciunsigned gallivm_perf = 0; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic const struct debug_named_value lp_bld_perf_flags[] = { 61bf215546Sopenharmony_ci { "brilinear", GALLIVM_PERF_BRILINEAR, "enable brilinear optimization" }, 62bf215546Sopenharmony_ci { "rho_approx", GALLIVM_PERF_RHO_APPROX, "enable rho_approx optimization" }, 63bf215546Sopenharmony_ci { "no_quad_lod", GALLIVM_PERF_NO_QUAD_LOD, "disable quad_lod optimization" }, 64bf215546Sopenharmony_ci { "no_aos_sampling", GALLIVM_PERF_NO_AOS_SAMPLING, "disable aos sampling optimization" }, 65bf215546Sopenharmony_ci { "nopt", GALLIVM_PERF_NO_OPT, "disable optimization passes to speed up shader compilation" }, 66bf215546Sopenharmony_ci DEBUG_NAMED_VALUE_END 67bf215546Sopenharmony_ci}; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci#ifdef DEBUG 70bf215546Sopenharmony_ciunsigned gallivm_debug = 0; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic const struct debug_named_value lp_bld_debug_flags[] = { 73bf215546Sopenharmony_ci { "tgsi", GALLIVM_DEBUG_TGSI, NULL }, 74bf215546Sopenharmony_ci { "ir", GALLIVM_DEBUG_IR, NULL }, 75bf215546Sopenharmony_ci { "asm", GALLIVM_DEBUG_ASM, NULL }, 76bf215546Sopenharmony_ci { "perf", GALLIVM_DEBUG_PERF, NULL }, 77bf215546Sopenharmony_ci { "gc", GALLIVM_DEBUG_GC, NULL }, 78bf215546Sopenharmony_ci { "dumpbc", GALLIVM_DEBUG_DUMP_BC, NULL }, 79bf215546Sopenharmony_ci DEBUG_NAMED_VALUE_END 80bf215546Sopenharmony_ci}; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ciDEBUG_GET_ONCE_FLAGS_OPTION(gallivm_debug, "GALLIVM_DEBUG", lp_bld_debug_flags, 0) 83bf215546Sopenharmony_ci#endif 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistatic boolean gallivm_initialized = FALSE; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ciunsigned lp_native_vector_width; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/* 92bf215546Sopenharmony_ci * Optimization values are: 93bf215546Sopenharmony_ci * - 0: None (-O0) 94bf215546Sopenharmony_ci * - 1: Less (-O1) 95bf215546Sopenharmony_ci * - 2: Default (-O2, -Os) 96bf215546Sopenharmony_ci * - 3: Aggressive (-O3) 97bf215546Sopenharmony_ci * 98bf215546Sopenharmony_ci * See also CodeGenOpt::Level in llvm/Target/TargetMachine.h 99bf215546Sopenharmony_ci */ 100bf215546Sopenharmony_cienum LLVM_CodeGenOpt_Level { 101bf215546Sopenharmony_ci None, // -O0 102bf215546Sopenharmony_ci Less, // -O1 103bf215546Sopenharmony_ci Default, // -O2, -Os 104bf215546Sopenharmony_ci Aggressive // -O3 105bf215546Sopenharmony_ci}; 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci/** 109bf215546Sopenharmony_ci * Create the LLVM (optimization) pass manager and install 110bf215546Sopenharmony_ci * relevant optimization passes. 111bf215546Sopenharmony_ci * \return TRUE for success, FALSE for failure 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_cistatic boolean 114bf215546Sopenharmony_cicreate_pass_manager(struct gallivm_state *gallivm) 115bf215546Sopenharmony_ci{ 116bf215546Sopenharmony_ci#if GALLIVM_USE_NEW_PASS == 0 117bf215546Sopenharmony_ci assert(!gallivm->passmgr); 118bf215546Sopenharmony_ci assert(gallivm->target); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci gallivm->passmgr = LLVMCreateFunctionPassManagerForModule(gallivm->module); 121bf215546Sopenharmony_ci if (!gallivm->passmgr) 122bf215546Sopenharmony_ci return FALSE; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 125bf215546Sopenharmony_ci gallivm->cgpassmgr = LLVMCreatePassManager(); 126bf215546Sopenharmony_ci#endif 127bf215546Sopenharmony_ci /* 128bf215546Sopenharmony_ci * TODO: some per module pass manager with IPO passes might be helpful - 129bf215546Sopenharmony_ci * the generated texture functions may benefit from inlining if they are 130bf215546Sopenharmony_ci * simple, or constant propagation into them, etc. 131bf215546Sopenharmony_ci */ 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci { 134bf215546Sopenharmony_ci char *td_str; 135bf215546Sopenharmony_ci // New ones from the Module. 136bf215546Sopenharmony_ci td_str = LLVMCopyStringRepOfTargetData(gallivm->target); 137bf215546Sopenharmony_ci LLVMSetDataLayout(gallivm->module, td_str); 138bf215546Sopenharmony_ci free(td_str); 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 142bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR <= 8 && (defined(PIPE_ARCH_AARCH64) || defined (PIPE_ARCH_ARM) || defined(PIPE_ARCH_S390) || defined(PIPE_ARCH_MIPS64)) 143bf215546Sopenharmony_ci LLVMAddArgumentPromotionPass(gallivm->cgpassmgr); 144bf215546Sopenharmony_ci LLVMAddFunctionAttrsPass(gallivm->cgpassmgr); 145bf215546Sopenharmony_ci#endif 146bf215546Sopenharmony_ci LLVMAddCoroEarlyPass(gallivm->cgpassmgr); 147bf215546Sopenharmony_ci LLVMAddCoroSplitPass(gallivm->cgpassmgr); 148bf215546Sopenharmony_ci LLVMAddCoroElidePass(gallivm->cgpassmgr); 149bf215546Sopenharmony_ci#endif 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if ((gallivm_perf & GALLIVM_PERF_NO_OPT) == 0) { 152bf215546Sopenharmony_ci /* 153bf215546Sopenharmony_ci * TODO: Evaluate passes some more - keeping in mind 154bf215546Sopenharmony_ci * both quality of generated code and compile times. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_ci /* 157bf215546Sopenharmony_ci * NOTE: if you change this, don't forget to change the output 158bf215546Sopenharmony_ci * with GALLIVM_DEBUG_DUMP_BC in gallivm_compile_module. 159bf215546Sopenharmony_ci */ 160bf215546Sopenharmony_ci LLVMAddScalarReplAggregatesPass(gallivm->passmgr); 161bf215546Sopenharmony_ci LLVMAddEarlyCSEPass(gallivm->passmgr); 162bf215546Sopenharmony_ci LLVMAddCFGSimplificationPass(gallivm->passmgr); 163bf215546Sopenharmony_ci /* 164bf215546Sopenharmony_ci * FIXME: LICM is potentially quite useful. However, for some 165bf215546Sopenharmony_ci * rather crazy shaders the compile time can reach _hours_ per shader, 166bf215546Sopenharmony_ci * due to licm implying lcssa (since llvm 3.5), which can take forever. 167bf215546Sopenharmony_ci * Even for sane shaders, the cost of licm is rather high (and not just 168bf215546Sopenharmony_ci * due to lcssa, licm itself too), though mostly only in cases when it 169bf215546Sopenharmony_ci * can actually move things, so having to disable it is a pity. 170bf215546Sopenharmony_ci * LLVMAddLICMPass(gallivm->passmgr); 171bf215546Sopenharmony_ci */ 172bf215546Sopenharmony_ci LLVMAddReassociatePass(gallivm->passmgr); 173bf215546Sopenharmony_ci LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr); 174bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR <= 11 175bf215546Sopenharmony_ci LLVMAddConstantPropagationPass(gallivm->passmgr); 176bf215546Sopenharmony_ci#else 177bf215546Sopenharmony_ci LLVMAddInstructionSimplifyPass(gallivm->passmgr); 178bf215546Sopenharmony_ci#endif 179bf215546Sopenharmony_ci LLVMAddInstructionCombiningPass(gallivm->passmgr); 180bf215546Sopenharmony_ci LLVMAddGVNPass(gallivm->passmgr); 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci else { 183bf215546Sopenharmony_ci /* We need at least this pass to prevent the backends to fail in 184bf215546Sopenharmony_ci * unexpected ways. 185bf215546Sopenharmony_ci */ 186bf215546Sopenharmony_ci LLVMAddPromoteMemoryToRegisterPass(gallivm->passmgr); 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 189bf215546Sopenharmony_ci LLVMAddCoroCleanupPass(gallivm->passmgr); 190bf215546Sopenharmony_ci#endif 191bf215546Sopenharmony_ci#endif 192bf215546Sopenharmony_ci return TRUE; 193bf215546Sopenharmony_ci} 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci/** 196bf215546Sopenharmony_ci * Free gallivm object's LLVM allocations, but not any generated code 197bf215546Sopenharmony_ci * nor the gallivm object itself. 198bf215546Sopenharmony_ci */ 199bf215546Sopenharmony_civoid 200bf215546Sopenharmony_cigallivm_free_ir(struct gallivm_state *gallivm) 201bf215546Sopenharmony_ci{ 202bf215546Sopenharmony_ci#if GALLIVM_USE_NEW_PASS == 0 203bf215546Sopenharmony_ci if (gallivm->passmgr) { 204bf215546Sopenharmony_ci LLVMDisposePassManager(gallivm->passmgr); 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 208bf215546Sopenharmony_ci if (gallivm->cgpassmgr) { 209bf215546Sopenharmony_ci LLVMDisposePassManager(gallivm->cgpassmgr); 210bf215546Sopenharmony_ci } 211bf215546Sopenharmony_ci#endif 212bf215546Sopenharmony_ci#endif 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci if (gallivm->engine) { 215bf215546Sopenharmony_ci /* This will already destroy any associated module */ 216bf215546Sopenharmony_ci LLVMDisposeExecutionEngine(gallivm->engine); 217bf215546Sopenharmony_ci } else if (gallivm->module) { 218bf215546Sopenharmony_ci LLVMDisposeModule(gallivm->module); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci if (gallivm->cache) { 222bf215546Sopenharmony_ci lp_free_objcache(gallivm->cache->jit_obj_cache); 223bf215546Sopenharmony_ci free(gallivm->cache->data); 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci FREE(gallivm->module_name); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci if (gallivm->target) { 228bf215546Sopenharmony_ci LLVMDisposeTargetData(gallivm->target); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (gallivm->builder) 232bf215546Sopenharmony_ci LLVMDisposeBuilder(gallivm->builder); 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /* The LLVMContext should be owned by the parent of gallivm. */ 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci gallivm->engine = NULL; 237bf215546Sopenharmony_ci gallivm->target = NULL; 238bf215546Sopenharmony_ci gallivm->module = NULL; 239bf215546Sopenharmony_ci gallivm->module_name = NULL; 240bf215546Sopenharmony_ci#if GALLIVM_USE_NEW_PASS == 0 241bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 242bf215546Sopenharmony_ci gallivm->cgpassmgr = NULL; 243bf215546Sopenharmony_ci#endif 244bf215546Sopenharmony_ci gallivm->passmgr = NULL; 245bf215546Sopenharmony_ci#endif 246bf215546Sopenharmony_ci gallivm->context = NULL; 247bf215546Sopenharmony_ci gallivm->builder = NULL; 248bf215546Sopenharmony_ci gallivm->cache = NULL; 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci/** 253bf215546Sopenharmony_ci * Free LLVM-generated code. Should be done AFTER gallivm_free_ir(). 254bf215546Sopenharmony_ci */ 255bf215546Sopenharmony_cistatic void 256bf215546Sopenharmony_cigallivm_free_code(struct gallivm_state *gallivm) 257bf215546Sopenharmony_ci{ 258bf215546Sopenharmony_ci assert(!gallivm->module); 259bf215546Sopenharmony_ci assert(!gallivm->engine); 260bf215546Sopenharmony_ci lp_free_generated_code(gallivm->code); 261bf215546Sopenharmony_ci gallivm->code = NULL; 262bf215546Sopenharmony_ci lp_free_memory_manager(gallivm->memorymgr); 263bf215546Sopenharmony_ci gallivm->memorymgr = NULL; 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_cistatic boolean 268bf215546Sopenharmony_ciinit_gallivm_engine(struct gallivm_state *gallivm) 269bf215546Sopenharmony_ci{ 270bf215546Sopenharmony_ci if (1) { 271bf215546Sopenharmony_ci enum LLVM_CodeGenOpt_Level optlevel; 272bf215546Sopenharmony_ci char *error = NULL; 273bf215546Sopenharmony_ci int ret; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci if (gallivm_perf & GALLIVM_PERF_NO_OPT) { 276bf215546Sopenharmony_ci optlevel = None; 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci else { 279bf215546Sopenharmony_ci optlevel = Default; 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci ret = lp_build_create_jit_compiler_for_module(&gallivm->engine, 283bf215546Sopenharmony_ci &gallivm->code, 284bf215546Sopenharmony_ci gallivm->cache, 285bf215546Sopenharmony_ci gallivm->module, 286bf215546Sopenharmony_ci gallivm->memorymgr, 287bf215546Sopenharmony_ci (unsigned) optlevel, 288bf215546Sopenharmony_ci &error); 289bf215546Sopenharmony_ci if (ret) { 290bf215546Sopenharmony_ci _debug_printf("%s\n", error); 291bf215546Sopenharmony_ci LLVMDisposeMessage(error); 292bf215546Sopenharmony_ci goto fail; 293bf215546Sopenharmony_ci } 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci if (0) { 297bf215546Sopenharmony_ci /* 298bf215546Sopenharmony_ci * Dump the data layout strings. 299bf215546Sopenharmony_ci */ 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci LLVMTargetDataRef target = LLVMGetExecutionEngineTargetData(gallivm->engine); 302bf215546Sopenharmony_ci char *data_layout; 303bf215546Sopenharmony_ci char *engine_data_layout; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci data_layout = LLVMCopyStringRepOfTargetData(gallivm->target); 306bf215546Sopenharmony_ci engine_data_layout = LLVMCopyStringRepOfTargetData(target); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (1) { 309bf215546Sopenharmony_ci debug_printf("module target data = %s\n", data_layout); 310bf215546Sopenharmony_ci debug_printf("engine target data = %s\n", engine_data_layout); 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci free(data_layout); 314bf215546Sopenharmony_ci free(engine_data_layout); 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci return TRUE; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_cifail: 320bf215546Sopenharmony_ci return FALSE; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci/** 325bf215546Sopenharmony_ci * Allocate gallivm LLVM objects. 326bf215546Sopenharmony_ci * \return TRUE for success, FALSE for failure 327bf215546Sopenharmony_ci */ 328bf215546Sopenharmony_cistatic boolean 329bf215546Sopenharmony_ciinit_gallivm_state(struct gallivm_state *gallivm, const char *name, 330bf215546Sopenharmony_ci LLVMContextRef context, struct lp_cached_code *cache) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci assert(!gallivm->context); 333bf215546Sopenharmony_ci assert(!gallivm->module); 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci if (!lp_build_init()) 336bf215546Sopenharmony_ci return FALSE; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci gallivm->context = context; 339bf215546Sopenharmony_ci gallivm->cache = cache; 340bf215546Sopenharmony_ci if (!gallivm->context) 341bf215546Sopenharmony_ci goto fail; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci gallivm->module_name = NULL; 344bf215546Sopenharmony_ci if (name) { 345bf215546Sopenharmony_ci size_t size = strlen(name) + 1; 346bf215546Sopenharmony_ci gallivm->module_name = MALLOC(size); 347bf215546Sopenharmony_ci if (gallivm->module_name) { 348bf215546Sopenharmony_ci memcpy(gallivm->module_name, name, size); 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci gallivm->module = LLVMModuleCreateWithNameInContext(name, 353bf215546Sopenharmony_ci gallivm->context); 354bf215546Sopenharmony_ci if (!gallivm->module) 355bf215546Sopenharmony_ci goto fail; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci#if defined(PIPE_ARCH_X86) 358bf215546Sopenharmony_ci lp_set_module_stack_alignment_override(gallivm->module, 4); 359bf215546Sopenharmony_ci#endif 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci gallivm->builder = LLVMCreateBuilderInContext(gallivm->context); 362bf215546Sopenharmony_ci if (!gallivm->builder) 363bf215546Sopenharmony_ci goto fail; 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci gallivm->memorymgr = lp_get_default_memory_manager(); 366bf215546Sopenharmony_ci if (!gallivm->memorymgr) 367bf215546Sopenharmony_ci goto fail; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci /* FIXME: MC-JIT only allows compiling one module at a time, and it must be 370bf215546Sopenharmony_ci * complete when MC-JIT is created. So defer the MC-JIT engine creation for 371bf215546Sopenharmony_ci * now. 372bf215546Sopenharmony_ci */ 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci /* 375bf215546Sopenharmony_ci * MC-JIT engine compiles the module immediately on creation, so we can't 376bf215546Sopenharmony_ci * obtain the target data from it. Instead we create a target data layout 377bf215546Sopenharmony_ci * from a string. 378bf215546Sopenharmony_ci * 379bf215546Sopenharmony_ci * The produced layout strings are not precisely the same, but should make 380bf215546Sopenharmony_ci * no difference for the kind of optimization passes we run. 381bf215546Sopenharmony_ci * 382bf215546Sopenharmony_ci * For reference this is the layout string on x64: 383bf215546Sopenharmony_ci * 384bf215546Sopenharmony_ci * e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64 385bf215546Sopenharmony_ci * 386bf215546Sopenharmony_ci * See also: 387bf215546Sopenharmony_ci * - http://llvm.org/docs/LangRef.html#datalayout 388bf215546Sopenharmony_ci */ 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci { 391bf215546Sopenharmony_ci const unsigned pointer_size = 8 * sizeof(void *); 392bf215546Sopenharmony_ci char layout[512]; 393bf215546Sopenharmony_ci snprintf(layout, sizeof layout, "%c-p:%u:%u:%u-i64:64:64-a0:0:%u-s0:%u:%u", 394bf215546Sopenharmony_ci#if UTIL_ARCH_LITTLE_ENDIAN 395bf215546Sopenharmony_ci 'e', // little endian 396bf215546Sopenharmony_ci#else 397bf215546Sopenharmony_ci 'E', // big endian 398bf215546Sopenharmony_ci#endif 399bf215546Sopenharmony_ci pointer_size, pointer_size, pointer_size, // pointer size, abi alignment, preferred alignment 400bf215546Sopenharmony_ci pointer_size, // aggregate preferred alignment 401bf215546Sopenharmony_ci pointer_size, pointer_size); // stack objects abi alignment, preferred alignment 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci gallivm->target = LLVMCreateTargetData(layout); 404bf215546Sopenharmony_ci if (!gallivm->target) { 405bf215546Sopenharmony_ci return FALSE; 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci } 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci if (!create_pass_manager(gallivm)) 410bf215546Sopenharmony_ci goto fail; 411bf215546Sopenharmony_ci 412bf215546Sopenharmony_ci lp_build_coro_declare_malloc_hooks(gallivm); 413bf215546Sopenharmony_ci return TRUE; 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_cifail: 416bf215546Sopenharmony_ci gallivm_free_ir(gallivm); 417bf215546Sopenharmony_ci gallivm_free_code(gallivm); 418bf215546Sopenharmony_ci return FALSE; 419bf215546Sopenharmony_ci} 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ciboolean 423bf215546Sopenharmony_cilp_build_init(void) 424bf215546Sopenharmony_ci{ 425bf215546Sopenharmony_ci if (gallivm_initialized) 426bf215546Sopenharmony_ci return TRUE; 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci /* LLVMLinkIn* are no-ops at runtime. They just ensure the respective 430bf215546Sopenharmony_ci * component is linked at buildtime, which is sufficient for its static 431bf215546Sopenharmony_ci * constructors to be called at load time. 432bf215546Sopenharmony_ci */ 433bf215546Sopenharmony_ci LLVMLinkInMCJIT(); 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci#ifdef DEBUG 436bf215546Sopenharmony_ci gallivm_debug = debug_get_option_gallivm_debug(); 437bf215546Sopenharmony_ci#endif 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci gallivm_perf = debug_get_flags_option("GALLIVM_PERF", lp_bld_perf_flags, 0 ); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci lp_set_target_options(); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* For simulating less capable machines */ 444bf215546Sopenharmony_ci#ifdef DEBUG 445bf215546Sopenharmony_ci if (debug_get_bool_option("LP_FORCE_SSE2", FALSE)) { 446bf215546Sopenharmony_ci extern struct util_cpu_caps_t util_cpu_caps; 447bf215546Sopenharmony_ci assert(util_cpu_caps.has_sse2); 448bf215546Sopenharmony_ci util_cpu_caps.has_sse3 = 0; 449bf215546Sopenharmony_ci util_cpu_caps.has_ssse3 = 0; 450bf215546Sopenharmony_ci util_cpu_caps.has_sse4_1 = 0; 451bf215546Sopenharmony_ci util_cpu_caps.has_sse4_2 = 0; 452bf215546Sopenharmony_ci util_cpu_caps.has_avx = 0; 453bf215546Sopenharmony_ci util_cpu_caps.has_avx2 = 0; 454bf215546Sopenharmony_ci util_cpu_caps.has_f16c = 0; 455bf215546Sopenharmony_ci util_cpu_caps.has_fma = 0; 456bf215546Sopenharmony_ci } 457bf215546Sopenharmony_ci#endif 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci if (util_get_cpu_caps()->has_avx2 || util_get_cpu_caps()->has_avx) { 460bf215546Sopenharmony_ci lp_native_vector_width = 256; 461bf215546Sopenharmony_ci } else { 462bf215546Sopenharmony_ci /* Leave it at 128, even when no SIMD extensions are available. 463bf215546Sopenharmony_ci * Really needs to be a multiple of 128 so can fit 4 floats. 464bf215546Sopenharmony_ci */ 465bf215546Sopenharmony_ci lp_native_vector_width = 128; 466bf215546Sopenharmony_ci } 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci lp_native_vector_width = debug_get_num_option("LP_NATIVE_VECTOR_WIDTH", 469bf215546Sopenharmony_ci lp_native_vector_width); 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR < 4 472bf215546Sopenharmony_ci if (lp_native_vector_width <= 128) { 473bf215546Sopenharmony_ci /* Hide AVX support, as often LLVM AVX intrinsics are only guarded by 474bf215546Sopenharmony_ci * "util_get_cpu_caps()->has_avx" predicate, and lack the 475bf215546Sopenharmony_ci * "lp_native_vector_width > 128" predicate. And also to ensure a more 476bf215546Sopenharmony_ci * consistent behavior, allowing one to test SSE2 on AVX machines. 477bf215546Sopenharmony_ci * XXX: should not play games with util_cpu_caps directly as it might 478bf215546Sopenharmony_ci * get used for other things outside llvm too. 479bf215546Sopenharmony_ci */ 480bf215546Sopenharmony_ci util_get_cpu_caps()->has_avx = 0; 481bf215546Sopenharmony_ci util_get_cpu_caps()->has_avx2 = 0; 482bf215546Sopenharmony_ci util_get_cpu_caps()->has_f16c = 0; 483bf215546Sopenharmony_ci util_get_cpu_caps()->has_fma = 0; 484bf215546Sopenharmony_ci } 485bf215546Sopenharmony_ci#endif 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci#ifdef PIPE_ARCH_PPC_64 488bf215546Sopenharmony_ci /* Set the NJ bit in VSCR to 0 so denormalized values are handled as 489bf215546Sopenharmony_ci * specified by IEEE standard (PowerISA 2.06 - Section 6.3). This guarantees 490bf215546Sopenharmony_ci * that some rounding and half-float to float handling does not round 491bf215546Sopenharmony_ci * incorrectly to 0. 492bf215546Sopenharmony_ci * XXX: should eventually follow same logic on all platforms. 493bf215546Sopenharmony_ci * Right now denorms get explicitly disabled (but elsewhere) for x86, 494bf215546Sopenharmony_ci * whereas ppc64 explicitly enables them... 495bf215546Sopenharmony_ci */ 496bf215546Sopenharmony_ci if (util_get_cpu_caps()->has_altivec) { 497bf215546Sopenharmony_ci unsigned short mask[] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 498bf215546Sopenharmony_ci 0xFFFF, 0xFFFF, 0xFFFE, 0xFFFF }; 499bf215546Sopenharmony_ci __asm ( 500bf215546Sopenharmony_ci "mfvscr %%v1\n" 501bf215546Sopenharmony_ci "vand %0,%%v1,%0\n" 502bf215546Sopenharmony_ci "mtvscr %0" 503bf215546Sopenharmony_ci : 504bf215546Sopenharmony_ci : "r" (*mask) 505bf215546Sopenharmony_ci ); 506bf215546Sopenharmony_ci } 507bf215546Sopenharmony_ci#endif 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci gallivm_initialized = TRUE; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci return TRUE; 512bf215546Sopenharmony_ci} 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci/** 517bf215546Sopenharmony_ci * Create a new gallivm_state object. 518bf215546Sopenharmony_ci */ 519bf215546Sopenharmony_cistruct gallivm_state * 520bf215546Sopenharmony_cigallivm_create(const char *name, LLVMContextRef context, 521bf215546Sopenharmony_ci struct lp_cached_code *cache) 522bf215546Sopenharmony_ci{ 523bf215546Sopenharmony_ci struct gallivm_state *gallivm; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci gallivm = CALLOC_STRUCT(gallivm_state); 526bf215546Sopenharmony_ci if (gallivm) { 527bf215546Sopenharmony_ci if (!init_gallivm_state(gallivm, name, context, cache)) { 528bf215546Sopenharmony_ci FREE(gallivm); 529bf215546Sopenharmony_ci gallivm = NULL; 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci } 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci assert(gallivm != NULL); 534bf215546Sopenharmony_ci return gallivm; 535bf215546Sopenharmony_ci} 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci/** 539bf215546Sopenharmony_ci * Destroy a gallivm_state object. 540bf215546Sopenharmony_ci */ 541bf215546Sopenharmony_civoid 542bf215546Sopenharmony_cigallivm_destroy(struct gallivm_state *gallivm) 543bf215546Sopenharmony_ci{ 544bf215546Sopenharmony_ci gallivm_free_ir(gallivm); 545bf215546Sopenharmony_ci gallivm_free_code(gallivm); 546bf215546Sopenharmony_ci FREE(gallivm); 547bf215546Sopenharmony_ci} 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci/** 551bf215546Sopenharmony_ci * Validate a function. 552bf215546Sopenharmony_ci * Verification is only done with debug builds. 553bf215546Sopenharmony_ci */ 554bf215546Sopenharmony_civoid 555bf215546Sopenharmony_cigallivm_verify_function(struct gallivm_state *gallivm, 556bf215546Sopenharmony_ci LLVMValueRef func) 557bf215546Sopenharmony_ci{ 558bf215546Sopenharmony_ci /* Verify the LLVM IR. If invalid, dump and abort */ 559bf215546Sopenharmony_ci#ifdef DEBUG 560bf215546Sopenharmony_ci if (LLVMVerifyFunction(func, LLVMPrintMessageAction)) { 561bf215546Sopenharmony_ci lp_debug_dump_value(func); 562bf215546Sopenharmony_ci assert(0); 563bf215546Sopenharmony_ci return; 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci#endif 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_IR) { 568bf215546Sopenharmony_ci /* Print the LLVM IR to stderr */ 569bf215546Sopenharmony_ci lp_debug_dump_value(func); 570bf215546Sopenharmony_ci debug_printf("\n"); 571bf215546Sopenharmony_ci } 572bf215546Sopenharmony_ci} 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci/** 576bf215546Sopenharmony_ci * Compile a module. 577bf215546Sopenharmony_ci * This does IR optimization on all functions in the module. 578bf215546Sopenharmony_ci */ 579bf215546Sopenharmony_civoid 580bf215546Sopenharmony_cigallivm_compile_module(struct gallivm_state *gallivm) 581bf215546Sopenharmony_ci{ 582bf215546Sopenharmony_ci int64_t time_begin = 0; 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci assert(!gallivm->compiled); 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci if (gallivm->builder) { 587bf215546Sopenharmony_ci LLVMDisposeBuilder(gallivm->builder); 588bf215546Sopenharmony_ci gallivm->builder = NULL; 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci LLVMSetDataLayout(gallivm->module, ""); 592bf215546Sopenharmony_ci assert(!gallivm->engine); 593bf215546Sopenharmony_ci if (!init_gallivm_engine(gallivm)) { 594bf215546Sopenharmony_ci assert(0); 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci assert(gallivm->engine); 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci if (gallivm->cache && gallivm->cache->data_size) { 599bf215546Sopenharmony_ci goto skip_cached; 600bf215546Sopenharmony_ci } 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci /* Dump bitcode to a file */ 603bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_DUMP_BC) { 604bf215546Sopenharmony_ci char filename[256]; 605bf215546Sopenharmony_ci assert(gallivm->module_name); 606bf215546Sopenharmony_ci snprintf(filename, sizeof(filename), "ir_%s.bc", gallivm->module_name); 607bf215546Sopenharmony_ci LLVMWriteBitcodeToFile(gallivm->module, filename); 608bf215546Sopenharmony_ci debug_printf("%s written\n", filename); 609bf215546Sopenharmony_ci debug_printf("Invoke as \"opt %s %s | llc -O%d %s%s\"\n", 610bf215546Sopenharmony_ci gallivm_perf & GALLIVM_PERF_NO_OPT ? "-mem2reg" : 611bf215546Sopenharmony_ci "-sroa -early-cse -simplifycfg -reassociate " 612bf215546Sopenharmony_ci "-mem2reg -constprop -instcombine -gvn", 613bf215546Sopenharmony_ci filename, gallivm_perf & GALLIVM_PERF_NO_OPT ? 0 : 2, 614bf215546Sopenharmony_ci "[-mcpu=<-mcpu option>] ", 615bf215546Sopenharmony_ci "[-mattr=<-mattr option(s)>]"); 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_PERF) 619bf215546Sopenharmony_ci time_begin = os_time_get(); 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci#if GALLIVM_USE_NEW_PASS == 1 622bf215546Sopenharmony_ci char passes[1024]; 623bf215546Sopenharmony_ci passes[0] = 0; 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci /* 626bf215546Sopenharmony_ci * there should be some way to combine these two pass runs but I'm not seeing it, 627bf215546Sopenharmony_ci * at the time of writing. 628bf215546Sopenharmony_ci */ 629bf215546Sopenharmony_ci strcpy(passes, "default<O0>"); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci LLVMPassBuilderOptionsRef opts = LLVMCreatePassBuilderOptions(); 632bf215546Sopenharmony_ci LLVMRunPasses(gallivm->module, passes, LLVMGetExecutionEngineTargetMachine(gallivm->engine), opts); 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci if (!(gallivm_perf & GALLIVM_PERF_NO_OPT)) 635bf215546Sopenharmony_ci strcpy(passes, "sroa,early-cse,simplifycfg,reassociate,mem2reg,instsimplify,instcombine"); 636bf215546Sopenharmony_ci else 637bf215546Sopenharmony_ci strcpy(passes, "mem2reg"); 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci LLVMRunPasses(gallivm->module, passes, LLVMGetExecutionEngineTargetMachine(gallivm->engine), opts); 640bf215546Sopenharmony_ci LLVMDisposePassBuilderOptions(opts); 641bf215546Sopenharmony_ci#else 642bf215546Sopenharmony_ci#if GALLIVM_HAVE_CORO == 1 643bf215546Sopenharmony_ci LLVMRunPassManager(gallivm->cgpassmgr, gallivm->module); 644bf215546Sopenharmony_ci#endif 645bf215546Sopenharmony_ci /* Run optimization passes */ 646bf215546Sopenharmony_ci LLVMInitializeFunctionPassManager(gallivm->passmgr); 647bf215546Sopenharmony_ci LLVMValueRef func; 648bf215546Sopenharmony_ci func = LLVMGetFirstFunction(gallivm->module); 649bf215546Sopenharmony_ci while (func) { 650bf215546Sopenharmony_ci if (0) { 651bf215546Sopenharmony_ci debug_printf("optimizing func %s...\n", LLVMGetValueName(func)); 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci /* Disable frame pointer omission on debug/profile builds */ 655bf215546Sopenharmony_ci /* XXX: And workaround http://llvm.org/PR21435 */ 656bf215546Sopenharmony_ci#if defined(DEBUG) || defined(PROFILE) || defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) 657bf215546Sopenharmony_ci LLVMAddTargetDependentFunctionAttr(func, "no-frame-pointer-elim", "true"); 658bf215546Sopenharmony_ci LLVMAddTargetDependentFunctionAttr(func, "no-frame-pointer-elim-non-leaf", "true"); 659bf215546Sopenharmony_ci#endif 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci LLVMRunFunctionPassManager(gallivm->passmgr, func); 662bf215546Sopenharmony_ci func = LLVMGetNextFunction(func); 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci LLVMFinalizeFunctionPassManager(gallivm->passmgr); 665bf215546Sopenharmony_ci#endif 666bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_PERF) { 667bf215546Sopenharmony_ci int64_t time_end = os_time_get(); 668bf215546Sopenharmony_ci int time_msec = (int)((time_end - time_begin) / 1000); 669bf215546Sopenharmony_ci assert(gallivm->module_name); 670bf215546Sopenharmony_ci debug_printf("optimizing module %s took %d msec\n", 671bf215546Sopenharmony_ci gallivm->module_name, time_msec); 672bf215546Sopenharmony_ci } 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci /* Setting the module's DataLayout to an empty string will cause the 675bf215546Sopenharmony_ci * ExecutionEngine to copy to the DataLayout string from its target machine 676bf215546Sopenharmony_ci * to the module. As of LLVM 3.8 the module and the execution engine are 677bf215546Sopenharmony_ci * required to have the same DataLayout. 678bf215546Sopenharmony_ci * 679bf215546Sopenharmony_ci * We must make sure we do this after running the optimization passes, 680bf215546Sopenharmony_ci * because those passes need a correct datalayout string. For example, if 681bf215546Sopenharmony_ci * those optimization passes see an empty datalayout, they will assume this 682bf215546Sopenharmony_ci * is a little endian target and will do optimizations that break big endian 683bf215546Sopenharmony_ci * machines. 684bf215546Sopenharmony_ci * 685bf215546Sopenharmony_ci * TODO: This is just a temporary work-around. The correct solution is for 686bf215546Sopenharmony_ci * gallivm_init_state() to create a TargetMachine and pull the DataLayout 687bf215546Sopenharmony_ci * from there. Currently, the TargetMachine used by llvmpipe is being 688bf215546Sopenharmony_ci * implicitly created by the EngineBuilder in 689bf215546Sopenharmony_ci * lp_build_create_jit_compiler_for_module() 690bf215546Sopenharmony_ci */ 691bf215546Sopenharmony_ci skip_cached: 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci ++gallivm->compiled; 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci lp_init_printf_hook(gallivm); 696bf215546Sopenharmony_ci LLVMAddGlobalMapping(gallivm->engine, gallivm->debug_printf_hook, debug_printf); 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci lp_build_coro_add_malloc_hooks(gallivm); 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_ASM) { 702bf215546Sopenharmony_ci LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module); 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_ci while (llvm_func) { 705bf215546Sopenharmony_ci /* 706bf215546Sopenharmony_ci * Need to filter out functions which don't have an implementation, 707bf215546Sopenharmony_ci * such as the intrinsics. May not be sufficient in case of IPO? 708bf215546Sopenharmony_ci * LLVMGetPointerToGlobal() will abort otherwise. 709bf215546Sopenharmony_ci */ 710bf215546Sopenharmony_ci if (!LLVMIsDeclaration(llvm_func)) { 711bf215546Sopenharmony_ci void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func); 712bf215546Sopenharmony_ci lp_disassemble(llvm_func, func_code); 713bf215546Sopenharmony_ci } 714bf215546Sopenharmony_ci llvm_func = LLVMGetNextFunction(llvm_func); 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci } 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci#if defined(PROFILE) 719bf215546Sopenharmony_ci { 720bf215546Sopenharmony_ci LLVMValueRef llvm_func = LLVMGetFirstFunction(gallivm->module); 721bf215546Sopenharmony_ci 722bf215546Sopenharmony_ci while (llvm_func) { 723bf215546Sopenharmony_ci if (!LLVMIsDeclaration(llvm_func)) { 724bf215546Sopenharmony_ci void *func_code = LLVMGetPointerToGlobal(gallivm->engine, llvm_func); 725bf215546Sopenharmony_ci lp_profile(llvm_func, func_code); 726bf215546Sopenharmony_ci } 727bf215546Sopenharmony_ci llvm_func = LLVMGetNextFunction(llvm_func); 728bf215546Sopenharmony_ci } 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci#endif 731bf215546Sopenharmony_ci} 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_cifunc_pointer 736bf215546Sopenharmony_cigallivm_jit_function(struct gallivm_state *gallivm, 737bf215546Sopenharmony_ci LLVMValueRef func) 738bf215546Sopenharmony_ci{ 739bf215546Sopenharmony_ci void *code; 740bf215546Sopenharmony_ci func_pointer jit_func; 741bf215546Sopenharmony_ci int64_t time_begin = 0; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci assert(gallivm->compiled); 744bf215546Sopenharmony_ci assert(gallivm->engine); 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_PERF) 747bf215546Sopenharmony_ci time_begin = os_time_get(); 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci code = LLVMGetPointerToGlobal(gallivm->engine, func); 750bf215546Sopenharmony_ci assert(code); 751bf215546Sopenharmony_ci jit_func = pointer_to_func(code); 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci if (gallivm_debug & GALLIVM_DEBUG_PERF) { 754bf215546Sopenharmony_ci int64_t time_end = os_time_get(); 755bf215546Sopenharmony_ci int time_msec = (int)(time_end - time_begin) / 1000; 756bf215546Sopenharmony_ci debug_printf(" jitting func %s took %d msec\n", 757bf215546Sopenharmony_ci LLVMGetValueName(func), time_msec); 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci return jit_func; 761bf215546Sopenharmony_ci} 762bf215546Sopenharmony_ci 763bf215546Sopenharmony_ciunsigned gallivm_get_perf_flags(void) 764bf215546Sopenharmony_ci{ 765bf215546Sopenharmony_ci return gallivm_perf; 766bf215546Sopenharmony_ci} 767