On Sat, Sep 20, 2014 at 10:22 AM, Jason Ekstrand <ja...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev