diff mbox

[committed] Some 4.5/4.4 backports

Message ID 20110116230406.GD2724@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 16, 2011, 11:04 p.m. UTC
Hi!

Attached is a bunch of 4.5 and 4.4 backports of my recent patches I've
committed after bootstrap/regtest on x86_64-linux and i686-linux.

	Jakub
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-10  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/46864
	* tree-ssa-loop-im.c (loop_suitable_for_sm): Return false even
	when there are EDGE_EH exit edges.

	* g++.dg/opt/pr46864.C: New test.
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-16  Jakub Jelinek  <jakub@redhat.com>

	PR debug/46893
	* cfgexpand.c (expand_debug_expr): If GET_MODE (op0) is VOIDmode,
	use TYPE_MODE (TREE_TYPE (tem)) instead of mode1.

	* gcc.dg/pr46893.c: New test.

--- gcc/cfgexpand.c	(revision 167948)
+++ gcc/cfgexpand.c	(revision 167949)
@@ -2703,7 +2703,7 @@ expand_debug_expr (tree exp)
 	    enum machine_mode opmode = GET_MODE (op0);
 
 	    if (opmode == VOIDmode)
-	      opmode = mode1;
+	      opmode = TYPE_MODE (TREE_TYPE (tem));
 
 	    /* This condition may hold if we're expanding the address
 	       right past the end of an array that turned out not to
@@ -2724,7 +2724,8 @@ expand_debug_expr (tree exp)
 				     ? SIGN_EXTRACT
 				     : ZERO_EXTRACT, mode,
 				     GET_MODE (op0) != VOIDmode
-				     ? GET_MODE (op0) : mode1,
+				     ? GET_MODE (op0)
+				     : TYPE_MODE (TREE_TYPE (tem)),
 				     op0, GEN_INT (bitsize), GEN_INT (bitpos));
       }
 
--- gcc/testsuite/gcc.dg/pr46893.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr46893.c	(revision 167949)
@@ -0,0 +1,13 @@
+/* PR debug/46893 */
+/* { dg-do compile } */
+/* { dg-options "-O -g" } */
+
+void
+foo (void)
+{
+  union { unsigned long long l; double d; } u = { 0x7ff0000000000000ULL };
+  double v = 0, w = -u.d;
+
+  if (w)
+    w = v;
+}
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/46874
	* trans-openmp.c (gfc_trans_omp_array_reduction): Handle allocatable
	dummy variables.

	* libgomp.fortran/allocatable6.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 167797)
