This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: remove reverse_die_lists


+/* Evaluate 'expr' while 'c' is set to each child of DIE in order.  */
+#define FOR_EACH_CHILD(die, c, expr) do {	\
+  c = die->die_child;				\
+  if (c) do {					\
+    c = c->die_sib;				\
+    expr;					\
+  } while (c != die->die_child);		\
+} while (0)
+

If you want to write this in a "iterator" style, it can be helpful to know that GCC optimizes this completely:


  #define NULL 0
  #define TRUE 1

  struct s {
    int x;
    struct s *next;
  };

  int s(struct s *last) {
    struct s *p;
    int n = 0;
    for (p = NULL;
         p != last && (p || (p = last)) && (p = p->next, 1); )
      n += p->x;

    return n;
  }

The NULL pointer checking optimization detects that p is dereferenced in the loop, and deletes the "p || (p == last)" part after the first iteration on the loop. Dually, when entering the loop jump threading simplifies the code to "p = last->next".

The result is this (massaged from the .optimized dump):

  if (last == 0)
    return 0;

  p = last;
  n = 0;
  do {
    p = p->next;
    n = p->x + n;
  } while (p != last);
  return n;

In your case that would be:

  #define FOR_EACH_CHILD(die, c)		\
    for (c = NULL;				\
         c != die->die_child			\
         && (c || (c = die->die_child))		\
         && (c = c->die_sib, 1); )

Paolo


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]