lgm@ODDJOB.UCHICAGO.EDU (11/26/88)
SYNOPSIS: The '-fstrength-reduce' flag can produce incorrect code when it attempts to reduce the strength of a nontrivial (i.e., function- requiring) multiplication more than once within the same loop. The example below shows incorrect assembly language generated by '-O -fstrength-reduce'; '-O' alone generates correct code. The example is simplified from "cccp.c". MACHINE AND OS: AT&T UNIX PC 3B1 (based on Motorola 68010 microprocessor) running OS Version 3.5 (compatible with UNIX System V Release 2). CONFIGURATION FILES: (usual for the UNIX PC) "tm-3b1.h" "xm-3b1.h" <== By the way, the reference to "config-m68k.h" in this file must be changed to "xm-m68k.h". "m68k.md" "output-m68k.c" TRANSCRIPT (INPUT FILE, COMMAND LINE, OUTPUT): _______________________________________ $ cat badstr.c struct S { /* structure is 14 bytes long */ int dummy1; short dummy2; char *field1; char *field2; }; extern void g(); void f( nels, arr ) int nels; struct S *arr; { int i; for ( i = 0; i < nels; ++i ) { if ( arr[ i ].field1 ) g( arr[ i ].field1 ); if ( arr[ i ].field2 ) g( arr[ i ].field2 ); } } $ gcc -v -S -O -fstrength-reduce badstr.c gcc version 1.31 /usr/local/lib/gcc-cpp -v -undef -D__GNU__ -D__GNUC__ -Dmc68k -Dunix -Dunixpc -D__OPTIMIZE__ badstr.c /tmp/cca03041.cpp GNU CPP version 1.31 /usr/local/lib/gcc-cc1 /tmp/cca03041.cpp -quiet -dumpbase badstr.c -fstrength-reduce -O -version -o badstr.s GNU C version 1.31 (68k, SGS/AT&T unixpc syntax) compiled by GNU C version 1.31. $ cat badstr.s file "badstr.c" text even global f f: link.w %a6,&0 movm.l &0x3f20,-(%sp) mov.l 8(%fp),%d4 mov.l 12(%fp),%a2 clr.l %d2 cmp.l %d4,%d2 ble.w L%8 clr.l %d3 L%7: tst.l 6(%a2,%d3.l) # %d3 is correct here beq.w L%5 mov.l 6(%a2,%d5.l),-(%sp) # %d5 is garbage here jsr g addq.w &4,%sp L%5: tst.l 10(%a2,%d6.l) # %d6 is garbage here beq.w L%4 mov.l 10(%a2,%d7.l),-(%sp) # %d7 is garbage here jsr g addq.w &4,%sp L%4: mov.l &14,%d0 add.l %d0,%d3 # %d3 is correctly incremented by 14 addq.l &1,%d2 cmp.l %d4,%d2 bgt.w L%7 L%8: movm.l -28(%a6),&0x4fc unlk %a6 rts $ _______________________________________ EXPLANATION OF TRANSCRIPT: The generated assembly language above *uses* %d5 , %d6 , and %d7 without ever assigning them meaningful values. The correct register to use in all three places would have been %d3 . Lawrence G. Mayka Aurora, Illinois chinet!lmayk!lgm
james@bigtex.cactus.org (James Van Artsdalen) (11/27/88)
> Lawrence G. Mayka In <8811260051.aa00576@gamma.eecs.nwu.edu>, Lawrence G. Mayka (lmayk!lgm@ODDJOB.UCHICAGO.EDU) submitted a bug report about -fstrength-reduce. I tried the example on my SysVr3 gcc 1.31 and did not see the failure mode. But I did see some strange, sub-optimal code: This: --- struct S { /* structure is 14 bytes long */ int dummy1; short dummy2; char *field1; char *field2; }; extern void g(); void f( nels, arr ) int nels; struct S *arr; { int i; for ( i = 0; i < nels; ++i ) { if ( arr[ i ].field1 ) g( arr[ i ].field1 ); if ( arr[ i ].field2 ) g( arr[ i ].field2 ); } } --- gives (via gcc -O -fstrength-reduce -S) this: --- .file "strength1.c" .text .align 4 .globl f f: pushl %ebp movl %esp,%ebp subl $4,%esp ; we don't need this temp. space pushl %ebx pushl %esi pushl %edi xorl %ebx,%ebx ; i cmpl 8(%ebp),%ebx ; cmp nels ,i jge .L8 xorl %edi,%edi ; expected nifty array-index follower .L7: movl 12(%ebp),%esi ; arr cmpl $0,8(%edi,%esi) ; why not copy this to ax for push? je .L5 pushl 8(%edi,%esi) call g leal 4(%esp),%esp .L5: movl %edi,-4(%ebp) ; huh? -4(%ebp) is never read! movl 12(%ebp),%esi ; arr cmpl $0,12(%edi,%esi) je .L4 pushl 12(%edi,%esi) call g leal 4(%esp),%esp .L4: leal 16(%edi),%edi ; "add" is slightly faster than lea. incl %ebx ; i cmpl 8(%ebp),%ebx ; cmp nels, i jl .L7 .L8: leal -16(%ebp),%esp popl %edi popl %esi popl %ebx leave ret -- James R. Van Artsdalen james@bigtex.cactus.org "Live Free or Die" Home: 512-346-2444 Work: 338-8789 9505 Arboretum Blvd Austin TX 78759