[Mesa-dev] [PATCH v2 61/73] ac/nir: add always_vector argument to ac_build_gather_values_extended

Nicolai Hähnle nhaehnle at gmail.com
Wed Jul 5 10:48:45 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

This simplifies a bunch of places that no longer need special treatment
of value_count == 1. We rely on LLVM to optimize away the 1-element vector
types.

This fixes a bunch of bugs where 1-element arrays are indexed indirectly.
---
 src/amd/common/ac_llvm_build.c  |  7 ++++---
 src/amd/common/ac_llvm_build.h  |  3 ++-
 src/amd/common/ac_nir_to_llvm.c | 22 +++++++---------------
 3 files changed, 13 insertions(+), 19 deletions(-)

diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c
index 2cc4eae..2dddf44 100644
--- a/src/amd/common/ac_llvm_build.c
+++ b/src/amd/common/ac_llvm_build.c
@@ -174,27 +174,28 @@ void ac_build_type_name_for_intr(LLVMTypeRef type, char *buf, unsigned bufsize)
 		snprintf(buf, bufsize, "f64");
 		break;
 	}
 }
 
 LLVMValueRef
 ac_build_gather_values_extended(struct ac_llvm_context *ctx,
 				LLVMValueRef *values,
 				unsigned value_count,
 				unsigned value_stride,
-				bool load)
+				bool load,
+				bool always_vector)
 {
 	LLVMBuilderRef builder = ctx->builder;
 	LLVMValueRef vec = NULL;
 	unsigned i;
 
-	if (value_count == 1) {
+	if (value_count == 1 && !always_vector) {
 		if (load)
 			return LLVMBuildLoad(builder, values[0], "");
 		return values[0];
 	} else if (!value_count)
 		unreachable("value_count is 0");
 
 	for (i = 0; i < value_count; i++) {
 		LLVMValueRef value = values[i * value_stride];
 		if (load)
 			value = LLVMBuildLoad(builder, value, "");
@@ -205,21 +206,21 @@ ac_build_gather_values_extended(struct ac_llvm_context *ctx,
 		vec = LLVMBuildInsertElement(builder, vec, value, index, "");
 	}
 	return vec;
 }
 
 LLVMValueRef
 ac_build_gather_values(struct ac_llvm_context *ctx,
 		       LLVMValueRef *values,
 		       unsigned value_count)
 {
-	return ac_build_gather_values_extended(ctx, values, value_count, 1, false);
+	return ac_build_gather_values_extended(ctx, values, value_count, 1, false, false);
 }
 
 LLVMValueRef
 ac_build_fdiv(struct ac_llvm_context *ctx,
 	      LLVMValueRef num,
 	      LLVMValueRef den)
 {
 	LLVMValueRef ret = LLVMBuildFDiv(ctx->builder, num, den, "");
 
 	if (!LLVMIsConstant(ret))
diff --git a/src/amd/common/ac_llvm_build.h b/src/amd/common/ac_llvm_build.h
index 10efabb..f25af8b 100644
--- a/src/amd/common/ac_llvm_build.h
+++ b/src/amd/common/ac_llvm_build.h
@@ -71,21 +71,22 @@ ac_build_intrinsic(struct ac_llvm_context *ctx, const char *name,
 		   LLVMTypeRef return_type, LLVMValueRef *params,
 		   unsigned param_count, unsigned attrib_mask);
 
 void ac_build_type_name_for_intr(LLVMTypeRef type, char *buf, unsigned bufsize);
 
 LLVMValueRef
 ac_build_gather_values_extended(struct ac_llvm_context *ctx,
 				LLVMValueRef *values,
 				unsigned value_count,
 				unsigned value_stride,
-				bool load);
+				bool load,
+				bool always_vector);
 LLVMValueRef
 ac_build_gather_values(struct ac_llvm_context *ctx,
 		       LLVMValueRef *values,
 		       unsigned value_count);
 
 LLVMValueRef
 ac_build_fdiv(struct ac_llvm_context *ctx,
 	      LLVMValueRef num,
 	      LLVMValueRef den);
 
diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index bc3cb2d..c5b28d1 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -1024,25 +1024,20 @@ static LLVMValueRef trim_vector(struct ac_llvm_context *ctx,
 static void
 build_store_values_extended(struct ac_llvm_context *ac,
 			     LLVMValueRef *values,
 			     unsigned value_count,
 			     unsigned value_stride,
 			     LLVMValueRef vec)
 {
 	LLVMBuilderRef builder = ac->builder;
 	unsigned i;
 
-	if (value_count == 1) {
-		LLVMBuildStore(builder, vec, values[0]);
-		return;
-	}
-
 	for (i = 0; i < value_count; i++) {
 		LLVMValueRef ptr = values[i * value_stride];
 		LLVMValueRef index = LLVMConstInt(ac->i32, i, false);
 		LLVMValueRef value = LLVMBuildExtractElement(builder, vec, index, "");
 		LLVMBuildStore(builder, value, ptr);
 	}
 }
 
 static LLVMTypeRef get_def_type(struct ac_nir_context *ctx,
                                 const nir_ssa_def *def)
@@ -2954,58 +2949,58 @@ static LLVMValueRef visit_load_var(struct ac_nir_context *ctx,
 			return load_gs_input(ctx->nctx, instr);
 		}
 		for (unsigned chan = 0; chan < ve; chan++) {
 			if (indir_index) {
 				unsigned count = glsl_count_attribute_slots(
 						instr->variables[0]->var->type,
 						ctx->stage == MESA_SHADER_VERTEX);
 				count -= chan / 4;
 				LLVMValueRef tmp_vec = ac_build_gather_values_extended(
 						&ctx->ac, ctx->abi->inputs + idx + chan, count,
-						4, false);
+						4, false, true);
 
 				values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
 								       tmp_vec,
 								       indir_index, "");
 			} else
 				values[chan] = ctx->abi->inputs[idx + chan + const_index * 4];
 		}
 		break;
 	case nir_var_local:
 		for (unsigned chan = 0; chan < ve; chan++) {
 			if (indir_index) {
 				unsigned count = glsl_count_attribute_slots(
 					instr->variables[0]->var->type, false);
 				count -= chan / 4;
 				LLVMValueRef tmp_vec = ac_build_gather_values_extended(
 						&ctx->ac, ctx->locals + idx + chan, count,
-						4, true);
+						4, true, true);
 
 				values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
 								       tmp_vec,
 								       indir_index, "");
 			} else {
 				values[chan] = LLVMBuildLoad(ctx->ac.builder, ctx->locals[idx + chan + const_index * 4], "");
 			}
 		}
 		break;
 	case nir_var_shader_out:
 		if (ctx->stage == MESA_SHADER_TESS_CTRL)
 			return load_tcs_output(ctx->nctx, instr);
 		for (unsigned chan = 0; chan < ve; chan++) {
 			if (indir_index) {
 				unsigned count = glsl_count_attribute_slots(
 						instr->variables[0]->var->type, false);
 				count -= chan / 4;
 				LLVMValueRef tmp_vec = ac_build_gather_values_extended(
 						&ctx->ac, ctx->outputs + idx + chan, count,
-						4, true);
+						4, true, true);
 
 				values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
 								       tmp_vec,
 								       indir_index, "");
 			} else {
 				values[chan] = LLVMBuildLoad(ctx->ac.builder,
 						     ctx->outputs[idx + chan + const_index * 4],
 						     "");
 			}
 		}
