Oh, so they're actually part of the optimizations? I didn't know it is that clever omitting variables that are never used elsewhere and turning very small functions into in-line code
.
somefunc() simply sets a global variable:
Code: Select all
void somefunc(int value) {
global_var = value;
}
I decided to do another test but this time with a volatile variable set to a hardcoded address (ie. an I/O port):
Code: Select all
char global_array[256];
int global_var;
int ival;
volatile int *ioport = (int*)0x1f800000;
void somefunc(int value) {
global_var = value;
*ioport = value;
}
void myfunc() {
ival = 0;
somefunc( ival );
do {
ival++;
ival = ival * 2;
somefunc( ival );
somefunc( ival/2 );
} while( 1 );
}
And the assembler output looks like this:
Code: Select all
somefunc:
.frame $sp,0,$31 # v
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
lw $2,%gp_rel(ioport)($28)
sw $4,%gp_rel(global_var)($28)
sw $4,0($2)
jr $31
nop
.set macro
.set reorder
.end somefunc
.size somefunc, .-somefunc
.align 2
.globl myfunc
.set nomips16
.set nomicromips
.ent myfunc
.type myfunc, @function
myfunc:
.frame $sp,0,$31 # v
.mask 0x00000000,0
.fmask 0x00000000,0
.set noreorder
.set nomacro
lw $4,%gp_rel(ioport)($28)
sw $0,%gp_rel(ival)($28)
sw $0,0($4)
$L4:
lw $2,%gp_rel(ival)($28)
nop
addiu $2,$2,1
sll $2,$2,1
sw $2,%gp_rel(ival)($28)
sw $2,0($4)
lw $3,%gp_rel(ival)($28)
nop
srl $2,$3,31
addu $2,$2,$3
sra $2,$2,1
sw $2,%gp_rel(global_var)($28)
sw $2,0($4)
b $L4
nop
Looks like it reduces somefunc() into just a few instructions and it calls it as in-line. I really didn't know that GCC's optimizer is this sophisticated.
I still remember running into a few compiler bugs with GCC like this bit of code from PSXSDK's SsUpload() would produce an infinite loop which I had to fix by placing some dummy operations in it:
Code: Select all
while( ( SPU_STATUS2 & 0x7ff ) != spu_status );
And there was also an instance where performing an OR operation behaved like I was doing an = operation instead:
Code: Select all
// To avoid confusion, these are from homebrew libs of my own that follow Sony's syntax
typedef struct {
unsigned int tag;
unsigned int code[1];
} DR_TPAGE;
DR_TPAGE *tpri = (DR_TPAGE*)nextpri;
setTPagePri( tpri, 0, 0, tim.prect->x, tim.prect->y ); // Sets tag and code[0]
tpri->code[0] |= 0x200; // OR 0x200 to code[0] (behaved like = at one point)
Strangely, that OR bug I ran into above is gone now.
Please don't forget to include my name if you share my work around. Credit where it is due.
Dev. Console: SCPH-7000 with SCPH-7501 ROM, MM3, PAL color fix, Direct AV ports, DB-9 port for Serial I/O, and a Xplorer FX with Caetla 0.35.
DTL-H2000 PC: Dell Optiplex GX110, Windows 98SE & Windows XP, Pentium III 933MHz, 384MB SDRAM, ATI Radeon 7000 VE 64MB, Soundblaster Audigy, 40GB Seagate HDD, Hitachi Lite-on CD-RW Drive, ZIP 250 and 3.5" Floppy.