summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2014-08-13 12:25:58 -0700
committerJason Ekstrand <jason.ekstrand@intel.com>2014-09-30 10:29:14 -0700
commit24d023b9fe18847158ec6c14e1e0e32ff022f060 (patch)
tree5d0ed4217a5bc26fb9ab208393d4b4442fad6ebb
parent1030ee6e9b0cc6c05a7f25c17c0cf722a6731c89 (diff)
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 <jason.ekstrand@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp61
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h21
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;
};