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.