@@ -3077,27 +3072,24 @@ visit_store_var(struct ac_nir_context *ctx,
 			value = llvm_extract_elem(&ctx->ac, src, chan);
 
 			if (instr->variables[0]->var->data.compact)
 				stride = 1;
 			if (indir_index) {
 				unsigned count = glsl_count_attribute_slots(
 						instr->variables[0]->var->type, false);
 				count -= chan / 4;
 				LLVMValueRef tmp_vec = ac_build_gather_values_extended(
 						&ctx->ac, ctx->outputs + idx + chan, count,
-						stride, true);
+						stride, true, true);
 
-				if (get_llvm_num_components(tmp_vec) > 1) {
-					tmp_vec = LLVMBuildInsertElement(ctx->ac.builder, tmp_vec,
-									 value, indir_index, "");
-				} else
-					tmp_vec = value;
+				tmp_vec = LLVMBuildInsertElement(ctx->ac.builder, tmp_vec,
+							         value, indir_index, "");
 				build_store_values_extended(&ctx->ac, ctx->outputs + idx + chan,
 							    count, stride, tmp_vec);
 
 			} else {
 				temp_ptr = ctx->outputs[idx + chan + const_index * stride];
 
 				LLVMBuildStore(ctx->ac.builder, value, temp_ptr);
 			}
 		}
 		break;
@@ -3106,21 +3098,21 @@ visit_store_var(struct ac_nir_context *ctx,
 			if (!(writemask & (1 << chan)))
 				continue;
 
 			value = llvm_extract_elem(&ctx->ac, src, chan);
 			if (indir_index) {
 				unsigned count = glsl_count_attribute_slots(
 					instr->variables[0]->var->type, false);
 				count -= chan / 4;
 				LLVMValueRef tmp_vec = ac_build_gather_values_extended(
 					&ctx->ac, ctx->locals + idx + chan, count,
-					4, true);
+					4, true, true);
 
 				tmp_vec = LLVMBuildInsertElement(ctx->ac.builder, tmp_vec,
 								 value, indir_index, "");
 				build_store_values_extended(&ctx->ac, ctx->locals + idx + chan,
 							    count, 4, tmp_vec);
 			} else {
 				temp_ptr = ctx->locals[idx + chan + const_index * 4];
 
 				LLVMBuildStore(ctx->ac.builder, value, temp_ptr);
 			}
-- 
2.9.3



More information about the mesa-dev mailing list