http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59535
--- Comment #13 from Richard Earnshaw <rearnsha at gcc dot gnu.org> --- The original reason we took most high registers out of the available registers list for -Os is because saving them (they're mostly callee-saved) is quite expensive -- they have to be copied to low registers first. IP was the exception, since it's call-clobbered and there's thus no code cost to make it available. While I'm happy to take IP out of the available registers list for now as a short-term expedient work-around, I see this as being indicative a more fundamental problem. When not optimizing for size, the register allocator should be able to use the high registers as alternatives to spill slots (copy the value to a high register rather than spill it to the stack). Once we have that, it would make sense for the few cases where high registers are permitted to legitimately use the copy that is up there rather than moving it back again to a low register first, so I wouldn't want to change the insn patterns to remove high registers entirely from operations like add, sub and compare. On the other hand, LRA does need to be aware that once a value is in a high register, really spilling it to memory, or loading it from memory is an expensive operation, since such transfers have to go via a low register.