[Mesa-dev] [PATCH 03/41] i965/fs: Add a concept of a width to fs_reg
Matt Turner
mattst88 at gmail.com
Tue Sep 23 10:22:28 PDT 2014
On Sat, Sep 20, 2014 at 10:22 AM, Jason Ekstrand <jason at jlekstrand.net> wrote:
> Every register in i965 assembly implicitly has a concept of a "width".
> Usually, this is derived from the execution size of the instruction.
> However, when writing a compiler it turns out that it is frequently a
> useful to have the width explicitly in the register and derive the
> execution size of the instruction from the widths of the registers used in
> it.
>
> This commit adds a width field to fs_reg along with an effective_width()
> helper function. The effective_width() function tells you how wide the
> register effectively is when used in an instruction. For example, uniform
> values have width 1 since the data is not actually repeated, but when used
> in an instruction they take on the width of the instruction. However, for
> some instructions (LOAD_PAYLOAD being the notable exception), the width is
> not the same.
> ---
> src/mesa/drivers/dri/i965/brw_fs.cpp | 59 ++++++++++++++++++++++++++++++++++--
> src/mesa/drivers/dri/i965/brw_fs.h | 19 ++++++++++++
> 2 files changed, 76 insertions(+), 2 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
> index 527467a..67bb529 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
> @@ -422,6 +422,7 @@ fs_reg::fs_reg(float f)
> this->file = IMM;
> this->type = BRW_REGISTER_TYPE_F;
> this->fixed_hw_reg.dw1.f = f;
> + this->width = 1;
> }
>
> /** Immediate value constructor. */
> @@ -431,6 +432,7 @@ fs_reg::fs_reg(int32_t i)
> this->file = IMM;
> this->type = BRW_REGISTER_TYPE_D;
> this->fixed_hw_reg.dw1.d = i;
> + this->width = 1;
> }
>
> /** Immediate value constructor. */
> @@ -440,6 +442,7 @@ fs_reg::fs_reg(uint32_t u)
> this->file = IMM;
> this->type = BRW_REGISTER_TYPE_UD;
> this->fixed_hw_reg.dw1.ud = u;
> + this->width = 1;
> }
>
> /** Fixed brw_reg. */
> @@ -449,6 +452,7 @@ fs_reg::fs_reg(struct brw_reg fixed_hw_reg)
> this->file = HW_REG;
> this->fixed_hw_reg = fixed_hw_reg;
> this->type = fixed_hw_reg.type;
> + this->width = 1 << fixed_hw_reg.width;
> }
>
> bool
> @@ -462,11 +466,33 @@ fs_reg::equals(const fs_reg &r) const
> negate == r.negate &&
> abs == r.abs &&
> !reladdr && !r.reladdr &&
> - memcmp(&fixed_hw_reg, &r.fixed_hw_reg,
> - sizeof(fixed_hw_reg)) == 0 &&
> + memcmp(&fixed_hw_reg, &r.fixed_hw_reg, sizeof(fixed_hw_reg)) == 0 &&
> + width == r.width &&
> stride == r.stride);
> }
>
> +uint8_t
> +fs_reg::effective_width(const fs_visitor *v) const
> +{
> + switch (this->file) {
> + case BAD_FILE:
> + return 8;
> + case UNIFORM:
> + case IMM:
> + assert(this->width == 1);
> + return v->dispatch_width;
> + case GRF:
> + case HW_REG:
> + assert(this->width > 1 && this->width <= v->dispatch_width);
> + assert(this->width % 8 == 0);
> + return this->width;
> + case MRF:
> + unreachable("MRF registers cannot be used as sources");
> + default:
> + unreachable("Invalid register file");
> + }
> +}
> +
> fs_reg &
> fs_reg::apply_stride(unsigned stride)
> {
> @@ -880,6 +906,14 @@ fs_reg::fs_reg(enum register_file file, int reg)
> this->file = file;
> this->reg = reg;
> this->type = BRW_REGISTER_TYPE_F;
> +
> + switch (file) {
> + case UNIFORM:
> + this->width = 1;
> + break;
> + default:
> + this->width = 8;
> + }
> }
>
> /** Fixed HW reg constructor. */
> @@ -889,6 +923,25 @@ fs_reg::fs_reg(enum register_file file, int reg, enum brw_reg_type type)
> this->file = file;
> this->reg = reg;
> this->type = type;
> +
> + switch (file) {
> + case UNIFORM:
> + this->width = 1;
> + break;
> + default:
> + this->width = 8;
> + }
> +}
> +
> +/** Fixed HW reg constructor. */
> +fs_reg::fs_reg(enum register_file file, int reg, enum brw_reg_type type,
> + uint8_t width)
> +{
> + init();
> + this->file = file;
> + this->reg = reg;
> + this->type = type;
> + this->width = width;
> }
>
> /** Automatic reg constructor. */
> @@ -900,6 +953,8 @@ fs_reg::fs_reg(class fs_visitor *v, const struct glsl_type *type)
> this->reg = v->virtual_grf_alloc(v->type_size(type));
> this->reg_offset = 0;
> this->type = brw_type_for_base_type(type);
> + this->width = v->dispatch_width;
> + assert(this->width == 8 || this->width == 16);
> }
>
> fs_reg *
> diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
> index 50b5fc1..5d2fbe5 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs.h
> +++ b/src/mesa/drivers/dri/i965/brw_fs.h
> @@ -62,6 +62,8 @@ namespace brw {
> class fs_live_variables;
> }
>
> +class fs_visitor;
I'm guessing we haven't needed this, because...
> +
> class fs_reg : public backend_reg {
> public:
> DECLARE_RALLOC_CXX_OPERATORS(fs_reg)
> @@ -75,6 +77,7 @@ public:
> fs_reg(struct brw_reg fixed_hw_reg);
> fs_reg(enum register_file file, int reg);
> fs_reg(enum register_file file, int reg, enum brw_reg_type type);
> + fs_reg(enum register_file file, int reg, enum brw_reg_type type, uint8_t width);
> fs_reg(class fs_visitor *v, const struct glsl_type *type);
we say 'class fs_visitor' here. I'd either do the same below, or
remove the class keyword here at the same time. Just saying 'class...'
seems fine.
>
> bool equals(const fs_reg &r) const;
> @@ -93,6 +96,22 @@ public:
>
> fs_reg *reladdr;
>
> + /**
> + * The register width. This indicates how many hardware values are
> + * represented by each virtual value. Valid values are 1, 8, or 16.
> + * For immediate values, this is 1. Most of the rest of the time, it
> + * will be equal to the dispatch width.
> + */
> + uint8_t width;
> +
> + /**
> + * Returns the effective register width when used as a source in the
> + * given instruction. Registers such as uniforms and immediates
> + * effectively take on the width of the instruction in which they are
> + * used.
> + */
> + uint8_t effective_width(const fs_visitor *v) const;
> +
> /** Register region horizontal stride */
> uint8_t stride;
> };
> --
> 2.1.0
More information about the mesa-dev
mailing list