1/*
2 * Copyright 2016 Bas Nieuwenhuizen
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
26#ifndef AC_LLVM_UTIL_H
27#define AC_LLVM_UTIL_H
28
29#include <stdbool.h>
30#include <llvm-c/TargetMachine.h>
31
32#include "amd_family.h"
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38struct ac_shader_binary;
39struct ac_compiler_passes;
40
41enum ac_func_attr {
42	AC_FUNC_ATTR_ALWAYSINLINE = (1 << 0),
43	AC_FUNC_ATTR_INREG        = (1 << 2),
44	AC_FUNC_ATTR_NOALIAS      = (1 << 3),
45	AC_FUNC_ATTR_NOUNWIND     = (1 << 4),
46	AC_FUNC_ATTR_READNONE     = (1 << 5),
47	AC_FUNC_ATTR_READONLY     = (1 << 6),
48	AC_FUNC_ATTR_WRITEONLY    = (1 << 7),
49	AC_FUNC_ATTR_INACCESSIBLE_MEM_ONLY = (1 << 8),
50	AC_FUNC_ATTR_CONVERGENT = (1 << 9),
51
52	/* Legacy intrinsic that needs attributes on function declarations
53	 * and they must match the internal LLVM definition exactly, otherwise
54	 * intrinsic selection fails.
55	 */
56	AC_FUNC_ATTR_LEGACY       = (1u << 31),
57};
58
59enum ac_target_machine_options {
60	AC_TM_SUPPORTS_SPILL = (1 << 0),
61	AC_TM_SISCHED = (1 << 1),
62	AC_TM_FORCE_ENABLE_XNACK = (1 << 2),
63	AC_TM_FORCE_DISABLE_XNACK = (1 << 3),
64	AC_TM_PROMOTE_ALLOCA_TO_SCRATCH = (1 << 4),
65	AC_TM_CHECK_IR = (1 << 5),
66	AC_TM_ENABLE_GLOBAL_ISEL = (1 << 6),
67	AC_TM_CREATE_LOW_OPT = (1 << 7),
68	AC_TM_NO_LOAD_STORE_OPT = (1 << 8),
69};
70
71enum ac_float_mode {
72	AC_FLOAT_MODE_DEFAULT,
73	AC_FLOAT_MODE_NO_SIGNED_ZEROS_FP_MATH,
74	AC_FLOAT_MODE_UNSAFE_FP_MATH,
75};
76
77/* Per-thread persistent LLVM objects. */
78struct ac_llvm_compiler {
79	LLVMTargetLibraryInfoRef	target_library_info;
80	LLVMPassManagerRef		passmgr;
81
82	/* Default compiler. */
83	LLVMTargetMachineRef		tm;
84	struct ac_compiler_passes	*passes;
85
86	/* Optional compiler for faster compilation with fewer optimizations.
87	 * LLVM modules can be created with "tm" too. There is no difference.
88	 */
89	LLVMTargetMachineRef		low_opt_tm; /* uses -O1 instead of -O2 */
90	struct ac_compiler_passes	*low_opt_passes;
91};
92
93const char *ac_get_llvm_processor_name(enum radeon_family family);
94void ac_add_attr_dereferenceable(LLVMValueRef val, uint64_t bytes);
95bool ac_is_sgpr_param(LLVMValueRef param);
96void ac_add_function_attr(LLVMContextRef ctx, LLVMValueRef function,
97                          int attr_idx, enum ac_func_attr attr);
98void ac_add_func_attributes(LLVMContextRef ctx, LLVMValueRef function,
99			    unsigned attrib_mask);
100void ac_dump_module(LLVMModuleRef module);
101
102LLVMValueRef ac_llvm_get_called_value(LLVMValueRef call);
103bool ac_llvm_is_function(LLVMValueRef v);
104LLVMModuleRef ac_create_module(LLVMTargetMachineRef tm, LLVMContextRef ctx);
105
106LLVMBuilderRef ac_create_builder(LLVMContextRef ctx,
107				 enum ac_float_mode float_mode);
108
109void
110ac_llvm_add_target_dep_function_attr(LLVMValueRef F,
111				     const char *name, unsigned value);
112
113static inline unsigned
114ac_get_load_intr_attribs(bool can_speculate)
115{
116	/* READNONE means writes can't affect it, while READONLY means that
117	 * writes can affect it. */
118	return can_speculate ? AC_FUNC_ATTR_READNONE :
119			       AC_FUNC_ATTR_READONLY;
120}
121
122static inline unsigned
123ac_get_store_intr_attribs(bool writeonly_memory)
124{
125	return writeonly_memory ? AC_FUNC_ATTR_INACCESSIBLE_MEM_ONLY :
126				  AC_FUNC_ATTR_WRITEONLY;
127}
128
129unsigned
130ac_count_scratch_private_memory(LLVMValueRef function);
131
132LLVMTargetLibraryInfoRef ac_create_target_library_info(const char *triple);
133void ac_dispose_target_library_info(LLVMTargetLibraryInfoRef library_info);
134void ac_init_llvm_once(void);
135
136
137bool ac_init_llvm_compiler(struct ac_llvm_compiler *compiler,
138			   enum radeon_family family,
139			   enum ac_target_machine_options tm_options);
140void ac_destroy_llvm_compiler(struct ac_llvm_compiler *compiler);
141
142struct ac_compiler_passes *ac_create_llvm_passes(LLVMTargetMachineRef tm);
143void ac_destroy_llvm_passes(struct ac_compiler_passes *p);
144bool ac_compile_module_to_binary(struct ac_compiler_passes *p, LLVMModuleRef module,
145				 struct ac_shader_binary *binary);
146void ac_llvm_add_barrier_noop_pass(LLVMPassManagerRef passmgr);
147void ac_enable_global_isel(LLVMTargetMachineRef tm);
148
149#ifdef __cplusplus
150}
151#endif
152
153#endif /* AC_LLVM_UTIL_H */
154