I'm trying to determine why two compilers seem to think an int and a float
array are aliased (and therefore addresses of elements must be constantly
reloaded), even when my (perhaps naive) interpretation of ANSI rules says
the arrays cannot be aliased.
In particular, I'd like to understand why:
-------------------------------------------------
float test2d(float ****ff, int ***solid, int ni, int nz, int ny, int nx)
{
int i,z,y,x;
float fsum;
for(fsum=0.0f, isum=i=0; i<ni; i++){
for(z=0; z<nz; z++){
for(y=0; y<ny; y++){
for(x=0; x<nx; x++){
fsum += ff[i][z][y][x]*solid[z][y][x];
}
}
}
}
return(fsum);
Quote:
}
----------------------------------------------
generates an efficient inner loop:
----------------------------------------------
$B1$10: ; Preds $B1$9 $B1$10
fild DWORD PTR [edi+ebp*4] ;19.29
fmul DWORD PTR [esi+ebp*4] ;19.29
faddp st(1), st ;19.6
fstp DWORD PTR [esp+80] ;19.6
cvtsi2ss xmm1, DWORD PTR [edi+ebp*4+4] ;19.29
mulss xmm1, DWORD PTR [esi+ebp*4+4] ;19.29
addss xmm1, DWORD PTR [esp+80] ;19.6
cvtsi2ss xmm0, DWORD PTR [edi+ebp*4+8] ;19.29
mulss xmm0, DWORD PTR [esi+ebp*4+8] ;19.29
addss xmm1, xmm0 ;19.6
movss DWORD PTR [esp+80], xmm1 ;19.6
fld DWORD PTR [esp+80] ;19.6
add ebp, 3 ;18.20
cmp ebp, ecx ;18.5
jle $B1$10 ; Prob 97% ;18.5
----------------------------------------------
(no loads other than floating point loads; pointers to ff are dereferenced
in the outer loop, and the offsets incremented, rather than reloading and
reconstructing the total ff[][][][] address at each x value), whereas:
----------------------------------------------
float test2(float ****ff, int ***solid, int ni, int nz, int ny, int nx)
{
int i,z,y,x;
float sum;
for(sum=0.0f, i=0; i<ni; i++){
for(z=0; z<nz; z++){
for(y=0; y<ny; y++){
for(x=0; x<nx; x++){
sum += ff[i][z][y][x];
solid[z][y][x] <<= 1;
}
}
}
}
return(sum);
Quote:
}
----------------------------------------------
generates an inner loop with:
----------------------------------------------
$B1$9: ; Preds $B1$8 $B1$9
mov eax, DWORD PTR [esp+68] ;19.13
mov eax, DWORD PTR [eax] ;19.13
mov esi, DWORD PTR [esp+72] ;19.13
mov eax, DWORD PTR [eax+esi*2] ;19.13
mov eax, DWORD PTR [eax+ebp*2] ;19.13
fadd DWORD PTR [eax+edx*4] ;19.6
fstp DWORD PTR [esp+48] ;19.6
fld DWORD PTR [esp+48] ;19.6
;;; solid[z][y][x] <<= 1;
mov eax, DWORD PTR [ecx+ebx*4] ;20.6
mov eax, DWORD PTR [eax+ebp*2] ;20.6
mov esi, DWORD PTR [eax+edx*4] ;20.6
add esi, esi ;20.6
mov DWORD PTR [eax+edx*4], esi ;20.6
inc edx ;18.20
cmp edx, edi ;18.5
jl $B1$9 ; Prob 97% ;18.5
----------------------------------------------
....that is, the higher-level pointers in ff get reloaded from memory with
every iteration of the inner loop, apparently because solid[][][] is stored
back, even though by ansi rules the ff and solid arrays cannot be aliased.
The problem arises with both Intel C v5 and Microsoft VC 6, with pure C
code. Neither compiler mentions a switch to turn off the ansi rules, so I
naively assumed that ansi must be the default. I can overcome the problem
with manual dereferencing, but I'd still like to understand what is going
on.
--