void init();
fs_reg();
- explicit fs_reg(float f);
- explicit fs_reg(int32_t i);
- explicit fs_reg(uint32_t u);
- explicit fs_reg(uint8_t vf[4]);
- explicit fs_reg(uint8_t vf0, uint8_t vf1, uint8_t vf2, uint8_t vf3);
- fs_reg(struct brw_reg reg);
+ fs_reg(struct ::brw_reg reg);
fs_reg(enum brw_reg_file file, int nr);
fs_reg(enum brw_reg_file file, int nr, enum brw_reg_type type);
*/
int subreg_offset;
- fs_reg *reladdr;
-
/** Register region horizontal stride */
uint8_t stride;
};
break;
case VGRF:
case ATTR:
- reg.reg_offset += delta / 32;
+ case UNIFORM: {
+ const unsigned reg_size = (reg.file == UNIFORM ? 4 : REG_SIZE);
+ const unsigned suboffset = reg.subreg_offset + delta;
+ reg.reg_offset += suboffset / reg_size;
+ reg.subreg_offset = suboffset % reg_size;
break;
- case MRF:
- reg.nr += delta / 32;
+ }
+ case MRF: {
+ const unsigned suboffset = reg.subreg_offset + delta;
+ reg.nr += suboffset / REG_SIZE;
+ reg.subreg_offset = suboffset % REG_SIZE;
break;
+ }
case ARF:
- case FIXED_GRF:
+ case FIXED_GRF: {
+ const unsigned suboffset = reg.subnr + delta;
+ reg.nr += suboffset / REG_SIZE;
+ reg.subnr = suboffset % REG_SIZE;
+ break;
+ }
case IMM:
- case UNIFORM:
+ default:
assert(delta == 0);
}
- reg.subreg_offset += delta % 32;
return reg;
}
return reg;
}
+/**
+ * Get the scalar channel of \p reg given by \p idx and replicate it to all
+ * channels of the result.
+ */
static inline fs_reg
component(fs_reg reg, unsigned idx)
{
- assert(reg.subreg_offset == 0);
- reg.subreg_offset = idx * type_sz(reg.type);
+ reg = horiz_offset(reg, idx);
reg.stride = 0;
return reg;
}
+/**
+ * Return whether the given register region is n-periodic, i.e. whether the
+ * original region remains invariant after shifting it by \p n scalar
+ * channels.
+ */
+static inline bool
+is_periodic(const fs_reg ®, unsigned n)
+{
+ if (reg.file == BAD_FILE || reg.is_null()) {
+ return true;
+
+ } else if (reg.file == IMM) {
+ const unsigned period = (reg.type == BRW_REGISTER_TYPE_UV ||
+ reg.type == BRW_REGISTER_TYPE_V ? 8 :
+ reg.type == BRW_REGISTER_TYPE_VF ? 4 :
+ 1);
+ return n % period == 0;
+
+ } else if (reg.file == ARF || reg.file == FIXED_GRF) {
+ const unsigned period = (reg.hstride == 0 && reg.vstride == 0 ? 1 :
+ reg.vstride == 0 ? 1 << reg.width :
+ ~0);
+ return n % period == 0;
+
+ } else {
+ return reg.stride == 0;
+ }
+}
+
static inline bool
is_uniform(const fs_reg ®)
{
- return (reg.stride == 0 || reg.is_null()) &&
- (!reg.reladdr || is_uniform(*reg.reladdr));
+ return is_periodic(reg, 1);
}
/**
return reg;
}
+/**
+ * Reinterpret each channel of register \p reg as a vector of values of the
+ * given smaller type and take the i-th subcomponent from each.
+ */
+static inline fs_reg
+subscript(fs_reg reg, brw_reg_type type, unsigned i)
+{
+ assert((i + 1) * type_sz(type) <= type_sz(reg.type));
+
+ if (reg.file == ARF || reg.file == FIXED_GRF) {
+ /* The stride is encoded inconsistently for fixed GRF and ARF registers
+ * as the log2 of the actual vertical and horizontal strides.
+ */
+ const int delta = _mesa_logbase2(type_sz(reg.type)) -
+ _mesa_logbase2(type_sz(type));
+ reg.hstride += (reg.hstride ? delta : 0);
+ reg.vstride += (reg.vstride ? delta : 0);
+
+ } else if (reg.file == IMM) {
+ assert(reg.type == type);
+
+ } else {
+ reg.stride *= type_sz(reg.type) / type_sz(type);
+ }
+
+ return byte_offset(retype(reg, type), i * type_sz(type));
+}
+
static const fs_reg reg_undef;
class fs_inst : public backend_instruction {
bool can_do_source_mods(const struct brw_device_info *devinfo);
bool can_change_types() const;
bool has_side_effects() const;
+ bool has_source_and_destination_hazard() const;
- bool reads_flag() const;
- bool writes_flag() const;
+ /**
+ * Return the subset of flag registers read by the instruction as a bitset
+ * with byte granularity.
+ */
+ unsigned flags_read(const brw_device_info *devinfo) const;
+
+ /**
+ * Return the subset of flag registers updated by the instruction (either
+ * partially or fully) as a bitset with byte granularity.
+ */
+ unsigned flags_written() const;
fs_reg dst;
fs_reg *src;
*/
uint8_t exec_size;
+ /**
+ * Channel group from the hardware execution and predication mask that
+ * should be applied to the instruction. The subset of channel enable
+ * signals (calculated from the EU control flow and predication state)
+ * given by [group, group + exec_size) will be used to mask GRF writes and
+ * any other side effects of the instruction.
+ */
+ uint8_t group;
+
bool eot:1;
- bool force_sechalf:1;
bool pi_noperspective:1; /**< Pixel interpolator noperspective flag */
};
-/**
- * Set second-half quarter control on \p inst.
- */
-static inline fs_inst *
-set_sechalf(fs_inst *inst)
-{
- inst->force_sechalf = true;
- return inst;
-}
-
/**
* Make the execution of \p inst dependent on the evaluation of a possibly
* inverted predicate.