diff mbox

[committed] 4.8 backports

Message ID 20141128170903.GW1892@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 28, 2014, 5:09 p.m. UTC
Hi!

I've committed following backports to 4.8 branch, after
bootstrapping/regtesting on x86_64-linux and i686-linux.

	Jakub
2014-11-28  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-10-03  Jakub Jelinek  <jakub@redhat.com>

	PR libgomp/61200
	* omp-low.c (taskreg_contexts): New variable.
	(scan_omp_parallel): Push newly created context into taskreg_contexts
	vector and move record layout code to finish_taskreg_scan.
	(scan_omp_task): Likewise.
	(finish_taskreg_scan): New function.
	(execute_lower_omp): Call finish_taskreg_scan on all taskreg_contexts
	vector elements and release it.

	* c-c++-common/gomp/pr61200.c: New test.

	* testsuite/libgomp.c/pr61200.c: New test.
2014-11-28  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-10-31  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/63659
	* ree.c (update_reg_equal_equiv_notes): New function.
	(combine_set_extension, transform_ifelse): Use it.

	* gcc.c-torture/execute/pr63659.c: New test.

--- gcc/ree.c	(revision 216984)
+++ gcc/ree.c	(revision 216985)
@@ -261,6 +261,50 @@ typedef struct ext_cand
 
 static int max_insn_uid;
 
+/* Update or remove REG_EQUAL or REG_EQUIV notes for INSN.  */
+
+static bool
+update_reg_equal_equiv_notes (rtx insn, enum machine_mode new_mode,
+			      enum machine_mode old_mode, enum rtx_code code)
+{
+  rtx *loc = &REG_NOTES (insn);
+  while (*loc)
+    {
+      enum reg_note kind = REG_NOTE_KIND (*loc);
+      if (kind == REG_EQUAL || kind == REG_EQUIV)
+	{
+	  rtx orig_src = XEXP (*loc, 0);
+	  /* Update equivalency constants.  Recall that RTL constants are
+	     sign-extended.  */
+	  if (GET_CODE (orig_src) == CONST_INT
+	      && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode))
+	    {
+	      if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND)
+		/* Nothing needed.  */;
+	      else
+		{
+		  /* Zero-extend the negative constant by masking out the
+		     bits outside the source mode.  */
+		  rtx new_const_int
+		    = gen_int_mode (INTVAL (orig_src)
+				    & GET_MODE_MASK (old_mode),
+				    new_mode);
+		  if (!validate_change (insn, &XEXP (*loc, 0),
+					new_const_int, true))
+		    return false;
+		}
+	      loc = &XEXP (*loc, 1);
+	    }
+	  /* Drop all other notes, they assume a wrong mode.  */
+	  else if (!validate_change (insn, loc, XEXP (*loc, 1), true))
+	    return false;
+	}
+      else
+	loc = &XEXP (*loc, 1);
+    }
+  return true;
+}
+
 /* Given a insn (CURR_INSN), an extension candidate for removal (CAND)
    and a pointer to the SET rtx (ORIG_SET) that needs to be modified,
    this code modifies the SET rtx to a new SET rtx that extends the
@@ -282,6 +326,7 @@ static bool
 combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set)
 {
   rtx orig_src = SET_SRC (*orig_set);
+  enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set));
   rtx new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
   rtx new_set;
 
@@ -296,9 +341,8 @@ combine_set_extension (ext_cand *cand, r
 	{
 	  /* Zero-extend the negative constant by masking out the bits outside
 	     the source mode.  */
-	  enum machine_mode src_mode = GET_MODE (SET_DEST (*orig_set));
 	  rtx new_const_int
-	    = GEN_INT (INTVAL (orig_src) & GET_MODE_MASK (src_mode));
+	    = GEN_INT (INTVAL (orig_src) & GET_MODE_MASK (orig_mode));
 	  new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int);
 	}
     }
