This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Committed] PR target/13889: Constants in conversion operators


The following patch is my solution for PR target/13889 which is an ICE
on valid regression on 3.3, 3.4 and 3.5 that triggers on m68k-linux.
In my anaylsis, the underlying problem is in CSE's fold_rtx and affects
all platforms, but is only exposed on targets with poorly tuned rtx_costs
such as the m68k.


The problem is that fold_rtx is creating the invalid RTL expression:

(zero_extend:DI (const_int -1))

The problem is that the identity of a unary conversion operator
depends upon both the mode of of the result *and* the mode of its
argument/operand.  For this reason, its unsafe to substitute
VOIDmode integer constants into such expressions without care.

The patch below detects the case where this is potentially hazardous,
and avoids creating invalid RTL.  Fortunately, the correct way to
propagate a constant into a unary expression appears just a few lines
later, so don't miss any optimization opportunities.

The reason why this is a problem for m68k and not for most other
platforms, is the curious parameterization that the folded
const_double actually costs more than the zero_extend (const_int)!
On most platforms, the constant folded zero_extension that's created
by the call to simplify_unary_opertion scores less than (or equal to)
the invalid zero extension.  Hence, cse_insn replaces the invalid
equivalent with the "correct" const_double.


Clearly, a target-specific solution would be to tweak m68k's rtx_costs
so that it behaves like other platforms.  I believe the more correct
solution is to prevent the middle-end generating nonsense RTL, and
then expecting the backend to give it a poor cost.  In an ideal world
we'd only ever call the rtx_costs target hook with valid and canonical
RTL...

I've committed the following patch to mainline as "obvious" after testing
on i686-pc-linux-gnu with a complete bootstrap, all languages except
treelang, and regression testing with no new failures.

Ok for 3.4 and 3.3 after the usual testing?


2004-03-20  Roger Sayle  <roger@eyesopen.com>

	PR target/13889
	* cse.c (fold_rtx): Avoid substituting constants into unary
	conversion operations.

	* gcc.c-torture/compile/pr13889.c: New test case.


Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.295
diff -c -3 -p -r1.295 cse.c
*** cse.c	11 Mar 2004 05:54:24 -0000	1.295
--- cse.c	20 Mar 2004 16:48:22 -0000
*************** fold_rtx (rtx x, rtx insn)
*** 3662,3667 ****
--- 3662,3684 ----
  		|| (new_cost == old_cost && CONSTANT_P (XEXP (x, i))))
  	      break;

+ 	    /* It's not safe to substitute the operand of a conversion
+ 	       operator with a constant, as the conversion's identity
+ 	       depends upon the mode of it's operand.  This optimization
+ 	       is handled by the call to simplify_unary_operation.  */
+ 	    if (GET_RTX_CLASS (code) == RTX_UNARY
+ 		&& GET_MODE (replacements[j]) != mode_arg0
+ 		&& (code == ZERO_EXTEND
+ 		    || code == SIGN_EXTEND
+ 		    || code == TRUNCATE
+ 		    || code == FLOAT_TRUNCATE
+ 		    || code == FLOAT_EXTEND
+ 		    || code == FLOAT
+ 		    || code == FIX
+ 		    || code == UNSIGNED_FLOAT
+ 		    || code == UNSIGNED_FIX))
+ 	      continue;
+
  	    if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
  	      break;



/* PR target/13889 */
struct { long long a; } *p;
void initNetFlowFunct(void) {
  unsigned int b = (unsigned int)-1;
  p->a = b;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]