1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2014 Advanced Micro Devices, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
6bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
7bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
8bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
9bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
10bf215546Sopenharmony_ci * the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15bf215546Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
19bf215546Sopenharmony_ci *
20bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
21bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
22bf215546Sopenharmony_ci * of the Software.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci */
25bf215546Sopenharmony_ci/* based on pieces from si_pipe.c and radeon_llvm_emit.c */
26bf215546Sopenharmony_ci#include "ac_llvm_util.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "ac_llvm_build.h"
29bf215546Sopenharmony_ci#include "c11/threads.h"
30bf215546Sopenharmony_ci#include "util/bitscan.h"
31bf215546Sopenharmony_ci#include "util/u_math.h"
32bf215546Sopenharmony_ci#include <llvm-c/Core.h>
33bf215546Sopenharmony_ci#include <llvm-c/Support.h>
34bf215546Sopenharmony_ci#include <llvm-c/Transforms/IPO.h>
35bf215546Sopenharmony_ci#include <llvm-c/Transforms/Scalar.h>
36bf215546Sopenharmony_ci#include <llvm-c/Transforms/Utils.h>
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include <assert.h>
39bf215546Sopenharmony_ci#include <stdio.h>
40bf215546Sopenharmony_ci#include <string.h>
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic void ac_init_llvm_target(void)
43bf215546Sopenharmony_ci{
44bf215546Sopenharmony_ci   LLVMInitializeAMDGPUTargetInfo();
45bf215546Sopenharmony_ci   LLVMInitializeAMDGPUTarget();
46bf215546Sopenharmony_ci   LLVMInitializeAMDGPUTargetMC();
47bf215546Sopenharmony_ci   LLVMInitializeAMDGPUAsmPrinter();
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   /* For inline assembly. */
50bf215546Sopenharmony_ci   LLVMInitializeAMDGPUAsmParser();
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   /* For ACO disassembly. */
53bf215546Sopenharmony_ci   LLVMInitializeAMDGPUDisassembler();
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   const char *argv[] = {
56bf215546Sopenharmony_ci      /* error messages prefix */
57bf215546Sopenharmony_ci      "mesa",
58bf215546Sopenharmony_ci      "-amdgpu-atomic-optimizations=true",
59bf215546Sopenharmony_ci#if LLVM_VERSION_MAJOR == 11
60bf215546Sopenharmony_ci      /* This fixes variable indexing on LLVM 11. It also breaks atomic.cmpswap on LLVM >= 12. */
61bf215546Sopenharmony_ci      "-structurizecfg-skip-uniform-regions",
62bf215546Sopenharmony_ci#endif
63bf215546Sopenharmony_ci   };
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   ac_reset_llvm_all_options_occurences();
66bf215546Sopenharmony_ci   LLVMParseCommandLineOptions(ARRAY_SIZE(argv), argv, NULL);
67bf215546Sopenharmony_ci}
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ciPUBLIC void ac_init_shared_llvm_once(void)
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   static once_flag ac_init_llvm_target_once_flag = ONCE_FLAG_INIT;
72bf215546Sopenharmony_ci   call_once(&ac_init_llvm_target_once_flag, ac_init_llvm_target);
73bf215546Sopenharmony_ci}
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci#if !LLVM_IS_SHARED
76bf215546Sopenharmony_cistatic once_flag ac_init_static_llvm_target_once_flag = ONCE_FLAG_INIT;
77bf215546Sopenharmony_cistatic void ac_init_static_llvm_once(void)
78bf215546Sopenharmony_ci{
79bf215546Sopenharmony_ci   call_once(&ac_init_static_llvm_target_once_flag, ac_init_llvm_target);
80bf215546Sopenharmony_ci}
81bf215546Sopenharmony_ci#endif
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_civoid ac_init_llvm_once(void)
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci#if LLVM_IS_SHARED
86bf215546Sopenharmony_ci   ac_init_shared_llvm_once();
87bf215546Sopenharmony_ci#else
88bf215546Sopenharmony_ci   ac_init_static_llvm_once();
89bf215546Sopenharmony_ci#endif
90bf215546Sopenharmony_ci}
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ciLLVMTargetRef ac_get_llvm_target(const char *triple)
93bf215546Sopenharmony_ci{
94bf215546Sopenharmony_ci   LLVMTargetRef target = NULL;
95bf215546Sopenharmony_ci   char *err_message = NULL;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   if (LLVMGetTargetFromTriple(triple, &target, &err_message)) {
98bf215546Sopenharmony_ci      fprintf(stderr, "Cannot find target for triple %s ", triple);
99bf215546Sopenharmony_ci      if (err_message) {
100bf215546Sopenharmony_ci         fprintf(stderr, "%s\n", err_message);
101bf215546Sopenharmony_ci      }
102bf215546Sopenharmony_ci      LLVMDisposeMessage(err_message);
103bf215546Sopenharmony_ci      return NULL;
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci   return target;
106bf215546Sopenharmony_ci}
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ciconst char *ac_get_llvm_processor_name(enum radeon_family family)
109bf215546Sopenharmony_ci{
110bf215546Sopenharmony_ci   switch (family) {
111bf215546Sopenharmony_ci   case CHIP_TAHITI:
112bf215546Sopenharmony_ci      return "tahiti";
113bf215546Sopenharmony_ci   case CHIP_PITCAIRN:
114bf215546Sopenharmony_ci      return "pitcairn";
115bf215546Sopenharmony_ci   case CHIP_VERDE:
116bf215546Sopenharmony_ci      return "verde";
117bf215546Sopenharmony_ci   case CHIP_OLAND:
118bf215546Sopenharmony_ci      return "oland";
119bf215546Sopenharmony_ci   case CHIP_HAINAN:
120bf215546Sopenharmony_ci      return "hainan";
121bf215546Sopenharmony_ci   case CHIP_BONAIRE:
122bf215546Sopenharmony_ci      return "bonaire";
123bf215546Sopenharmony_ci   case CHIP_KABINI:
124bf215546Sopenharmony_ci      return "kabini";
125bf215546Sopenharmony_ci   case CHIP_KAVERI:
126bf215546Sopenharmony_ci      return "kaveri";
127bf215546Sopenharmony_ci   case CHIP_HAWAII:
128bf215546Sopenharmony_ci      return "hawaii";
129bf215546Sopenharmony_ci   case CHIP_TONGA:
130bf215546Sopenharmony_ci      return "tonga";
131bf215546Sopenharmony_ci   case CHIP_ICELAND:
132bf215546Sopenharmony_ci      return "iceland";
133bf215546Sopenharmony_ci   case CHIP_CARRIZO:
134bf215546Sopenharmony_ci      return "carrizo";
135bf215546Sopenharmony_ci   case CHIP_FIJI:
136bf215546Sopenharmony_ci      return "fiji";
137bf215546Sopenharmony_ci   case CHIP_STONEY:
138bf215546Sopenharmony_ci      return "stoney";
139bf215546Sopenharmony_ci   case CHIP_POLARIS10:
140bf215546Sopenharmony_ci      return "polaris10";
141bf215546Sopenharmony_ci   case CHIP_POLARIS11:
142bf215546Sopenharmony_ci   case CHIP_POLARIS12:
143bf215546Sopenharmony_ci   case CHIP_VEGAM:
144bf215546Sopenharmony_ci      return "polaris11";
145bf215546Sopenharmony_ci   case CHIP_VEGA10:
146bf215546Sopenharmony_ci      return "gfx900";
147bf215546Sopenharmony_ci   case CHIP_RAVEN:
148bf215546Sopenharmony_ci      return "gfx902";
149bf215546Sopenharmony_ci   case CHIP_VEGA12:
150bf215546Sopenharmony_ci      return "gfx904";
151bf215546Sopenharmony_ci   case CHIP_VEGA20:
152bf215546Sopenharmony_ci      return "gfx906";
153bf215546Sopenharmony_ci   case CHIP_RAVEN2:
154bf215546Sopenharmony_ci   case CHIP_RENOIR:
155bf215546Sopenharmony_ci      return "gfx909";
156bf215546Sopenharmony_ci   case CHIP_ARCTURUS:
157bf215546Sopenharmony_ci      return "gfx908";
158bf215546Sopenharmony_ci   case CHIP_ALDEBARAN:
159bf215546Sopenharmony_ci      return "gfx90a";
160bf215546Sopenharmony_ci   case CHIP_NAVI10:
161bf215546Sopenharmony_ci      return "gfx1010";
162bf215546Sopenharmony_ci   case CHIP_NAVI12:
163bf215546Sopenharmony_ci      return "gfx1011";
164bf215546Sopenharmony_ci   case CHIP_NAVI14:
165bf215546Sopenharmony_ci      return "gfx1012";
166bf215546Sopenharmony_ci   case CHIP_NAVI21:
167bf215546Sopenharmony_ci      return "gfx1030";
168bf215546Sopenharmony_ci   case CHIP_NAVI22:
169bf215546Sopenharmony_ci      return LLVM_VERSION_MAJOR >= 12 ? "gfx1031" : "gfx1030";
170bf215546Sopenharmony_ci   case CHIP_NAVI23:
171bf215546Sopenharmony_ci      return LLVM_VERSION_MAJOR >= 12 ? "gfx1032" : "gfx1030";
172bf215546Sopenharmony_ci   case CHIP_VANGOGH:
173bf215546Sopenharmony_ci      return LLVM_VERSION_MAJOR >= 12 ? "gfx1033" : "gfx1030";
174bf215546Sopenharmony_ci   case CHIP_NAVI24:
175bf215546Sopenharmony_ci      return LLVM_VERSION_MAJOR >= 13 ? "gfx1034" : "gfx1030";
176bf215546Sopenharmony_ci   case CHIP_REMBRANDT:
177bf215546Sopenharmony_ci      return LLVM_VERSION_MAJOR >= 13 ? "gfx1035" : "gfx1030";
178bf215546Sopenharmony_ci   case CHIP_GFX1036: /* TODO: LLVM 15 doesn't support this yet */
179bf215546Sopenharmony_ci      return "gfx1030";
180bf215546Sopenharmony_ci   case CHIP_GFX1100:
181bf215546Sopenharmony_ci      return "gfx1100";
182bf215546Sopenharmony_ci   case CHIP_GFX1101:
183bf215546Sopenharmony_ci      return "gfx1101";
184bf215546Sopenharmony_ci   case CHIP_GFX1102:
185bf215546Sopenharmony_ci      return "gfx1102";
186bf215546Sopenharmony_ci   case CHIP_GFX1103:
187bf215546Sopenharmony_ci      return "gfx1103";
188bf215546Sopenharmony_ci   default:
189bf215546Sopenharmony_ci      return "";
190bf215546Sopenharmony_ci   }
191bf215546Sopenharmony_ci}
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_cistatic LLVMTargetMachineRef ac_create_target_machine(enum radeon_family family,
194bf215546Sopenharmony_ci                                                     enum ac_target_machine_options tm_options,
195bf215546Sopenharmony_ci                                                     LLVMCodeGenOptLevel level,
196bf215546Sopenharmony_ci                                                     const char **out_triple)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   assert(family >= CHIP_TAHITI);
199bf215546Sopenharmony_ci   const char *triple = (tm_options & AC_TM_SUPPORTS_SPILL) ? "amdgcn-mesa-mesa3d" : "amdgcn--";
200bf215546Sopenharmony_ci   LLVMTargetRef target = ac_get_llvm_target(triple);
201bf215546Sopenharmony_ci   const char *name = ac_get_llvm_processor_name(family);
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci   LLVMTargetMachineRef tm =
204bf215546Sopenharmony_ci      LLVMCreateTargetMachine(target, triple, name, "", level,
205bf215546Sopenharmony_ci                              LLVMRelocDefault, LLVMCodeModelDefault);
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   if (!ac_is_llvm_processor_supported(tm, name)) {
208bf215546Sopenharmony_ci      LLVMDisposeTargetMachine(tm);
209bf215546Sopenharmony_ci      fprintf(stderr, "amd: LLVM doesn't support %s, bailing out...\n", name);
210bf215546Sopenharmony_ci      return NULL;
211bf215546Sopenharmony_ci   }
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   if (out_triple)
214bf215546Sopenharmony_ci      *out_triple = triple;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   return tm;
217bf215546Sopenharmony_ci}
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_cistatic LLVMPassManagerRef ac_create_passmgr(LLVMTargetLibraryInfoRef target_library_info,
220bf215546Sopenharmony_ci                                            bool check_ir)
221bf215546Sopenharmony_ci{
222bf215546Sopenharmony_ci   LLVMPassManagerRef passmgr = LLVMCreatePassManager();
223bf215546Sopenharmony_ci   if (!passmgr)
224bf215546Sopenharmony_ci      return NULL;
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   if (target_library_info)
227bf215546Sopenharmony_ci      LLVMAddTargetLibraryInfo(target_library_info, passmgr);
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   if (check_ir)
230bf215546Sopenharmony_ci      LLVMAddVerifierPass(passmgr);
231bf215546Sopenharmony_ci   LLVMAddAlwaysInlinerPass(passmgr);
232bf215546Sopenharmony_ci   /* Normally, the pass manager runs all passes on one function before
233bf215546Sopenharmony_ci    * moving onto another. Adding a barrier no-op pass forces the pass
234bf215546Sopenharmony_ci    * manager to run the inliner on all functions first, which makes sure
235bf215546Sopenharmony_ci    * that the following passes are only run on the remaining non-inline
236bf215546Sopenharmony_ci    * function, so it removes useless work done on dead inline functions.
237bf215546Sopenharmony_ci    */
238bf215546Sopenharmony_ci   ac_llvm_add_barrier_noop_pass(passmgr);
239bf215546Sopenharmony_ci   /* This pass should eliminate all the load and store instructions. */
240bf215546Sopenharmony_ci   LLVMAddPromoteMemoryToRegisterPass(passmgr);
241bf215546Sopenharmony_ci   LLVMAddScalarReplAggregatesPass(passmgr);
242bf215546Sopenharmony_ci   LLVMAddLICMPass(passmgr);
243bf215546Sopenharmony_ci   LLVMAddAggressiveDCEPass(passmgr);
244bf215546Sopenharmony_ci   LLVMAddCFGSimplificationPass(passmgr);
245bf215546Sopenharmony_ci   /* This is recommended by the instruction combining pass. */
246bf215546Sopenharmony_ci   LLVMAddEarlyCSEMemSSAPass(passmgr);
247bf215546Sopenharmony_ci   LLVMAddInstructionCombiningPass(passmgr);
248bf215546Sopenharmony_ci   return passmgr;
249bf215546Sopenharmony_ci}
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_cistatic const char *attr_to_str(enum ac_func_attr attr)
252bf215546Sopenharmony_ci{
253bf215546Sopenharmony_ci   switch (attr) {
254bf215546Sopenharmony_ci   case AC_FUNC_ATTR_ALWAYSINLINE:
255bf215546Sopenharmony_ci      return "alwaysinline";
256bf215546Sopenharmony_ci   case AC_FUNC_ATTR_INREG:
257bf215546Sopenharmony_ci      return "inreg";
258bf215546Sopenharmony_ci   case AC_FUNC_ATTR_NOALIAS:
259bf215546Sopenharmony_ci      return "noalias";
260bf215546Sopenharmony_ci   case AC_FUNC_ATTR_NOUNWIND:
261bf215546Sopenharmony_ci      return "nounwind";
262bf215546Sopenharmony_ci   case AC_FUNC_ATTR_READNONE:
263bf215546Sopenharmony_ci      return "readnone";
264bf215546Sopenharmony_ci   case AC_FUNC_ATTR_READONLY:
265bf215546Sopenharmony_ci      return "readonly";
266bf215546Sopenharmony_ci   case AC_FUNC_ATTR_WRITEONLY:
267bf215546Sopenharmony_ci      return "writeonly";
268bf215546Sopenharmony_ci   case AC_FUNC_ATTR_INACCESSIBLE_MEM_ONLY:
269bf215546Sopenharmony_ci      return "inaccessiblememonly";
270bf215546Sopenharmony_ci   case AC_FUNC_ATTR_CONVERGENT:
271bf215546Sopenharmony_ci      return "convergent";
272bf215546Sopenharmony_ci   default:
273bf215546Sopenharmony_ci      fprintf(stderr, "Unhandled function attribute: %x\n", attr);
274bf215546Sopenharmony_ci      return 0;
275bf215546Sopenharmony_ci   }
276bf215546Sopenharmony_ci}
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_civoid ac_add_function_attr(LLVMContextRef ctx, LLVMValueRef function, int attr_idx,
279bf215546Sopenharmony_ci                          enum ac_func_attr attr)
280bf215546Sopenharmony_ci{
281bf215546Sopenharmony_ci   const char *attr_name = attr_to_str(attr);
282bf215546Sopenharmony_ci   unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
283bf215546Sopenharmony_ci   LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(ctx, kind_id, 0);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   if (LLVMIsAFunction(function))
286bf215546Sopenharmony_ci      LLVMAddAttributeAtIndex(function, attr_idx, llvm_attr);
287bf215546Sopenharmony_ci   else
288bf215546Sopenharmony_ci      LLVMAddCallSiteAttribute(function, attr_idx, llvm_attr);
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_civoid ac_add_func_attributes(LLVMContextRef ctx, LLVMValueRef function, unsigned attrib_mask)
292bf215546Sopenharmony_ci{
293bf215546Sopenharmony_ci   attrib_mask |= AC_FUNC_ATTR_NOUNWIND;
294bf215546Sopenharmony_ci   attrib_mask &= ~AC_FUNC_ATTR_LEGACY;
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   while (attrib_mask) {
297bf215546Sopenharmony_ci      enum ac_func_attr attr = 1u << u_bit_scan(&attrib_mask);
298bf215546Sopenharmony_ci      ac_add_function_attr(ctx, function, -1, attr);
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_civoid ac_dump_module(LLVMModuleRef module)
303bf215546Sopenharmony_ci{
304bf215546Sopenharmony_ci   char *str = LLVMPrintModuleToString(module);
305bf215546Sopenharmony_ci   fprintf(stderr, "%s", str);
306bf215546Sopenharmony_ci   LLVMDisposeMessage(str);
307bf215546Sopenharmony_ci}
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_civoid ac_llvm_add_target_dep_function_attr(LLVMValueRef F, const char *name, unsigned value)
310bf215546Sopenharmony_ci{
311bf215546Sopenharmony_ci   char str[16];
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   snprintf(str, sizeof(str), "0x%x", value);
314bf215546Sopenharmony_ci   LLVMAddTargetDependentFunctionAttr(F, name, str);
315bf215546Sopenharmony_ci}
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_civoid ac_llvm_set_workgroup_size(LLVMValueRef F, unsigned size)
318bf215546Sopenharmony_ci{
319bf215546Sopenharmony_ci   if (!size)
320bf215546Sopenharmony_ci      return;
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci   char str[32];
323bf215546Sopenharmony_ci   snprintf(str, sizeof(str), "%u,%u", size, size);
324bf215546Sopenharmony_ci   LLVMAddTargetDependentFunctionAttr(F, "amdgpu-flat-work-group-size", str);
325bf215546Sopenharmony_ci}
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_civoid ac_llvm_set_target_features(LLVMValueRef F, struct ac_llvm_context *ctx)
328bf215546Sopenharmony_ci{
329bf215546Sopenharmony_ci   char features[2048];
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   snprintf(features, sizeof(features), "+DumpCode%s%s",
332bf215546Sopenharmony_ci            /* GFX9 has broken VGPR indexing, so always promote alloca to scratch. */
333bf215546Sopenharmony_ci            ctx->gfx_level == GFX9 ? ",-promote-alloca" : "",
334bf215546Sopenharmony_ci            /* Wave32 is the default. */
335bf215546Sopenharmony_ci            ctx->gfx_level >= GFX10 && ctx->wave_size == 64 ?
336bf215546Sopenharmony_ci               ",+wavefrontsize64,-wavefrontsize32" : "");
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci   LLVMAddTargetDependentFunctionAttr(F, "target-features", features);
339bf215546Sopenharmony_ci}
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_cibool ac_init_llvm_compiler(struct ac_llvm_compiler *compiler, enum radeon_family family,
342bf215546Sopenharmony_ci                           enum ac_target_machine_options tm_options)
343bf215546Sopenharmony_ci{
344bf215546Sopenharmony_ci   const char *triple;
345bf215546Sopenharmony_ci   memset(compiler, 0, sizeof(*compiler));
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   compiler->tm = ac_create_target_machine(family, tm_options, LLVMCodeGenLevelDefault, &triple);
348bf215546Sopenharmony_ci   if (!compiler->tm)
349bf215546Sopenharmony_ci      return false;
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   if (tm_options & AC_TM_CREATE_LOW_OPT) {
352bf215546Sopenharmony_ci      compiler->low_opt_tm =
353bf215546Sopenharmony_ci         ac_create_target_machine(family, tm_options, LLVMCodeGenLevelLess, NULL);
354bf215546Sopenharmony_ci      if (!compiler->low_opt_tm)
355bf215546Sopenharmony_ci         goto fail;
356bf215546Sopenharmony_ci   }
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci   compiler->target_library_info = ac_create_target_library_info(triple);
359bf215546Sopenharmony_ci   if (!compiler->target_library_info)
360bf215546Sopenharmony_ci      goto fail;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   compiler->passmgr =
363bf215546Sopenharmony_ci      ac_create_passmgr(compiler->target_library_info, tm_options & AC_TM_CHECK_IR);
364bf215546Sopenharmony_ci   if (!compiler->passmgr)
365bf215546Sopenharmony_ci      goto fail;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   return true;
368bf215546Sopenharmony_cifail:
369bf215546Sopenharmony_ci   ac_destroy_llvm_compiler(compiler);
370bf215546Sopenharmony_ci   return false;
371bf215546Sopenharmony_ci}
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_civoid ac_destroy_llvm_compiler(struct ac_llvm_compiler *compiler)
374bf215546Sopenharmony_ci{
375bf215546Sopenharmony_ci   ac_destroy_llvm_passes(compiler->passes);
376bf215546Sopenharmony_ci   ac_destroy_llvm_passes(compiler->low_opt_passes);
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   if (compiler->passmgr)
379bf215546Sopenharmony_ci      LLVMDisposePassManager(compiler->passmgr);
380bf215546Sopenharmony_ci   if (compiler->target_library_info)
381bf215546Sopenharmony_ci      ac_dispose_target_library_info(compiler->target_library_info);
382bf215546Sopenharmony_ci   if (compiler->low_opt_tm)
383bf215546Sopenharmony_ci      LLVMDisposeTargetMachine(compiler->low_opt_tm);
384bf215546Sopenharmony_ci   if (compiler->tm)
385bf215546Sopenharmony_ci      LLVMDisposeTargetMachine(compiler->tm);
386bf215546Sopenharmony_ci}
387