#include "util/u_debug.h"
#include "util/u_string.h"
+#include "util/bitscan.h"
#include "lp_bld_const.h"
#include "lp_bld_intr.h"
}
+#if HAVE_LLVM < 0x0400
+static LLVMAttribute lp_attr_to_llvm_attr(enum lp_func_attr attr)
+{
+ switch (attr) {
+ case LP_FUNC_ATTR_ALWAYSINLINE: return LLVMAlwaysInlineAttribute;
+ case LP_FUNC_ATTR_BYVAL: return LLVMByValAttribute;
+ case LP_FUNC_ATTR_INREG: return LLVMInRegAttribute;
+ case LP_FUNC_ATTR_NOALIAS: return LLVMNoAliasAttribute;
+ case LP_FUNC_ATTR_NOUNWIND: return LLVMNoUnwindAttribute;
+ case LP_FUNC_ATTR_READNONE: return LLVMReadNoneAttribute;
+ case LP_FUNC_ATTR_READONLY: return LLVMReadOnlyAttribute;
+ default:
+ _debug_printf("Unhandled function attribute: %x\n", attr);
+ return 0;
+ }
+}
+
+#else
+
+static const char *attr_to_str(enum lp_func_attr attr)
+{
+ switch (attr) {
+ case LP_FUNC_ATTR_ALWAYSINLINE: return "alwaysinline";
+ case LP_FUNC_ATTR_BYVAL: return "byval";
+ case LP_FUNC_ATTR_INREG: return "inreg";
+ case LP_FUNC_ATTR_NOALIAS: return "noalias";
+ case LP_FUNC_ATTR_NOUNWIND: return "nounwind";
+ case LP_FUNC_ATTR_READNONE: return "readnone";
+ case LP_FUNC_ATTR_READONLY: return "readonly";
+ default:
+ _debug_printf("Unhandled function attribute: %x\n", attr);
+ return 0;
+ }
+}
+
+#endif
+
+void
+lp_add_function_attr(LLVMValueRef function,
+ int attr_idx,
+ enum lp_func_attr attr)
+{
+
+#if HAVE_LLVM < 0x0400
+ LLVMAttribute llvm_attr = lp_attr_to_llvm_attr(attr);
+ if (attr_idx == -1) {
+ LLVMAddFunctionAttr(function, llvm_attr);
+ } else {
+ LLVMAddAttribute(LLVMGetParam(function, attr_idx - 1), llvm_attr);
+ }
+#else
+ LLVMContextRef context = LLVMGetModuleContext(LLVMGetGlobalParent(function));
+ const char *attr_name = attr_to_str(attr);
+ unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name,
+ strlen(attr_name));
+ LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context, kind_id, 0);
+ LLVMAddAttributeAtIndex(function, attr_idx, llvm_attr);
+#endif
+}
+
LLVMValueRef
lp_build_intrinsic(LLVMBuilderRef builder,
const char *name,
LLVMTypeRef ret_type,
LLVMValueRef *args,
unsigned num_args,
- LLVMAttribute attr)
+ unsigned attr_mask)
{
LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
LLVMValueRef function;
/* NoUnwind indicates that the intrinsic never raises a C++ exception.
* Set it for all intrinsics.
*/
- LLVMAddFunctionAttr(function, attr | LLVMNoUnwindAttribute);
+ attr_mask |= LP_FUNC_ATTR_NOUNWIND;
+
+ while (attr_mask) {
+ enum lp_func_attr attr = 1 << u_bit_scan(&attr_mask);
+ lp_add_function_attr(function, -1, attr);
+ }
if (gallivm_debug & GALLIVM_DEBUG_IR) {
lp_debug_dump_value(function);
args[2] = buffer_index;
input = lp_build_intrinsic(gallivm->builder,
"llvm.SI.vs.load.input", ctx->v4f32, args, 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* Break up the vec4 into individual components */
for (chan = 0; chan < 4; chan++) {
type_names[func]);
return lp_build_intrinsic(gallivm->builder, name, types[func], args,
- ARRAY_SIZE(args), LLVMReadOnlyAttribute);
+ ARRAY_SIZE(args), LP_FUNC_ATTR_READONLY);
} else {
LLVMValueRef args[] = {
LLVMBuildBitCast(gallivm->builder, rsrc, ctx->v16i8, ""),
type_names[func], arg_type);
return lp_build_intrinsic(gallivm->builder, name, types[func], args,
- ARRAY_SIZE(args), LLVMReadOnlyAttribute);
+ ARRAY_SIZE(args), LP_FUNC_ATTR_READONLY);
}
}
value = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LLVMReadOnlyAttribute);
+ LP_FUNC_ATTR_READONLY);
if (tgsi_type_is_64bit(type)) {
LLVMValueRef value2;
args[2] = lp_build_const_int32(gallivm, (param * 4 + swizzle + 1) * 256);
value2 = lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx->i32, args, 9,
- LLVMReadOnlyAttribute);
+ LP_FUNC_ATTR_READONLY);
return si_llvm_emit_fetch_64bit(bld_base, type,
value, value2);
}
args[1] = attr_number;
front = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
args[1] = back_attr_number;
back = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
result[chan] = LLVMBuildSelect(gallivm->builder,
is_face_positive,
args[3] = interp_param;
result[0] = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
result[1] =
result[2] = lp_build_const_float(gallivm, 0.0f);
result[3] = lp_build_const_float(gallivm, 1.0f);
args[3] = interp_param;
result[chan] = lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
}
}
if (HAVE_LLVM < 0x0308) {
tid = lp_build_intrinsic(gallivm->builder, "llvm.SI.tid",
- ctx->i32, NULL, 0, LLVMReadNoneAttribute);
+ ctx->i32, NULL, 0, LP_FUNC_ATTR_READNONE);
} else {
LLVMValueRef tid_args[2];
tid_args[0] = lp_build_const_int32(gallivm, 0xffffffff);
tid_args[1] = lp_build_const_int32(gallivm, 0);
tid_args[1] = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.mbcnt.lo", ctx->i32,
- tid_args, 2, LLVMReadNoneAttribute);
+ tid_args, 2, LP_FUNC_ATTR_READNONE);
tid = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.mbcnt.hi", ctx->i32,
- tid_args, 2, LLVMReadNoneAttribute);
+ tid_args, 2, LP_FUNC_ATTR_READNONE);
}
set_range_metadata(ctx, tid, 0, 64);
return tid;
LLVMValueRef args[2] = {resource, offset};
return lp_build_intrinsic(builder, "llvm.SI.load.const", ctx->f32, args, 2,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
static LLVMValueRef load_sample_position(struct si_shader_context *radeon_bld, LLVMValueRef sample_id)
value = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.ps.live",
ctx->i1, NULL, 0,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
value = LLVMBuildNot(gallivm->builder, value, "");
value = LLVMBuildSExt(gallivm->builder, value, ctx->i32, "");
break;
packed = lp_build_intrinsic(base->gallivm->builder,
"llvm.SI.packf16",
ctx->i32, pack_args, 2,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
args[chan + 5] =
LLVMBuildBitCast(base->gallivm->builder,
packed, ctx->f32, "");
coverage = lp_build_intrinsic(gallivm->builder, "llvm.ctpop.i32",
ctx->i32,
- &coverage, 1, LLVMReadNoneAttribute);
+ &coverage, 1, LP_FUNC_ATTR_READNONE);
coverage = LLVMBuildUIToFP(gallivm->builder, coverage,
ctx->f32, "");
emit_data->output[emit_data->chan] = lp_build_intrinsic(
builder, intrinsic_name, dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute);
+ LP_FUNC_ATTR_READONLY);
}
static LLVMValueRef get_memory_ptr(struct si_shader_context *ctx,
lp_build_intrinsic(
builder, "llvm.amdgcn.buffer.load.format.v4f32", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute);
+ LP_FUNC_ATTR_READONLY);
} else {
get_image_intr_name("llvm.amdgcn.image.load",
emit_data->dst_type, /* vdata */
lp_build_intrinsic(
builder, intrinsic_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadOnlyAttribute);
+ LP_FUNC_ATTR_READONLY);
}
}
out = lp_build_intrinsic(
builder, "llvm.SI.getresinfo.i32", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* Divide the number of layers by 6 to get the number of cubes. */
if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY) {
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder, "llvm.SI.getresinfo.i32",
emit_data->dst_type, emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* Divide the number of layers by 6 to get the number of cubes. */
if (target == TGSI_TEXTURE_CUBE_ARRAY ||
emit_data->output[emit_data->chan] =
lp_build_intrinsic(builder, intr_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
static void build_tex_intrinsic(const struct lp_build_tgsi_action *action,
base->gallivm->builder,
"llvm.SI.vs.load.input", emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
return;
}
emit_data->output[emit_data->chan] = lp_build_intrinsic(
base->gallivm->builder, intr_name, emit_data->dst_type,
emit_data->args, emit_data->arg_count,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
static void si_llvm_emit_txqs(
args[1] = val;
tl = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.ds.bpermute", ctx->i32,
- args, 2, LLVMReadNoneAttribute);
+ args, 2, LP_FUNC_ATTR_READNONE);
args[0] = LLVMBuildMul(gallivm->builder, trbl_tid,
lp_build_const_int32(gallivm, 4), "");
trbl = lp_build_intrinsic(gallivm->builder,
"llvm.amdgcn.ds.bpermute", ctx->i32,
- args, 2, LLVMReadNoneAttribute);
+ args, 2, LP_FUNC_ATTR_READNONE);
} else {
LLVMValueRef store_ptr, load_ptr0, load_ptr1;
emit_data->output[chan] =
lp_build_intrinsic(gallivm->builder, intr_name,
ctx->f32, args, args[3] ? 4 : 3,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
}
* SGPR spilling significantly.
*/
if (LLVMGetTypeKind(LLVMTypeOf(P)) == LLVMPointerTypeKind) {
- LLVMAddAttribute(P, LLVMByValAttribute);
+ lp_add_function_attr(ctx->main_fn, i + 1, LP_FUNC_ATTR_BYVAL);
lp_add_attr_dereferenceable(P, UINT64_MAX);
} else
- LLVMAddAttribute(P, LLVMInRegAttribute);
+ lp_add_function_attr(ctx->main_fn, i + 1, LP_FUNC_ATTR_INREG);
}
if (ctx->screen->b.debug_flags & DBG_UNSAFE_MATH) {
lp_build_intrinsic(gallivm->builder,
"llvm.SI.buffer.load.dword.i32.i32",
ctx.i32, args, 9,
- LLVMReadOnlyAttribute),
+ LP_FUNC_ATTR_READONLY),
ctx.f32, "");
}
}
unsigned gprs;
for (unsigned i = 0; i < num_parts; ++i) {
- LLVMAddFunctionAttr(parts[i], LLVMAlwaysInlineAttribute);
+ lp_add_function_attr(parts[i], -1, LP_FUNC_ATTR_ALWAYSINLINE);
LLVMSetLinkage(parts[i], LLVMPrivateLinkage);
}
is_sgpr = ac_is_sgpr_param(param);
if (is_sgpr) {
+#if HAVE_LLVM < 0x0400
LLVMRemoveAttribute(param, LLVMByValAttribute);
- LLVMAddAttribute(param, LLVMInRegAttribute);
+#else
+ unsigned kind_id = LLVMGetEnumAttributeKindForName("byval", 5);
+ LLVMRemoveEnumAttributeAtIndex(parts[part], param_idx + 1, kind_id);
+#endif
+ lp_add_function_attr(parts[part], param_idx + 1, LP_FUNC_ATTR_INREG);
}
assert(out_idx + param_size <= (is_sgpr ? num_out_sgpr : num_out));
LLVMValueRef floor = lp_build_intrinsic(builder, intr, emit_data->dst_type,
&emit_data->args[0], 1,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
emit_data->output[emit_data->chan] = LLVMBuildFSub(builder,
emit_data->args[0], floor, "");
}
emit_data->output[emit_data->chan] =
lp_build_intrinsic(base->gallivm->builder, action->intr_name,
emit_data->dst_type, emit_data->args,
- emit_data->arg_count, LLVMReadNoneAttribute);
+ emit_data->arg_count, LP_FUNC_ATTR_READNONE);
}
static void emit_bfi(const struct lp_build_tgsi_action *action,
bfe_sm5 = lp_build_intrinsic(builder, action->intr_name,
emit_data->dst_type, emit_data->args,
- emit_data->arg_count, LLVMReadNoneAttribute);
+ emit_data->arg_count, LP_FUNC_ATTR_READNONE);
/* Correct for GLSL semantics. */
cond = LLVMBuildICmp(builder, LLVMIntUGE, emit_data->args[2],
LLVMValueRef lsb =
lp_build_intrinsic(gallivm->builder, "llvm.cttz.i32",
emit_data->dst_type, args, ARRAY_SIZE(args),
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* TODO: We need an intrinsic to skip this conditional. */
/* Check for zero: */
LLVMValueRef msb =
lp_build_intrinsic(builder, "llvm.ctlz.i32",
emit_data->dst_type, args, ARRAY_SIZE(args),
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* The HW returns the last bit index from MSB, but TGSI wants
* the index from LSB. Invert it by doing "31 - msb". */
LLVMValueRef msb =
lp_build_intrinsic(builder, "llvm.AMDGPU.flbit.i32",
emit_data->dst_type, &arg, 1,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
/* The HW returns the last bit index from MSB, but TGSI wants
* the index from LSB. Invert it by doing "31 - msb". */
LLVMValueRef out[4];
out[0] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubetc",
- f32, in, 3, LLVMReadNoneAttribute);
+ f32, in, 3, LP_FUNC_ATTR_READNONE);
out[1] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubesc",
- f32, in, 3, LLVMReadNoneAttribute);
+ f32, in, 3, LP_FUNC_ATTR_READNONE);
out[2] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubema",
- f32, in, 3, LLVMReadNoneAttribute);
+ f32, in, 3, LP_FUNC_ATTR_READNONE);
out[3] = lp_build_intrinsic(gallivm->builder, "llvm.amdgcn.cubeid",
- f32, in, 3, LLVMReadNoneAttribute);
+ f32, in, 3, LP_FUNC_ATTR_READNONE);
return lp_build_gather_values(gallivm, out, 4);
} else {
return lp_build_intrinsic(gallivm->builder, "llvm.AMDGPU.cube",
LLVMTypeOf(vec), &vec, 1,
- LLVMReadNoneAttribute);
+ LP_FUNC_ATTR_READNONE);
}
}
lp_build_const_int32(gallivm, i), "");
coords[2] = lp_build_intrinsic(builder, "llvm.fabs.f32",
- type, &coords[2], 1, LLVMReadNoneAttribute);
+ type, &coords[2], 1, LP_FUNC_ATTR_READNONE);
coords[2] = lp_build_emit_llvm_unary(bld_base, TGSI_OPCODE_RCP, coords[2]);
mad_args[1] = coords[2];