diff options
author | Maciej W. Rozycki <macro@orcam.me.uk> | 2024-06-29 23:26:55 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@orcam.me.uk> | 2024-07-22 10:11:28 +0100 |
commit | 4ce7c81212c7819dfe6dbbe2399220fb12da6d71 (patch) | |
tree | 194944728085dd3ccd437943629a6bbe39629ab9 | |
parent | 9778ad559f8288a2965fe865b93eb93a45dd43d7 (diff) | |
download | gcc-4ce7c81212c7819dfe6dbbe2399220fb12da6d71.zip gcc-4ce7c81212c7819dfe6dbbe2399220fb12da6d71.tar.gz gcc-4ce7c81212c7819dfe6dbbe2399220fb12da6d71.tar.bz2 |
[PR115565] cse: Don't use a valid regno for non-register in comparison_qty
Use INT_MIN rather than -1 in `comparison_qty' where a comparison is not
with a register, because the value of -1 is actually a valid reference
to register 0 in the case where it has not been assigned a quantity.
Using -1 makes `REG_QTY (REGNO (folded_arg1)) == ent->comparison_qty'
comparison in `fold_rtx' to incorrectly trigger in rare circumstances
and return true for a memory reference, making CSE consider a comparison
operation to evaluate to a constant expression and consequently make the
resulting code incorrectly execute or fail to execute conditional
blocks.
This has caused a miscompilation of rwlock.c from LinuxThreads for the
`alpha-linux-gnu' target, where `rwlock->__rw_writer != thread_self ()'
expression (where `thread_self' returns the thread pointer via a PALcode
call) has been decided to be always true (with `ent->comparison_qty'
using -1 for a reference to to `rwlock->__rw_writer', while register 0
holding the thread pointer retrieved by `thread_self') and code for the
false case has been optimized away where it mustn't have, causing
program lockups.
The issue has been observed as a regression from commit 08a692679fb8
("Undefined cse.c behaviour causes 3.4 regression on HPUX"),
<https://gcc.gnu.org/ml/gcc-patches/2004-10/msg02027.html>, and up to
commit 932ad4d9b550 ("Make CSE path following use the CFG"),
<https://gcc.gnu.org/ml/gcc-patches/2006-12/msg00431.html>, where CSE
has been restructured sufficiently for the issue not to trigger with the
original reproducer anymore. However the original bug remains and can
trigger, because `comparison_qty' will still be assigned -1 for a memory
reference and the `reg_qty' member of a `cse_reg_info_table' entry will
still be assigned -1 for register 0 where the entry has not been
assigned a quantity, e.g. at initialization.
Use INT_MIN then as noted above, so that the value remains negative, for
consistency with the REGNO_QTY_VALID_P macro (even though not used on
`comparison_qty'), and then so that it should not ever match a valid
negated register number, fixing the regression with commit 08a692679fb8.
gcc/
PR rtl-optimization/115565
* cse.cc (record_jump_cond): Use INT_MIN rather than -1 for
`comparison_qty' if !REG_P.
(cherry picked from commit 69bc5fb97dc3fada81869e00fa65d39f7def6acf)
-rw-r--r-- | gcc/cse.cc | 4 |
1 files changed, 2 insertions, 2 deletions
@@ -239,7 +239,7 @@ static int next_qty; the constant being compared against, or zero if the comparison is not against a constant. `comparison_qty' holds the quantity being compared against when the result is known. If the comparison - is not with a register, `comparison_qty' is -1. */ + is not with a register, `comparison_qty' is INT_MIN. */ struct qty_table_elem { @@ -4068,7 +4068,7 @@ record_jump_cond (enum rtx_code code, machine_mode mode, rtx op0, else { ent->comparison_const = op1; - ent->comparison_qty = -1; + ent->comparison_qty = INT_MIN; } return; |