http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46186
--- Comment #21 from Dominique d'Humieres <dominiq at lps dot ens.fr>
2010-10-26 21:06:48 UTC ---
> I guess you mean LLVM instead of clang,
Yes, if you prefer. I was referring to the command I used.
> F (6, a * a * a * a * a + 2 * a * a * a + 5 * a)
you probably mean
F (6, sum +=a * a * a * a * a + 2 * a * a * a + 5 * a)
> It's a bit more complicated than that, in that you can't just compute
> (b*(b-1)-a*(a-1)) mod 2^n, then divide by 2, as that will lose the top
> bit. (I haven't checked exactly what the generated code is doing here.)
This is right if you do the multiply before the division. However b or b-1 can
be divided exactly by 2, so you have to do (b/2)*(b-1) if b is even and
b*((b-1)/2) if b is odd. The same result applies for the sum of square and
cubes, although you may be one more trick if 2*b+1 wrap and can be divided
exactly by 3.
I have tested the following variant
[macbook] f90/bug% cat pr46186_db.c
#include <stdio.h>
#define len 1000000000L
unsigned long f(unsigned long a, unsigned long b) __attribute__((noinline));
int main()
{
unsigned long res;
res = f(2, 2*len);
/* printf("%lu\n", res); */
return 0;
}
unsigned long f(unsigned long a, unsigned long b)
{
unsigned long sum = 0, sum0 = 0, sum2 = 0, sum5 = 0;
for (; a < b; a++)
{
sum0 += 2;
sum += a;
sum2 += a*a;
sum5 += a*a*a*a*a + 2*a*a*a +5*a;
}
printf("%lu\n", sum0);
printf("%lu\n", sum);
printf("%lu\n", sum2);
printf("%lu\n", sum5);
return sum;
}
which gives
[macbook] f90/bug% gcc46 -Ofast -ftree-vectorizer-verbose=2 pr46186_db.c
pr46186_db.c:18: note: LOOP VECTORIZED.
pr46186_db.c:15: note: vectorized 1 loops in function.
[macbook] f90/bug% time a.out
3999999996
1999999998999999999
10262176583330622975
11833798674328980984
18.114u 0.012s 0:18.15 99.8% 0+0k 0+0io 0pf+0w
[macbook] f90/bug% clang -O pr46186_db.c
[macbook] f90/bug% time a.out
3999999996
1999999998999999999
10262176583330622975
11833798674328980984
0.000u 0.000s 0:00.00 0.0% 0+0k 0+0io 0pf+0w
So the wrapping seems properly handled for the loop replacement.
Now I have also tested the following variant
[macbook] f90/bug% cat pr46186_db_1.c
#include <stdio.h>
#define len 1000000000L
unsigned long f(unsigned long a, unsigned long b) __attribute__((noinline));
int main()
{
unsigned long res;
res = f(2, 2*len);
/* printf("%lu\n", res); */
return 0;
}
unsigned long f(unsigned long a, unsigned long b)
{
unsigned long sum = 0, sum0 = 0, sum2 = 0, sum5 = 0;
unsigned long a2;
for (; a < b; a++)
{
sum0 += 2;
sum += a;
a2 = a*a;
sum2 += a2;
sum5 += a*(a2*(a2 + 2) +5);
}
printf("%lu\n", sum0);
printf("%lu\n", sum);
printf("%lu\n", sum2);
printf("%lu\n", sum5);
return sum;
}
and the timings are
[macbook] f90/bug% gcc46 -Ofast -ftree-vectorizer-verbose=2 pr46186_db_1.c
pr46186_db_1.c:19: note: LOOP VECTORIZED.
pr46186_db_1.c:15: note: vectorized 1 loops in function.
[macbook] f90/bug% time a.out
3999999996
1999999998999999999
10262176583330622975
11833798674328980984
12.227u 0.016s 0:12.36 98.9% 0+0k 0+0io 0pf+0w <== was 18.114u 0.012s
0:18.15 without
hand optimization
[macbook] f90/bug% clang -O pr46186_db_1.c
[macbook] f90/bug% time a.out
3999999996
1999999998999999999
10262176583330622975
11833798674328980984
0.000u 0.000s 0:00.00 0.0% 0+0k 0+0io 0pf+0w
So clearly gcc is missing some generic optimizations in products.