OSDN Git Service

Backported from mainline
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Apr 2013 18:01:51 +0000 (18:01 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Apr 2013 18:01:51 +0000 (18:01 +0000)
2013-01-18  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/56015
* expr.c (expand_expr_real_2) <case COMPLEX_EXPR>: Handle
the case where writing real complex part of target modifies
op1.

* gfortran.dg/pr56015.f90: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@197448 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/pr56015.f90 [new file with mode: 0644]

index 5cc55c1..2593b4c 100644 (file)
@@ -1,6 +1,13 @@
 2013-04-03  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2013-01-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/56015
+       * expr.c (expand_expr_real_2) <case COMPLEX_EXPR>: Handle
+       the case where writing real complex part of target modifies
+       op1.
+
        2013-01-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/55921
index e4f6cae..c931396 100644 (file)
@@ -8308,6 +8308,54 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
       if (!target)
        target = gen_reg_rtx (TYPE_MODE (type));
+      else
+       /* If target overlaps with op1, then either we need to force
+          op1 into a pseudo (if target also overlaps with op0),
+          or write the complex parts in reverse order.  */
+       switch (GET_CODE (target))
+         {
+         case CONCAT:
+           if (reg_overlap_mentioned_p (XEXP (target, 0), op1))
+             {
+               if (reg_overlap_mentioned_p (XEXP (target, 1), op0))
+                 {
+                 complex_expr_force_op1:
+                   temp = gen_reg_rtx (GET_MODE_INNER (GET_MODE (target)));
+                   emit_move_insn (temp, op1);
+                   op1 = temp;
+                   break;
+                 }
+             complex_expr_swap_order:
+               /* Move the imaginary (op1) and real (op0) parts to their
+                  location.  */
+               write_complex_part (target, op1, true);
+               write_complex_part (target, op0, false);
+
+               return target;
+             }
+           break;
+         case MEM:
+           temp = adjust_address_nv (target,
+                                     GET_MODE_INNER (GET_MODE (target)), 0);
+           if (reg_overlap_mentioned_p (temp, op1))
+             {
+               enum machine_mode imode = GET_MODE_INNER (GET_MODE (target));
+               temp = adjust_address_nv (target, imode,
+                                         GET_MODE_SIZE (imode));
+               if (reg_overlap_mentioned_p (temp, op0))
+                 goto complex_expr_force_op1;
+               goto complex_expr_swap_order;
+             }
+           break;
+         default:
+           if (reg_overlap_mentioned_p (target, op1))
+             {
+               if (reg_overlap_mentioned_p (target, op0))
+                 goto complex_expr_force_op1;
+               goto complex_expr_swap_order;
+             }
+           break;
+         }
 
       /* Move the real (op0) and imaginary (op1) parts to their location.  */
       write_complex_part (target, op0, false);
index 43de522..47e2801 100644 (file)
@@ -1,6 +1,11 @@
 2013-04-03  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2013-01-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/56015
+       * gfortran.dg/pr56015.f90: New test.
+
        2012-10-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/54858
diff --git a/gcc/testsuite/gfortran.dg/pr56015.f90 b/gcc/testsuite/gfortran.dg/pr56015.f90
new file mode 100644 (file)
index 0000000..a615f66
--- /dev/null
@@ -0,0 +1,16 @@
+! PR middle-end/56015
+! { dg-do run }
+! { dg-options "-O3 -ffast-math -fno-inline" }
+
+program pr56015
+  implicit none
+  complex*16 p(10)
+  p(:) = (0.1d0, 0.2d0)
+  p(:) = (0.0d0, 1.0d0) * p(:)
+  call foo (p)
+contains
+  subroutine foo (p)
+    complex*16 p(10)
+    if (any (p .ne. (-0.2d0, 0.1d0))) call abort
+  end subroutine
+end program pr56015