[gcc r15-1724] [PR115565] cse: Don't use a valid regno for non-register in comparison_qty

Maciej W. Rozycki macro@gcc.gnu.org
Sat Jun 29 22:27:45 GMT 2024


https://gcc.gnu.org/g:69bc5fb97dc3fada81869e00fa65d39f7def6acf

commit r15-1724-g69bc5fb97dc3fada81869e00fa65d39f7def6acf
Author: Maciej W. Rozycki <macro@orcam.me.uk>
Date:   Sat Jun 29 23:26:55 2024 +0100

    [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.

Diff:
---
 gcc/cse.cc | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/cse.cc b/gcc/cse.cc
index c53deecbe54..65794ac5f2c 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
 {
@@ -4058,7 +4058,7 @@ record_jump_cond (enum rtx_code code, machine_mode mode, rtx op0, rtx op1)
       else
 	{
 	  ent->comparison_const = op1;
-	  ent->comparison_qty = -1;
+	  ent->comparison_qty = INT_MIN;
 	}
 
       return;


More information about the Gcc-cvs mailing list