@@ -336,7 +380,9 @@ combine_set_extension (ext_cand *cand, r
 
   /* This change is a part of a group of changes.  Hence,
      validate_change will not try to commit the change.  */
-  if (validate_change (curr_insn, orig_set, new_set, true))
+  if (validate_change (curr_insn, orig_set, new_set, true)
+      && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode,
+				       cand->code))
     {
       if (dump_file)
         {
@@ -385,7 +431,9 @@ transform_ifelse (ext_cand *cand, rtx de
   ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2);
   new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr);
 
-  if (validate_change (def_insn, &PATTERN (def_insn), new_set, true))
+  if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)
+      && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg),
+				       cand->code))
     {
       if (dump_file)
         {
--- gcc/testsuite/gcc.c-torture/execute/pr63659.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr63659.c	(revision 216985)
@@ -0,0 +1,29 @@
+/* PR rtl-optimization/63659 */
+
+int a, b, c, *d = &b, g, h, i;
+unsigned char e;
+char f;
+
+int
+main ()
+{
+  while (a)
+    {
+      for (a = 0; a; a++)
+	for (; c; c++)
+	  ;
+      if (i)
+	break;
+    }
+
+  char j = c, k = -1, l;
+  l = g = j >> h;
+  f = l == 0 ? k : k % l;
+  e = 0 ? 0 : f;
+  *d = e;
+
+  if (b != 255)
+    __builtin_abort ();
+
+  return 0;
+}
2014-11-28  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-11-24  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/63938
	* trans-openmp.c (gfc_trans_omp_atomic): Make sure lhsaddr is
	simple enough for goa_lhs_expr_p.

	* libgomp.fortran/pr63938-1.f90: New test.
	* libgomp.fortran/pr63938-2.f90: New test.

--- gcc/fortran/trans-openmp.c	(revision 218030)
+++ gcc/fortran/trans-openmp.c	(revision 218031)
@@ -1227,6 +1227,18 @@ gfc_trans_omp_atomic (gfc_code *code)
     }
 
   lhsaddr = save_expr (lhsaddr);
+  if (TREE_CODE (lhsaddr) != SAVE_EXPR
+      && (TREE_CODE (lhsaddr) != ADDR_EXPR
+	  || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL))
+    {
+      /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
+	 it even after unsharing function body.  */
+      tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr), NULL);
+      DECL_CONTEXT (var) = current_function_decl;
+      lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
+			NULL_TREE, NULL_TREE);
+    }
+
   rhs = gfc_evaluate_now (rse.expr, &block);
 
   if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
--- libgomp/testsuite/libgomp.fortran/pr63938-1.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/pr63938-1.f90	(revision 218031)
@@ -0,0 +1,14 @@
+! PR fortran/63938
+! { dg-do run }
+
+program pr63938_1
+  integer :: i, x(1)
+  x(1) = 0
+!$omp parallel do
+  do i = 1, 1000
+    !$omp atomic
+    x(1) = x(1) + 1
+  end do
+!$omp end parallel do
+  if (x(1) .ne. 1000) call abort
+end program pr63938_1
--- libgomp/testsuite/libgomp.fortran/pr63938-2.f90	(revision 0)
+++ libgomp/testsuite/libgomp.fortran/pr63938-2.f90	(revision 218031)
@@ -0,0 +1,18 @@
+! PR fortran/63938
+! { dg-do run }
+
+program pr63938_2
+  type t
+    integer :: x
+  end type
+  integer :: i
+  type(t) :: x
+  x%x = 0
+!$omp parallel do
+  do i = 1, 1000
+    !$omp atomic
+    x%x = x%x + 1
+  end do
+!$omp end parallel do
+  if (x%x .ne. 1000) call abort
+end program pr63938_2
2014-11-28  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-11-25  Jakub Jelinek  <jakub@redhat.com>

	PR preprocessor/60436
	* line-map.c (linemap_line_start): If highest is above 0x60000000
	and we are still tracking columns or highest is above 0x70000000,
	force add_map.

--- libcpp/line-map.c	(revision 218041)
+++ libcpp/line-map.c	(revision 218042)
@@ -529,10 +529,10 @@ linemap_line_start (struct line_maps *se
 	  && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000)
       || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)))
       || (max_column_hint <= 80
-	  && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10))
-    {
-      add_map = true;
-    }
+	  && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10)
+      || (highest > 0x60000000
+	  && (set->max_column_hint || highest > 0x70000000)))
+    add_map = true;
   else
     max_column_hint = set->max_column_hint;
   if (add_map)
@@ -543,7 +543,7 @@ linemap_line_start (struct line_maps *se
 	  /* If the column number is ridiculous or we've allocated a huge
 	     number of source_locations, give up on column numbers. */
 	  max_column_hint = 0;
-	  if (highest >0x70000000)
+	  if (highest > 0x70000000)
 	    return 0;
 	  column_bits = 0;
 	}
2014-11-28  Jakub Jelinek  <jakub@redhat.com>

	Backported from mainline
	2014-11-27  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/64067
	* expr.c (expand_expr_addr_expr_1) <case COMPOUND_LITERAL_EXPR>:
	Handle it by returning address of COMPOUND_LITERAL_EXPR_DECL
	not only if modifier is EXPAND_INITIALIZER, but whenever
	COMPOUND_LITERAL_EXPR_DECL is non-NULL and TREE_STATIC.

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

