Bill Stoddard wrote:
> While trying to create a simple testcase demonstrating a bug in the xlc
> compiler, I did a little experiment. Here is a code snip from core.c:
>
I'm just wondering if there is any kind of measureable performance
benefit in keeping these as a macro vs putting them in a function
(possibly inline if the compiler can support it).
> <snip>
> /* Code from core.c */
> if (mode == AP_MODE_INIT) {
> return APR_SUCCESS;
> }
> if (!ctx)
> {
> ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
> ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
>
> e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
> APR_BRIGADE_INSERT_TAIL(ctx->b, e);
> net->in_ctx = ctx;
> }
> else if (APR_BRIGADE_EMPTY(ctx->b)) {
> return APR_EOF;
> }
> avoid_xlc_bug(f->c->base_server);
> BRIGADE_NORMALIZE(ctx->b);
> </snip>
>
> And here is that same code with the macros unrolled. The xlc optimizer
> chokes on this. avoid_xlc_bug() just returns 1 and does nothing else (and
> makes the optimzer happy again). This is just nasty.
>
> /* Code from core.c with macros unrolled. */
> if (mode == AP_MODE_INIT) {
> #line 3330
> return 0;
> }
> if (!ctx)
> {
> ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
> ctx->b = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
> #line 3339
> e = apr_bucket_socket_create(net->client_socket, f->c->bucket_alloc);
> do { apr_bucket *ap__b = (e); do { ((((ap__b))))->link.next = ((struct
> apr_bucket
> *)((char *)(((&(ctx->b)->list))) - ((l
> ong) (((char *) (&(((struct apr_bucket*)0)->link))) - ((char *) 0)))));
> ((((ap__b))))->link.prev = (((struct apr_bucket *)((char
> *)(((&(ctx->b)->list))) - ((long) (((char *) (&(((struct
> apr_bucket*)0)->link))) - ((char
> *) 0))))))->link.prev; ((((struct apr
> _bucket *)((char *)(((&(ctx->b)->list))) - ((long) (((char *) (&(((struct
> apr_bucket*)0)->link))) - ((char *) 0))))))->link.prev
> )->link.next = (((ap__b))); (((struct apr_bucket *)((char
> *)(((&(ctx->b)->list))) -
> ((long) (((char *) (&(((struct apr_bucket*)0
> )->link))) - ((char *) 0))))))->link.prev = (((ap__b))); } while (0); }
> while (0);
> net->in_ctx = ctx;
> }
> else if ((((&(ctx->b)->list))->next == (struct apr_bucket *)((char
> *)((&(ctx->b)->list)) - ((long) (((char *) (&(((struct ap
> r_bucket*)0)->link))) - ((char *) 0)))))) {
> return ((20000 + 500) + 14);
> }
>
> avoid_xlc_bug(f->c->base_server);
> #line 3350
> do { apr_bucket *e = (&(ctx->b)->list)->next; do { if (e->length == 0)
> { apr_bucket
> *d; d = ((e))->link.next; do { do { ((((
> (e))))->link.prev)->link.next = ((((e))))->link.next;
> (((((e))))->link.next)->link.prev =
> ((((e))))->link.prev; } while (0); do
> { (e)->type->destroy((e)->data); (e)->free(e); } while (0); } while (0); e =
> d; } e =
> ((e))->link.next; } while (!(((&(ctx->b)->
> list))->next == (struct apr_bucket *)((char *)((&(ctx->b)->list)) - ((long)
> (((char *)
> (&(((struct apr_bucket*)0)->link))) - ((c
> har *) 0))))) && (e != (struct apr_bucket *)((char *)(&(ctx->b)->list) -
> ((long) (((char
> *) (&(((struct apr_bucket*)0)->link)))
> - ((char *) 0)))))); } while (0);
> #line 3358
> if ((((&(ctx->b)->list))->next == (struct apr_bucket *)((char
> *)((&(ctx->b)->list)) -
> ((long) (((char *) (&(((struct apr_buc
> ket*)0)->link))) - ((char *) 0)))))) {
> return ((20000 + 500) + 14);
> }
> #line 3365
>