*/
#include "brw_fs.h"
-#include "brw_fs_live_variables.h"
#include "brw_cfg.h"
+using namespace brw;
+
+static const bool debug = false;
+
/* Returns whether an instruction could co-issue if its immediate source were
* replaced with a GRF source.
*/
static bool
-could_coissue(const struct brw_device_info *devinfo, const fs_inst *inst)
+could_coissue(const struct gen_device_info *devinfo, const fs_inst *inst)
{
if (devinfo->gen != 7)
return false;
* Returns true for instructions that don't support immediate sources.
*/
static bool
-must_promote_imm(const struct brw_device_info *devinfo, const fs_inst *inst)
+must_promote_imm(const struct gen_device_info *devinfo, const fs_inst *inst)
{
switch (inst->opcode) {
case SHADER_OPCODE_POW:
- case SHADER_OPCODE_INT_QUOTIENT:
- case SHADER_OPCODE_INT_REMAINDER:
return devinfo->gen < 8;
case BRW_OPCODE_MAD:
case BRW_OPCODE_LRP:
* constant value.
*/
uint8_t subreg_offset;
- uint16_t reg;
+ uint16_t nr;
/** The number of coissuable instructions using this immediate. */
uint16_t uses_by_coissue;
static struct imm *
find_imm(struct table *table, float val)
{
- assert(signbit(val) == 0);
-
for (int i = 0; i < table->len; i++) {
if (table->imm[i].val == val) {
return &table->imm[i];
inst->src[i].type != BRW_REGISTER_TYPE_F)
continue;
- float val = fabsf(inst->src[i].fixed_hw_reg.dw1.f);
+ float val = !inst->can_do_source_mods(devinfo) ? inst->src[i].f :
+ fabs(inst->src[i].f);
struct imm *imm = find_imm(&table, val);
if (imm) {
if (cfg->num_blocks != 1)
qsort(table.imm, table.len, sizeof(struct imm), compare);
-
/* Insert MOVs to load the constant values into GRFs. */
- fs_reg reg(GRF, alloc.allocate(dispatch_width / 8));
+ fs_reg reg(VGRF, alloc.allocate(1));
reg.stride = 0;
for (int i = 0; i < table.len; i++) {
struct imm *imm = &table.imm[i];
-
- fs_inst *mov = MOV(reg, fs_reg(imm->val));
- mov->force_writemask_all = true;
- if (imm->inst) {
- imm->inst->insert_before(imm->block, mov);
- } else {
- backend_instruction *inst = imm->block->last_non_control_flow_inst();
- inst->insert_after(imm->block, mov);
- }
- imm->reg = reg.reg;
- imm->subreg_offset = reg.subreg_offset;
-
- reg.subreg_offset += sizeof(float);
- if ((unsigned)reg.subreg_offset == dispatch_width * sizeof(float)) {
- reg.reg = alloc.allocate(dispatch_width / 8);
- reg.subreg_offset = 0;
+ /* Insert it either before the instruction that generated the immediate
+ * or after the last non-control flow instruction of the common ancestor.
+ */
+ exec_node *n = (imm->inst ? imm->inst :
+ imm->block->last_non_control_flow_inst()->next);
+ const fs_builder ibld = bld.at(imm->block, n).exec_all().group(1, 0);
+
+ ibld.MOV(reg, brw_imm_f(imm->val));
+ imm->nr = reg.nr;
+ imm->subreg_offset = reg.offset;
+
+ reg.offset += sizeof(float);
+ if (reg.offset == 8 * sizeof(float)) {
+ reg.nr = alloc.allocate(1);
+ reg.offset = 0;
}
}
promoted_constants = table.len;
for (int i = 0; i < table.len; i++) {
foreach_list_typed(reg_link, link, link, table.imm[i].uses) {
fs_reg *reg = link->reg;
- reg->file = GRF;
- reg->reg = table.imm[i].reg;
- reg->subreg_offset = table.imm[i].subreg_offset;
+ reg->file = VGRF;
+ reg->nr = table.imm[i].nr;
+ reg->offset = table.imm[i].subreg_offset;
reg->stride = 0;
- reg->negate = signbit(reg->fixed_hw_reg.dw1.f) !=
- signbit(table.imm[i].val);
- assert(fabsf(reg->fixed_hw_reg.dw1.f) == table.imm[i].val);
+ reg->negate = signbit(reg->f) != signbit(table.imm[i].val);
+ assert((isnan(reg->f) && isnan(table.imm[i].val)) ||
+ fabsf(reg->f) == fabs(table.imm[i].val));
+ }
+ }
+
+ if (debug) {
+ for (int i = 0; i < table.len; i++) {
+ struct imm *imm = &table.imm[i];
+
+ printf("%.3fF - block %3d, reg %3d sub %2d, Uses: (%2d, %2d), "
+ "IP: %4d to %4d, length %4d\n",
+ imm->val,
+ imm->block->num,
+ imm->nr,
+ imm->subreg_offset,
+ imm->must_promote,
+ imm->uses_by_coissue,
+ imm->first_use_ip,
+ imm->last_use_ip,
+ imm->last_use_ip - imm->first_use_ip);
}
}