--- gcc/expr.c	(revision 218120)
+++ gcc/expr.c	(revision 218121)
@@ -7677,11 +7677,13 @@ expand_expr_addr_expr_1 (tree exp, rtx t
       break;
 
     case COMPOUND_LITERAL_EXPR:
-      /* Allow COMPOUND_LITERAL_EXPR in initializers, if e.g.
-	 rtl_for_decl_init is called on DECL_INITIAL with
-	 COMPOUNT_LITERAL_EXPRs in it, they aren't gimplified.  */
-      if (modifier == EXPAND_INITIALIZER
-	  && COMPOUND_LITERAL_EXPR_DECL (exp))
+      /* Allow COMPOUND_LITERAL_EXPR in initializers or coming from
+	 initializers, if e.g. rtl_for_decl_init is called on DECL_INITIAL
+	 with COMPOUND_LITERAL_EXPRs in it, or ARRAY_REF on a const static
+	 array with address of COMPOUND_LITERAL_EXPR in DECL_INITIAL;
+	 the initializers aren't gimplified.  */
+      if (COMPOUND_LITERAL_EXPR_DECL (exp)
+	  && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
 	return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp),
 					target, tmode, modifier, as);
       /* FALLTHRU */
--- gcc/testsuite/gcc.c-torture/compile/pr64067.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr64067.c	(revision 218121)
@@ -0,0 +1,10 @@
+/* PR middle-end/64067 */
+
+struct S { int s; };
+int *const v[1] = { &((struct S) { .s = 42 }).s };
+
+int *
+foo (void)
+{
+  return v[0];
+}
diff mbox

Patch

--- gcc/omp-low.c	(revision 215834)
+++ gcc/omp-low.c	(revision 215835)
@@ -128,6 +128,7 @@  static splay_tree all_contexts;
 static int taskreg_nesting_level;
 struct omp_region *root_omp_region;
 static bitmap task_shared_vars;
+static vec<omp_context *> taskreg_contexts;
 
 static void scan_omp (gimple_seq *, omp_context *);
 static tree scan_omp_1_op (tree *, int *, void *);
@@ -1655,6 +1656,7 @@  scan_omp_parallel (gimple_stmt_iterator
     }
 
   ctx = new_omp_context (stmt, outer_ctx);
+  taskreg_contexts.safe_push (ctx);
   if (taskreg_nesting_level > 1)
     ctx->is_nested = true;
   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
@@ -1674,11 +1676,6 @@  scan_omp_parallel (gimple_stmt_iterator
 
   if (TYPE_FIELDS (ctx->record_type) == NULL)
     ctx->record_type = ctx->receiver_decl = NULL;
-  else
-    {
-      layout_type (ctx->record_type);
-      fixup_child_record_type (ctx);
-    }
 }
 
 /* Scan an OpenMP task directive.  */
