<p dir="ltr"><br>
On Apr 30, 2015 7:37 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
><br>
> On Tue, Apr 28, 2015 at 12:03 AM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> > This commit switches us from the current setup of using hash sets for<br>
> > use/def sets to using linked lists.  Doing so should save us quite a bit of<br>
> > memory because we aren't carrying around 3 hash sets per register and 2 per<br>
> > SSA value.  It should also save us CPU time because adding/removing things<br>
> > from use/def sets is 4 pointer manipulations instead of a hash lookup.<br>
> ><br>
> > On the code complexity side of things, some things are now much easier and<br>
> > others are a bit harder.  One of the operations we perform constantly in<br>
> > optimization passes is to replace one source with another.  Due to the fact<br>
> > that an instruction can use the same SSA value multiple times, we had to<br>
> > iterate through the sources of the instruction and determine if the use we<br>
> > were replacing was the only one before removing it from the set of uses.<br>
> > With this patch, uses are per-source not per-instruction so we can just<br>
> > remove it safely.  On the other hand, trying to iterate over all of the<br>
> > instructions that use a given value is more difficult.  Fortunately, the<br>
> > two places we do that are the ffma peephole where it doesn't matter and GCM<br>
> > where we already gracefully handle duplicates visits to an instruction.<br>
> ><br>
> > Another aspect here is that using linked lists in this way can be tricky to<br>
> > get right.  With sets, things were quite forgiving and the worst that<br>
> > happened if you didn't properly remove a use was that it would get caught<br>
> > in the validator.  With linked lists, it can lead to linked list corruption<br>
> > which can be harder to track.  However, we do just as much validation of<br>
> > the linked lists as we did of the sets so the validator should still catch<br>
> > these problems.  While working on this series, the vast majority of the<br>
> > bugs I had to fix were caught by assertions.  I don't think the lists are<br>
> > going to be that much worse than the sets.<br>
> > ---<br>
> >  src/glsl/nir/nir.c          | 228 +++++++++++++++-----------------------------<br>
> >  src/glsl/nir/nir.h          |  45 +++++++--<br>
> >  src/glsl/nir/nir_validate.c | 158 +++++++++++++++---------------<br>
> >  3 files changed, 194 insertions(+), 237 deletions(-)<br>
> ><br>
> > diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c<br>
> > index b8f5dd4..be13c90 100644<br>
> > --- a/src/glsl/nir/nir.c<br>
> > +++ b/src/glsl/nir/nir.c<br>
> > @@ -58,12 +58,9 @@ reg_create(void *mem_ctx, struct exec_list *list)<br>
> >     nir_register *reg = ralloc(mem_ctx, nir_register);<br>
> ><br>
> >     reg->parent_instr = NULL;<br>
> > -   reg->uses = _mesa_set_create(reg, _mesa_hash_pointer,<br>
> > -                                _mesa_key_pointer_equal);<br>
> > -   reg->defs = _mesa_set_create(reg, _mesa_hash_pointer,<br>
> > -                                _mesa_key_pointer_equal);<br>
> > -   reg->if_uses = _mesa_set_create(reg, _mesa_hash_pointer,<br>
> > -                                   _mesa_key_pointer_equal);<br>
> > +   list_inithead(&reg->uses);<br>
> > +   list_inithead(&reg->defs);<br>
> > +   list_inithead(&reg->if_uses);<br>
> ><br>
> >     reg->num_components = 0;<br>
> >     reg->num_array_elems = 0;<br>
> > @@ -1070,11 +1067,14 @@ update_if_uses(nir_cf_node *node)<br>
> ><br>
> >     nir_if *if_stmt = nir_cf_node_as_if(node);<br>
> ><br>
> > -   struct set *if_uses_set = if_stmt->condition.is_ssa ?<br>
> > -                             if_stmt->condition.ssa->if_uses :<br>
> > -                             if_stmt->condition.reg.reg->uses;<br>
> > -<br>
> > -   _mesa_set_add(if_uses_set, if_stmt);<br>
> > +   if_stmt->condition.parent_if = if_stmt;<br>
> > +   if (if_stmt->condition.is_ssa) {<br>
> > +      list_addtail(&if_stmt->condition.use_link,<br>
> > +                   &if_stmt->condition.ssa->if_uses);<br>
> > +   } else {<br>
> > +      list_addtail(&if_stmt->condition.use_link,<br>
> > +                   &if_stmt->condition.reg.reg->if_uses);<br>
> > +   }<br>
> >  }<br>
> ><br>
> >  void<br>
> > @@ -1227,16 +1227,7 @@ cleanup_cf_node(nir_cf_node *node)<br>
> >        foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)<br>
> >           cleanup_cf_node(child);<br>
> ><br>
> > -      struct set *if_uses;<br>
> > -      if (if_stmt->condition.is_ssa) {<br>
> > -         if_uses = if_stmt->condition.ssa->if_uses;<br>
> > -      } else {<br>
> > -         if_uses = if_stmt->condition.reg.reg->if_uses;<br>
> > -      }<br>
> > -<br>
> > -      struct set_entry *entry = _mesa_set_search(if_uses, if_stmt);<br>
> > -      assert(entry);<br>
> > -      _mesa_set_remove(if_uses, entry);<br>
> > +      list_del(&if_stmt->condition.use_link);<br>
> >        break;<br>
> >     }<br>
> ><br>
> > @@ -1293,9 +1284,9 @@ add_use_cb(nir_src *src, void *state)<br>
> >  {<br>
> >     nir_instr *instr = state;<br>
> ><br>
> > -   struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses;<br>
> > -<br>
> > -   _mesa_set_add(uses_set, instr);<br>
> > +   src->parent_instr = instr;<br>
> > +   list_addtail(&src->use_link,<br>
> > +                src->is_ssa ? &src->ssa->uses : &src->reg.reg->uses);<br>
> ><br>
> >     return true;<br>
> >  }<br>
> > @@ -1320,8 +1311,10 @@ add_reg_def_cb(nir_dest *dest, void *state)<br>
> >  {<br>
> >     nir_instr *instr = state;<br>
> ><br>
> > -   if (!dest->is_ssa)<br>
> > -      _mesa_set_add(dest->reg.reg->defs, instr);<br>
> > +   if (!dest->is_ssa) {<br>
> > +      dest->reg.parent_instr = instr;<br>
> > +      list_addtail(&dest->reg.def_link, &dest->reg.reg->defs);<br>
> > +   }<br>
> ><br>
> >     return true;<br>
> >  }<br>
> > @@ -1436,13 +1429,7 @@ nir_instr_insert_after_cf_list(struct exec_list *list, nir_instr *after)<br>
> >  static bool<br>
> >  remove_use_cb(nir_src *src, void *state)<br>
> >  {<br>
> > -   nir_instr *instr = state;<br>
> > -<br>
> > -   struct set *uses_set = src->is_ssa ? src->ssa->uses : src->reg.reg->uses;<br>
> > -<br>
> > -   struct set_entry *entry = _mesa_set_search(uses_set, instr);<br>
> > -   if (entry)<br>
> > -      _mesa_set_remove(uses_set, entry);<br>
> > +   list_del(&src->use_link);<br>
> ><br>
> >     return true;<br>
> >  }<br>
> > @@ -1450,16 +1437,8 @@ remove_use_cb(nir_src *src, void *state)<br>
> >  static bool<br>
> >  remove_def_cb(nir_dest *dest, void *state)<br>
> >  {<br>
> > -   nir_instr *instr = state;<br>
> > -<br>
> > -   if (dest->is_ssa)<br>
> > -      return true;<br>
> > -<br>
> > -   nir_register *reg = dest->reg.reg;<br>
> > -<br>
> > -   struct set_entry *entry = _mesa_set_search(reg->defs, instr);<br>
> > -   if (entry)<br>
> > -      _mesa_set_remove(reg->defs, entry);<br>
> > +   if (!dest->is_ssa)<br>
> > +      list_del(&dest->reg.def_link);<br>
> ><br>
> >     return true;<br>
> >  }<br>
> > @@ -1834,86 +1813,65 @@ nir_srcs_equal(nir_src src1, nir_src src2)<br>
> >  }<br>
> ><br>
> >  static bool<br>
> > -src_does_not_use_def(nir_src *src, void *void_def)<br>
> > +src_is_valid(const nir_src *src)<br>
> >  {<br>
> > -   nir_ssa_def *def = void_def;<br>
> > -<br>
> > -   if (src->is_ssa) {<br>
> > -      return src->ssa != def;<br>
> > -   } else {<br>
> > -      return true;<br>
> > -   }<br>
> > +   return src->is_ssa ? (src->ssa != NULL) : (src->reg.reg != NULL);<br>
> >  }<br>
> ><br>
> > -static bool<br>
> > -src_does_not_use_reg(nir_src *src, void *void_reg)<br>
> > +static void<br>
> > +src_remove_all_uses(nir_src *src)<br>
> >  {<br>
> > -   nir_register *reg = void_reg;<br>
> > +   for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {<br>
> > +      if (!src_is_valid(src))<br>
> > +         continue;<br>
> ><br>
> > -   if (src->is_ssa) {<br>
> > -      return true;<br>
> > -   } else {<br>
> > -      return src->reg.reg != reg;<br>
> > +      list_del(&src->use_link);<br>
> >     }<br>
> >  }<br>
> ><br>
> > -void<br>
> > -nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src)<br>
> > -{<br>
> > -   nir_src old_src = *src;<br>
> > -   *src = new_src;<br>
> > -<br>
> > -   for (nir_src *iter_src = &old_src; iter_src;<br>
> > -        iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) {<br>
> > -      if (iter_src->is_ssa) {<br>
> > -         nir_ssa_def *ssa = iter_src->ssa;<br>
> > -         if (ssa && nir_foreach_src(instr, src_does_not_use_def, ssa)) {<br>
> > -            struct set_entry *entry = _mesa_set_search(ssa->uses, instr);<br>
> > -            assert(entry);<br>
> > -            _mesa_set_remove(ssa->uses, entry);<br>
> > -         }<br>
> > +static void<br>
> > +src_add_all_uses(nir_src *src, nir_instr *parent_instr, nir_if *parent_if)<br>
> > +{<br>
> > +   for (; src; src = src->is_ssa ? NULL : src->reg.indirect) {<br>
> > +      if (!src_is_valid(src))<br>
> > +         continue;<br>
> > +<br>
> > +      if (parent_instr) {<br>
> > +         src->parent_instr = parent_instr;<br>
> > +         if (src->is_ssa)<br>
> > +            list_addtail(&src->use_link, &src->ssa->uses);<br>
> > +         else<br>
> > +            list_addtail(&src->use_link, &src->reg.reg->uses);<br>
> >        } else {<br>
> > -         nir_register *reg = iter_src->reg.reg;<br>
> > -         if (reg && nir_foreach_src(instr, src_does_not_use_reg, reg)) {<br>
> > -            struct set_entry *entry = _mesa_set_search(reg->uses, instr);<br>
> > -            assert(entry);<br>
> > -            _mesa_set_remove(reg->uses, entry);<br>
> > -         }<br>
> > +         assert(parent_if);<br>
> > +         src->parent_if = parent_if;<br>
> > +         if (src->is_ssa)<br>
> > +            list_addtail(&src->use_link, &src->ssa->if_uses);<br>
> > +         else<br>
> > +            list_addtail(&src->use_link, &src->reg.reg->if_uses);<br>
> >        }<br>
> >     }<br>
> > +}<br>
> ><br>
> > -   for (nir_src *iter_src = &new_src; iter_src;<br>
> > -        iter_src = iter_src->is_ssa ? NULL : iter_src->reg.indirect) {<br>
> > -      if (iter_src->is_ssa) {<br>
> > -         if (iter_src->ssa)<br>
> > -            _mesa_set_add(iter_src->ssa->uses, instr);<br>
> > -      } else {<br>
> > -         if (iter_src->reg.reg)<br>
> > -            _mesa_set_add(iter_src->reg.reg->uses, instr);<br>
> > -      }<br>
> > -   }<br>
> > +void<br>
> > +nir_instr_rewrite_src(nir_instr *instr, nir_src *src, nir_src new_src)<br>
> > +{<br>
> > +   assert(!src_is_valid(src) || src->parent_instr == instr);<br>
> > +<br>
> > +   src_remove_all_uses(src);<br>
> > +   *src = new_src;<br>
> > +   src_add_all_uses(src, instr, NULL);<br>
> >  }<br>
> ><br>
> >  void<br>
> >  nir_if_rewrite_condition(nir_if *if_stmt, nir_src new_src)<br>
> >  {<br>
> > -   for (nir_src *src = &if_stmt->condition; src;<br>
> > -        src = src->is_ssa ? NULL : src->reg.indirect) {<br>
> > -      struct set *uses = src->is_ssa ? src->ssa->if_uses<br>
> > -                                     : src->reg.reg->if_uses;<br>
> > -      struct set_entry *entry = _mesa_set_search(uses, if_stmt);<br>
> > -      assert(entry);<br>
> > -      _mesa_set_remove(uses, entry);<br>
> > -   }<br>
> > -<br>
> > -   if_stmt->condition = new_src;<br>
> > +   nir_src *src = &if_stmt->condition;<br>
> > +   assert(!src_is_valid(src) || src->parent_if == if_stmt);<br>
> ><br>
> > -   for (nir_src *src = &if_stmt->condition; src;<br>
> > -        src = src->is_ssa ? NULL : src->reg.indirect) {<br>
> > -      struct set *uses = src->is_ssa ? src->ssa->if_uses<br>
> > -                                     : src->reg.reg->if_uses;<br>
> > -      _mesa_set_add(uses, if_stmt);<br>
> > -   }<br>
> > +   src_remove_all_uses(src);<br>
> > +   *src = new_src;<br>
> > +   src_add_all_uses(src, NULL, if_stmt);<br>
> >  }<br>
> ><br>
> >  void<br>
> > @@ -1922,10 +1880,8 @@ nir_ssa_def_init(nir_instr *instr, nir_ssa_def *def,<br>
> >  {<br>
> >     def->name = name;<br>
> >     def->parent_instr = instr;<br>
> > -   def->uses = _mesa_set_create(instr, _mesa_hash_pointer,<br>
> > -                                _mesa_key_pointer_equal);<br>
> > -   def->if_uses = _mesa_set_create(instr, _mesa_hash_pointer,<br>
> > -                                   _mesa_key_pointer_equal);<br>
> > +   list_inithead(&def->uses);<br>
> > +   list_inithead(&def->if_uses);<br>
> >     def->num_components = num_components;<br>
> ><br>
> >     if (instr->block) {<br>
> > @@ -1946,57 +1902,23 @@ nir_ssa_dest_init(nir_instr *instr, nir_dest *dest,<br>
> >     nir_ssa_def_init(instr, &dest->ssa, num_components, name);<br>
> >  }<br>
> ><br>
> > -struct ssa_def_rewrite_state {<br>
> > -   void *mem_ctx;<br>
> > -   nir_ssa_def *old;<br>
> > -   nir_src new_src;<br>
> > -};<br>
> > -<br>
> > -static bool<br>
> > -ssa_def_rewrite_uses_src(nir_src *src, void *void_state)<br>
> > -{<br>
> > -   struct ssa_def_rewrite_state *state = void_state;<br>
> > -<br>
> > -   if (src->is_ssa && src->ssa == state->old)<br>
> > -      nir_src_copy(src, &state->new_src, state->mem_ctx);<br>
> > -<br>
> > -   return true;<br>
> > -}<br>
> > -<br>
> >  void<br>
> >  nir_ssa_def_rewrite_uses(nir_ssa_def *def, nir_src new_src, void *mem_ctx)<br>
> >  {<br>
> > -   struct ssa_def_rewrite_state state;<br>
> > -   state.mem_ctx = mem_ctx;<br>
> > -   state.old = def;<br>
> > -   state.new_src = new_src;<br>
> > -<br>
> >     assert(!new_src.is_ssa || def != new_src.ssa);<br>
> ><br>
> > -   struct set *new_uses, *new_if_uses;<br>
> > -   if (new_src.is_ssa) {<br>
> > -      new_uses = new_src.ssa->uses;<br>
> > -      new_if_uses = new_src.ssa->if_uses;<br>
> > -   } else {<br>
> > -      new_uses = new_src.reg.reg->uses;<br>
> > -      new_if_uses = new_src.reg.reg->if_uses;<br>
> > -   }<br>
> > -<br>
> > -   struct set_entry *entry;<br>
> > -   set_foreach(def->uses, entry) {<br>
> > -      nir_instr *instr = (nir_instr *)entry->key;<br>
> > -<br>
> > -      _mesa_set_remove(def->uses, entry);<br>
> > -      nir_foreach_src(instr, ssa_def_rewrite_uses_src, &state);<br>
> > -      _mesa_set_add(new_uses, instr);<br>
> > +   nir_foreach_use_safe(def, use_src) {<br>
> > +      nir_instr *src_parent_instr = use_src->parent_instr;<br>
> > +      list_del(&use_src->use_link);<br>
> > +      nir_src_copy(use_src, &new_src, mem_ctx);<br>
> > +      src_add_all_uses(use_src, src_parent_instr, NULL);<br>
> >     }<br>
> ><br>
> > -   set_foreach(def->if_uses, entry) {<br>
> > -      nir_if *if_use = (nir_if *)entry->key;<br>
> > -<br>
> > -      _mesa_set_remove(def->if_uses, entry);<br>
> > -      nir_src_copy(&if_use->condition, &new_src, mem_ctx);<br>
> > -      _mesa_set_add(new_if_uses, if_use);<br>
> > +   nir_foreach_if_use_safe(def, use_src) {<br>
> > +      nir_if *src_parent_if = use_src->parent_if;<br>
> > +      list_del(&use_src->use_link);<br>
> > +      nir_src_copy(use_src, &new_src, mem_ctx);<br>
> > +      src_add_all_uses(use_src, NULL, src_parent_if);<br>
> >     }<br>
> >  }<br>
> ><br>
> > diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h<br>
> > index aaf1c57..ac027b0 100644<br>
> > --- a/src/glsl/nir/nir.h<br>
> > +++ b/src/glsl/nir/nir.h<br>
> > @@ -30,6 +30,7 @@<br>
> >  #include "util/hash_table.h"<br>
> >  #include "../list.h"<br>
> >  #include "GL/gl.h" /* GLenum */<br>
> > +#include "util/list.h"<br>
> >  #include "util/ralloc.h"<br>
> >  #include "util/set.h"<br>
> >  #include "util/bitset.h"<br>
> > @@ -397,13 +398,13 @@ typedef struct {<br>
> >     struct nir_instr *parent_instr;<br>
> ><br>
> >     /** set of nir_instr's where this register is used (read from) */<br>
> > -   struct set *uses;<br>
> > +   struct list_head uses;<br>
> ><br>
> >     /** set of nir_instr's where this register is defined (written to) */<br>
> > -   struct set *defs;<br>
> > +   struct list_head defs;<br>
> ><br>
> >     /** set of nir_if's where this register is used as a condition */<br>
> > -   struct set *if_uses;<br>
> > +   struct list_head if_uses;<br>
> >  } nir_register;<br>
> ><br>
> >  typedef enum {<br>
> > @@ -462,10 +463,10 @@ typedef struct {<br>
> >     nir_instr *parent_instr;<br>
> ><br>
> >     /** set of nir_instr's where this register is used (read from) */<br>
> > -   struct set *uses;<br>
> > +   struct list_head uses;<br>
> ><br>
> >     /** set of nir_if's where this register is used as a condition */<br>
> > -   struct set *if_uses;<br>
> > +   struct list_head if_uses;<br>
> ><br>
> >     uint8_t num_components;<br>
> >  } nir_ssa_def;<br>
> > @@ -481,6 +482,9 @@ typedef struct {<br>
> >  } nir_reg_src;<br>
> ><br>
> >  typedef struct {<br>
> > +   nir_instr *parent_instr;<br>
> > +   struct list_head def_link;<br>
> > +<br>
> >     nir_register *reg;<br>
> >     struct nir_src *indirect; /** < NULL for no indirect offset */<br>
> >     unsigned base_offset;<br>
> > @@ -488,8 +492,17 @@ typedef struct {<br>
> >     /* TODO def-use chain goes here */<br>
> >  } nir_reg_dest;<br>
> ><br>
> > +struct nir_if;<br>
> > +<br>
> >  typedef struct nir_src {<br>
> >     union {<br>
> > +      nir_instr *parent_instr;<br>
> > +      struct nir_if *parent_if;<br>
> > +   };<br>
> > +<br>
> > +   struct list_head use_link;<br>
><br>
> So I was thinking about this, and I realized that putting the list<br>
> link here would mean that having SSA-only sources, like my experiments<br>
> with making derefs instructions, would be a massive pain. Making a<br>
> separate nir_ssa_src to put the use_link and parent_instr/parent_if in<br>
> seems like a lot more churn, but would it be harder/even more churn to<br>
> do it after this series rather than as a part of it? I don't think it<br>
> necessitates re-doing everything or giving up entirely, but I thought<br>
> it would be useful to note. I guess we could always use the full<br>
> nir_src and then do an assert(is_ssa) in the validator.</p>
<p dir="ltr">We could also put it in nir_reg_src and nir_ssa_src.  Since the list is embedded in a ssa value, we know what kind of source it is.  It would mean that we would have to split up the iterators though. Not a big deal.</p>
<p dir="ltr">> > +<br>
> > +   union {<br>
> >        nir_reg_src reg;<br>
> >        nir_ssa_def *ssa;<br>
> >     };<br>
> > @@ -497,7 +510,19 @@ typedef struct nir_src {<br>
> >     bool is_ssa;<br>
> >  } nir_src;<br>
> ><br>
> > -#define NIR_SRC_INIT (nir_src) { { { NULL } } }<br>
> > +#define NIR_SRC_INIT (nir_src) { { NULL } }<br>
> > +<br>
> > +#define nir_foreach_use(reg_or_ssa_def, src) \<br>
> > +   list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)<br>
> > +<br>
> > +#define nir_foreach_use_safe(reg_or_ssa_def, src) \<br>
> > +   list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->uses, use_link)<br>
> > +<br>
> > +#define nir_foreach_if_use(reg_or_ssa_def, src) \<br>
> > +   list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)<br>
> > +<br>
> > +#define nir_foreach_if_use_safe(reg_or_ssa_def, src) \<br>
> > +   list_for_each_entry_safe(nir_src, src, &(reg_or_ssa_def)->if_uses, use_link)<br>
> ><br>
> >  typedef struct {<br>
> >     union {<br>
> > @@ -510,6 +535,12 @@ typedef struct {<br>
> ><br>
> >  #define NIR_DEST_INIT (nir_dest) { { { NULL } } }<br>
> ><br>
> > +#define nir_foreach_def(reg, dest) \<br>
> > +   list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)<br>
> > +<br>
> > +#define nir_foreach_def_safe(reg, dest) \<br>
> > +   list_for_each_entry_safe(nir_dest, dest, &(reg)->defs, reg.def_link)<br>
> > +<br>
> >  static inline nir_src<br>
> >  nir_src_for_ssa(nir_ssa_def *def)<br>
> >  {<br>
> > @@ -1208,7 +1239,7 @@ nir_block_last_instr(nir_block *block)<br>
> >  #define nir_foreach_instr_safe(block, instr) \<br>
> >     foreach_list_typed_safe(nir_instr, instr, node, &(block)->instr_list)<br>
> ><br>
> > -typedef struct {<br>
> > +typedef struct nir_if {<br>
> >     nir_cf_node cf_node;<br>
> >     nir_src condition;<br>
> ><br>
> > diff --git a/src/glsl/nir/nir_validate.c b/src/glsl/nir/nir_validate.c<br>
> > index 35a853d..da92ed9 100644<br>
> > --- a/src/glsl/nir/nir_validate.c<br>
> > +++ b/src/glsl/nir/nir_validate.c<br>
> > @@ -97,50 +97,47 @@ typedef struct {<br>
> >  static void validate_src(nir_src *src, validate_state *state);<br>
> ><br>
> >  static void<br>
> > -validate_reg_src(nir_reg_src *src, validate_state *state)<br>
> > +validate_reg_src(nir_src *src, validate_state *state)<br>
> >  {<br>
> > -   assert(src->reg != NULL);<br>
> > +   assert(src->reg.reg != NULL);<br>
> ><br>
> >     struct hash_entry *entry;<br>
> > -   entry = _mesa_hash_table_search(state->regs, src->reg);<br>
> > +   entry = _mesa_hash_table_search(state->regs, src->reg.reg);<br>
> >     assert(entry);<br>
> ><br>
> >     reg_validate_state *reg_state = (reg_validate_state *) entry->data;<br>
> ><br>
> >     if (state->instr) {<br>
> > -      _mesa_set_add(reg_state->uses, state->instr);<br>
> > -<br>
> > -      assert(_mesa_set_search(src->reg->uses, state->instr));<br>
> > +      _mesa_set_add(reg_state->uses, src);<br>
> >     } else {<br>
> >        assert(state->if_stmt);<br>
> > -      _mesa_set_add(reg_state->if_uses, state->if_stmt);<br>
> > -<br>
> > -      assert(_mesa_set_search(src->reg->if_uses, state->if_stmt));<br>
> > +      _mesa_set_add(reg_state->if_uses, src);<br>
> >     }<br>
> ><br>
> > -   if (!src->reg->is_global) {<br>
> > +   if (!src->reg.reg->is_global) {<br>
> >        assert(reg_state->where_defined == state->impl &&<br>
> >               "using a register declared in a different function");<br>
> >     }<br>
> ><br>
> > -   assert((src->reg->num_array_elems == 0 ||<br>
> > -          src->base_offset < src->reg->num_array_elems) &&<br>
> > +   assert((src->reg.reg->num_array_elems == 0 ||<br>
> > +          src->reg.base_offset < src->reg.reg->num_array_elems) &&<br>
> >            "definitely out-of-bounds array access");<br>
> ><br>
> > -   if (src->indirect) {<br>
> > -      assert(src->reg->num_array_elems != 0);<br>
> > -      assert((src->indirect->is_ssa || src->indirect->reg.indirect == NULL) &&<br>
> > +   if (src->reg.indirect) {<br>
> > +      assert(src->reg.reg->num_array_elems != 0);<br>
> > +      assert((src->reg.indirect->is_ssa ||<br>
> > +              src->reg.indirect->reg.indirect == NULL) &&<br>
> >               "only one level of indirection allowed");<br>
> > -      validate_src(src->indirect, state);<br>
> > +      validate_src(src->reg.indirect, state);<br>
> >     }<br>
> >  }<br>
> ><br>
> >  static void<br>
> > -validate_ssa_src(nir_ssa_def *def, validate_state *state)<br>
> > +validate_ssa_src(nir_src *src, validate_state *state)<br>
> >  {<br>
> > -   assert(def != NULL);<br>
> > +   assert(src->ssa != NULL);<br>
> ><br>
> > -   struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def);<br>
> > +   struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, src->ssa);<br>
> ><br>
> >     assert(entry);<br>
> ><br>
> > @@ -150,14 +147,10 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state)<br>
> >            "using an SSA value defined in a different function");<br>
> ><br>
> >     if (state->instr) {<br>
> > -      _mesa_set_add(def_state->uses, state->instr);<br>
> > -<br>
> > -      assert(_mesa_set_search(def->uses, state->instr));<br>
> > +      _mesa_set_add(def_state->uses, src);<br>
> >     } else {<br>
> >        assert(state->if_stmt);<br>
> > -      _mesa_set_add(def_state->if_uses, state->if_stmt);<br>
> > -<br>
> > -      assert(_mesa_set_search(def->if_uses, state->if_stmt));<br>
> > +      _mesa_set_add(def_state->if_uses, src);<br>
> >     }<br>
> ><br>
> >     /* TODO validate that the use is dominated by the definition */<br>
> > @@ -166,10 +159,15 @@ validate_ssa_src(nir_ssa_def *def, validate_state *state)<br>
> >  static void<br>
> >  validate_src(nir_src *src, validate_state *state)<br>
> >  {<br>
> > +   if (state->instr)<br>
> > +      assert(src->parent_instr == state->instr);<br>
> > +   else<br>
> > +      assert(src->parent_if == state->if_stmt);<br>
> > +<br>
> >     if (src->is_ssa)<br>
> > -      validate_ssa_src(src->ssa, state);<br>
> > +      validate_ssa_src(src, state);<br>
> >     else<br>
> > -      validate_reg_src(&src->reg, state);<br>
> > +      validate_reg_src(src, state);<br>
> >  }<br>
> ><br>
> >  static void<br>
> > @@ -201,8 +199,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state)<br>
> >  {<br>
> >     assert(dest->reg != NULL);<br>
> ><br>
> > -   struct set_entry *entry = _mesa_set_search(dest->reg->defs, state->instr);<br>
> > -   assert(entry && "definition not in nir_register.defs");<br>
> > +   assert(dest->parent_instr == state->instr);<br>
> ><br>
> >     struct hash_entry *entry2;<br>
> >     entry2 = _mesa_hash_table_search(state->regs, dest->reg);<br>
> > @@ -210,7 +207,7 @@ validate_reg_dest(nir_reg_dest *dest, validate_state *state)<br>
> >     assert(entry2);<br>
> ><br>
> >     reg_validate_state *reg_state = (reg_validate_state *) entry2->data;<br>
> > -   _mesa_set_add(reg_state->defs, state->instr);<br>
> > +   _mesa_set_add(reg_state->defs, dest);<br>
> ><br>
> >     if (!dest->reg->is_global) {<br>
> >        assert(reg_state->where_defined == state->impl &&<br>
> > @@ -240,6 +237,9 @@ validate_ssa_def(nir_ssa_def *def, validate_state *state)<br>
> ><br>
> >     assert(def->num_components <= 4);<br>
> ><br>
> > +   list_validate(&def->uses);<br>
> > +   list_validate(&def->if_uses);<br>
> > +<br>
> >     ssa_def_validate_state *def_state = ralloc(state->ssa_defs,<br>
> >                                                ssa_def_validate_state);<br>
> >     def_state->where_defined = state->impl;<br>
> > @@ -701,6 +701,10 @@ prevalidate_reg_decl(nir_register *reg, bool is_global, validate_state *state)<br>
> >     assert(!BITSET_TEST(state->regs_found, reg->index));<br>
> >     BITSET_SET(state->regs_found, reg->index);<br>
> ><br>
> > +   list_validate(&reg->uses);<br>
> > +   list_validate(&reg->defs);<br>
> > +   list_validate(&reg->if_uses);<br>
> > +<br>
> >     reg_validate_state *reg_state = ralloc(state->regs, reg_validate_state);<br>
> >     reg_state->uses = _mesa_set_create(reg_state, _mesa_hash_pointer,<br>
> >                                        _mesa_key_pointer_equal);<br>
> > @@ -721,47 +725,47 @@ postvalidate_reg_decl(nir_register *reg, validate_state *state)<br>
> ><br>
> >     reg_validate_state *reg_state = (reg_validate_state *) entry->data;<br>
> ><br>
> > -   if (reg_state->uses->entries != reg->uses->entries) {<br>
> > +   nir_foreach_use(reg, src) {<br>
> > +      struct set_entry *entry = _mesa_set_search(reg_state->uses, src);<br>
> > +      assert(entry);<br>
> > +      _mesa_set_remove(reg_state->uses, entry);<br>
> > +   }<br>
> > +<br>
> > +   if (reg_state->uses->entries != 0) {<br>
> >        printf("extra entries in register uses:\n");<br>
> >        struct set_entry *entry;<br>
> > -      set_foreach(reg->uses, entry) {<br>
> > -         struct set_entry *entry2 =<br>
> > -            _mesa_set_search(reg_state->uses, entry->key);<br>
> > -<br>
> > -         if (entry2 == NULL) {<br>
> > -            printf("%p\n", entry->key);<br>
> > -         }<br>
> > -      }<br>
> > +      set_foreach(reg_state->uses, entry)<br>
> > +         printf("%p\n", entry->key);<br>
> ><br>
> >        abort();<br>
> >     }<br>
> ><br>
> > -   if (reg_state->if_uses->entries != reg->if_uses->entries) {<br>
> > +   nir_foreach_if_use(reg, src) {<br>
> > +      struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src);<br>
> > +      assert(entry);<br>
> > +      _mesa_set_remove(reg_state->if_uses, entry);<br>
> > +   }<br>
> > +<br>
> > +   if (reg_state->if_uses->entries != 0) {<br>
> >        printf("extra entries in register if_uses:\n");<br>
> >        struct set_entry *entry;<br>
> > -      set_foreach(reg->if_uses, entry) {<br>
> > -         struct set_entry *entry2 =<br>
> > -            _mesa_set_search(reg_state->if_uses, entry->key);<br>
> > -<br>
> > -         if (entry2 == NULL) {<br>
> > -            printf("%p\n", entry->key);<br>
> > -         }<br>
> > -      }<br>
> > +      set_foreach(reg_state->if_uses, entry)<br>
> > +         printf("%p\n", entry->key);<br>
> ><br>
> >        abort();<br>
> >     }<br>
> ><br>
> > -   if (reg_state->defs->entries != reg->defs->entries) {<br>
> > +   nir_foreach_def(reg, src) {<br>
> > +      struct set_entry *entry = _mesa_set_search(reg_state->defs, src);<br>
> > +      assert(entry);<br>
> > +      _mesa_set_remove(reg_state->defs, entry);<br>
> > +   }<br>
> > +<br>
> > +   if (reg_state->defs->entries != 0) {<br>
> >        printf("extra entries in register defs:\n");<br>
> >        struct set_entry *entry;<br>
> > -      set_foreach(reg->defs, entry) {<br>
> > -         struct set_entry *entry2 =<br>
> > -            _mesa_set_search(reg_state->defs, entry->key);<br>
> > -<br>
> > -         if (entry2 == NULL) {<br>
> > -            printf("%p\n", entry->key);<br>
> > -         }<br>
> > -      }<br>
> > +      set_foreach(reg_state->defs, entry)<br>
> > +         printf("%p\n", entry->key);<br>
> ><br>
> >        abort();<br>
> >     }<br>
> > @@ -790,32 +794,32 @@ postvalidate_ssa_def(nir_ssa_def *def, void *void_state)<br>
> >     struct hash_entry *entry = _mesa_hash_table_search(state->ssa_defs, def);<br>
> >     ssa_def_validate_state *def_state = (ssa_def_validate_state *)entry->data;<br>
> ><br>
> > -   if (def_state->uses->entries != def->uses->entries) {<br>
> > -      printf("extra entries in SSA def uses:\n");<br>
> > -      struct set_entry *entry;<br>
> > -      set_foreach(def->uses, entry) {<br>
> > -         struct set_entry *entry2 =<br>
> > -            _mesa_set_search(def_state->uses, entry->key);<br>
> > +   nir_foreach_use(def, src) {<br>
> > +      struct set_entry *entry = _mesa_set_search(def_state->uses, src);<br>
> > +      assert(entry);<br>
> > +      _mesa_set_remove(def_state->uses, entry);<br>
> > +   }<br>
> ><br>
> > -         if (entry2 == NULL) {<br>
> > -            printf("%p\n", entry->key);<br>
> > -         }<br>
> > -      }<br>
> > +   if (def_state->uses->entries != 0) {<br>
> > +      printf("extra entries in register uses:\n");<br>
> > +      struct set_entry *entry;<br>
> > +      set_foreach(def_state->uses, entry)<br>
> > +         printf("%p\n", entry->key);<br>
> ><br>
> >        abort();<br>
> >     }<br>
> ><br>
> > -   if (def_state->if_uses->entries != def->if_uses->entries) {<br>
> > -      printf("extra entries in SSA def uses:\n");<br>
> > -      struct set_entry *entry;<br>
> > -      set_foreach(def->if_uses, entry) {<br>
> > -         struct set_entry *entry2 =<br>
> > -            _mesa_set_search(def_state->if_uses, entry->key);<br>
> > +   nir_foreach_if_use(def, src) {<br>
> > +      struct set_entry *entry = _mesa_set_search(def_state->if_uses, src);<br>
> > +      assert(entry);<br>
> > +      _mesa_set_remove(def_state->if_uses, entry);<br>
> > +   }<br>
> ><br>
> > -         if (entry2 == NULL) {<br>
> > -            printf("%p\n", entry->key);<br>
> > -         }<br>
> > -      }<br>
> > +   if (def_state->if_uses->entries != 0) {<br>
> > +      printf("extra entries in register uses:\n");<br>
> > +      struct set_entry *entry;<br>
> > +      set_foreach(def_state->if_uses, entry)<br>
> > +         printf("%p\n", entry->key);<br>
> ><br>
> >        abort();<br>
> >     }<br>
> > --<br>
> > 2.3.6<br>
> ><br>
> > _______________________________________________<br>
> > mesa-dev mailing list<br>
> > <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> > <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>