+++ gcc/fortran/trans-openmp.c	(revision 167799)
@@ -482,13 +482,23 @@ gfc_trans_omp_array_reduction (tree c, g
   gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
   gfc_expr *e1, *e2, *e3, *e4;
   gfc_ref *ref;
-  tree decl, backend_decl, stmt;
+  tree decl, backend_decl, stmt, type, outer_decl;
   locus old_loc = gfc_current_locus;
   const char *iname;
   gfc_try t;
 
   decl = OMP_CLAUSE_DECL (c);
   gfc_current_locus = where;
+  type = TREE_TYPE (decl);
+  outer_decl = create_tmp_var_raw (type, NULL);
+  if (TREE_CODE (decl) == PARM_DECL
+      && TREE_CODE (type) == REFERENCE_TYPE
+      && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
+      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
+    {
+      decl = build_fold_indirect_ref (decl);
+      type = TREE_TYPE (type);
+    }
 
   /* Create a fake symbol for init value.  */
   memset (&init_val_sym, 0, sizeof (init_val_sym));
@@ -507,7 +517,9 @@ gfc_trans_omp_array_reduction (tree c, g
   outer_sym.attr.dummy = 0;
   outer_sym.attr.result = 0;
   outer_sym.attr.flavor = FL_VARIABLE;
-  outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
+  outer_sym.backend_decl = outer_decl;
+  if (decl != OMP_CLAUSE_DECL (c))
+    outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
 
   /* Create fake symtrees for it.  */
   symtree1 = gfc_new_symtree (&root1, sym->name);
@@ -624,12 +636,12 @@ gfc_trans_omp_array_reduction (tree c, g
 
   /* Create the init statement list.  */
   pushlevel (0);
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
-      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+  if (GFC_DESCRIPTOR_TYPE_P (type)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     {
       /* If decl is an allocatable array, it needs to be allocated
 	 with the same bounds as the outer var.  */
-      tree type = TREE_TYPE (decl), rank, size, esize, ptr;
+      tree rank, size, esize, ptr;
       stmtblock_t block;
 
       gfc_start_block (&block);
@@ -669,8 +681,8 @@ gfc_trans_omp_array_reduction (tree c, g
 
   /* Create the merge statement list.  */
   pushlevel (0);
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
-      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+  if (GFC_DESCRIPTOR_TYPE_P (type)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     {
       /* If decl is an allocatable array, it needs to be deallocated
 	 afterwards.  */
@@ -691,7 +703,7 @@ gfc_trans_omp_array_reduction (tree c, g
   OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
 
   /* And stick the placeholder VAR_DECL into the clause as well.  */
-  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
+  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
 
   gfc_current_locus = old_loc;
 
--- libgomp/testsuite/libgomp.fortran/allocatable6.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/allocatable6.f90	(revision 167799)
@@ -0,0 +1,45 @@
+! PR fortran/46874
+! { dg-do run }
+
+  interface
+    subroutine sub (a, b, c, d, n)
+      integer :: n
+      integer, allocatable :: a(:), b(:), c(:), d(:)
+    end subroutine
+  end interface
+
+  integer, allocatable :: a(:), b(:), c(:), d(:)
+  integer :: i, j
+  allocate (a(50), b(50), c(50), d(50))
+  do i = 1, 50
+    a(i) = 2 + modulo (i, 7)
+    b(i) = 179 - modulo (i, 11)
+  end do
+  c = 0
+  d = 2147483647
+  call sub (a, b, c, d, 50)
+  do i = 1, 50
+    j = 0
+    if (i .eq. 3) then
+      j = 8
+    else if (i .gt. 1 .and. i .lt. 9) then
+      j = 7
+    end if
+    if (c(i) .ne. j) call abort
+    j = 179 - modulo (i, 11)
+    if (i .gt. 1 .and. i .lt. 9) j = i
+    if (d(i) .ne. j) call abort
+  end do
+  deallocate (a, b, c, d)
+end
+
+subroutine sub (a, b, c, d, n)
+  integer :: n
+  integer, allocatable :: a(:), b(:), c(:), d(:)
+!$omp parallel do shared(a, b) reduction(+:c) reduction(min:d)
+  do i = 1, n
+    c(a(i)) = c(a(i)) + 1
+    d(i) = min(d(i), b(i))
+    d(a(i)) = min(d(a(i)), a(i))
+  end do
+end
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-01-07  Jakub Jelinek  <jakub@redhat.com>

	PR target/47201
	* config/i386/i386.c (ix86_delegitimize_address): If
	simplify_gen_subreg fails, return orig_x.

	* gcc.dg/pr47201.c: New test.

--- gcc/config/i386/i386.c	(revision 168581)
+++ gcc/config/i386/i386.c	(revision 168582)
@@ -13254,7 +13254,11 @@ ix86_delegitimize_address (rtx x)
 	return ix86_delegitimize_tls_address (orig_x);
       x = XVECEXP (XEXP (x, 0), 0, 0);
       if (GET_MODE (orig_x) != Pmode)
-	return simplify_gen_subreg (GET_MODE (orig_x), x, Pmode, 0);
+	{
+	  x = simplify_gen_subreg (GET_MODE (orig_x), x, Pmode, 0);
+	  if (x == NULL_RTX)
+	    return orig_x;
+	}
       return x;
     }
 
@@ -13323,7 +13327,11 @@ ix86_delegitimize_address (rtx x)
 	return orig_x;
     }
   if (GET_MODE (orig_x) != Pmode && MEM_P (orig_x))
-    return simplify_gen_subreg (GET_MODE (orig_x), result, Pmode, 0);
+    {
+      result = simplify_gen_subreg (GET_MODE (orig_x), result, Pmode, 0);
+      if (result == NULL_RTX)
+	return orig_x;
+    }
   return result;
 }
 
--- gcc/testsuite/gcc.dg/pr47201.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr47201.c	(revision 168582)
@@ -0,0 +1,18 @@
+/* PR target/47201 */
+/* { dg-do compile } */
+/* { dg-options "-O -fpic -g" { target fpic } } */
+
+union U
+{
+  __UINTPTR_TYPE__ m;
+  float d;
+} u;
+
+int
+foo (void)
+{
+  union U v = {
+    (__UINTPTR_TYPE__)&u
+  };
+  return u.d == v.d;
+}
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2011-01-06  Jakub Jelinek  <jakub@redhat.com>

	PR c/47150
	* c-convert.c (convert): When converting a complex expression
	other than COMPLEX_EXPR to a different complex type, ensure
	c_save_expr is called instead of save_expr, unless in_late_binary_op.
	* c-typeck.c (convert_for_assignment): Set in_late_binary_op also
	when converting COMPLEX_TYPE.

	* gcc.c-torture/compile/pr47150.c: New test.

--- gcc/c-typeck.c	(revision 168536)
+++ gcc/c-typeck.c	(revision 168537)
@@ -5274,10 +5274,10 @@ convert_for_assignment (location_t locat
     {
       tree ret;
       bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
 	in_late_binary_op = true;
       ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
 	in_late_binary_op = save;
       return ret;
     }
--- gcc/c-convert.c	(revision 168536)
+++ gcc/c-convert.c	(revision 168537)
@@ -130,6 +130,32 @@ convert (tree type, tree expr)
       goto maybe_fold;
 
     case COMPLEX_TYPE:
+      /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
+	 and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
+	 but for the C FE c_save_expr needs to be called instead.  */
+      if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
+	{
+	  tree subtype = TREE_TYPE (type);
+	  tree elt_type = TREE_TYPE (TREE_TYPE (e));
+
+	  if (TYPE_MAIN_VARIANT (elt_type) != TYPE_MAIN_VARIANT (subtype)
+	      && TREE_CODE (e) != COMPLEX_EXPR)
+	    {
+	      if (in_late_binary_op)
+		e = save_expr (e);
+	      else
+		e = c_save_expr (e);
+	      ret
+		= fold_build2 (COMPLEX_EXPR, type,
+			       convert (subtype,
+					fold_build1 (REALPART_EXPR,
+						     elt_type, e)),
+			       convert (subtype,
+					fold_build1 (IMAGPART_EXPR,
+						     elt_type, e)));
+	      goto maybe_fold;
+	    }
+	}
       ret = convert_to_complex (type, e);
       goto maybe_fold;
 
--- gcc/testsuite/gcc.c-torture/compile/pr47150.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr47150.c	(revision 168537)
@@ -0,0 +1,11 @@
+/* PR c/47150 */
+
+float _Complex foo (float, float);
+
+void
+bar ()
+{
+  float w = 2;
+  float _Complex b;
+  b = 0.5 * (foo (0, w) + foo (1, w) / w);
+}
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR target/46880
	* config/i386/sse.md (sse2_loadlpd, sse2_movsd): Fix shufpd source
	operand.

	* gcc.target/i386/pr46880.c: New test.

--- gcc/config/i386/sse.md	(revision 168134)
+++ gcc/config/i386/sse.md	(revision 168135)
@@ -4990,7 +4990,7 @@ (define_insn "sse2_loadlpd"
    movsd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
    movsd\t{%2, %0|%0, %2}
-   shufpd\t{$2, %2, %0|%0, %2, 2}
+   shufpd\t{$2, %1, %0|%0, %1, 2}
    movhpd\t{%H1, %0|%0, %H1}
    #
    #
@@ -5067,7 +5067,7 @@ (define_insn "sse2_movsd"
    movsd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
-   shufpd\t{$2, %2, %0|%0, %2, 2}
+   shufpd\t{$2, %1, %0|%0, %1, 2}
    movhps\t{%H1, %0|%0, %H1}
    movhps\t{%1, %H0|%H0, %1}"
   [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
--- gcc/testsuite/gcc.target/i386/pr46880.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46880.c	(revision 168135)
@@ -0,0 +1,28 @@
+/* PR target/46880 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-require-effective-target sse2_runtime } */
+
+typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef double (*T)[2];
+
+static __attribute__ ((noinline, noclone)) __m128d
+foo (__m128d c, __m128d d)
+{
+  T cp = (T) &c;
+  T dp = (T) &d;
+  __m128d e = { (*cp)[1], (*dp)[1] };
+  return e;
+}
+
+int
+main ()
+{
+  __m128d c = { 1.0, 2.0 };
+  __m128d d = { 3.0, 4.0 };
+  union { __m128d x; double d[2]; } u;
+  u.x = foo (c, d);
+  if (u.d[0] != 2.0 || u.d[1] != 4.0)
+    __builtin_abort ();
+  return 0;
+}
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/45852
	* expr.c (store_expr): Ignore alt_rtl if equal to target,
	but has side-effects.

	* gcc.target/i386/pr45852.c: New test.

--- gcc/expr.c	(revision 168104)
+++ gcc/expr.c	(revision 168105)
@@ -4712,7 +4712,10 @@ store_expr (tree exp, rtx target, int ca
       /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
 	 but TARGET is not valid memory reference, TEMP will differ
 	 from TARGET although it is really the same location.  */
-      && !(alt_rtl && rtx_equal_p (alt_rtl, target))
+      && !(alt_rtl
+	   && rtx_equal_p (alt_rtl, target)
+	   && !side_effects_p (alt_rtl)
+	   && !side_effects_p (target))
       /* If there's nothing to copy, don't bother.  Don't call
 	 expr_size unless necessary, because some front-ends (C++)
 	 expr_size-hook must not be given objects that are not
--- gcc/testsuite/gcc.target/i386/pr45852.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr45852.c	(revision 168105)
@@ -0,0 +1,16 @@
+/* PR middle-end/45852 */
+/* { dg-options "-O2 -mcmodel=small" } */
+/* { dg-do compile { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */
+/* { dg-require-visibility "" } */
+
+struct S { int s; };
+
+volatile struct S globvar __attribute__((visibility ("hidden"))) = { -6 };
+
+void
+foo (void)
+{
+  globvar = globvar;
+}
+
+/* { dg-final { scan-assembler-times "globvar.%?rip" 2 } } */
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-16  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/43655
	* tree-ssa-ter.c (is_replaceable_p): Don't use
	gimple_references_memory_p for -O0, instead check for load
	by looking at rhs.

	* g++.dg/opt/pr43655.C: New test.

--- gcc/tree-ssa-ter.c	(revision 167954)
+++ gcc/tree-ssa-ter.c	(revision 167955)
@@ -416,7 +416,9 @@ is_replaceable_p (gimple stmt)
     return false;
 
   /* Without alias info we can't move around loads.  */
-  if (gimple_references_memory_p (stmt) && !optimize)
+  if (!optimize
+      && gimple_assign_single_p (stmt)
+      && !is_gimple_val (gimple_assign_rhs1 (stmt)))
     return false;
 
   /* Float expressions must go through memory if float-store is on.  */
--- gcc/testsuite/g++.dg/opt/pr43655.C	(revision 0)
+++ gcc/testsuite/g++.dg/opt/pr43655.C	(revision 167955)
@@ -0,0 +1,34 @@
+// PR tree-optimization/43655
+// { dg-do run }
+// { dg-options "-O0 -ftree-ter" }
+
+extern "C" void abort ();
+
+struct C
+{
+  C (int i) : val(i) { }
+  C (const C& c) : val(c.val) { }
+  ~C (void) { val = 999; }
+  C& operator = (const C& c) { val = c.val; return *this; }
+  C& inc (int i) { val += i; return *this; }
+  int val;
+};
+
+C
+f ()
+{
+  return C (3);
+}
+
+C
+f (int i)
+{
+  return f ().inc (i);
+}
+
+int
+main ()
+{
+  if (f (2).val != 5)
+    abort ();
+}
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-10  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/46804
	* regmove.c (optimize_reg_copy_3): Look for REG_EQUAL note
	on the setter of src_reg rather than on insn.  If it is
	equal to the setter's original SET_SRC, replace it with its
	zero or sign extension instead of dropping it.

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

--- gcc/regmove.c	(revision 167694)
+++ gcc/regmove.c	(revision 167695)
@@ -514,7 +514,7 @@ optimize_reg_copy_3 (rtx insn, rtx dest,
   rtx src_reg = XEXP (src, 0);
   int src_no = REGNO (src_reg);
   int dst_no = REGNO (dest);
-  rtx p, set;
+  rtx p, set, set_insn;
   enum machine_mode old_mode;
   basic_block bb = BLOCK_FOR_INSN (insn);
 
@@ -552,6 +552,7 @@ optimize_reg_copy_3 (rtx insn, rtx dest,
 				 GET_MODE_BITSIZE (GET_MODE (src_reg))))
     return;
 
+  set_insn = p;
   old_mode = GET_MODE (src_reg);
   PUT_MODE (src_reg, GET_MODE (src));
   XEXP (src, 0) = SET_SRC (set);
@@ -584,9 +585,19 @@ optimize_reg_copy_3 (rtx insn, rtx dest,
     }
   else
     {
-      rtx note = find_reg_note (p, REG_EQUAL, NULL_RTX);
+      rtx note = find_reg_note (set_insn, REG_EQUAL, NULL_RTX);
       if (note)
-	remove_note (p, note);
+	{
+	  if (rtx_equal_p (XEXP (note, 0), XEXP (src, 0)))
+	    {
+	      XEXP (note, 0)
+		= gen_rtx_fmt_e (GET_CODE (src), GET_MODE (src),
+				 XEXP (note, 0));
+	      df_notes_rescan (set_insn);
+	    }
+	  else
+	    remove_note (set_insn, note);
+	}
     }
 }
 
--- gcc/testsuite/gfortran.dg/pr46804.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/pr46804.f90	(revision 167695)
@@ -0,0 +1,36 @@
+! PR rtl-optimization/46804
+! { dg-do run }
+! { dg-options "-O -fPIC -fexpensive-optimizations -fgcse -foptimize-register-move -fpeel-loops -fno-tree-loop-optimize" }
+
+program main
+  integer, parameter :: n1 = 2, n2 = 3, n3 = 4, slen = 3
+  character (len = slen), dimension (n1, n2, n3) :: a
+  integer (kind = 1), dimension (2, 4) :: shift1
+  integer (kind = 2), dimension (2, 4) :: shift2
+  integer (kind = 4), dimension (2, 4) :: shift3
+  do i3 = 1, n3
+    do i2 = 1, n2
+      do i1 = 1, n1
+        a (i1, i2, i3) = 'ab'(i1:i1) // 'cde'(i2:i2) // 'fghi'(i3:i3)
+      end do
+    end do
+  end do
+  shift1 (1, :) = (/ 4, 11, 19, 20 /)
+  shift1 (2, :) = (/ 55, 5, 1, 2 /)
+  shift2 = shift1
+  shift3 = shift1
+  call test (cshift (a, shift2, 2))
+  call test (cshift (a, shift3, 2))
+contains
+  subroutine test (b)
+    character (len = slen), dimension (n1, n2, n3) :: b
+    do i3 = 1, n3
+      do i2 = 1, n2
+        do i1 = 1, n1
+          i2p = mod (shift1 (i1, i3) + i2 - 1, n2) + 1
+          if (b (i1, i2, i3) .ne. a (i1, i2p, i3)) call abort
+        end do
+      end do
+    end do
+  end subroutine test
+end program main
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-10  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/46865
	* rtl.c (rtx_equal_p_cb, rtx_equal_p): For last operand of
	ASM_OPERANDS and ASM_INPUT if integers are different,
	call locator_eq.
	* jump.c (rtx_renumbered_equal_p): Likewise.

	* gcc.target/i386/pr46865-1.c: New test.
	* gcc.target/i386/pr46865-2.c: New test.

--- gcc/jump.c	(revision 167685)
+++ gcc/jump.c	(revision 167686)
@@ -1727,7 +1727,13 @@ rtx_renumbered_equal_p (const_rtx x, con
 
 	case 'i':
 	  if (XINT (x, i) != XINT (y, i))
-	    return 0;
+	    {
+	      if (((code == ASM_OPERANDS && i == 6)
+		   || (code == ASM_INPUT && i == 1))
+		  && locator_eq (XINT (x, i), XINT (y, i)))
+		break;
+	      return 0;
+	    }
 	  break;
 
 	case 't':
--- gcc/rtl.c	(revision 167685)
+++ gcc/rtl.c	(revision 167686)
@@ -431,7 +431,15 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
 	case 'n':
 	case 'i':
 	  if (XINT (x, i) != XINT (y, i))
-	    return 0;
+	    {
+#ifndef GENERATOR_FILE
+	      if (((code == ASM_OPERANDS && i == 6)
+		   || (code == ASM_INPUT && i == 1))
+		  && locator_eq (XINT (x, i), XINT (y, i)))
+		break;
+#endif
+	      return 0;
+	    }
 	  break;
 
 	case 'V':
@@ -555,7 +563,15 @@ rtx_equal_p (const_rtx x, const_rtx y)
 	case 'n':
 	case 'i':
 	  if (XINT (x, i) != XINT (y, i))
-	    return 0;
+	    {
+#ifndef GENERATOR_FILE
+	      if (((code == ASM_OPERANDS && i == 6)
+		   || (code == ASM_INPUT && i == 1))
+		  && locator_eq (XINT (x, i), XINT (y, i)))
+		break;
+#endif
+	      return 0;
+	    }
 	  break;
 
 	case 'V':
--- gcc/testsuite/gcc.target/i386/pr46865-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46865-1.c	(revision 167686)
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/46865 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern unsigned long f;
+
+#define m1(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n");			\
+  else								\
+    asm volatile ("nop /* asmnop */\n");
+
+#define m2(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");	\
+  else								\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
+
+void
+foo (void)
+{
+  m1 (f);
+}
+
+void
+bar (void)
+{
+  m2 (f);
+}
+
+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
--- gcc/testsuite/gcc.target/i386/pr46865-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46865-2.c	(revision 167686)
@@ -0,0 +1,32 @@
+/* PR rtl-optimization/46865 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -save-temps" } */
+
+extern unsigned long f;
+
+#define m1(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n");			\
+  else								\
+    asm volatile ("nop /* asmnop */\n");
+
+#define m2(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");	\
+  else								\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
+
+void
+foo (void)
+{
+  m1 (f);
+}
+
+void
+bar (void)
+{
+  m2 (f);
+}
+
+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-09  Jakub Jelinek  <jakub@redhat.com>

	PR target/41082
	* config/rs6000/rs6000.c (rs6000_expand_vector_extract): Use stvx
	instead of stve*x.
	(altivec_expand_stv_builtin): For op0 use mode of operand 1 instead
	of operand 0.
	* config/rs6000/altivec.md (VI_scalar): New mode attr.
	(altivec_stve<VI_char>x, *altivec_stvesfx): Use scalar instead of
	vector mode for operand 0, put operand 1 into UNSPEC.

--- gcc/config/rs6000/rs6000.c	(revision 167628)
+++ gcc/config/rs6000/rs6000.c	(revision 167629)
@@ -5436,7 +5436,7 @@ rs6000_expand_vector_extract (rtx target
 {
   enum machine_mode mode = GET_MODE (vec);
   enum machine_mode inner_mode = GET_MODE_INNER (mode);
-  rtx mem, x;
+  rtx mem;
 
   if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
     {
@@ -5449,17 +5449,11 @@ rs6000_expand_vector_extract (rtx target
   /* Allocate mode-sized buffer.  */
   mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
 
+  emit_move_insn (mem, vec);
+
   /* Add offset to field within buffer matching vector element.  */
-  mem = adjust_address_nv (mem, mode, elt * GET_MODE_SIZE (inner_mode));
+  mem = adjust_address_nv (mem, inner_mode, elt * GET_MODE_SIZE (inner_mode));
 
-  /* Store single field into mode-sized buffer.  */
-  x = gen_rtx_UNSPEC (VOIDmode,
-		      gen_rtvec (1, const0_rtx), UNSPEC_STVE);
-  emit_insn (gen_rtx_PARALLEL (VOIDmode,
-			       gen_rtvec (2,
-					  gen_rtx_SET (VOIDmode,
-						       mem, vec),
-					  x)));
   emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
 }
 
@@ -11114,6 +11108,7 @@ altivec_expand_stv_builtin (enum insn_co
   rtx op2 = expand_normal (arg2);
   rtx pat, addr;
   enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode smode = insn_data[icode].operand[1].mode;
   enum machine_mode mode1 = Pmode;
   enum machine_mode mode2 = Pmode;
 
@@ -11123,8 +11118,8 @@ altivec_expand_stv_builtin (enum insn_co
       || arg2 == error_mark_node)
     return const0_rtx;
 
-  if (! (*insn_data[icode].operand[1].predicate) (op0, tmode))
-    op0 = copy_to_mode_reg (tmode, op0);
+  if (! (*insn_data[icode].operand[1].predicate) (op0, smode))
+    op0 = copy_to_mode_reg (smode, op0);
 
   op2 = copy_to_mode_reg (mode2, op2);
 
--- gcc/config/rs6000/altivec.md	(revision 167628)
+++ gcc/config/rs6000/altivec.md	(revision 167629)
@@ -169,6 +169,7 @@ (define_mode_iterator VM [V4SI V8HI V16Q
 (define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI])
 
 (define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
+(define_mode_attr VI_scalar [(V4SI "SI") (V8HI "HI") (V16QI "QI")])
 
 ;; Vector move instructions.
 (define_insn "*altivec_mov<mode>"
@@ -1775,19 +1776,15 @@ (define_insn "altivec_stvxl"
   [(set_attr "type" "vecstore")])
 
 (define_insn "altivec_stve<VI_char>x"
-  [(parallel
-    [(set (match_operand:VI 0 "memory_operand" "=Z")
-	  (match_operand:VI 1 "register_operand" "v"))
-     (unspec [(const_int 0)] UNSPEC_STVE)])]
+  [(set (match_operand:<VI_scalar> 0 "memory_operand" "=Z")
+	(unspec:<VI_scalar> [(match_operand:VI 1 "register_operand" "v")] UNSPEC_STVE))]
   "TARGET_ALTIVEC"
   "stve<VI_char>x %1,%y0"
   [(set_attr "type" "vecstore")])
 
 (define_insn "*altivec_stvesfx"
-  [(parallel
-    [(set (match_operand:V4SF 0 "memory_operand" "=Z")
-	  (match_operand:V4SF 1 "register_operand" "v"))
-     (unspec [(const_int 0)] UNSPEC_STVE)])]
+  [(set (match_operand:SF 0 "memory_operand" "=Z")
+	(unspec:SF [(match_operand:V4SF 1 "register_operand" "v")] UNSPEC_STVE))]
   "TARGET_ALTIVEC"
   "stvewx %1,%y0"
   [(set_attr "type" "vecstore")])
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-10  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/46865
	* rtl.c (rtx_equal_p_cb): For last operand of
	ASM_OPERANDS and ASM_INPUT if integers are different,
	call locator_eq.
	* jump.c (rtx_renumbered_equal_p): Likewise.

	* gcc.target/i386/pr46865-1.c: New test.
	* gcc.target/i386/pr46865-2.c: New test.

--- gcc/jump.c	(revision 167685)
+++ gcc/jump.c	(revision 167686)
@@ -1727,7 +1727,13 @@ rtx_renumbered_equal_p (const_rtx x, con
 
 	case 'i':
 	  if (XINT (x, i) != XINT (y, i))
-	    return 0;
+	    {
+	      if (((code == ASM_OPERANDS && i == 5)
+		   || (code == ASM_INPUT && i == 1))
+		  && locator_eq (XINT (x, i), XINT (y, i)))
+		break;
+	      return 0;
+	    }
 	  break;
 
 	case 't':
--- gcc/rtl.c	(revision 167685)
+++ gcc/rtl.c	(revision 167686)
@@ -431,7 +431,15 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
 	case 'n':
 	case 'i':
 	  if (XINT (x, i) != XINT (y, i))
-	    return 0;
+	    {
+#ifndef GENERATOR_FILE
+	      if (((code == ASM_OPERANDS && i == 5)
+		   || (code == ASM_INPUT && i == 1))
+		  && locator_eq (XINT (x, i), XINT (y, i)))
+		break;
+#endif
+	      return 0;
+	    }
 	  break;
 
 	case 'V':
--- gcc/testsuite/gcc.target/i386/pr46865-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46865-1.c	(revision 167686)
@@ -0,0 +1,31 @@
+/* PR rtl-optimization/46865 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern unsigned long f;
+
+#define m1(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n");			\
+  else								\
+    asm volatile ("nop /* asmnop */\n");
+
+#define m2(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");	\
+  else								\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
+
+void
+foo (void)
+{
+  m1 (f);
+}
+
+void
+bar (void)
+{
+  m2 (f);
+}
+
+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
--- gcc/testsuite/gcc.target/i386/pr46865-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46865-2.c	(revision 167686)
@@ -0,0 +1,32 @@
+/* PR rtl-optimization/46865 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -save-temps" } */
+
+extern unsigned long f;
+
+#define m1(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n");			\
+  else								\
+    asm volatile ("nop /* asmnop */\n");
+
+#define m2(f)							\
+  if (f & 1)							\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");	\
+  else								\
+    asm volatile ("nop /* asmnop */\n" : : "i" (6) : "cx");
+
+void
+foo (void)
+{
+  m1 (f);
+}
+
+void
+bar (void)
+{
+  m2 (f);
+}
+
+/* { dg-final { scan-assembler-times "asmnop" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/46874
	* trans-openmp.c (gfc_trans_omp_array_reduction): Handle allocatable
	dummy variables.

	* libgomp.fortran/allocatable6.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 167797)
+++ gcc/fortran/trans-openmp.c	(revision 167799)
@@ -482,13 +482,23 @@ gfc_trans_omp_array_reduction (tree c, g
   gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
   gfc_expr *e1, *e2, *e3, *e4;
   gfc_ref *ref;
-  tree decl, backend_decl, stmt;
+  tree decl, backend_decl, stmt, type, outer_decl;
   locus old_loc = gfc_current_locus;
   const char *iname;
   gfc_try t;
 
   decl = OMP_CLAUSE_DECL (c);
   gfc_current_locus = where;
+  type = TREE_TYPE (decl);
+  outer_decl = create_tmp_var_raw (type, NULL);
+  if (TREE_CODE (decl) == PARM_DECL
+      && TREE_CODE (type) == REFERENCE_TYPE
+      && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
+      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
+    {
+      decl = build_fold_indirect_ref (decl);
+      type = TREE_TYPE (type);
+    }
 
   /* Create a fake symbol for init value.  */
   memset (&init_val_sym, 0, sizeof (init_val_sym));
@@ -507,7 +517,9 @@ gfc_trans_omp_array_reduction (tree c, g
   outer_sym.attr.dummy = 0;
   outer_sym.attr.result = 0;
   outer_sym.attr.flavor = FL_VARIABLE;
-  outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
+  outer_sym.backend_decl = outer_decl;
+  if (decl != OMP_CLAUSE_DECL (c))
+    outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
 
   /* Create fake symtrees for it.  */
   symtree1 = gfc_new_symtree (&root1, sym->name);
@@ -624,12 +636,12 @@ gfc_trans_omp_array_reduction (tree c, g
 
   /* Create the init statement list.  */
   pushlevel (0);
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
-      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+  if (GFC_DESCRIPTOR_TYPE_P (type)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     {
       /* If decl is an allocatable array, it needs to be allocated
 	 with the same bounds as the outer var.  */
-      tree type = TREE_TYPE (decl), rank, size, esize, ptr;
+      tree rank, size, esize, ptr;
       stmtblock_t block;
 
       gfc_start_block (&block);
@@ -669,8 +681,8 @@ gfc_trans_omp_array_reduction (tree c, g
 
   /* Create the merge statement list.  */
   pushlevel (0);
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
-      && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_ALLOCATABLE)
+  if (GFC_DESCRIPTOR_TYPE_P (type)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
     {
       /* If decl is an allocatable array, it needs to be deallocated
 	 afterwards.  */
@@ -691,7 +703,7 @@ gfc_trans_omp_array_reduction (tree c, g
   OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
 
   /* And stick the placeholder VAR_DECL into the clause as well.  */
-  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
+  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
 
   gfc_current_locus = old_loc;
 
--- libgomp/testsuite/libgomp.fortran/allocatable6.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/allocatable6.f90	(revision 167799)
@@ -0,0 +1,45 @@
+! PR fortran/46874
+! { dg-do run }
+
+  interface
+    subroutine sub (a, b, c, d, n)
+      integer :: n
+      integer, allocatable :: a(:), b(:), c(:), d(:)
+    end subroutine
+  end interface
+
+  integer, allocatable :: a(:), b(:), c(:), d(:)
+  integer :: i, j
+  allocate (a(50), b(50), c(50), d(50))
+  do i = 1, 50
+    a(i) = 2 + modulo (i, 7)
+    b(i) = 179 - modulo (i, 11)
+  end do
+  c = 0
+  d = 2147483647
+  call sub (a, b, c, d, 50)
+  do i = 1, 50
+    j = 0
+    if (i .eq. 3) then
+      j = 8
+    else if (i .gt. 1 .and. i .lt. 9) then
+      j = 7
+    end if
+    if (c(i) .ne. j) call abort
+    j = 179 - modulo (i, 11)
+    if (i .gt. 1 .and. i .lt. 9) j = i
+    if (d(i) .ne. j) call abort
+  end do
+  deallocate (a, b, c, d)
+end
+
+subroutine sub (a, b, c, d, n)
+  integer :: n
+  integer, allocatable :: a(:), b(:), c(:), d(:)
+!$omp parallel do shared(a, b) reduction(+:c) reduction(min:d)
+  do i = 1, n
+    c(a(i)) = c(a(i)) + 1
+    d(i) = min(d(i), b(i))
+    d(a(i)) = min(d(a(i)), a(i))
+  end do
+end
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/45852
	* expr.c (store_expr): Ignore alt_rtl if equal to target,
	but has side-effects.

	* gcc.target/i386/pr45852.c: New test.

--- gcc/expr.c	(revision 168104)
+++ gcc/expr.c	(revision 168105)
@@ -4712,7 +4712,10 @@ store_expr (tree exp, rtx target, int ca
       /* If store_expr stores a DECL whose DECL_RTL(exp) == TARGET,
 	 but TARGET is not valid memory reference, TEMP will differ
 	 from TARGET although it is really the same location.  */
-      && !(alt_rtl && rtx_equal_p (alt_rtl, target))
+      && !(alt_rtl
+	   && rtx_equal_p (alt_rtl, target)
+	   && !side_effects_p (alt_rtl)
+	   && !side_effects_p (target))
       /* If there's nothing to copy, don't bother.  Don't call
 	 expr_size unless necessary, because some front-ends (C++)
 	 expr_size-hook must not be given objects that are not
--- gcc/testsuite/gcc.target/i386/pr45852.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr45852.c	(revision 168105)
@@ -0,0 +1,16 @@
+/* PR middle-end/45852 */
+/* { dg-options "-O2 -mcmodel=small" } */
+/* { dg-do compile { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */
+/* { dg-require-visibility "" } */
+
+struct S { int s; };
+
+volatile struct S globvar __attribute__((visibility ("hidden"))) = { -6 };
+
+void
+foo (void)
+{
+  globvar = globvar;
+}
+
+/* { dg-final { scan-assembler-times "globvar.%?rip" 2 } } */
2011-01-16  Jakub Jelinek  <jakub@redhat.com>

	Backport from mainline
	2010-12-21  Jakub Jelinek  <jakub@redhat.com>

	PR target/46880
	* config/i386/sse.md (sse2_loadlpd, sse2_movsd): Fix shufpd source
	operand.

	* gcc.target/i386/pr46880.c: New test.

--- gcc/config/i386/sse.md	(revision 168134)
+++ gcc/config/i386/sse.md	(revision 168135)
@@ -4990,7 +4990,7 @@ (define_insn "sse2_loadlpd"
    movsd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
    movsd\t{%2, %0|%0, %2}
-   shufpd\t{$2, %2, %0|%0, %2, 2}
+   shufpd\t{$2, %1, %0|%0, %1, 2}
    movhpd\t{%H1, %0|%0, %H1}
    #
    #
@@ -5067,7 +5067,7 @@ (define_insn "sse2_movsd"
    movsd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
    movlpd\t{%2, %0|%0, %2}
-   shufpd\t{$2, %2, %0|%0, %2, 2}
+   shufpd\t{$2, %1, %0|%0, %1, 2}
    movhps\t{%H1, %0|%0, %H1}
    movhps\t{%1, %H0|%H0, %1}"
   [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
--- gcc/testsuite/gcc.target/i386/pr46880.c	(revision 0)
+++ gcc/testsuite/gcc.target/i386/pr46880.c	(revision 168135)
@@ -0,0 +1,28 @@
+/* PR target/46880 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-require-effective-target sse2_runtime } */
+
+typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef double (*T)[2];
+
+static __attribute__ ((noinline)) __m128d
+foo (__m128d c, __m128d d)
+{
+  T cp = (T) &c;
+  T dp = (T) &d;
+  __m128d e = { (*cp)[1], (*dp)[1] };
+  return e;
+}
+
+int
+main ()
+{
+  __m128d c = { 1.0, 2.0 };
+  __m128d d = { 3.0, 4.0 };
+  union { __m128d x; double d[2]; } u;
+  u.x = foo (c, d);
+  if (u.d[0] != 2.0 || u.d[1] != 4.0)
+    __builtin_abort ();
+  return 0;
+}
diff mbox

Patch

--- gcc/tree-ssa-loop-im.c	(revision 167684)
+++ gcc/tree-ssa-loop-im.c	(revision 167685)
@@ -2139,7 +2139,7 @@  loop_suitable_for_sm (struct loop *loop 
   edge ex;
 
   for (i = 0; VEC_iterate (edge, exits, i, ex); i++)
-    if (ex->flags & EDGE_ABNORMAL)
+    if (ex->flags & (EDGE_ABNORMAL | EDGE_EH))
       return false;
 
   return true;
--- gcc/testsuite/g++.dg/opt/pr46864.C	(revision 0)
+++ gcc/testsuite/g++.dg/opt/pr46864.C	(revision 167685)
@@ -0,0 +1,26 @@ 
+// PR tree-optimization/46864
+// { dg-do compile }
+// { dg-options "-O -fnon-call-exceptions" }
+
+int baz ();
+
+struct S
+{
+  int k;
+  bool bar () throw ()
+  {
+    int m = baz ();
+    for (int i = 0; i < m; i++)
+      k = i;
+    return m;
+  }
+};
+
+extern S *s;
+
+void
+foo ()
+{
+  while (baz () && s->bar ())
+    ;
+}