[Mesa-dev] [PATCH 1/3] ac: first parse VS exports before eliminating constant ones

Marek Olšák maraeo at gmail.com
Mon May 1 12:42:59 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

A later commit will make use of this.
---
 src/amd/common/ac_llvm_build.c | 82 +++++++++++++++++++++++++++++-------------
 1 file changed, 58 insertions(+), 24 deletions(-)

diff --git a/src/amd/common/ac_llvm_build.c b/src/amd/common/ac_llvm_build.c
index ba92e7e..4856c06 100644
--- a/src/amd/common/ac_llvm_build.c
+++ b/src/amd/common/ac_llvm_build.c
@@ -1170,97 +1170,111 @@ void ac_get_image_intr_name(const char *base_name,
                 ac_build_type_name_for_intr(rsrc_type, rsrc_type_name,
                                         sizeof(rsrc_type_name));
                 snprintf(out_name, out_len, "%s.%s.%s.%s", base_name,
                          data_type_name, coords_type_name, rsrc_type_name);
         }
 }
 
 #define AC_EXP_TARGET (HAVE_LLVM >= 0x0500 ? 0 : 3)
 #define AC_EXP_OUT0 (HAVE_LLVM >= 0x0500 ? 2 : 5)
 
+enum ac_ir_type {
+	AC_IR_UNDEF,
+	AC_IR_CONST,
+	AC_IR_VALUE,
+};
+
+struct ac_vs_exp_chan
+{
+	LLVMValueRef value;
+	float const_float;
+	enum ac_ir_type type;
+};
+
+struct ac_vs_exp_inst {
+	unsigned offset;
+	LLVMValueRef inst;
+	struct ac_vs_exp_chan chan[4];
+};
+
+struct ac_vs_exports {
+	unsigned num;
+	struct ac_vs_exp_inst exp[VARYING_SLOT_MAX];
+};
+
 /* Return true if the PARAM export has been eliminated. */
 static bool ac_eliminate_const_output(uint8_t *vs_output_param_offset,
 				      uint32_t num_outputs,
-				      LLVMValueRef inst, unsigned offset)
+				      struct ac_vs_exp_inst *exp)
 {
 	unsigned i, default_val; /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL */
 	bool is_zero[4] = {}, is_one[4] = {};
 
 	for (i = 0; i < 4; i++) {
-		LLVMBool loses_info;
-		LLVMValueRef p = LLVMGetOperand(inst, AC_EXP_OUT0 + i);
-
 		/* It's a constant expression. Undef outputs are eliminated too. */
-		if (LLVMIsUndef(p)) {
+		if (exp->chan[i].type == AC_IR_UNDEF) {
 			is_zero[i] = true;
 			is_one[i] = true;
-		} else if (LLVMIsAConstantFP(p)) {
-			double a = LLVMConstRealGetDouble(p, &loses_info);
-
-			if (a == 0)
+		} else if (exp->chan[i].type == AC_IR_CONST) {
+			if (exp->chan[i].const_float == 0)
 				is_zero[i] = true;
-			else if (a == 1)
+			else if (exp->chan[i].const_float == 1)
 				is_one[i] = true;
 			else
 				return false; /* other constant */
 		} else
 			return false;
 	}
 
 	/* Only certain combinations of 0 and 1 can be eliminated. */
 	if (is_zero[0] && is_zero[1] && is_zero[2])
 		default_val = is_zero[3] ? 0 : 1;
 	else if (is_one[0] && is_one[1] && is_one[2])
 		default_val = is_zero[3] ? 2 : 3;
 	else
 		return false;
 
 	/* The PARAM export can be represented as DEFAULT_VAL. Kill it. */
-	LLVMInstructionEraseFromParent(inst);
+	LLVMInstructionEraseFromParent(exp->inst);
 
 	/* Change OFFSET to DEFAULT_VAL. */
 	for (i = 0; i < num_outputs; i++) {
-		if (vs_output_param_offset[i] == offset) {
+		if (vs_output_param_offset[i] == exp->offset) {
 			vs_output_param_offset[i] =
 				AC_EXP_PARAM_DEFAULT_VAL_0000 + default_val;
 			break;
 		}
 	}
 	return true;
 }
 
-struct ac_vs_exports {
-	unsigned num;
-	unsigned offset[VARYING_SLOT_MAX];
-	LLVMValueRef inst[VARYING_SLOT_MAX];
-};
-
 void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ctx,
 				   LLVMValueRef main_fn,
 				   uint8_t *vs_output_param_offset,
 				   uint32_t num_outputs,
 				   uint8_t *num_param_exports)
 {
 	LLVMBasicBlockRef bb;
 	bool removed_any = false;
 	struct ac_vs_exports exports;
 
 	exports.num = 0;
 
 	/* Process all LLVM instructions. */
 	bb = LLVMGetFirstBasicBlock(main_fn);
 	while (bb) {
 		LLVMValueRef inst = LLVMGetFirstInstruction(bb);
 
 		while (inst) {
 			LLVMValueRef cur = inst;
 			inst = LLVMGetNextInstruction(inst);
+			struct ac_vs_exp_inst exp;
 
 			if (LLVMGetInstructionOpcode(cur) != LLVMCall)
 				continue;
 
 			LLVMValueRef callee = ac_llvm_get_called_value(cur);
 
 			if (!ac_llvm_is_function(callee))
 				continue;
 
 			const char *name = LLVMGetValueName(callee);
@@ -1273,54 +1287,74 @@ void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ctx,
 				continue;
 
 			LLVMValueRef arg = LLVMGetOperand(cur, AC_EXP_TARGET);
 			unsigned target = LLVMConstIntGetZExtValue(arg);
 
 			if (target < V_008DFC_SQ_EXP_PARAM)
 				continue;
 
 			target -= V_008DFC_SQ_EXP_PARAM;
 
+			/* Parse the instruction. */
+			memset(&exp, 0, sizeof(exp));
+			exp.offset = target;
+			exp.inst = cur;
+
+			for (unsigned i = 0; i < 4; i++) {
+				LLVMValueRef v = LLVMGetOperand(cur, AC_EXP_OUT0 + i);
+
+				exp.chan[i].value = v;
+
+				if (LLVMIsUndef(v)) {
+					exp.chan[i].type = AC_IR_UNDEF;
+				} else if (LLVMIsAConstantFP(v)) {
+					LLVMBool loses_info;
+					exp.chan[i].type = AC_IR_CONST;
+					exp.chan[i].const_float =
+						LLVMConstRealGetDouble(v, &loses_info);
+				} else {
+					exp.chan[i].type = AC_IR_VALUE;
+				}
+			}
+
 			/* Eliminate constant value PARAM exports. */
 			if (ac_eliminate_const_output(vs_output_param_offset,
-						      num_outputs, cur, target)) {
+						      num_outputs, &exp)) {
 				removed_any = true;
 			} else {
-				exports.offset[exports.num] = target;
-				exports.inst[exports.num] = cur;
-				exports.num++;
+				exports.exp[exports.num++] = exp;
 			}
 		}
 		bb = LLVMGetNextBasicBlock(bb);
 	}
 
 	/* Remove holes in export memory due to removed PARAM exports.
 	 * This is done by renumbering all PARAM exports.
 	 */
 	if (removed_any) {
 		uint8_t current_offset[VARYING_SLOT_MAX];
 		unsigned new_count = 0;
 		unsigned out, i;
 
 		/* Make a copy of the offsets. We need the old version while
 		 * we are modifying some of them. */
 		memcpy(current_offset, vs_output_param_offset,
 		       sizeof(current_offset));
 
 		for (i = 0; i < exports.num; i++) {
-			unsigned offset = exports.offset[i];
+			unsigned offset = exports.exp[i].offset;
 
 			for (out = 0; out < num_outputs; out++) {
 				if (current_offset[out] != offset)
 					continue;
 
-				LLVMSetOperand(exports.inst[i], AC_EXP_TARGET,
+				LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET,
 					       LLVMConstInt(ctx->i32,
 							    V_008DFC_SQ_EXP_PARAM + new_count, 0));
 				vs_output_param_offset[out] = new_count;
 				new_count++;
 				break;
 			}
 		}
 		*num_param_exports = new_count;
 	}
 }
-- 
2.7.4



More information about the mesa-dev mailing list