https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92180
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org, | |segher at gcc dot gnu.org, | |uros at gcc dot gnu.org Component|tree-optimization |rtl-optimization --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I think that is because the combiner doesn't even try to combine into instruction setting a hard register. Consider: unsigned int foo (void) { return __builtin_ia32_rdtsc (); } void bar (unsigned int *p) { *p = __builtin_ia32_rdtsc (); } Both have pretty much the same code before the combine, except (insn 14 7 15 2 (set (reg/i:SI 0 ax) (subreg:SI (reg:DI 84) 0)) "pr92180.c":5:1 67 {*movsi_internal} (expr_list:REG_DEAD (reg:DI 84) (nil))) (insn 15 14 0 2 (use (reg/i:SI 0 ax)) "pr92180.c":5:1 -1 (nil)) in foo and (insn 10 8 0 2 (set (mem:SI (reg/v/f:DI 84 [ p ]) [1 *p_5(D)+0 S4 A32]) (subreg:SI (reg:DI 85) 0)) "pr92180.c":10:6 67 {*movsi_internal} (expr_list:REG_DEAD (reg:DI 85) (expr_list:REG_DEAD (reg/v/f:DI 84 [ p ]) (nil)))) in bar. For bar, combine uses the nonzero_bits to optimize the (unsigned int) ((x << 32) | y) into (unsigned int) y, but in foo, probably because of the hard register in there, it doesn't try anything. Of course propagating anything into an insn setting a hard register is risky, but in this case we'd just replace one pseudo in the SUBREG_REG of the SET_SRC with another one. GIMPLE optimizations can't do anything here, because the (x << 32) | y isn't exposed there, we'd need a builtin with two return values for that kind of thing.