diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-04-03 20:01:51 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-04-03 20:01:51 +0200 |
commit | 54e1155185fd41a33a34ea246591372b63a447b5 (patch) | |
tree | 8af71f76308876bb4a3727d1386905faec21d008 | |
parent | b4de1dd6f5530913c4caf9c0f1404d9c507b0038 (diff) |
backport: re PR middle-end/56015 (expand expands p[9] = COMPLEX_EXPR <-IMAGPART_EXPR <p[9]>, REALPART_EXPR <p[9]>>; incorrectly.)
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.
* gfortran.dg/pr56015.f90: New test.
From-SVN: r197448
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/expr.c | 48 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pr56015.f90 | 16 |
4 files changed, 76 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5cc55c15b1c..2593b4cac4d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/expr.c b/gcc/expr.c index e4f6cae80b0..c9313969fc1 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 43de522fccd..47e28017074 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 00000000000..a615f663fe3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr56015.f90 @@ -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 |