diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2020-08-09 23:14:58 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2020-08-09 23:14:58 +0100 |
commit | 71197a5d13d0b540a9b5efe7ae2512d76386e9d1 (patch) | |
tree | b6842e0d0dbd0d46b8586d39da37c8cbe096a7c6 /gcc | |
parent | 94d4f4387de8264ee289cf71f692d59ca6ac36f8 (diff) | |
download | gcc-71197a5d13d0b540a9b5efe7ae2512d76386e9d1.zip gcc-71197a5d13d0b540a9b5efe7ae2512d76386e9d1.tar.gz gcc-71197a5d13d0b540a9b5efe7ae2512d76386e9d1.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/expmed.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr71321.c | 3 |
2 files changed, 4 insertions, 2 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 3d2d234..d34f0fb 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -155,6 +155,8 @@ init_expmed_one_conv (struct init_expmed_rtl *all, scalar_int_mode to_mode, PUT_MODE (all->reg, from_mode); set_convert_cost (to_mode, from_mode, speed, set_src_cost (which, to_mode, speed)); + /* Restore all->reg's mode. */ + PUT_MODE (all->reg, to_mode); } static void @@ -229,6 +231,7 @@ init_expmed_one_mode (struct init_expmed_rtl *all, if (GET_MODE_CLASS (int_mode_to) == MODE_INT && GET_MODE_WIDER_MODE (int_mode_to).exists (&wider_mode)) { + PUT_MODE (all->reg, mode); PUT_MODE (all->zext, wider_mode); PUT_MODE (all->wide_mult, wider_mode); PUT_MODE (all->wide_lshr, wider_mode); diff --git a/gcc/testsuite/gcc.target/i386/pr71321.c b/gcc/testsuite/gcc.target/i386/pr71321.c index 86ad812..24d144b 100644 --- a/gcc/testsuite/gcc.target/i386/pr71321.c +++ b/gcc/testsuite/gcc.target/i386/pr71321.c @@ -12,5 +12,4 @@ unsigned cvt_to_2digit_ascii(uint8_t i) { return cvt_to_2digit(i, 10) + 0x0a3030; } -/* { dg-final { scan-assembler-times "lea.\t\\(%\[0-9a-z\]+,%\[0-9a-z\]+,4" 3 } } */ -/* { dg-final { scan-assembler-times "lea.\t\\(%\[0-9a-z\]+,%\[0-9a-z\]+,8" 1 } } */ +/* { dg-final { scan-assembler-not "lea.*0" } } */ |