summaryrefslogtreecommitdiffstats
path: root/src/amd
diff options
context:
space:
mode:
Diffstat (limited to 'src/amd')
-rw-r--r--src/amd/common/ac_llvm_util.c48
-rw-r--r--src/amd/common/ac_llvm_util.h6
2 files changed, 53 insertions, 1 deletions
diff --git a/src/amd/common/ac_llvm_util.c b/src/amd/common/ac_llvm_util.c
index bc309bd81c4..4c114585292 100644
--- a/src/amd/common/ac_llvm_util.c
+++ b/src/amd/common/ac_llvm_util.c
@@ -168,6 +168,9 @@ ac_llvm_context_init(struct ac_llvm_context *ctx, LLVMContextRef context)
ctx->v4f32 = LLVMVectorType(ctx->f32, 4);
ctx->v16i8 = LLVMVectorType(ctx->i8, 16);
+ ctx->range_md_kind = LLVMGetMDKindIDInContext(ctx->context,
+ "range", 5);
+
ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(ctx->context,
"invariant.load", 14);
@@ -803,3 +806,48 @@ ac_build_buffer_load(struct ac_llvm_context *ctx,
ARRAY_SIZE(args), AC_FUNC_ATTR_READONLY);
}
}
+
+/**
+ * Set range metadata on an instruction. This can only be used on load and
+ * call instructions. If you know an instruction can only produce the values
+ * 0, 1, 2, you would do set_range_metadata(value, 0, 3);
+ * \p lo is the minimum value inclusive.
+ * \p hi is the maximum value exclusive.
+ */
+static void set_range_metadata(struct ac_llvm_context *ctx,
+ LLVMValueRef value, unsigned lo, unsigned hi)
+{
+ LLVMValueRef range_md, md_args[2];
+ LLVMTypeRef type = LLVMTypeOf(value);
+ LLVMContextRef context = LLVMGetTypeContext(type);
+
+ md_args[0] = LLVMConstInt(type, lo, false);
+ md_args[1] = LLVMConstInt(type, hi, false);
+ range_md = LLVMMDNodeInContext(context, md_args, 2);
+ LLVMSetMetadata(value, ctx->range_md_kind, range_md);
+}
+
+LLVMValueRef
+ac_get_thread_id(struct ac_llvm_context *ctx)
+{
+ LLVMValueRef tid;
+
+ if (HAVE_LLVM < 0x0308) {
+ tid = ac_emit_llvm_intrinsic(ctx, "llvm.SI.tid",
+ ctx->i32,
+ NULL, 0, AC_FUNC_ATTR_READNONE);
+ } else {
+ LLVMValueRef tid_args[2];
+ tid_args[0] = LLVMConstInt(ctx->i32, 0xffffffff, false);
+ tid_args[1] = LLVMConstInt(ctx->i32, 0, false);
+ tid_args[1] = ac_emit_llvm_intrinsic(ctx,
+ "llvm.amdgcn.mbcnt.lo", ctx->i32,
+ tid_args, 2, AC_FUNC_ATTR_READNONE);
+
+ tid = ac_emit_llvm_intrinsic(ctx, "llvm.amdgcn.mbcnt.hi",
+ ctx->i32, tid_args,
+ 2, AC_FUNC_ATTR_READNONE);
+ }
+ set_range_metadata(ctx, tid, 0, 64);
+ return tid;
+}
diff --git a/src/amd/common/ac_llvm_util.h b/src/amd/common/ac_llvm_util.h
index 7b08a269fcb..0244dc48b3d 100644
--- a/src/amd/common/ac_llvm_util.h
+++ b/src/amd/common/ac_llvm_util.h
@@ -57,7 +57,8 @@ struct ac_llvm_context {
LLVMTypeRef v4i32;
LLVMTypeRef v4f32;
LLVMTypeRef v16i8;
-
+
+ unsigned range_md_kind;
unsigned invariant_load_md_kind;
unsigned uniform_md_kind;
unsigned fpmath_md_kind;
@@ -176,6 +177,9 @@ ac_build_buffer_load(struct ac_llvm_context *ctx,
unsigned inst_offset,
unsigned glc,
unsigned slc);
+
+LLVMValueRef
+ac_get_thread_id(struct ac_llvm_context *ctx);
#ifdef __cplusplus
}
#endif