This code is a tremendous example of what compiler optimization can do. Assuming you meant for (a = -3; a <= 3; a++) ...
then you can re-code this into:
#include <stdio.h>
#define val(a) (a*a*a*a*a*a*a - a*a*a*a*4 - a*a*a + a*a*7 + 30*a)
#define MIN(X, Y) ((X) > (Y) ? (Y) : (X))
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
int main(int argc, char **argv)
{
int c = 0, d = 0, a;
for (a = -3; a <= 3; a++)
c = MAX(val(a), c), d = MIN(val(a), d);
printf("max value is %d,\nmin value is %d\n", c, d);
return 0;
}
Intel's ICC turns this directly into:
4006f9: [ ... meaningless "ICC glue" instruction ... ]
4006fd: bf 7c 0b 40 00 mov $0x400b7c,%edi
400702: be c5 07 00 00 mov $0x7c5,%esi
400707: [ ... meaningless "ICC glue" instruction ... ]
40070e: ba 31 f6 ff ff mov $0xfffff631,%edx
400713: 33 c0 xor %eax,%eax
400715: [ ... meaningless "ICC glue" instruction ... ]
400719: e8 2a fe ff ff callq 400548 <printf@plt>
40071e: 33 c0 xor %eax,%eax
400720: 48 89 ec mov %rbp,%rsp
400723: 5d pop %rbp
400724: c3 retq
CLang (3.3) also can to it, it creates:
0000000000400b60 <main>:
400b60: 50 push %rax
400b61: bf 6c 0c 40 00 mov $0x400c6c,%edi
400b66: be c5 07 00 00 mov $0x7c5,%esi
400b6b: ba 31 f6 ff ff mov $0xfffff631,%edx
400b70: 30 c0 xor %al,%al
400b72: e8 39 fd ff ff callq 4008b0 <printf@plt>
400b77: 31 c0 xor %eax,%eax
400b79: 5a pop %rdx
400b7a: c3 retq
GCC (up to and including 4.8.1) doesn't seem able to compile-time calculate in this case, while it unrolls the loop it inserts a sequence of multiplies, conditional moves / SSE min/max instructions.
But if you explicitly unroll the loop in code, manually, then you get:
c = MAX(val(-3), 0); d = MIN(val(-3), 0);
c = MAX(val(-2), c); d = MIN(val(-2), d);
c = MAX(val(-1), c); d = MIN(val(-1), d);
c = MAX(val(0), c); d = MIN(val(0), d);
c = MAX(val(1), c); d = MIN(val(1), d);
c = MAX(val(2), c); d = MIN(val(2), d);
c = MAX(val(3), c); d = MIN(val(3), d);
and GCC is able to calculate it at compile-time:
0000000000400630 <main>:
400630: 48 83 ec 08 sub $0x8,%rsp
400634: ba 31 f6 ff ff mov $0xfffff631,%edx
400639: be c5 07 00 00 mov $0x7c5,%esi
40063e: bf 50 07 40 00 mov $0x400750,%edi
400643: 31 c0 xor %eax,%eax
400645: e8 79 fe ff ff callq 4004c0 <printf@plt>
40064a: 31 c0 xor %eax,%eax
40064c: 48 83 c4 08 add $0x8,%rsp
400650: c3 retq
Morale: The best result in this case you get by not trying to optimize the assembler output :)