public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Optimization attributes const vs. pure
@ 2012-05-28 12:35 Johannes Bauer
  2012-05-28 14:40 ` Ángel González
  2012-05-29 22:45 ` Ian Lance Taylor
  0 siblings, 2 replies; 6+ messages in thread
From: Johannes Bauer @ 2012-05-28 12:35 UTC (permalink / raw)
  To: gcc-help

Hi list,

I have a question about the optimizations conducted by gcc when
functions are declared pure or const. I'm using gcc 4.6.2 on Gentoo
Linux x86-64. Here's a minimal example:

----8<----8<---- int.c ----8<----8<----8<
#include <string.h>
#include "int.h"
int intcmp(const struct mi *a, const struct mi *b) {
	return memcmp(a, b, sizeof(struct mi));
}



----8<----8<---- int.h ----8<----8<----8<
struct mi {
	int foo;
	unsigned char x[16];
};

int intcmp(const struct mi *a, const struct mi *b) __attribute__ ((pure));


----8<----8<---- main.c ----8<----8<----8<
#include <stdio.h>
#include <string.h>
#include "int.h"
int main() {
	struct mi a, b;
	memset(&a, 0, sizeof(struct mi));
	memset(&b, 0, sizeof(struct mi));
	for (unsigned int i = 0; i < 100; i++) {
		fprintf(stderr, "%d\n", intcmp(&a, &b));
	}
	return 0;
}


I'm compiling using

$ gcc -O3 -march=nocona -std=c99 main.c int.c -o out

This is the observation I'm making: The generated assembly does not
differ from a function declared as "pure" from a function not declared
with any special attribute.

As soon as I declare the function (wrongly!) as const, the optimization
that I'd expect with "pure" occurs (i.e. intcmp() is only called once).

Now from my understanding I cannot use the attribute "const" for
intcmp() since intcmp() dereferences the pointers that it's passed (and
thus accesses global memory in a reading fashion).

So "pure" would be the perfect fit: Global memory is read but not
modified (which is also asserted by passing the arguments as "const").
Why is gcc then not doing the optimization that I'd want it to perform?

Best regards,
Joe

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Optimization attributes const vs. pure
  2012-05-28 12:35 Optimization attributes const vs. pure Johannes Bauer
@ 2012-05-28 14:40 ` Ángel González
  2012-05-28 14:49   ` Johannes Bauer
  2012-05-29 22:45 ` Ian Lance Taylor
  1 sibling, 1 reply; 6+ messages in thread
From: Ángel González @ 2012-05-28 14:40 UTC (permalink / raw)
  To: Johannes Bauer; +Cc: gcc-help

On 28/05/12 14:35, Johannes Bauer wrote:
> So "pure" would be the perfect fit: Global memory is read but not
> modified (which is also asserted by passing the arguments as "const").
> Why is gcc then not doing the optimization that I'd want it to perform?
I have no idea.
I wondered if it feared fprintf changing global variables on which
intcmp() depended,
so I modified it to create the following program, where there is no
side-effect.
But it still exhibits the same behavior (intcmp called 100 times if
pure, 1 if const).

#include <stdio.h>
#include <string.h>
#include "int.h"
int main() {
    struct mi a, b;
    int vals[100];
    memset(&a, 0, sizeof(struct mi));
    memset(&b, 0, sizeof(struct mi));
    for (unsigned int i = 0; i < 100; i++) {
        vals[i] = intcmp(&a, &b);
    }
    for (unsigned int i = 0; i < 100; i++) {
        fprintf(stderr, "%d\n", vals[i]);
    }
    return 0;
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Optimization attributes const vs. pure
  2012-05-28 14:40 ` Ángel González
@ 2012-05-28 14:49   ` Johannes Bauer
  2012-05-28 17:05     ` Ángel González
  0 siblings, 1 reply; 6+ messages in thread
From: Johannes Bauer @ 2012-05-28 14:49 UTC (permalink / raw)
  To: gcc-help; +Cc: keisial

On 28.05.2012 16:40, Ángel González wrote:
> On 28/05/12 14:35, Johannes Bauer wrote:
>> So "pure" would be the perfect fit: Global memory is read but not
>> modified (which is also asserted by passing the arguments as "const").
>> Why is gcc then not doing the optimization that I'd want it to perform?
> I have no idea.
> I wondered if it feared fprintf changing global variables on which
> intcmp() depended,
> so I modified it to create the following program, where there is no
> side-effect.
> But it still exhibits the same behavior (intcmp called 100 times if
> pure, 1 if const).

Thank you for trying it out... good to get confirmation that this isn't
just the case with my arch/gcc combination. Would you mind sharing which
platform/gcc version you've tried it out with?

Best regards,
Johannes

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Optimization attributes const vs. pure
  2012-05-28 14:49   ` Johannes Bauer
@ 2012-05-28 17:05     ` Ángel González
  0 siblings, 0 replies; 6+ messages in thread
From: Ángel González @ 2012-05-28 17:05 UTC (permalink / raw)
  To: Johannes Bauer; +Cc: gcc-help