@@ -1689,7 +1686,6 @@  scan_omp_task (gimple_stmt_iterator *gsi
   omp_context *ctx;
   tree name, t;
   gimple stmt = gsi_stmt (*gsi);
-  location_t loc = gimple_location (stmt);
 
   /* Ignore task directives with empty bodies.  */
   if (optimize > 0
@@ -1700,6 +1696,7 @@  scan_omp_task (gimple_stmt_iterator *gsi
     }
 
   ctx = new_omp_context (stmt, outer_ctx);
+  taskreg_contexts.safe_push (ctx);
   if (taskreg_nesting_level > 1)
     ctx->is_nested = true;
   ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
@@ -1737,8 +1734,71 @@  scan_omp_task (gimple_stmt_iterator *gsi
       t = build_int_cst (long_integer_type_node, 1);
       gimple_omp_task_set_arg_align (stmt, t);
     }
+}
+
+
+/* If any decls have been made addressable during scan_omp,
+   adjust their fields if needed, and layout record types
+   of parallel/task constructs.  */
+
+static void
+finish_taskreg_scan (omp_context *ctx)
+{
+  if (ctx->record_type == NULL_TREE)
+    return;
+
+  /* If any task_shared_vars were needed, verify all
+     OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
+     statements if use_pointer_for_field hasn't changed
+     because of that.  If it did, update field types now.  */
+  if (task_shared_vars)
+    {
+      tree c;
+
+      for (c = gimple_omp_taskreg_clauses (ctx->stmt);
+	   c; c = OMP_CLAUSE_CHAIN (c))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
+	  {
+	    tree decl = OMP_CLAUSE_DECL (c);
+
+	    /* Global variables don't need to be copied,
+	       the receiver side will use them directly.  */
+	    if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
+	      continue;
+	    if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
+		|| !use_pointer_for_field (decl, ctx))
+	      continue;
+	    tree field = lookup_field (decl, ctx);
+	    if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
+		&& TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
+	      continue;
+	    TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
+	    TREE_THIS_VOLATILE (field) = 0;
+	    DECL_USER_ALIGN (field) = 0;
+	    DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
+	    if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
+	      TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
+	    if (ctx->srecord_type)
+	      {
+		tree sfield = lookup_sfield (decl, ctx);
+		TREE_TYPE (sfield) = TREE_TYPE (field);
+		TREE_THIS_VOLATILE (sfield) = 0;
+		DECL_USER_ALIGN (sfield) = 0;
+		DECL_ALIGN (sfield) = DECL_ALIGN (field);
+		if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
+		  TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
+	      }
+	  }
+    }
+
+  if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
+    {
+      layout_type (ctx->record_type);
+      fixup_child_record_type (ctx);
+    }
   else
     {
+      location_t loc = gimple_location (ctx->stmt);
       tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
       /* Move VLA fields to the end.  */
       p = &TYPE_FIELDS (ctx->record_type);
@@ -1758,12 +1818,12 @@  scan_omp_task (gimple_stmt_iterator *gsi
       fixup_child_record_type (ctx);
       if (ctx->srecord_type)
 	layout_type (ctx->srecord_type);
-      t = fold_convert_loc (loc, long_integer_type_node,
-			TYPE_SIZE_UNIT (ctx->record_type));
-      gimple_omp_task_set_arg_size (stmt, t);
+      tree t = fold_convert_loc (loc, long_integer_type_node,
+				 TYPE_SIZE_UNIT (ctx->record_type));
+      gimple_omp_task_set_arg_size (ctx->stmt, t);
       t = build_int_cst (long_integer_type_node,
 			 TYPE_ALIGN_UNIT (ctx->record_type));
-      gimple_omp_task_set_arg_align (stmt, t);
+      gimple_omp_task_set_arg_align (ctx->stmt, t);
     }
 }
 
@@ -7112,6 +7172,8 @@  static unsigned int
 execute_lower_omp (void)
 {
   gimple_seq body;
+  int i;
+  omp_context *ctx;
 
   /* This pass always runs, to provide PROP_gimple_lomp.
      But there is nothing to do unless -fopenmp is given.  */
@@ -7124,6 +7186,9 @@  execute_lower_omp (void)
   body = gimple_body (current_function_decl);
   scan_omp (&body, NULL);
   gcc_assert (taskreg_nesting_level == 0);
+  FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
+    finish_taskreg_scan (ctx);
+  taskreg_contexts.release ();
 
   if (all_contexts->root)
     {
--- gcc/testsuite/c-c++-common/gomp/pr61200.c	(revision 0)
+++ gcc/testsuite/c-c++-common/gomp/pr61200.c	(revision 215835)
@@ -0,0 +1,13 @@ 
+/* PR libgomp/61200 */
+
+int
+main ()
+{
+  int var = 1;
+  #pragma omp parallel
+    if (var != 1)
+      __builtin_abort ();
+  #pragma omp task shared(var)
+    var = 2;
+  return 0;
+}
--- libgomp/testsuite/libgomp.c/pr61200.c	(revision 0)
+++ libgomp/testsuite/libgomp.c/pr61200.c	(revision 215835)
@@ -0,0 +1,87 @@ 
+/* PR libgomp/61200 */
+/* { dg-do run } */
+
+#include <omp.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+volatile int x;
+
+void
+foo ()
+{
+  int var = 1;
+  int i;
+
+  for (i = 0; i < 2; i++)
+    {
+      if (i == 1)
+	{
+	  #pragma omp parallel num_threads(2)
+	    if (x)
+	      var++;
+	    else
+	      {
+		#pragma omp single
+		  sleep (2);
+	      }
+	}
+      else
+	{
+	  #pragma omp task shared(var)
+	  {
+	    sleep (1);
+	    var = 2;
+	  }
+	}
+    }
+  #pragma omp taskwait
+  if (var != 2)
+    abort ();
+}
+
+void
+bar ()
+{
+  int var = 1;
+  int i;
+
+  for (i = 0; i < 2; i++)
+    {
+      if (i == 0)
+	{
+	  #pragma omp task shared(var)
+	  {
+	    sleep (1);
+	    var = 2;
+	  }
+	}
+      else
+	{
+	  #pragma omp parallel num_threads(2)
+	    if (x)
+	      var++;
+	    else
+	      {
+		#pragma omp single
+		  sleep (2);
+	      }
+	}
+    }
+  #pragma omp taskwait
+  if (var != 2)
+    abort ();
+}
+
+int
+main ()
+{
+  omp_set_nested (1);
+  #pragma omp parallel num_threads(2)
+    #pragma omp single
+      foo ();
+  #pragma omp parallel num_threads(2)
+    #pragma omp single
+      bar ();
+  return 0;
+}