[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