From 24d023b9fe18847158ec6c14e1e0e32ff022f060 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 13 Aug 2014 12:25:58 -0700 Subject: [PATCH] i965/fs: Add a concept of a width to fs_reg 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. Signed-off-by: Jason Ekstrand Reviewed-by: Matt Turner --- src/mesa/drivers/dri/i965/brw_fs.cpp | 61 ++++++++++++++++++++++++++-- src/mesa/drivers/dri/i965/brw_fs.h | 21 +++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 99a33bd0647..80fa4f3dd9a 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,10 +923,29 @@ 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. */ -fs_reg::fs_reg(class fs_visitor *v, const struct glsl_type *type) +fs_reg::fs_reg(fs_visitor *v, const struct glsl_type *type) { init(); @@ -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 1cdbf311977..30cce40dd2b 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; + class fs_reg : public backend_reg { public: DECLARE_RALLOC_CXX_OPERATORS(fs_reg) @@ -75,7 +77,8 @@ 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(class fs_visitor *v, const struct glsl_type *type); + fs_reg(enum register_file file, int reg, enum brw_reg_type type, uint8_t width); + fs_reg(fs_visitor *v, const struct glsl_type *type); bool equals(const fs_reg &r) const; bool is_valid_3src() 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.30.2