middle-end: Fix logical shift truncation (PR rtl-optimization/91838)
authorTamar Christina <tamar.christina@arm.com>
Fri, 31 Jan 2020 14:39:38 +0000 (14:39 +0000)
committerTamar Christina <tamar.christina@arm.com>
Fri, 31 Jan 2020 14:40:52 +0000 (14:40 +0000)
commite60b1e23626701939e8a2f0cf6fc1e48abdf867b
tree1d340c50cc2e18ed0a5cc603e1ecc0ff27d29758
parentc63ae7f0b8bb86b25255d26425887b75489ab162
middle-end: Fix logical shift truncation (PR rtl-optimization/91838)

This fixes a fall-out from a patch I had submitted two years ago which started
allowing simplify-rtx to fold logical right shifts by offsets a followed by b
into >> (a + b).

However this can generate inefficient code when the resulting shift count ends
up being the same as the size of the shift mode.  This will create some
undefined behavior on most platforms.

This patch changes to code to truncate to 0 if the shift amount goes out of
range.  Before my older patch this used to happen in combine when it saw the
two shifts.  However since we combine them here combine never gets a chance to
truncate them.

The issue mostly affects GCC 8 and 9 since on 10 the back-end knows how to deal
with this shift constant but it's better to do the right thing in simplify-rtx.

Note that this doesn't take care of the Arithmetic shift where you could replace
the constant with MODE_BITS (mode) - 1, but that's not a regression so punting it.

gcc/ChangeLog:

PR rtl-optimization/91838
* simplify-rtx.c (simplify_binary_operation_1): Update LSHIFTRT case
to truncate if allowed or reject combination.

gcc/testsuite/ChangeLog:

PR rtl-optimization/91838
* g++.dg/pr91838.C: New test.
gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr91838.C [new file with mode: 0644]