middle-end: Correct calculation of mul_widen_cost and mul_highpart_cost.
authorRoger Sayle <roger@nextmovesoftware.com>
Sun, 9 Aug 2020 22:14:58 +0000 (23:14 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Sun, 9 Aug 2020 22:14:58 +0000 (23:14 +0100)
commit71197a5d13d0b540a9b5efe7ae2512d76386e9d1
treeb6842e0d0dbd0d46b8586d39da37c8cbe096a7c6
parent94d4f4387de8264ee289cf71f692d59ca6ac36f8
middle-end: Correct calculation of mul_widen_cost and mul_highpart_cost.

This patch fixes a subtle bug in the depths of GCC's synth_mult,
where the middle-end queries whether (how well) the target supports
widening and highpart multiplications by calling targetm.rtx_costs.
The code in init_expmed and init_expmed_one_mode iterates over various
RTL patterns querying the cost of each.  To avoid generating & garbage
collecting too much junk, it reuses the same RTL over and over, but
adjusting the modes between each call.

Alas this reuse of state is a little fragile, and at some point a
change to init_expmed_one_conv has resulted in the state (mode of
a register) being changed, but not reset before being used again.

Using the old software engineering/defensive programming maxim of
"why fix a bug just once, if it can be fixed in multiple places",
this patch both restores the original value in init_expmed_one_conv,
and also sets it to the expected value in init_expmed_one_mode.
This should hopefully signal the need to be careful of invariants for
anyone modifying this code in future.

2020-08-09  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
* expmed.c (init_expmed_one_conv): Restore all->reg's mode.
(init_expmed_one_mode): Set all->reg to desired mode.

gcc/testsuite/ChangeLog
PR target/71321
* gcc.target/i386/pr71321.c: Check that the code doesn't use
the 4B zero displacement lea, not that it uses lea.
gcc/expmed.c
gcc/testsuite/gcc.target/i386/pr71321.c