https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78176
Matthew Fortune <matthew.fortune at imgtec dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |matthew.fortune at imgtec dot com --- Comment #5 from Matthew Fortune <matthew.fortune at imgtec dot com> --- I'm struggling to see what can be fixed in GCC for this (and I'm not sure I follow why there is a problem with GCC's behaviour) but... The issue may stem from the C front end where the dumps start off as below. Note that the '-1' in kappa-1 has ended up being represented as 1073741823 (0x3fffffff) presumably owing to the fact it will be multiplied by 4 eventually and hence be 'safe'. I can't figure out so far what creates this value but the behavior started some time between gcc 4.7 and 4.8 I believe. The questionably bad code then shows up dependent on optimisations and instruction availability. If the calculation had been done with ADDU instead of in the LDXC1 then all would be well. Regardless of whether this is a real bug for the compiler then the Linux kernel should be making use of the status.UX bit in order to properly emulate a 32-bit environment for o32 on 64-bit kernel/hardware and had this been run using a 32-bit kernel (on 64-bit hardware) then it would run correctly. There is an issue for N32 code with the UX bit in that you also need the PX bit available to independently control 64-bit instruction availability vs address space but this is only missing in MIPSIV cores. ;; Function ldxc1_test (null) ;; enabled by -tree-original { int kappa2 = kappa; double tmp = 0.0; int kappa2 = kappa; double tmp = 0.0; <D.1497>:; kappa-- ; if (zeros + 1 < kappa) { tmp = *(*(r->rows + ((sizetype) kappa + 1073741823) * 4) + ((sizetype) kappa + 536870911) * 8) * ctt; tmp = ldexp (tmp, *(expo + ((sizetype) kappa + 1073741823) * 4) - *(expo + (sizetype) ((unsigned int) kappa2 * 4))); } if (zeros + 1 < kappa && *(s + ((sizetype) kappa + 536870911) * 8) <= tmp) goto <D.1497>; else goto <D.1498>; <D.1498>:; return tmp;