A simple non-portable expression tha
Gregory Smith
greg at utcsri.UUCP
Tue May 6 05:13:14 AEST 1986
In article <972 at dataioDataio.UUCP> bright at dataio.UUCP (Walter Bright writes:
>In article <2609 at utcsri.UUCP> greg at utcsri.UUCP (Gregory Smith) writes:
>>However, I tried this ( using 16-bit short ints for I1,I2 ) on our
>>native vax compiler and on our 68K compiler. Both produced identical code
>>for (L+I1)+I2 and L+(I1+I2) and L+I1+I2: specifically, ((long)I1+L)+(long)I2.
>>I guess the a+b+c is recognized as a special case, and all three are widened
>>to a common width regardless of the original associativityy
>
>Shorts in C are always converted to ints before they are used. On the
>vax and most 68k compilers, ints are the same as longs. Therefore, this
>isn't any 'special case' recognized by the compiler.
>
>Different code for (L+I1)+I2 and L+(I1+I2) will only be generated if
>ints are smaller than longs.
You're quite right about the vax and 68K - since there's nothing wider than
an int, you can't get in trouble. This hadn't occurred to me. Maybe
someone with a PDP11 compiler could play with this and tell us what happens.
About the 'special case', though, let me quote 'A Tour through the UNIX
C Compiler', Dennis Ritchie ( about the PDP-11 compiler ):
The *acommute* routine, called for associative and commutative
operators, discovers clusters of the same operator at the top level
of the current tree, and arranges them in a list: for
`a+((b+c)+(d+f))' the list would be `a,b,c,d,e,f' [sic]. After each
subtree is optimized, the list is stored in increasing difficulty
of computation [...] the code generation algorithm works best when
left operands are the difficult ones. [...] a constant is
considered simpler than the address of a static or external, which
is simpler than reference to a variable. This makes it easy to fold
all the constants together, and also to merge together the sum of a
constant and the address of a static or external [...].
A special routine is invoked to handle sums of products. *Distrib*
is based on the fact that it is better to compute `c1*c2*x + c2*y' as
`c1*(c2*x+y)' and makes the divisibility tests required to assure the
correctness of the transformation. This transformation is rarely
possible with code directly written by the user, but it invariably
occurs as a result of the implementation of multidimensional arrays.
Finally, *acommute* reconstructs a tree from the list of
expressions which result.
Given this device, it wouldn't be hard, on a 16-bit machine, to detect
the presence of a long in a chained add, and to widen everything in the
list to long to avoid overflow problems.
Apparently there is no *Distrib* in the vax compiler:
The following code is generated for x=p[i]; int x,i,p[10];
movl _i,r0 ; get i in register
movl _p[r0],_x ; x = mem( &p + i*4 )
The following code is generated for x=a[i][j]: int x,i,j,a[10][20]
( with -O option ):
movl _j,r0 ; r0 = j
mull3 $80,_i,r1 ; r1 = 80*i
addl2 $_a,r1 ; r1 = &a + 80*i
ashl $2,r0,r0 ; r0 = 4*j
addl2 r0,r1 ; r1 = &a + 80*i + 4*j
movl (r1),_x ; do the move
this *could* have been done as
mull3 $20,_i,r1 ; r1 = 20*i
addl2 _j,r1 ; r1 = 20*i + j
movl _a[r1],_x
if the compiler had rearranged &a+80*i+4*j as &a+4*(20*i+j).
Why wouldn't the vax compiler be at least as smart as the PDP compiler
for things like this? Especially in the presence of a '_a[r1]' addressing
mode with implicit scaling.
--
"Canabee be said2b or not2b anin tire b, if half thabee isnotabee, due2
somain chunt injury?" - Eric's Dilemma
----------------------------------------------------------------------
Greg Smith University of Toronto UUCP: ..utzoo!utcsri!greg
More information about the Comp.lang.c
mailing list