ac_llvm_util.c revision b8e80941
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,-fp32-denormals,+fp64-denormals%s%s%s%s%s%s", 155 HAVE_LLVM >= 0x0800 ? "" : ",+vgpr-spilling", 156 tm_options & AC_TM_SISCHED ? ",+si-scheduler" : "", 157 tm_options & AC_TM_FORCE_ENABLE_XNACK ? ",+xnack" : "", 158 tm_options & AC_TM_FORCE_DISABLE_XNACK ? ",-xnack" : "", 159 tm_options & AC_TM_PROMOTE_ALLOCA_TO_SCRATCH ? ",-promote-alloca" : "", 160 tm_options & AC_TM_NO_LOAD_STORE_OPT ? ",-load-store-opt" : ""); 161 162 LLVMTargetMachineRef tm = LLVMCreateTargetMachine( 163 target, 164 triple, 165 ac_get_llvm_processor_name(family), 166 features, 167 level, 168 LLVMRelocDefault, 169 LLVMCodeModelDefault); 170 171 if (out_triple) 172 *out_triple = triple; 173 if (tm_options & AC_TM_ENABLE_GLOBAL_ISEL) 174 ac_enable_global_isel(tm); 175 return tm; 176} 177 178static LLVMPassManagerRef ac_create_passmgr(LLVMTargetLibraryInfoRef target_library_info, 179 bool check_ir) 180{ 181 LLVMPassManagerRef passmgr = LLVMCreatePassManager(); 182 if (!passmgr) 183 return NULL; 184 185 if (target_library_info) 186 LLVMAddTargetLibraryInfo(target_library_info, 187 passmgr); 188 189 if (check_ir) 190 LLVMAddVerifierPass(passmgr); 191 LLVMAddAlwaysInlinerPass(passmgr); 192 /* Normally, the pass manager runs all passes on one function before 193 * moving onto another. Adding a barrier no-op pass forces the pass 194 * manager to run the inliner on all functions first, which makes sure 195 * that the following passes are only run on the remaining non-inline 196 * function, so it removes useless work done on dead inline functions. 197 */ 198 ac_llvm_add_barrier_noop_pass(passmgr); 199 /* This pass should eliminate all the load and store instructions. */ 200 LLVMAddPromoteMemoryToRegisterPass(passmgr); 201 LLVMAddScalarReplAggregatesPass(passmgr); 202 LLVMAddLICMPass(passmgr); 203 LLVMAddAggressiveDCEPass(passmgr); 204 LLVMAddCFGSimplificationPass(passmgr); 205 /* This is recommended by the instruction combining pass. */ 206 LLVMAddEarlyCSEMemSSAPass(passmgr); 207 LLVMAddInstructionCombiningPass(passmgr); 208 return passmgr; 209} 210 211static const char *attr_to_str(enum ac_func_attr attr) 212{ 213 switch (attr) { 214 case AC_FUNC_ATTR_ALWAYSINLINE: return "alwaysinline"; 215 case AC_FUNC_ATTR_INREG: return "inreg"; 216 case AC_FUNC_ATTR_NOALIAS: return "noalias"; 217 case AC_FUNC_ATTR_NOUNWIND: return "nounwind"; 218 case AC_FUNC_ATTR_READNONE: return "readnone"; 219 case AC_FUNC_ATTR_READONLY: return "readonly"; 220 case AC_FUNC_ATTR_WRITEONLY: return "writeonly"; 221 case AC_FUNC_ATTR_INACCESSIBLE_MEM_ONLY: return "inaccessiblememonly"; 222 case AC_FUNC_ATTR_CONVERGENT: return "convergent"; 223 default: 224 fprintf(stderr, "Unhandled function attribute: %x\n", attr); 225 return 0; 226 } 227} 228 229void 230ac_add_function_attr(LLVMContextRef ctx, LLVMValueRef function, 231 int attr_idx, enum ac_func_attr attr) 232{ 233 const char *attr_name = attr_to_str(attr); 234 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, 235 strlen(attr_name)); 236 LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(ctx, kind_id, 0); 237 238 if (LLVMIsAFunction(function)) 239 LLVMAddAttributeAtIndex(function, attr_idx, llvm_attr); 240 else 241 LLVMAddCallSiteAttribute(function, attr_idx, llvm_attr); 242} 243 244void ac_add_func_attributes(LLVMContextRef ctx, LLVMValueRef function, 245 unsigned attrib_mask) 246{ 247 attrib_mask |= AC_FUNC_ATTR_NOUNWIND; 248 attrib_mask &= ~AC_FUNC_ATTR_LEGACY; 249 250 while (attrib_mask) { 251 enum ac_func_attr attr = 1u << u_bit_scan(&attrib_mask); 252 ac_add_function_attr(ctx, function, -1, attr); 253 } 254} 255 256void 257ac_dump_module(LLVMModuleRef module) 258{ 259 char *str = LLVMPrintModuleToString(module); 260 fprintf(stderr, "%s", str); 261 LLVMDisposeMessage(str); 262} 263 264void 265ac_llvm_add_target_dep_function_attr(LLVMValueRef F, 266 const char *name, unsigned value) 267{ 268 char str[16]; 269 270 snprintf(str, sizeof(str), "0x%x", value); 271 LLVMAddTargetDependentFunctionAttr(F, name, str); 272} 273 274unsigned 275ac_count_scratch_private_memory(LLVMValueRef function) 276{ 277 unsigned private_mem_vgprs = 0; 278 279 /* Process all LLVM instructions. */ 280 LLVMBasicBlockRef bb = LLVMGetFirstBasicBlock(function); 281 while (bb) { 282 LLVMValueRef next = LLVMGetFirstInstruction(bb); 283 284 while (next) { 285 LLVMValueRef inst = next; 286 next = LLVMGetNextInstruction(next); 287 288 if (LLVMGetInstructionOpcode(inst) != LLVMAlloca) 289 continue; 290 291 LLVMTypeRef type = LLVMGetElementType(LLVMTypeOf(inst)); 292 /* No idea why LLVM aligns allocas to 4 elements. */ 293 unsigned alignment = LLVMGetAlignment(inst); 294 unsigned dw_size = align(ac_get_type_size(type) / 4, alignment); 295 private_mem_vgprs += dw_size; 296 } 297 bb = LLVMGetNextBasicBlock(bb); 298 } 299 300 return private_mem_vgprs; 301} 302 303bool 304ac_init_llvm_compiler(struct ac_llvm_compiler *compiler, 305 enum radeon_family family, 306 enum ac_target_machine_options tm_options) 307{ 308 const char *triple; 309 memset(compiler, 0, sizeof(*compiler)); 310 311 compiler->tm = ac_create_target_machine(family, tm_options, 312 LLVMCodeGenLevelDefault, 313 &triple); 314 if (!compiler->tm) 315 return false; 316 317 if (tm_options & AC_TM_CREATE_LOW_OPT) { 318 compiler->low_opt_tm = 319 ac_create_target_machine(family, tm_options, 320 LLVMCodeGenLevelLess, NULL); 321 if (!compiler->low_opt_tm) 322 goto fail; 323 } 324 325 compiler->target_library_info = 326 ac_create_target_library_info(triple); 327 if (!compiler->target_library_info) 328 goto fail; 329 330 compiler->passmgr = ac_create_passmgr(compiler->target_library_info, 331 tm_options & AC_TM_CHECK_IR); 332 if (!compiler->passmgr) 333 goto fail; 334 335 return true; 336fail: 337 ac_destroy_llvm_compiler(compiler); 338 return false; 339} 340 341void 342ac_destroy_llvm_compiler(struct ac_llvm_compiler *compiler) 343{ 344 if (compiler->passmgr) 345 LLVMDisposePassManager(compiler->passmgr); 346 if (compiler->target_library_info) 347 ac_dispose_target_library_info(compiler->target_library_info); 348 if (compiler->low_opt_tm) 349 LLVMDisposeTargetMachine(compiler->low_opt_tm); 350 if (compiler->tm) 351 LLVMDisposeTargetMachine(compiler->tm); 352} 353