https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67032
Uroš Bizjak <ubizjak at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |ra Status|UNCONFIRMED |NEW Last reconfirmed| |2015-07-27 CC| |ubizjak at gmail dot com, | |vmakarov at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #6 from Uroš Bizjak <ubizjak at gmail dot com> --- Found the problem. geode is one of the targets that enable Ym and Yn constraints: (define_register_constraint "Ym" "TARGET_MMX && TARGET_INTER_UNIT_MOVES_TO_VEC ? MMX_REGS : NO_REGS" "@internal Any MMX register, when inter-unit moves to vector registers are enabled.") (define_register_constraint "Yn" "TARGET_MMX && TARGET_INTER_UNIT_MOVES_FROM_VEC ? MMX_REGS : NO_REGS" "@internal Any MMX register, when inter-unit moves from vector registers are enabled.") And ... the compiler generates insns that involve MMX registers. $ ./cc1plus -O2 -march=geode -m32 -dp main.ii $ grep %mm main.s movd %eax, %mm0 # 131 *zero_extendsidi2/6 [length = 3] movq %mm0, (%esp) # 330 *movdi_internal/10 [length = 4] movq %mm0, (%esp) # 333 *movdi_internal/10 [length = 4] movd %eax, %mm0 # 288 *zero_extendsidi2/6 [length = 3] GCC uses many tricks to penalize moves to/from MMX registers. Actually, MMX registers should not be allocated unless absolutely needed, that is the reason that every single constraint involving MMX regs is decorated by * and most of them are penalized by ? and/or !. One of the most important tricks is the one in inline_secondary_memory_needed, where: /* ??? This is a lie. We do have moves between mmx/general, and for mmx/sse2. But by saying we need secondary memory we discourage the register allocator from using the mmx registers unless needed. */ if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)) return true; It looks that with new and improved RA, this trick is not effective any more and delicate balance that prevented MMX regs to be allocated is broken. CC register allocator expert for opinion.