aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@orcam.me.uk>2024-06-29 23:26:55 +0100
committerMaciej W. Rozycki <macro@orcam.me.uk>2024-07-22 10:13:45 +0100
commit8d8f804b18e4a38671957b3e4c239ef625506317 (patch)
tree1299ad5ac5dc7ebfd17b7d53cd195b0dfa3006f0
parent5f5c379607c36f177fe46de1222a11bf1b1e7f4c (diff)
downloadgcc-releases/gcc-12.zip
gcc-releases/gcc-12.tar.gz
gcc-releases/gcc-12.tar.bz2
[PR115565] cse: Don't use a valid regno for non-register in comparison_qtyreleases/gcc-12
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.cc4
1 files changed, 2 insertions, 2 deletions
diff --git a/gcc/cse.cc b/gcc/cse.cc
index ca53974..32e8ea7 100644
--- a/gcc/cse.cc
+++ b/gcc/cse.cc
@@ -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;