Mesa (main): ac/llvm: remove LLVM pass ac_optimize_vs_outputs

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 22 22:47:28 UTC 2022


Module: Mesa
Branch: main
Commit: 5af4d0c2dca66ed4d563f62d5790e7b931a16bd8
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5af4d0c2dca66ed4d563f62d5790e7b931a16bd8

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Sun Dec 26 19:12:17 2021 -0500

ac/llvm: remove LLVM pass ac_optimize_vs_outputs

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14414>

---

 src/amd/llvm/ac_llvm_build.c | 262 -------------------------------------------
 src/amd/llvm/ac_llvm_build.h |   3 -
 2 files changed, 265 deletions(-)

diff --git a/src/amd/llvm/ac_llvm_build.c b/src/amd/llvm/ac_llvm_build.c
index 33836b6d18e..aae410de3da 100644
--- a/src/amd/llvm/ac_llvm_build.c
+++ b/src/amd/llvm/ac_llvm_build.c
@@ -2714,268 +2714,6 @@ LLVMValueRef ac_build_bitfield_reverse(struct ac_llvm_context *ctx, LLVMValueRef
    return result;
 }
 
-#define AC_EXP_TARGET           0
-#define AC_EXP_ENABLED_CHANNELS 1
-#define AC_EXP_OUT0             2
-
-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,
-                                      struct ac_vs_exp_inst *exp)
-{
-   unsigned i, default_val; /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL */
-   bool is_zero[4] = {0}, is_one[4] = {0};
-
-   for (i = 0; i < 4; i++) {
-      /* It's a constant expression. Undef outputs are eliminated too. */
-      if (exp->chan[i].type == AC_IR_UNDEF) {
-         is_zero[i] = true;
-         is_one[i] = true;
-      } else if (exp->chan[i].type == AC_IR_CONST) {
-         if (exp->chan[i].const_float == 0)
-            is_zero[i] = true;
-         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(exp->inst);
-
-   /* Change OFFSET to DEFAULT_VAL. */
-   for (i = 0; i < num_outputs; i++) {
-      if (vs_output_param_offset[i] == exp->offset) {
-         vs_output_param_offset[i] = AC_EXP_PARAM_DEFAULT_VAL_0000 + default_val;
-         break;
-      }
-   }
-   return true;
-}
-
-static bool ac_eliminate_duplicated_output(struct ac_llvm_context *ctx,
-                                           uint8_t *vs_output_param_offset, uint32_t num_outputs,
-                                           struct ac_vs_exports *processed,
-                                           struct ac_vs_exp_inst *exp)
-{
-   unsigned p, copy_back_channels = 0;
-
-   /* See if the output is already in the list of processed outputs.
-    * The LLVMValueRef comparison relies on SSA.
-    */
-   for (p = 0; p < processed->num; p++) {
-      bool different = false;
-
-      for (unsigned j = 0; j < 4; j++) {
-         struct ac_vs_exp_chan *c1 = &processed->exp[p].chan[j];
-         struct ac_vs_exp_chan *c2 = &exp->chan[j];
-
-         /* Treat undef as a match. */
-         if (c2->type == AC_IR_UNDEF)
-            continue;
-
-         /* If c1 is undef but c2 isn't, we can copy c2 to c1
-          * and consider the instruction duplicated.
-          */
-         if (c1->type == AC_IR_UNDEF) {
-            copy_back_channels |= 1 << j;
-            continue;
-         }
-
-         /* Test whether the channels are not equal. */
-         if (c1->type != c2->type ||
-             (c1->type == AC_IR_CONST && c1->const_float != c2->const_float) ||
-             (c1->type == AC_IR_VALUE && c1->value != c2->value)) {
-            different = true;
-            break;
-         }
-      }
-      if (!different)
-         break;
-
-      copy_back_channels = 0;
-   }
-   if (p == processed->num)
-      return false;
-
-   /* If a match was found, but the matching export has undef where the new
-    * one has a normal value, copy the normal value to the undef channel.
-    */
-   struct ac_vs_exp_inst *match = &processed->exp[p];
-
-   /* Get current enabled channels mask. */
-   LLVMValueRef arg = LLVMGetOperand(match->inst, AC_EXP_ENABLED_CHANNELS);
-   unsigned enabled_channels = LLVMConstIntGetZExtValue(arg);
-
-   while (copy_back_channels) {
-      unsigned chan = u_bit_scan(&copy_back_channels);
-
-      assert(match->chan[chan].type == AC_IR_UNDEF);
-      LLVMSetOperand(match->inst, AC_EXP_OUT0 + chan, exp->chan[chan].value);
-      match->chan[chan] = exp->chan[chan];
-
-      /* Update number of enabled channels because the original mask
-       * is not always 0xf.
-       */
-      enabled_channels |= (1 << chan);
-      LLVMSetOperand(match->inst, AC_EXP_ENABLED_CHANNELS,
-                     LLVMConstInt(ctx->i32, enabled_channels, 0));
-   }
-
-   /* The PARAM export is duplicated. Kill it. */
-   LLVMInstructionEraseFromParent(exp->inst);
-
-   /* Change OFFSET to the matching export. */
-   for (unsigned i = 0; i < num_outputs; i++) {
-      if (vs_output_param_offset[i] == exp->offset) {
-         vs_output_param_offset[i] = match->offset;
-         break;
-      }
-   }
-   return true;
-}
-
-void ac_optimize_vs_outputs(struct ac_llvm_context *ctx, LLVMValueRef main_fn,
-                            uint8_t *vs_output_param_offset, uint32_t num_outputs,
-                            uint32_t skip_output_mask, 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);
-         unsigned num_args = LLVMCountParams(callee);
-
-         /* Check if this is an export instruction. */
-         if ((num_args != 9 && num_args != 8) ||
-             (strcmp(name, "llvm.SI.export") && strcmp(name, "llvm.amdgcn.exp.f32")))
-            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 and duplicated PARAM exports. */
-         if (!((1u << target) & skip_output_mask) &&
-             (ac_eliminate_const_output(vs_output_param_offset, num_outputs, &exp) ||
-              ac_eliminate_duplicated_output(ctx, vs_output_param_offset, num_outputs, &exports,
-                                             &exp))) {
-            removed_any = true;
-         } else {
-            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 old_offset[VARYING_SLOT_MAX];
-      unsigned out, i;
-
-      /* Make a copy of the offsets. We need the old version while
-       * we are modifying some of them. */
-      memcpy(old_offset, vs_output_param_offset, sizeof(old_offset));
-
-      for (i = 0; i < exports.num; i++) {
-         unsigned offset = exports.exp[i].offset;
-
-         /* Update vs_output_param_offset. Multiple outputs can
-          * have the same offset.
-          */
-         for (out = 0; out < num_outputs; out++) {
-            if (old_offset[out] == offset)
-               vs_output_param_offset[out] = i;
-         }
-
-         /* Change the PARAM offset in the instruction. */
-         LLVMSetOperand(exports.exp[i].inst, AC_EXP_TARGET,
-                        LLVMConstInt(ctx->i32, V_008DFC_SQ_EXP_PARAM + i, 0));
-      }
-      *num_param_exports = exports.num;
-   }
-}
-
 void ac_init_exec_full_mask(struct ac_llvm_context *ctx)
 {
    LLVMValueRef full_mask = LLVMConstInt(ctx->i64, ~0ull, 0);
diff --git a/src/amd/llvm/ac_llvm_build.h b/src/amd/llvm/ac_llvm_build.h
index 488a5400fe4..42928a4e66b 100644
--- a/src/amd/llvm/ac_llvm_build.h
+++ b/src/amd/llvm/ac_llvm_build.h
@@ -460,9 +460,6 @@ LLVMValueRef ac_build_fsat(struct ac_llvm_context *ctx, LLVMValueRef src,
 
 LLVMValueRef ac_build_bitfield_reverse(struct ac_llvm_context *ctx, LLVMValueRef src0);
 
-void ac_optimize_vs_outputs(struct ac_llvm_context *ac, LLVMValueRef main_fn,
-                            uint8_t *vs_output_param_offset, uint32_t num_outputs,
-                            uint32_t skip_output_mask, uint8_t *num_param_exports);
 void ac_init_exec_full_mask(struct ac_llvm_context *ctx);
 
 void ac_declare_lds_as_pointer(struct ac_llvm_context *ac);



More information about the mesa-commit mailing list