This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: remove reverse_die_lists
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Geoff Keating <geoffk at geoffk dot org>
- Date: Mon, 24 Apr 2006 09:12:04 +0200
- Subject: Re: remove reverse_die_lists
- References: <20060422084538.8CD38340D6F6@geoffk5.apple.com>
+/* 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