This bug was very hard to trace. I'm on the ScummVM dev team and I develop specifically for the PSP(MIPS). I came across a crash when trying to start one of our engines. The bug only occurred under very specific circumstances -- I bisected it and adding class variables or adding some code made it go away, but I'm not sure what the pattern is.
Here's the problematic code, packaged together easily: void Logic::logicUp(uint32 new_script) { debug(5, "new pc = %d", new_script & 0xffff); // going up a level - and we'll keep going this cycle _curObjectHub.setLogicLevel(_curObjectHub.getLogicLevel() + 1); assert(_curObjectHub.getLogicLevel() < 3); // Can be 0, 1, 2 logicReplace(new_script); } void Logic::logicReplace(uint32 new_script) { uint32 level = _curObjectHub.getLogicLevel(); _curObjectHub.setScriptId(level, new_script); _curObjectHub.setScriptPc(level, new_script & 0xffff); } void setScriptId(int level, uint32 x) { WRITE_LE_UINT32(_addr + 20 + 4 * level, x); } uint32 getScriptId(int level) { return READ_LE_UINT32(_addr + 20 + 4 * level); } void setScriptPc(int level, uint32 x) { WRITE_LE_UINT32(_addr + 32 + 4 * level, x); } G++ optimized these 2 functions into 1 and came up with this code: 8934bc0 <_ZN6Sword25Logic7logicUpEj>: 8934bc0: 27bdfff0 addiu sp,sp,-16 8934bc4: afb20008 sw s2,8(sp) 8934bc8: afb10004 sw s1,4(sp) 8934bcc: 30b2ffff andi s2,a1,0xffff # s2 = new_scip & 0xffff 8934bd0: 00a08821 move s1,a1 # s1 = new_scipt 8934bd4: 3c0508aa lui a1,0x8aa # a1 = 0x8aa0000 8934bd8: afb00000 sw s0,0(sp) 8934bdc: 24a50d68 addiu a1,a1,3432 # a1 = 0x8aa3432 8934be0: 00808021 move s0,a0 # s0 = this 8934be4: 02403021 move a2,s2 # a2 = new_script & 0xffff 8934be8: afbf000c sw ra,12(sp) 8934bec: 0e286377 jal 8a18ddc <_Z5debugiPKcz> 8934bf0: 24040005 li a0,5 # a0 = 5 (jump) 8934bf4: 8e0400d8 lw a0,216(s0) # a0 = *(this + 216) 8934bf8: 88850007 lwl a1,7(a0) # a1 = 8934bfc: 98850004 lwr a1,4(a0) # a1 = logicLevel 8934c00: 24a20001 addiu v0,a1,1 # v0 = logicLevel + 1 8934c04: a8820007 swl v0,7(a0) # 7(a0) = 0.5 new logicLevel 8934c08: 2ca30003 sltiu v1,a1,3 # v1 = a1 < 3? 8934c0c: 10600011 beqz v1,8934c54 <_ZN6Sword25Logic7logicUpEj+0x94> # assert 8934c10: b8820004 swr v0,4(a0) # 4(a0) = 0.5 new logicLevel 8934c14: 24a20005 addiu v0,a1,5 # v0 = logicLevel + 5 ??? 8934c18: 00021080 sll v0,v0,0x2 # v0 = 4*logicLevel + 20 (scriptId offset) 8934c1c: 00821021 addu v0,a0,v0 # v0 = &scriptId 8934c20: 24a30008 addiu v1,a1,8 # v1 = logicLevel + 8 8934c24: a8510003 swl s1,3(v0) # scriptId[3] = new_script 8934c28: 00031880 sll v1,v1,0x2 # v1 = logicLevel * 4 + 32 8934c2c: b8510000 swr s1,0(v0) # scriptId[0] = new_script 8934c30: 00831821 addu v1,a0,v1 # v1 = *(this + 216) Note the mistake in line 8934c00. v0 is used for incrementing the logicLevel, and v0 is indeed saved into memory (ie. _curObjectHub.setLogicLevel(_curObjectHub.getLogicLevel() + 1); ) But the optimization gcc made prevents it from realizing it needs to use the newly incremented logicLevel value for the other calculations, so instead it keeps using a1 in the rest of the function. This causes it to write the new scriptId value in the wrong place, which causes the VM to think its next scriptId is 0. I'd like to attach the .ii files but I don't know how (can't find a button for it). You can see the full code at https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm. The 'problem' code is under the engines/sword2 directory in header.h, logic.cpp and function.cpp. This bug does not happen on any other platform as far as I know, but there's a huge random element involved regarding a particular memory layout. Thanks Yotam Barnoy -- Summary: Bad optimization in -O3 sometimes Product: gcc Version: 4.3.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: yotambarnoy at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45462