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]

[PATCH] PR middle-end/12705: Overlapping complex expressions


The following patch addresses PR middle-end/12705, which is a latent
bug in tree->RTL expansion.  When expanding complex binary operations
we weren't testing whether the suggested target rtx overlapped with one
or other of the input operands.  This can cause us to overwrite the
real or imaginary components of an operands before we've finished using
them.  This problem was discovered using gfortran on the tree-ssa branch,
and diagnosed as a middle-end problem by RTH.

I considered using safe_from_p to identify when the operands and the
target actually overlap, but I wasn't immediately sure how well these
functions handled complex modes or whether I'd need to perform pairwise
safe_from_p tests on the individual real and imaginary components.
The safest and easiest solution is to just evaluate these expressions
into a new pseudo, which will get cleaned up by the RTL optimizers if
needed, but also exposes the intermediate values to CSE and GCSE.

Many thanks to Paul Brook for confirming this patch cures the problem.

The following patch has been tested against mainline on i686-pc-linux-gnu
with a complete "make bootstrap", all languages except treelang, and
regression tested with a top-level "make -k check" with no new failures.
As mentioned previously, this failure isn't reproducable with any of the
mainline front-ends, but I assume a gfortran testcase can be added to
the tree-ssa branch once this patch gets merged.

Ok for mainline?


2003-10-22  Roger Sayle  <roger@eyesopen.com>

	PR middle-end/12705
	* optabs.c (expand_binop): When expanding complex operations
	inline, always calculate result in a new temporary register.
	Minor code clean-ups.


Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.201
diff -c -3 -p -r1.201 optabs.c
*** optabs.c	20 Oct 2003 18:28:27 -0000	1.201
--- optabs.c	22 Oct 2003 02:38:08 -0000
*************** expand_binop (enum machine_mode mode, op
*** 1521,1544 ****
        rtx real0 = 0, imag0 = 0;
        rtx real1 = 0, imag1 = 0;
        rtx realr, imagr, res;
!       rtx seq;
!       rtx equiv_value;
        int ok = 0;

        /* Find the correct mode for the real and imaginary parts.  */
!       enum machine_mode submode = GET_MODE_INNER(mode);

        if (submode == BLKmode)
  	abort ();

-       if (! target)
- 	target = gen_reg_rtx (mode);
-
        start_sequence ();

-       realr = gen_realpart (submode, target);
-       imagr = gen_imagpart (submode, target);
-
        if (GET_MODE (op0) == mode)
  	{
  	  real0 = gen_realpart (submode, op0);
--- 1521,1537 ----
        rtx real0 = 0, imag0 = 0;
        rtx real1 = 0, imag1 = 0;
        rtx realr, imagr, res;
!       rtx seq, result;
        int ok = 0;

        /* Find the correct mode for the real and imaginary parts.  */
!       enum machine_mode submode = GET_MODE_INNER (mode);

        if (submode == BLKmode)
  	abort ();

        start_sequence ();

        if (GET_MODE (op0) == mode)
  	{
  	  real0 = gen_realpart (submode, op0);
*************** expand_binop (enum machine_mode mode, op
*** 1558,1563 ****
--- 1551,1560 ----
        if (real0 == 0 || real1 == 0 || ! (imag0 != 0 || imag1 != 0))
  	abort ();

+       result = gen_reg_rtx (mode);
+       realr = gen_realpart (submode, result);
+       imagr = gen_imagpart (submode, result);
+
        switch (binoptab->code)
  	{
  	case PLUS:
*************** expand_binop (enum machine_mode mode, op
*** 1749,1764 ****

        if (ok)
  	{
! 	  if (binoptab->code != UNKNOWN)
! 	    equiv_value
! 	      = gen_rtx_fmt_ee (binoptab->code, mode,
! 				copy_rtx (op0), copy_rtx (op1));
! 	  else
! 	    equiv_value = 0;
!
! 	  emit_no_conflict_block (seq, target, op0, op1, equiv_value);
!
! 	  return target;
  	}
      }

--- 1746,1755 ----

        if (ok)
  	{
! 	  rtx equiv = gen_rtx_fmt_ee (binoptab->code, mode,
! 				      copy_rtx (op0), copy_rtx (op1));
! 	  emit_no_conflict_block (seq, result, op0, op1, equiv);
! 	  return result;
  	}
      }


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]