On 28/05/12 16:49, Johannes Bauer wrote:
> Thank you for trying it out... good to get confirmation that this
> isn't just the case with my arch/gcc combination. Would you mind
> sharing which platform/gcc version you've tried it out with?
I used gcc 4.7.0 on a x86_64 system (-m32 switch makes no difference).

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Optimization attributes const vs. pure
  2012-05-28 12:35 Optimization attributes const vs. pure Johannes Bauer
  2012-05-28 14:40 ` Ángel González
@ 2012-05-29 22:45 ` Ian Lance Taylor
  2012-05-29 23:39   ` Johannes Bauer
  1 sibling, 1 reply; 6+ messages in thread
From: Ian Lance Taylor @ 2012-05-29 22:45 UTC (permalink / raw)
  To: Johannes Bauer; +Cc: gcc-help

Johannes Bauer <dfnsonfsduifb@gmx.de> writes:

> I have a question about the optimizations conducted by gcc when
> functions are declared pure or const. I'm using gcc 4.6.2 on Gentoo
> Linux x86-64. Here's a minimal example:
>
> ----8<----8<---- int.c ----8<----8<----8<
> #include <string.h>
> #include "int.h"
> int intcmp(const struct mi *a, const struct mi *b) {
> 	return memcmp(a, b, sizeof(struct mi));
> }
>
>
>
> ----8<----8<---- int.h ----8<----8<----8<
> struct mi {
> 	int foo;
> 	unsigned char x[16];
> };
>
> int intcmp(const struct mi *a, const struct mi *b) __attribute__ ((pure));
>
>
> ----8<----8<---- main.c ----8<----8<----8<
> #include <stdio.h>
> #include <string.h>
> #include "int.h"
> int main() {
> 	struct mi a, b;
> 	memset(&a, 0, sizeof(struct mi));
> 	memset(&b, 0, sizeof(struct mi));
> 	for (unsigned int i = 0; i < 100; i++) {
> 		fprintf(stderr, "%d\n", intcmp(&a, &b));
> 	}
> 	return 0;
> }
>
>
> I'm compiling using
>
> $ gcc -O3 -march=nocona -std=c99 main.c int.c -o out
>
> This is the observation I'm making: The generated assembly does not
> differ from a function declared as "pure" from a function not declared
> with any special attribute.
>
> As soon as I declare the function (wrongly!) as const, the optimization
> that I'd expect with "pure" occurs (i.e. intcmp() is only called once).
>
> Now from my understanding I cannot use the attribute "const" for
> intcmp() since intcmp() dereferences the pointers that it's passed (and
> thus accesses global memory in a reading fashion).
>
> So "pure" would be the perfect fit: Global memory is read but not
> modified (which is also asserted by passing the arguments as "const").
> Why is gcc then not doing the optimization that I'd want it to perform?

GCC does not know that the function fprintf does not modify global
memory.  In fact, the function does modify global memory, in that it
will change stderr structure.  For example, for all GCC knows, the
function intcmp could call ferror(stderr)--that would be permitted by a
pure function.  And that means that the call can not be hoisted out of
the loop.

Ian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Optimization attributes const vs. pure
  2012-05-29 22:45 ` Ian Lance Taylor
@ 2012-05-29 23:39   ` Johannes Bauer
  0 siblings, 0 replies; 6+ messages in thread
From: Johannes Bauer @ 2012-05-29 23:39 UTC (permalink / raw)
  To: gcc-help; +Cc: iant

On 30.05.2012 00:44, Ian Lance Taylor wrote:

> GCC does not know that the function fprintf does not modify global
> memory.  In fact, the function does modify global memory, in that it
> will change stderr structure.  For example, for all GCC knows, the
> function intcmp could call ferror(stderr)--that would be permitted by a
> pure function.  And that means that the call can not be hoisted out of
> the loop.

That does explain why my original variant isn't optimized, but it does
not explain why Ángel's modified variant (with a deferred printf() call)
also exhibits the same phaenomenon. This is the modified variant of his:

#include <stdio.h>
#include <string.h>
#include "int.h"
int main() {
    struct mi a, b;
    int vals[100];
    memset(&a, 0, sizeof(struct mi));
    memset(&b, 0, sizeof(struct mi));
    for (unsigned int i = 0; i < 100; i++) {
        vals[i] = intcmp(&a, &b);
    }
    for (unsigned int i = 0; i < 100; i++) {
        fprintf(stderr, "%d\n", vals[i]);
    }
    return 0;
}

Here, there's definitely no modified global memory and yet intcmp() is
still called every time in the loop.

Best regards,
Johannes

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-05-29 23:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-28 12:35 Optimization attributes const vs. pure Johannes Bauer
2012-05-28 14:40 ` Ángel González
2012-05-28 14:49   ` Johannes Bauer
2012-05-28 17:05     ` Ángel González
2012-05-29 22:45 ` Ian Lance Taylor
2012-05-29 23:39   ` Johannes Bauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).