From: Marek Olšák <marek.ol...@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

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to