|  | 
|  | 1 | +From cf12274ce2dd09ce4f6632a27deff4c8f5bdcf34 Mon Sep 17 00:00:00 2001 | 
|  | 2 | +From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <[email protected] > | 
|  | 3 | +Date: Wed, 4 Jul 2018 01:11:47 -0400 | 
|  | 4 | +Subject: [PATCH 6/8] ac: add reusable helpers for direct LLVM compilation | 
|  | 5 | + | 
|  | 6 | +This is basically LLVMTargetMachineEmitToMemoryBuffer inlined and reworked. | 
|  | 7 | + | 
|  | 8 | +struct ac_compiler_passes (opaque type) contains the main pass manager. | 
|  | 9 | + | 
|  | 10 | +ac_create_llvm_passes -- the result can go to thread local storage | 
|  | 11 | +ac_destroy_llvm_passes -- can be called by a destructor in TLS | 
|  | 12 | +ac_compile_module_to_binary -- from LLVMModuleRef to ac_shader_binary | 
|  | 13 | + | 
|  | 14 | +The motivation is to do the expensive call addPassesToEmitFile once | 
|  | 15 | +per context or thread. | 
|  | 16 | + | 
|  | 17 | +Change-Id: Ic6f421ec42f58879c7655d6b5e917647d8f0e801 | 
|  | 18 | +Reviewed-by: Dave Airlie <[email protected] > | 
|  | 19 | +--- | 
|  | 20 | + src/amd/common/ac_binary.h        |  8 +++++ | 
|  | 21 | + src/amd/common/ac_llvm_helper.cpp | 62 ++++++++++++++++++++++++++++++++++++--- | 
|  | 22 | + src/amd/common/ac_llvm_util.h     |  9 ++++++ | 
|  | 23 | + 3 files changed, 75 insertions(+), 4 deletions(-) | 
|  | 24 | + | 
|  | 25 | +diff --git a/src/amd/common/ac_binary.h b/src/amd/common/ac_binary.h | 
|  | 26 | +index 4bd86b939f..735e393205 100644 | 
|  | 27 | +--- a/src/amd/common/ac_binary.h | 
|  | 28 | ++++ b/src/amd/common/ac_binary.h | 
|  | 29 | +@@ -27,6 +27,10 @@ | 
|  | 30 | + #include <stdint.h> | 
|  | 31 | + #include <stdbool.h> | 
|  | 32 | +  | 
|  | 33 | ++#ifdef __cplusplus | 
|  | 34 | ++extern "C" { | 
|  | 35 | ++#endif | 
|  | 36 | ++ | 
|  | 37 | + struct ac_shader_reloc { | 
|  | 38 | + 	char name[32]; | 
|  | 39 | + 	uint64_t offset; | 
|  | 40 | +@@ -98,4 +102,8 @@ void ac_shader_binary_read_config(struct ac_shader_binary *binary, | 
|  | 41 | + 				  bool supports_spill); | 
|  | 42 | + void ac_shader_binary_clean(struct ac_shader_binary *b); | 
|  | 43 | +  | 
|  | 44 | ++#ifdef __cplusplus | 
|  | 45 | ++} | 
|  | 46 | ++#endif | 
|  | 47 | ++ | 
|  | 48 | + #endif /* AC_BINARY_H */ | 
|  | 49 | +diff --git a/src/amd/common/ac_llvm_helper.cpp b/src/amd/common/ac_llvm_helper.cpp | 
|  | 50 | +index 35973dd1fa..4348ebd36e 100644 | 
|  | 51 | +--- a/src/amd/common/ac_llvm_helper.cpp | 
|  | 52 | ++++ b/src/amd/common/ac_llvm_helper.cpp | 
|  | 53 | +@@ -29,15 +29,18 @@ | 
|  | 54 | + #pragma push_macro("DEBUG") | 
|  | 55 | + #undef DEBUG | 
|  | 56 | +  | 
|  | 57 | ++#include "ac_binary.h" | 
|  | 58 | + #include "ac_llvm_util.h" | 
|  | 59 | ++ | 
|  | 60 | + #include <llvm-c/Core.h> | 
|  | 61 | +-#include <llvm/Target/TargetOptions.h> | 
|  | 62 | +-#include <llvm/ExecutionEngine/ExecutionEngine.h> | 
|  | 63 | +-#include <llvm/IR/Attributes.h> | 
|  | 64 | +-#include <llvm/IR/CallSite.h> | 
|  | 65 | ++#include <llvm/Target/TargetMachine.h> | 
|  | 66 | + #include <llvm/IR/IRBuilder.h> | 
|  | 67 | + #include <llvm/Analysis/TargetLibraryInfo.h> | 
|  | 68 | +  | 
|  | 69 | ++#include <llvm/IR/LegacyPassManager.h> | 
|  | 70 | ++#if HAVE_LLVM < 0x0700 | 
|  | 71 | ++#include "llvm/Support/raw_ostream.h" | 
|  | 72 | ++#endif | 
|  | 73 | +  | 
|  | 74 | + void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes) | 
|  | 75 | + { | 
|  | 76 | +@@ -111,3 +114,54 @@ ac_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info) | 
|  | 77 | + { | 
|  | 78 | + 	delete reinterpret_cast<llvm::TargetLibraryInfoImpl *>(library_info); | 
|  | 79 | + } | 
|  | 80 | ++ | 
|  | 81 | ++/* The LLVM compiler is represented as a pass manager containing passes for | 
|  | 82 | ++ * optimizations, instruction selection, and code generation. | 
|  | 83 | ++ */ | 
|  | 84 | ++struct ac_compiler_passes { | 
|  | 85 | ++	ac_compiler_passes(): ostream(code_string) {} | 
|  | 86 | ++ | 
|  | 87 | ++	llvm::SmallString<0> code_string;  /* ELF shader binary */ | 
|  | 88 | ++	llvm::raw_svector_ostream ostream; /* stream for appending data to the binary */ | 
|  | 89 | ++	llvm::legacy::PassManager passmgr; /* list of passes */ | 
|  | 90 | ++}; | 
|  | 91 | ++ | 
|  | 92 | ++struct ac_compiler_passes *ac_create_llvm_passes(LLVMTargetMachineRef tm) | 
|  | 93 | ++{ | 
|  | 94 | ++	struct ac_compiler_passes *p = new ac_compiler_passes(); | 
|  | 95 | ++	if (!p) | 
|  | 96 | ++		return NULL; | 
|  | 97 | ++ | 
|  | 98 | ++	llvm::TargetMachine *TM = reinterpret_cast<llvm::TargetMachine*>(tm); | 
|  | 99 | ++ | 
|  | 100 | ++	if (TM->addPassesToEmitFile(p->passmgr, p->ostream, | 
|  | 101 | ++#if HAVE_LLVM >= 0x0700 | 
|  | 102 | ++				    nullptr, | 
|  | 103 | ++#endif | 
|  | 104 | ++				    llvm::TargetMachine::CGFT_ObjectFile)) { | 
|  | 105 | ++		fprintf(stderr, "amd: TargetMachine can't emit a file of this type!\n"); | 
|  | 106 | ++		delete p; | 
|  | 107 | ++		return NULL; | 
|  | 108 | ++	} | 
|  | 109 | ++	return p; | 
|  | 110 | ++} | 
|  | 111 | ++ | 
|  | 112 | ++void ac_destroy_llvm_passes(struct ac_compiler_passes *p) | 
|  | 113 | ++{ | 
|  | 114 | ++	delete p; | 
|  | 115 | ++} | 
|  | 116 | ++ | 
|  | 117 | ++/* This returns false on failure. */ | 
|  | 118 | ++bool ac_compile_module_to_binary(struct ac_compiler_passes *p, LLVMModuleRef module, | 
|  | 119 | ++				 struct ac_shader_binary *binary) | 
|  | 120 | ++{ | 
|  | 121 | ++	p->passmgr.run(*llvm::unwrap(module)); | 
|  | 122 | ++ | 
|  | 123 | ++	llvm::StringRef data = p->ostream.str(); | 
|  | 124 | ++	bool success = ac_elf_read(data.data(), data.size(), binary); | 
|  | 125 | ++	p->code_string = ""; /* release the ELF shader binary */ | 
|  | 126 | ++ | 
|  | 127 | ++	if (!success) | 
|  | 128 | ++		fprintf(stderr, "amd: cannot read an ELF shader binary\n"); | 
|  | 129 | ++	return success; | 
|  | 130 | ++} | 
|  | 131 | +diff --git a/src/amd/common/ac_llvm_util.h b/src/amd/common/ac_llvm_util.h | 
|  | 132 | +index f083db186c..229fa96644 100644 | 
|  | 133 | +--- a/src/amd/common/ac_llvm_util.h | 
|  | 134 | ++++ b/src/amd/common/ac_llvm_util.h | 
|  | 135 | +@@ -35,6 +35,9 @@ | 
|  | 136 | + extern "C" { | 
|  | 137 | + #endif | 
|  | 138 | +  | 
|  | 139 | ++struct ac_shader_binary; | 
|  | 140 | ++struct ac_compiler_passes; | 
|  | 141 | ++ | 
|  | 142 | + enum ac_func_attr { | 
|  | 143 | + 	AC_FUNC_ATTR_ALWAYSINLINE = (1 << 0), | 
|  | 144 | + 	AC_FUNC_ATTR_INREG        = (1 << 2), | 
|  | 145 | +@@ -73,6 +76,7 @@ struct ac_llvm_compiler { | 
|  | 146 | + 	LLVMTargetMachineRef		tm; | 
|  | 147 | + 	LLVMTargetLibraryInfoRef	target_library_info; | 
|  | 148 | + 	LLVMPassManagerRef		passmgr; | 
|  | 149 | ++	struct ac_compiler_passes	*passes; | 
|  | 150 | + }; | 
|  | 151 | +  | 
|  | 152 | + const char *ac_get_llvm_processor_name(enum radeon_family family); | 
|  | 153 | +@@ -131,6 +135,11 @@ bool ac_init_llvm_compiler(struct ac_llvm_compiler *compiler, | 
|  | 154 | + 			   enum ac_target_machine_options tm_options); | 
|  | 155 | + void ac_destroy_llvm_compiler(struct ac_llvm_compiler *compiler); | 
|  | 156 | +  | 
|  | 157 | ++struct ac_compiler_passes *ac_create_llvm_passes(LLVMTargetMachineRef tm); | 
|  | 158 | ++void ac_destroy_llvm_passes(struct ac_compiler_passes *p); | 
|  | 159 | ++bool ac_compile_module_to_binary(struct ac_compiler_passes *p, LLVMModuleRef module, | 
|  | 160 | ++				 struct ac_shader_binary *binary); | 
|  | 161 | ++ | 
|  | 162 | + #ifdef __cplusplus | 
|  | 163 | + } | 
|  | 164 | + #endif | 
|  | 165 | +--  | 
|  | 166 | +2.15.1 | 
|  | 167 | + | 
0 commit comments