1/* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 18 * USE OR OTHER DEALINGS IN THE SOFTWARE. 19 * 20 * The above copyright notice and this permission notice (including the 21 * next paragraph) shall be included in all copies or substantial portions 22 * of the Software. 23 * 24 */ 25/* based on pieces from si_pipe.c and radeon_llvm_emit.c */ 26#include "ac_llvm_util.h" 27#include "ac_llvm_build.h" 28#include "util/bitscan.h" 29#include <llvm-c/Core.h> 30#include <llvm-c/Support.h> 31#include <llvm-c/Transforms/IPO.h> 32#include <llvm-c/Transforms/Scalar.h> 33#include <llvm-c/Transforms/Utils.h> 34#include "c11/threads.h" 35#include "gallivm/lp_bld_misc.h" 36#include "util/u_math.h" 37 38#include <assert.h> 39#include <stdio.h> 40#include <string.h> 41 42static void ac_init_llvm_target() 43{ 44 LLVMInitializeAMDGPUTargetInfo(); 45 LLVMInitializeAMDGPUTarget(); 46 LLVMInitializeAMDGPUTargetMC(); 47 LLVMInitializeAMDGPUAsmPrinter(); 48 49 /* For inline assembly. */ 50 LLVMInitializeAMDGPUAsmParser(); 51 52 /* Workaround for bug in llvm 4.0 that causes image intrinsics 53 * to disappear. 54 * https://reviews.llvm.org/D26348 55 * 56 * "mesa" is the prefix for error messages. 57 * 58 * -global-isel-abort=2 is a no-op unless global isel has been enabled. 59 * This option tells the backend to fall-back to SelectionDAG and print 60 * a diagnostic message if global isel fails. 61 */ 62 const char *argv[3] = { "mesa", "-simplifycfg-sink-common=false", "-global-isel-abort=2" }; 63 LLVMParseCommandLineOptions(3, argv, NULL); 64} 65 66static once_flag ac_init_llvm_target_once_flag = ONCE_FLAG_INIT; 67 68void ac_init_llvm_once(void) 69{ 70 call_once(&ac_init_llvm_target_once_flag, ac_init_llvm_target); 71} 72 73static LLVMTargetRef ac_get_llvm_target(const char *triple) 74{ 75 LLVMTargetRef target = NULL; 76 char *err_message = NULL; 77 78 if (LLVMGetTargetFromTriple(triple, &target, &err_message)) { 79 fprintf(stderr, "Cannot find target for triple %s ", triple); 80 if (err_message) { 81 fprintf(stderr, "%s\n", err_message); 82 } 83 LLVMDisposeMessage(err_message); 84 return NULL; 85 } 86 return target; 87} 88 89const char *ac_get_llvm_processor_name(enum radeon_family family) 90{ 91 switch (family) { 92 case CHIP_TAHITI: 93 return "tahiti"; 94 case CHIP_PITCAIRN: 95 return "pitcairn"; 96 case CHIP_VERDE: 97 return "verde"; 98 case CHIP_OLAND: 99 return "oland"; 100 case CHIP_HAINAN: 101 return "hainan"; 102 case CHIP_BONAIRE: 103 return "bonaire"; 104 case CHIP_KABINI: 105 return "kabini"; 106 case CHIP_KAVERI: 107 return "kaveri"; 108 case CHIP_HAWAII: 109 return "hawaii"; 110 case CHIP_MULLINS: 111 return "mullins"; 112 case CHIP_TONGA: 113 return "tonga"; 114 case CHIP_ICELAND: 115 return "iceland"; 116 case CHIP_CARRIZO: 117 return "carrizo"; 118 case CHIP_FIJI: 119 return "fiji"; 120 case CHIP_STONEY: 121 return "stoney"; 122 case CHIP_POLARIS10: 123 return "polaris10"; 124 case CHIP_POLARIS11: 125 case CHIP_POLARIS12: 126 case CHIP_VEGAM: 127 return "polaris11"; 128 case CHIP_VEGA10: 129 return "gfx900"; 130 case CHIP_RAVEN: 131 return "gfx902"; 132 case CHIP_VEGA12: 133 return "gfx904"; 134 case CHIP_VEGA20: 135 return "gfx906"; 136 case CHIP_RAVEN2: 137 return HAVE_LLVM >= 0x0800 ? "gfx909" : "gfx902"; 138 default: 139 return ""; 140 } 141} 142 143static LLVMTargetMachineRef ac_create_target_machine(enum radeon_family family, 144 enum ac_target_machine_options tm_options, 145 LLVMCodeGenOptLevel level, 146 const char **out_triple) 147{ 148 assert(family >= CHIP_TAHITI); 149 char features[256]; 150 const char *triple = (tm_options & AC_TM_SUPPORTS_SPILL) ? "amdgcn-mesa-mesa3d" : "amdgcn--"; 151 LLVMTargetRef target = ac_get_llvm_target(triple); 152 153 snprintf(features, sizeof(features), 154 "+DumpCode%s%s%s%s%s%s%s", 155 HAVE_LLVM >= 0x0B00 ? "" : ",-fp32-denormals,+fp64-denormals", 156 HAVE_LLVM >= 0x0800 ? "" : ",+vgpr-spilling", 157 tm_options & AC_TM_SISCHED ? ",+si-scheduler" : "", 158 (tm_options & AC_TM_FORCE_ENABLE_XNACK) && HAVE_LLVM <= 0x0800 ? ",+xnack" : "", 159 (tm_options & AC_TM_FORCE_DISABLE_XNACK) && HAVE_LLVM <= 0x0800 ? ",-xnack" : "", 160 tm_options & AC_TM_PROMOTE_ALLOCA_TO_SCRATCH ? ",-promote-alloca" : "", 161 tm_options & AC_TM_NO_LOAD_STORE_OPT ? ",-load-store-opt" : ""); 162 163 LLVMTargetMachineRef tm = LLVMCreateTargetMachine( 164 target, 165 triple, 166 ac_get_llvm_processor_name(family), 167 features, 168 level, 169 LLVMRelocDefault, 170 LLVMCodeModelDefault); 171 172 if (out_triple) 173 *out_triple = triple; 174 if (tm_options & AC_TM_ENABLE_GLOBAL_ISEL) 175 ac_enable_global_isel(tm); 176 return tm; 177} 178 179static LLVMPassManagerRef ac_create_passmgr(LLVMTargetLibraryInfoRef target_library_info, 180 bool check_ir) 181{ 182 LLVMPassManagerRef passmgr = LLVMCreatePassManager(); 183 if (!passmgr) 184 return NULL; 185 186 if (target_library_info) 187 LLVMAddTargetLibraryInfo(target_library_info, 188 passmgr); 189 190 if (check_ir) 191 LLVMAddVerifierPass(passmgr); 192 LLVMAddAlwaysInlinerPass(passmgr); 193 /* Normally, the pass manager runs all passes on one function before 194 * moving onto another. Adding a barrier no-op pass forces the pass 195 * manager to run the inliner on all functions first, which makes sure 196 * that the following passes are only run on the remaining non-inline 197 * function, so it removes useless work done on dead inline functions. 198 */ 199 ac_llvm_add_barrier_noop_pass(passmgr); 200 /* This pass should eliminate all the load and store instructions. */ 201 LLVMAddPromoteMemoryToRegisterPass(passmgr); 202 LLVMAddScalarReplAggregatesPass(passmgr); 203 LLVMAddLICMPass(passmgr); 204 LLVMAddAggressiveDCEPass(passmgr); 205 LLVMAddCFGSimplificationPass(passmgr); 206 /* This is recommended by the instruction combining pass. */ 207 LLVMAddEarlyCSEMemSSAPass(passmgr); 208 LLVMAddInstructionCombiningPass(passmgr); 209 return passmgr; 210} 211 212static const char *attr_to_str(enum ac_func_attr attr) 213{ 214 switch (attr) { 215 case AC_FUNC_ATTR_ALWAYSINLINE: return "alwaysinline"; 216 case AC_FUNC_ATTR_INREG: return "inreg"; 217 case AC_FUNC_ATTR_NOALIAS: return "noalias"; 218 case AC_FUNC_ATTR_NOUNWIND: return "nounwind"; 219 case AC_FUNC_ATTR_READNONE: return "readnone"; 220 case AC_FUNC_ATTR_READONLY: return "readonly"; 221 case AC_FUNC_ATTR_WRITEONLY: return "writeonly"; 222 case AC_FUNC_ATTR_INACCESSIBLE_MEM_ONLY: return "inaccessiblememonly"; 223 case AC_FUNC_ATTR_CONVERGENT: return "convergent"; 224 default: 225 fprintf(stderr, "Unhandled function attribute: %x\n", attr); 226 return 0; 227 } 228} 229 230void 231ac_add_function_attr(LLVMContextRef ctx, LLVMValueRef function, 232 int attr_idx, enum ac_func_attr attr) 233{ 234 const char *attr_name = attr_to_str(attr); 235 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, 236 strlen(attr_name)); 237 LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(ctx, kind_id, 0); 238 239 if (LLVMIsAFunction(function)) 240 LLVMAddAttributeAtIndex(function, attr_idx, llvm_attr); 241 else 242 LLVMAddCallSiteAttribute(function, attr_idx, llvm_attr); 243} 244 245void ac_add_func_attributes(LLVMContextRef ctx, LLVMValueRef function, 246 unsigned attrib_mask) 247{ 248 attrib_mask |= AC_FUNC_ATTR_NOUNWIND; 249 attrib_mask &= ~AC_FUNC_ATTR_LEGACY; 250 251 while (attrib_mask) { 252 enum ac_func_attr attr = 1u << u_bit_scan(&attrib_mask); 253 ac_add_function_attr(ctx, function, -1, attr); 254 } 255} 256 257void 258ac_dump_module(LLVMModuleRef module) 259{ 260 char *str = LLVMPrintModuleToString(module); 261 fprintf(stderr, "%s", str); 262 LLVMDisposeMessage(str); 263} 264 265void 266ac_llvm_add_target_dep_function_attr(LLVMValueRef F, 267 const char *name, unsigned value) 268{ 269 char str[16]; 270 271 snprintf(str, sizeof(str), "0x%x", value); 272 LLVMAddTargetDependentFunctionAttr(F, name, str); 273} 274 275unsigned 276ac_count_scratch_private_memory(LLVMValueRef function) 277{ 278 unsigned private_mem_vgprs = 0; 279 280 /* Process all LLVM instructions. */ 281 LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(function); 282 while (bb) { 283 LLVMValueRef next = LLVMGetFirstInstruction(bb); 284 285 while (next) { 286 LLVMValueRef inst = next; 287 next = LLVMGetNextInstruction(next); 288 289 if (LLVMGetInstructionOpcode(inst) != LLVMAlloca) 290 continue; 291 292 LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(inst)); 293 /* No idea why LLVM aligns allocas to 4 elements. */ 294 unsigned alignment = LLVMGetAlignment(inst); 295 unsigned dw_size = align(ac_get_type_size(type) / 4, alignment); 296 private_mem_vgprs += dw_size; 297 } 298 bb = LLVMGetNextBasicBlock(bb); 299 } 300 301 return private_mem_vgprs; 302} 303 304bool 305ac_init_llvm_compiler(struct ac_llvm_compiler *compiler, 306 enum radeon_family family, 307 enum ac_target_machine_options tm_options) 308{ 309 const char *triple; 310 memset(compiler, 0, sizeof(*compiler)); 311 312 compiler->tm = ac_create_target_machine(family, tm_options, 313 LLVMCodeGenLevelDefault, 314 &triple); 315 if (!compiler->tm) 316 return false; 317 318 if (tm_options & AC_TM_CREATE_LOW_OPT) { 319 compiler->low_opt_tm = 320 ac_create_target_machine(family, tm_options, 321 LLVMCodeGenLevelLess, NULL); 322 if (!compiler->low_opt_tm) 323 goto fail; 324 } 325 326 compiler->target_library_info = 327 ac_create_target_library_info(triple); 328 if (!compiler->target_library_info) 329 goto fail; 330 331 compiler->passmgr = ac_create_passmgr(compiler->target_library_info, 332 tm_options & AC_TM_CHECK_IR); 333 if (!compiler->passmgr) 334 goto fail; 335 336 return true; 337fail: 338 ac_destroy_llvm_compiler(compiler); 339 return false; 340} 341 342void 343ac_destroy_llvm_compiler(struct ac_llvm_compiler *compiler) 344{ 345 if (compiler->passmgr) 346 LLVMDisposePassManager(compiler->passmgr); 347 if (compiler->target_library_info) 348 ac_dispose_target_library_info(compiler->target_library_info); 349 if (compiler->low_opt_tm) 350 LLVMDisposeTargetMachine(compiler->low_opt_tm); 351 if (compiler->tm) 352 LLVMDisposeTargetMachine(compiler->tm); 353} 354