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