nir/from_ssa: Don't lower constant SSA values to registers
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 14 Jan 2015 19:19:41 +0000 (11:19 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Thu, 15 Jan 2015 15:19:01 +0000 (07:19 -0800)
Backends want to be able to do special things with constant values such as
put them into immediates or make decisions based on whether or not a value
is constant.  Before, constants always got lowered to a load_const into a
register and then a register use.  Now we leave constants as SSA values so
backends can special-case them if they want.  Since handling constant SSA
values is trivial, this shouldn't be a problem for backends.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
src/glsl/nir/nir_from_ssa.c

index 9f8c27df497f819c8d630d0daddb70c3b30a0fe9..3186c7d4aa88487f67efb2bc70b9b47c35bcbce6 100644 (file)
@@ -465,6 +465,12 @@ get_register_for_ssa_def(nir_ssa_def *def, struct from_ssa_state *state)
    if (entry) {
       return (nir_register *)entry->data;
    } else {
+      /* We leave load_const SSA values alone.  They act as immediates to
+       * the backend.  If it got coalesced into a phi, that's ok.
+       */
+      if (def->parent_instr->type == nir_instr_type_load_const)
+         return NULL;
+
       nir_register *reg = nir_local_reg_create(state->impl);
       reg->name = def->name;
       reg->num_components = def->num_components;
@@ -481,12 +487,18 @@ rewrite_ssa_src(nir_src *src, void *void_state)
    struct from_ssa_state *state = void_state;
 
    if (src->is_ssa) {
-      /* We don't need to remove it from the uses set because that is going
-       * away.  We just need to add it to the one for the register. */
       nir_register *reg = get_register_for_ssa_def(src->ssa, state);
+
+      if (reg == NULL) {
+         assert(src->ssa->parent_instr->type == nir_instr_type_load_const);
+         return true;
+      }
+
       memset(src, 0, sizeof *src);
       src->reg.reg = reg;
 
+      /* We don't need to remove it from the uses set because that is going
+       * away.  We just need to add it to the one for the register. */
       _mesa_set_add(reg->uses, _mesa_hash_pointer(state->instr), state->instr);
    }
 
@@ -499,10 +511,16 @@ rewrite_ssa_dest(nir_dest *dest, void *void_state)
    struct from_ssa_state *state = void_state;
 
    if (dest->is_ssa) {
+      nir_register *reg = get_register_for_ssa_def(&dest->ssa, state);
+
+      if (reg == NULL) {
+         assert(dest->ssa.parent_instr->type == nir_instr_type_load_const);
+         return true;
+      }
+
       _mesa_set_destroy(dest->ssa.uses, NULL);
       _mesa_set_destroy(dest->ssa.if_uses, NULL);
 
-      nir_register *reg = get_register_for_ssa_def(&dest->ssa, state);
       memset(dest, 0, sizeof *dest);
       dest->reg.reg = reg;
 
@@ -529,7 +547,6 @@ resolve_registers_block(nir_block *block, void *void_state)
           instr->type == nir_instr_type_phi) {
          nir_instr_remove(instr);
          ralloc_steal(state->dead_ctx, instr);
-         continue;
       }
    }
    state->instr = NULL;
@@ -538,11 +555,18 @@ resolve_registers_block(nir_block *block, void *void_state)
    if (following_if && following_if->condition.is_ssa) {
       nir_register *reg = get_register_for_ssa_def(following_if->condition.ssa,
                                                    state);
-      memset(&following_if->condition, 0, sizeof following_if->condition);
-      following_if->condition.reg.reg = reg;
+      if (reg) {
+         memset(&following_if->condition, 0, sizeof following_if->condition);
+         following_if->condition.reg.reg = reg;
 
-      _mesa_set_add(reg->if_uses, _mesa_hash_pointer(following_if),
-                    following_if);
+         _mesa_set_add(reg->if_uses, _mesa_hash_pointer(following_if),
+                       following_if);
+      } else {
+         /* FIXME: We really shouldn't hit this.  We should be doing
+          * constant control flow propagation.
+          */
+         assert(following_if->condition.ssa->parent_instr->type == nir_instr_type_load_const);
+      }
    }
 
    return true;