<p dir="ltr"><br>
On Apr 24, 2015 4:46 PM, "Rob Clark" <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
><br>
> On Fri, Apr 24, 2015 at 7:32 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> > This commit adds a C-based linked list implementation for NIR.  Unlike<br>
> > exec_list in glsl/list.h, there is no C++ API.  Also, this list is based on<br>
> > wl_list (from the Wayland project) which is, in turn, based on the kernel<br>
> > list.  As such, it should be fairly familiar to people who have done<br>
> > anything in kernel space.<br>
> ><br>
> > Doesn't exec_list already have a C api?<br>
> ><br>
> > Yes, it does.  However, exec_list has C++ constructors for exec_list and<br>
> > exec_node.  In the patches that follow, I use linked lists for use/def sets<br>
> > for registers and SSA values.  In order to do so, I have to be able to<br>
> > place lists and links inside of unions.  Since exec_list and exec_node have<br>
> > constructors, doing so causes any C++ code that includes nir.h to die in a<br>
> > fire.  Therefore, we can't just use exec_list.<br>
> ><br>
> > What about simple_list?  Why re-create it?<br>
> ><br>
> > I thought about that too.  However, the simple_list is badly named and the<br>
> > API isn't that great.  Making it usable as a first-class datastructure<br>
> > would have taken as much work as adding nir_list.  Also, simple_list isn't<br>
> > really a standard as it's only ever used in errors.c and the vc4 driver.<br>
> ><br>
> > Why a kernel list; why not keep the symantics of exec_list?<br>
> ><br>
> > The short version:  I like it better.  Also, while exec_list is familiar to<br>
> > people who have worked inside the mesa GLSL compiler, I think that the<br>
> > kernel list will be more familiar to people in the open-source graphics<br>
> > community in general.  For whatever it's worth, I explicitly designed it<br>
> > with separate nir_list and nir_link structures so that we can switch from<br>
> > kernel list to exec_list symantics if we want to.<br>
><br>
> jfwiw, I am in favor of kernel(ish) lists.. although (as mentioned on<br>
> irc) maybe we just want to hoist gallium's u_double_list.h out into<br>
> util so it can be used more widely.  (fwiw, I am already using<br>
> u_double_list in freedreno)</p>
<p dir="ltr">I took a quick look through it.  While I like the nir_list api a little better, it would work just as well.  I'm not going to quibble to much over what gets used.  I prefer C99 iterators, it's a *lot* better than simple_list.<br>
--Jason</p>
<p dir="ltr">> > Why put this in NIR and not in util?<br>
> ><br>
> > At the moment, NIR is the only user.  I do expect that Eric may want to use<br>
> > it in vc4 over simple_list.  However, vc4 is already using NIR anyway, so<br>
> > it's not really that polluting.<br>
> ><br>
> > It has also been suggested by Ken that we just pull the C bits out of<br>
> > exec_list and keep one underlying implementation for both C and C++ only<br>
> > with different names.  While I think that this is definitely doable and may<br>
> > be the best long-term solution, I didn't want to do that refactoring prior<br>
> > to getting this series up-and-going and adding a list was easier.  I'm ok<br>
> > with doing that instead of adding a list.<br>
> > ---<br>
> >  src/glsl/Makefile.sources |   1 +<br>
> >  src/glsl/nir/nir_list.h   | 183 ++++++++++++++++++++++++++++++++++++++++++++++<br>
> >  2 files changed, 184 insertions(+)<br>
> >  create mode 100644 src/glsl/nir/nir_list.h<br>
> ><br>
> > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources<br>
> > index c471eca..fa51dcb 100644<br>
> > --- a/src/glsl/Makefile.sources<br>
> > +++ b/src/glsl/Makefile.sources<br>
> > @@ -28,6 +28,7 @@ NIR_FILES = \<br>
> >         nir/nir_from_ssa.c \<br>
> >         nir/nir_intrinsics.c \<br>
> >         nir/nir_intrinsics.h \<br>
> > +       nir/nir_list.h \<br>
> >         nir/nir_live_variables.c \<br>
> >         nir/nir_lower_alu_to_scalar.c \<br>
> >         nir/nir_lower_atomics.c \<br>
> > diff --git a/src/glsl/nir/nir_list.h b/src/glsl/nir/nir_list.h<br>
> > new file mode 100644<br>
> > index 0000000..330a660<br>
> > --- /dev/null<br>
> > +++ b/src/glsl/nir/nir_list.h<br>
> > @@ -0,0 +1,183 @@<br>
> > +/*<br>
> > + * Copyright © 2015 Intel Corporation<br>
> > + *<br>
> > + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> > + * copy of this software and associated documentation files (the "Software"),<br>
> > + * to deal in the Software without restriction, including without limitation<br>
> > + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> > + * and/or sell copies of the Software, and to permit persons to whom the<br>
> > + * Software is furnished to do so, subject to the following conditions:<br>
> > + *<br>
> > + * The above copyright notice and this permission notice (including the next<br>
> > + * paragraph) shall be included in all copies or substantial portions of the<br>
> > + * Software.<br>
> > + *<br>
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> > + * IN THE SOFTWARE.<br>
> > + *<br>
> > + * Authors:<br>
> > + *    Jason Ekstrand (<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>)<br>
> > + *<br>
> > + */<br>
> > +<br>
> > +#pragma once<br>
> > +<br>
> > +#ifndef _NIR_LIST_H_<br>
> > +#define _NIR_LIST_H_<br>
> > +<br>
> > +/** A simple linked list implementation.<br>
> > + *<br>
> > + * This linked list implementation is based on wl_list from the Wayland<br>
> > + * project which is, in turn, based on the kernel list.  As such, it should<br>
> > + * be fairly familiar to anyone who has worked in kernel space.<br>
> > + */<br>
> > +<br>
> > +/* Required for exec_node_data */<br>
> > +#include "../list.h"<br>
> > +<br>
> > +struct nir_link;<br>
> > +<br>
> > +/** \class nir_list<br>
> > + *<br>
> > + * \brief doubly-linked list<br>
> > + *<br>
> > + * The list head is of type nir_list and must be initialized using<br>
> > + * nir_list_init().  All entries in the list must be of the same type.  The<br>
> > + * item type must have a nir_link member which must be initialized to zero.<br>
> > + * To query if the list is empty in O(1), use nir_list_is_empty().<br>
> > + *<br>
> > + * Let's call the list reference "nir_list foo_list", the item type as<br>
> > + * "item_t", and the item member as "nir_link link".<br>
> > + *<br>
> > + * The following code will initialize a list:<br>
> > + * \code<br>
> > + * nir_list foo_list;<br>
> > + *<br>
> > + * struct item_t {<br>
> > + *     int foo;<br>
> > + *     nir_link link;<br>
> > + * };<br>
> > + * struct item_t item1, item2, item3;<br>
> > + *<br>
> > + * nir_list_init(&foo_list);<br>
> > + * nir_list_insert_after(&foo_list, &item1.link);   // Pushes item1 at the head<br>
> > + * nir_list_insert_after(&foo_list, &item2.link);   // Pushes item2 at the head<br>
> > + * nir_list_insert_after(&item2.link, &item3.link); // Pushes item3 after item2<br>
> > + * \endcode<br>
> > + *<br>
> > + * The list now looks like [item2, item3, item1]<br>
> > + *<br>
> > + * Iterate the list in ascending order:<br>
> > + * \code<br>
> > + * item_t *item;<br>
> > + * nir_list_foreach(item, foo_list, link) {<br>
> > + *     Do_something_with_item(item);<br>
> > + * }<br>
> > + * \endcode<br>
> > + */<br>
> > +typedef struct nir_list {<br>
> > +   struct nir_link *tail;<br>
> > +   struct nir_link *head;<br>
> > +} nir_list;<br>
> > +<br>
> > +typedef struct nir_link {<br>
> > +   struct nir_link *prev;<br>
> > +   struct nir_link *next;<br>
> > +} nir_link;<br>
> > +<br>
> > +static inline void<br>
> > +nir_list_init(nir_list *list)<br>
> > +{<br>
> > +   list->head = (nir_link *)list;<br>
> > +   list->tail = (nir_link *)list;<br>
> > +}<br>
> > +<br>
> > +static inline bool<br>
> > +nir_list_is_empty(nir_list *list)<br>
> > +{<br>
> > +   return list->head == (nir_link *)list;<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_link_init(nir_link *link)<br>
> > +{<br>
> > +   link->next = NULL;<br>
> > +   link->prev = NULL;<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_link_insert_after(nir_link *link_in_list, nir_link *after)<br>
> > +{<br>
> > +   assert(after->next == NULL && after->prev == NULL);<br>
> > +   after->prev = link_in_list;<br>
> > +   after->next = link_in_list->next;<br>
> > +   link_in_list->next = after;<br>
> > +   after->next->prev = after;<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_link_insert_before(nir_link *link_in_list, nir_link *before)<br>
> > +{<br>
> > +   assert(before->next == NULL && before->prev == NULL);<br>
> > +   before->next = link_in_list;<br>
> > +   before->prev = link_in_list->prev;<br>
> > +   link_in_list->prev = before;<br>
> > +   before->prev->next = before;<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_link_remove(nir_link *link)<br>
> > +{<br>
> > +   link->prev->next = link->next;<br>
> > +   link->next->prev = link->prev;<br>
> > +   nir_link_init(link);<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_list_push_head(nir_list *list, nir_link *elem)<br>
> > +{<br>
> > +   nir_link_insert_after((nir_link *)list, elem);<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_list_push_tail(nir_list *list, nir_link *elem)<br>
> > +{<br>
> > +   nir_link_insert_before((nir_link *)list, elem);<br>
> > +}<br>
> > +<br>
> > +#define nir_list_foreach(__type, __node, __field, __list)                  \<br>
> > +   for (__type *__node = exec_node_data(__type, (__list)->head, __field);  \<br>
> > +        &(__node)->__field != (nir_link *)(__list);                        \<br>
> > +        __node = exec_node_data(__type, (__node)->__field.next, __field))<br>
> > +<br>
> > +#define nir_list_foreach_safe(__type, __node, __field, __list)             \<br>
> > +   for (__type *__node = exec_node_data(__type, (__list)->head, __field),  \<br>
> > +               *__next = exec_node_data(__type, (__node)->__field.next, __field); \<br>
> > +        &(__node)->__field != (nir_link *)(__list);                        \<br>
> > +        __node = __next,                                                   \<br>
> > +        __next = exec_node_data(__type, (__next)->__field.next, __field))<br>
> > +<br>
> > +static inline unsigned<br>
> > +nir_list_length(nir_list *list)<br>
> > +{<br>
> > +   unsigned count = 0;<br>
> > +   for (nir_link *l = list->head; l != (nir_link *)list; l = l->next)<br>
> > +      count++;<br>
> > +   return count;<br>
> > +}<br>
> > +<br>
> > +static inline void<br>
> > +nir_list_validate(nir_list *list)<br>
> > +{<br>
> > +   assert(list->head->prev == (nir_link *)list);<br>
> > +   assert(list->tail->next == (nir_link *)list);<br>
> > +   for (nir_link *l = list->head; l != (nir_link *)list; l = l->next)<br>
> > +      assert(l->next->prev == l && l->prev->next == l);<br>
> > +}<br>
> > +<br>
> > +#endif /* _NIR_LIST_H_ */<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>