i965: Enable EGL_KHR_gl_texture_3D_image
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_combine_constants.cpp
index a5bacf499907902d065189e75779e0dc4595388f..e0c95d379b88a45044271ecc300bddf73e50a79e 100644 (file)
  */
 
 #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;
@@ -62,12 +65,10 @@ could_coissue(const struct brw_device_info *devinfo, const fs_inst *inst)
  * 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:
@@ -121,7 +122,7 @@ struct imm {
     * 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;
@@ -146,8 +147,6 @@ struct table {
 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];
@@ -219,7 +218,8 @@ fs_visitor::opt_combine_constants()
              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) {
@@ -266,28 +266,26 @@ fs_visitor::opt_combine_constants()
    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;
@@ -296,13 +294,31 @@ fs_visitor::opt_combine_constants()
    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);
       }
    }