ac: first parse VS exports before eliminating constant ones
authorMarek Olšák <marek.olsak@amd.com>
Sat, 29 Apr 2017 21:47:08 +0000 (23:47 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 3 May 2017 18:55:00 +0000 (20:55 +0200)
A later commit will make use of this.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/amd/common/ac_llvm_build.c

index 209dfdd656a2376ed06395ea637094ecbb1a4c5b..5b42e47fa0c9bfaab27b51ebd84db102b1c006dc 100644 (file)
@@ -1250,28 +1250,47 @@ void ac_get_image_intr_name(const char *base_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 */
@@ -1288,11 +1307,11 @@ static bool ac_eliminate_const_output(uint8_t *vs_output_param_offset,
                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;
@@ -1301,12 +1320,6 @@ static bool ac_eliminate_const_output(uint8_t *vs_output_param_offset,
        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,
@@ -1327,6 +1340,7 @@ void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ctx,
                while (inst) {
                        LLVMValueRef cur = inst;
                        inst = LLVMGetNextInstruction(inst);
+                       struct ac_vs_exp_inst exp;
 
                        if (LLVMGetInstructionOpcode(cur) != LLVMCall)
                                continue;
@@ -1353,14 +1367,34 @@ void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ctx,
 
                        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);
@@ -1380,13 +1414,13 @@ void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ctx,
                       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;