summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNicolai Hähnle <[email protected]>2016-08-08 23:13:44 +0200
committerNicolai Hähnle <[email protected]>2016-08-17 12:11:23 +0200
commit4b150931c90598138ef2cf1e9e03ba59dbc30b05 (patch)
tree0a586b9efa8e80f4a9e3123fd39995c33067afe3 /src
parentdfbb8ea2845de0524ca7022f1b76d1dc2509a296 (diff)
gallium/radeon: extract common getelementptr logic into get_pointer_into_array
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c105
1 files changed, 66 insertions, 39 deletions
diff --git a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
index 531a8fefc7e..87fc07ec2e3 100644
--- a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
+++ b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
@@ -187,6 +187,41 @@ emit_array_index(struct lp_build_tgsi_soa_context *bld,
return LLVMBuildAdd(gallivm->builder, addr, lp_build_const_int32(gallivm, offset), "");
}
+/**
+ * For indirect registers, construct a pointer directly to the requested
+ * element using getelementptr if possible.
+ *
+ * Returns NULL if the insertelement/extractelement fallback for array access
+ * must be used.
+ */
+static LLVMValueRef
+get_pointer_into_array(struct radeon_llvm_context *ctx,
+ unsigned file,
+ unsigned swizzle,
+ unsigned reg_index,
+ const struct tgsi_ind_register *reg_indirect)
+{
+ const struct radeon_llvm_array *array;
+ struct gallivm_state *gallivm = ctx->soa.bld_base.base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef idxs[2];
+ LLVMValueRef index;
+
+ if (file != TGSI_FILE_TEMPORARY)
+ return NULL;
+
+ array = get_temp_array(&ctx->soa.bld_base, reg_index, reg_indirect);
+ if (!array || !array->alloca)
+ return NULL;
+
+ index = emit_array_index(&ctx->soa, reg_indirect, reg_index - array->range.First);
+ index = LLVMBuildMul(builder, index, lp_build_const_int32(gallivm, TGSI_NUM_CHANNELS), "");
+ index = LLVMBuildAdd(builder, index, lp_build_const_int32(gallivm, swizzle), "");
+ idxs[0] = ctx->soa.bld_base.uint_bld.zero;
+ idxs[1] = index;
+ return LLVMBuildGEP(builder, array->alloca, idxs, 2, "");
+}
+
LLVMValueRef
radeon_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base,
enum tgsi_opcode_type type,
@@ -243,36 +278,32 @@ load_value_from_array(struct lp_build_tgsi_context *bld_base,
unsigned reg_index,
const struct tgsi_ind_register *reg_indirect)
{
+ struct radeon_llvm_context *ctx = radeon_llvm_context(bld_base);
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
- struct tgsi_declaration_range range = get_array_range(bld_base, file, reg_index, reg_indirect);
- LLVMValueRef index = emit_array_index(bld, reg_indirect, reg_index - range.First);
- LLVMValueRef array = get_alloca_for_array(bld_base, file, reg_index, reg_indirect);
- LLVMValueRef ptr, val, indices[2];
-
- if (!array) {
- /* Handle the case where the array is stored as a vector. */
- return LLVMBuildExtractElement(builder,
- emit_array_fetch(bld_base, file, type, range, swizzle),
- index, "");
- }
+ LLVMValueRef ptr;
- index = LLVMBuildMul(builder, index, lp_build_const_int32(gallivm, TGSI_NUM_CHANNELS), "");
- index = LLVMBuildAdd(builder, index, lp_build_const_int32(gallivm, swizzle), "");
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = index;
- ptr = LLVMBuildGEP(builder, array, indices, 2, "");
- val = LLVMBuildLoad(builder, ptr, "");
- if (tgsi_type_is_64bit(type)) {
- LLVMValueRef ptr_hi, val_hi;
- indices[0] = lp_build_const_int32(gallivm, 1);
- ptr_hi = LLVMBuildGEP(builder, ptr, indices, 1, "");
- val_hi = LLVMBuildLoad(builder, ptr_hi, "");
- val = radeon_llvm_emit_fetch_64bit(bld_base, type, val, val_hi);
+ ptr = get_pointer_into_array(ctx, file, swizzle, reg_index, reg_indirect);
+ if (ptr) {
+ LLVMValueRef val = LLVMBuildLoad(builder, ptr, "");
+ if (tgsi_type_is_64bit(type)) {
+ LLVMValueRef ptr_hi, val_hi;
+ ptr_hi = LLVMBuildGEP(builder, ptr, &bld_base->uint_bld.one, 1, "");
+ val_hi = LLVMBuildLoad(builder, ptr_hi, "");
+ val = radeon_llvm_emit_fetch_64bit(bld_base, type, val, val_hi);
+ }
+ return val;
+ } else {
+ struct tgsi_declaration_range range =
+ get_array_range(bld_base, file, reg_index, reg_indirect);
+ LLVMValueRef index =
+ emit_array_index(bld, reg_indirect, reg_index - range.First);
+ LLVMValueRef array =
+ emit_array_fetch(bld_base, file, type, range, swizzle);
+ return LLVMBuildExtractElement(builder, array, index, "");
}
- return val;
}
static LLVMValueRef
@@ -283,26 +314,22 @@ store_value_to_array(struct lp_build_tgsi_context *bld_base,
unsigned reg_index,
const struct tgsi_ind_register *reg_indirect)
{
+ struct radeon_llvm_context *ctx = radeon_llvm_context(bld_base);
struct lp_build_tgsi_soa_context *bld = lp_soa_context(bld_base);
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
- struct tgsi_declaration_range range = get_array_range(bld_base, file, reg_index, reg_indirect);
- LLVMValueRef index = emit_array_index(bld, reg_indirect, reg_index - range.First);
- LLVMValueRef array = get_alloca_for_array(bld_base, file, reg_index, reg_indirect);
-
- if (array) {
- LLVMValueRef indices[2];
- index = LLVMBuildMul(builder, index, lp_build_const_int32(gallivm, TGSI_NUM_CHANNELS), "");
- index = LLVMBuildAdd(builder, index, lp_build_const_int32(gallivm, chan_index), "");
- indices[0] = bld_base->uint_bld.zero;
- indices[1] = index;
- LLVMValueRef pointer = LLVMBuildGEP(builder, array, indices, 2, "");
- LLVMBuildStore(builder, value, pointer);
+ LLVMValueRef ptr;
+
+ ptr = get_pointer_into_array(ctx, file, chan_index, reg_index, reg_indirect);
+ if (ptr) {
+ LLVMBuildStore(builder, value, ptr);
return NULL;
} else {
- return LLVMBuildInsertElement(builder,
- emit_array_fetch(bld_base, file, TGSI_TYPE_FLOAT, range, chan_index),
- value, index, "");
+ struct tgsi_declaration_range range = get_array_range(bld_base, file, reg_index, reg_indirect);
+ LLVMValueRef index = emit_array_index(bld, reg_indirect, reg_index - range.First);
+ LLVMValueRef array =
+ emit_array_fetch(bld_base, file, TGSI_TYPE_FLOAT, range, chan_index);
+ return LLVMBuildInsertElement(builder, array, value, index, "");
}
}