[Mesa-dev] [PATCH 1/2] radeonsi/ac: move vertex export remove to common code.
Dave Airlie
airlied at gmail.com
Thu Apr 27 10:42:07 UTC 2017
On 27 April 2017 at 20:17, Marek Olšák <maraeo at gmail.com> wrote:
>
>
> On Apr 27, 2017 10:50 AM, "Juan A. Suarez Romero" <jasuarez at igalia.com>
> wrote:
>
> On Wed, 2017-04-26 at 09:12 +1000, Dave Airlie wrote:
>> From: Dave Airlie <airlied at redhat.com>
>>
>> This code can be shared by radv, we bump the max to
>> VARYING_SLOT_MAX here, but that shouldn't have too
>> much fallout.
>>
>> Signed-off-by: Dave Airlie <airlied at redhat.com>
>> ---
>> src/amd/common/ac_exp_param.h | 40 ++++++
>> src/amd/common/ac_llvm_build.c | 156
>> +++++++++++++++++++++++-
>> src/amd/common/ac_llvm_build.h | 6 +
>> src/amd/common/ac_llvm_helper.cpp | 20 +++
>> src/amd/common/ac_llvm_util.h | 2 +
>> src/gallium/drivers/radeonsi/si_shader.c | 152
>> ++---------------------
>> src/gallium/drivers/radeonsi/si_shader.h | 12 --
>> src/gallium/drivers/radeonsi/si_state_shaders.c | 13 +-
>> 8 files changed, 237 insertions(+), 164 deletions(-)
>> create mode 100644 src/amd/common/ac_exp_param.h
>>
>> diff --git a/src/amd/common/ac_exp_param.h b/src/amd/common/ac_exp_param.h
>> new file mode 100644
>> index 0000000..b97ce81
>> --- /dev/null
>> +++ b/src/amd/common/ac_exp_param.h
>> @@ -0,0 +1,40 @@
>> +/*
>> + * Copyright 2014 Advanced Micro Devices, Inc.
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a
>> + * copy of this software and associated documentation files (the
>> + * "Software"), to deal in the Software without restriction, including
>> + * without limitation the rights to use, copy, modify, merge, publish,
>> + * distribute, sub license, and/or sell copies of the Software, and to
>> + * permit persons to whom the Software is furnished to do so, subject to
>> + * the following conditions:
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
>> CLAIM,
>> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
>> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
>> THE
>> + * USE OR OTHER DEALINGS IN THE SOFTWARE.
>> + *
>> + * The above copyright notice and this permission notice (including the
>> + * next paragraph) shall be included in all copies or substantial
>> portions
>> + * of the Software.
>> + *
>> + */
>> +#ifndef AC_EXP_PARAM_H
>> +#define AC_EXP_PARAM_H
>> +
>> +enum {
>> + /* SPI_PS_INPUT_CNTL_i.OFFSET[0:4] */
>> + AC_EXP_PARAM_OFFSET_0 = 0,
>> + AC_EXP_PARAM_OFFSET_31 = 31,
>> + /* SPI_PS_INPUT_CNTL_i.DEFAULT_VAL[0:1] */
>> + AC_EXP_PARAM_DEFAULT_VAL_0000 = 64,
>> + AC_EXP_PARAM_DEFAULT_VAL_0001,
>> + AC_EXP_PARAM_DEFAULT_VAL_1110,
>> + AC_EXP_PARAM_DEFAULT_VAL_1111,
>> + AC_EXP_PARAM_UNDEFINED = 255,
>> +};
>> +
>> +#endif
>> diff --git a/src/amd/common/ac_llvm_build.c
>> b/src/amd/common/ac_llvm_build.c
>> index d45094c..f452f3e 100644
>> --- a/src/amd/common/ac_llvm_build.c
>> +++ b/src/amd/common/ac_llvm_build.c
>> @@ -33,11 +33,13 @@
>> #include <stdio.h>
>>
>> #include "ac_llvm_util.h"
>> -
>> +#include "ac_exp_param.h"
>> #include "util/bitscan.h"
>> #include "util/macros.h"
>> #include "sid.h"
>>
>> +#include "shader_enums.h"
>> +
>> /* Initialize module-independent parts of the context.
>> *
>> * The caller is responsible for initializing ctx::module and
>> ctx::builder.
>> @@ -1244,3 +1246,155 @@ void ac_get_image_intr_name(const char *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)
>> +
>> +/* 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)
>> +{
>> + 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)) {
>> + is_zero[i] = true;
>> + is_one[i] = true;
>> + } else if (LLVMIsAConstantFP(p)) {
>> + double a = LLVMConstRealGetDouble(p, &loses_info);
>> +
>> + if (a == 0)
>> + is_zero[i] = true;
>> + else if (a == 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);
>> +
>> + /* Change OFFSET to DEFAULT_VAL. */
>> + for (i = 0; i < num_outputs; i++) {
>> + if (vs_output_param_offset[i] == 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;
>> +
>> + assert(num_outputs < VARYING_SLOT_MAX);
>> + 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);
>> +
>> + 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;
>> +
>> + /* Eliminate constant value PARAM exports. */
>> + if
>> (ac_eliminate_const_output(vs_output_param_offset,
>> + num_outputs, cur,
>> target)) {
>> + removed_any = true;
>> + } else {
>> + exports.offset[exports.num] = target;
>> + exports.inst[exports.num] = cur;
>> + exports.num++;
>> + }
>> + }
>> + 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];
>> +
>> + for (out = 0; out < num_outputs; out++) {
>> + if (current_offset[out] != offset)
>> + continue;
>> +
>> + LLVMSetOperand(exports.inst[i],
>> 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;
>> + }
>> +}
>> diff --git a/src/amd/common/ac_llvm_build.h
>> b/src/amd/common/ac_llvm_build.h
>> index d6edcde..1c3610a 100644
>> --- a/src/amd/common/ac_llvm_build.h
>> +++ b/src/amd/common/ac_llvm_build.h
>> @@ -239,6 +239,12 @@ void ac_get_image_intr_name(const char *base_name,
>> LLVMTypeRef coords_type,
>> LLVMTypeRef rsrc_type,
>> char *out_name, unsigned out_len);
>> +
>> +void ac_eliminate_const_vs_outputs(struct ac_llvm_context *ac,
>> + LLVMValueRef main_fn,
>> + uint8_t *vs_output_param_offset,
>> + uint32_t num_outputs,
>> + uint8_t *num_param_exports);
>> #ifdef __cplusplus
>> }
>> #endif
>> diff --git a/src/amd/common/ac_llvm_helper.cpp
>> b/src/amd/common/ac_llvm_helper.cpp
>> index 11fa809..582a8f7 100644
>> --- a/src/amd/common/ac_llvm_helper.cpp
>> +++ b/src/amd/common/ac_llvm_helper.cpp
>> @@ -61,3 +61,23 @@ bool ac_is_sgpr_param(LLVMValueRef arg)
>> return AS.hasAttribute(ArgNo + 1, llvm::Attribute::ByVal) ||
>> AS.hasAttribute(ArgNo + 1, llvm::Attribute::InReg);
>> }
>> +
>> +LLVMValueRef ac_llvm_get_called_value(LLVMValueRef call)
>> +{
>> +#if HAVE_LLVM >= 0x0309
>> + return LLVMGetCalledValue(call);
>> +#elif HAVE_LLVM >= 0x0305
>> + return
>> llvm::wrap(llvm::CallSite(llvm::unwrap<llvm::Instruction>(call)).getCalledValue());
>
>
> This patch is breaking build when using LLVM 3.8.1.
>
>
> Can you share the build error with us?
>
> BTW, I have a patch that removes support for LLVM 3.8.
I fixed it in master, was missing an include file, I also still had a
3.8 install to build against luckily.
Dave.
More information about the mesa-dev
mailing list