This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix infinite recursion in simplify_binary_operation
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 01 Sep 2008 19:57:16 +0100
- Subject: Fix infinite recursion in simplify_binary_operation
A MIPS patch I'm working on caused us to try to optimise the rather
odd combination:
(plus (plus (high ...) [== X]
(const_int 4) [== Y])
...)
and this led to infinite recursion between simplify_binary_operation
and simplify_plus_minus. The latter function has some special code
to avoid this:
/* Reject "simplifications" that just wrap the two
arguments in a CONST. Failure to do so can result
in infinite recursion with simplify_binary_operation
when it calls us to simplify CONST operations. */
if (tem
&& ! (GET_CODE (tem) == CONST
&& GET_CODE (XEXP (tem, 0)) == ncode
&& XEXP (XEXP (tem, 0), 0) == lhs
&& XEXP (XEXP (tem, 0), 1) == rhs))
{
lneg &= rneg;
if (GET_CODE (tem) == NEG)
tem = XEXP (tem, 0), lneg = !lneg;
if (GET_CODE (tem) == CONST_INT && lneg)
tem = neg_const_int (mode, tem), lneg = 0;
ops[i].op = tem;
ops[i].neg = lneg;
ops[j].op = NULL_RTX;
changed = 1;
}
Unfortunately, in this case, simplify_binary_operation (PLUS, Pmode, X, Y)
is returning (plus:P X Y) rather than (const:P (plus:P X Y)), which isn't
a simplification at all. (const:P (plus:P X Y)) isn't valid rtl, so the
return value ought to be NULL instead.
The problem is with the following code:
if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
&& GET_CODE (op1) == CONST_INT)
return plus_constant (op0, INTVAL (op1));
else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
&& GET_CODE (op0) == CONST_INT)
return plus_constant (op1, INTVAL (op0));
plus_constant only returns a CONST for three codes: CONST, SYMBOL_REF
and LABEL_REF, so those are the only types of rtx we should simplify.
I wondered about adding a "symbolic_constant_p" predicate, but not all
target-dependent CONSTs are strictly symbolic. The condition here is
more tied to plus_constant than to an abstract concept.
Tested on x86_64-linux-gnu and mips64-linux-gnu. OK to install?
Richard
gcc/
* simplify-rtx.c (simplify_binary_operation_1): Check for CONST,
SYMBOL_REF and LABEL_REF when applying plus_constant, instead of
checking for a non-VOID CONSTANT_P.
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c 2008-08-30 14:10:15.000000000 +0100
+++ gcc/simplify-rtx.c 2008-08-30 16:08:40.000000000 +0100
@@ -1594,10 +1594,14 @@ simplify_binary_operation_1 (enum rtx_co
to CONST_INT since overflow won't be computed properly if wider
than HOST_BITS_PER_WIDE_INT. */
- if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
+ if ((GET_CODE (op0) == CONST
+ || GET_CODE (op0) == SYMBOL_REF
+ || GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT)
return plus_constant (op0, INTVAL (op1));
- else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
+ else if ((GET_CODE (op1) == CONST
+ || GET_CODE (op1) == SYMBOL_REF
+ || GET_CODE (op1) == LABEL_REF)
&& GET_CODE (op0) == CONST_INT)
return plus_constant (op1, INTVAL (op0));