From 6a3fe7faa7f3eac3a0bea13ebb660e96f4286979 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 16 Dec 2013 17:13:08 -0500
Subject: [PATCH 37/89] Introduce gimple_omp_critical

gcc/
	* coretypes.h (gimple_omp_critical): New typedef.
	(const_gimple_omp_critical): New typedef.

	* gimple-pretty-print.c (dump_gimple_omp_critical): Require a
	gimple_omp_critical rather than a plain gimple.
	(pp_gimple_stmt_1): Add a checked cast to gimple_omp_critical
	within GIMPLE_OMP_CRITICAL case of switch statement.

	* gimple-walk.c (walk_gimple_op): Likewise.

	* gimple.c (gimple_build_omp_critical): Return a gimple_omp_critical
	rather than a plain gimple.
	(gimple_copy): Add checked casts to gimple_omp_critical
	within GIMPLE_OMP_CRITICAL case of switch statement.

	* gimple.h (gimple_statement_base::as_a_gimple_omp_critical): New.
	(gimple_statement_base::dyn_cast_gimple_omp_critical): New.
	(gimple_debug): Likewise.
	(gimple_build_omp_critical): Return a gimple_omp_critical rather
	than a plain gimple.
	(gimple_omp_critical_name): Require a const_gimple_omp_critical
	rather than a plain const_gimple.
	(gimple_omp_critical_name_ptr): Require a gimple_omp_critical
	rather than a plain gimple.
	(gimple_omp_critical_set_name): Likewise.

	* omp-low.c (check_omp_nesting_restrictions): Add a checked cast
	to gimple_omp_critical within GIMPLE_OMP_CRITICAL case of switch
	statement, introducing a new local "other_crit" for type-safety.
	(lower_omp_critical): Strengthen local "stmt" to
	gimple_omp_critical.

	* tree-inline.c (remap_gimple_stmt): Add a checked cast to
	gimple_omp_critical within GIMPLE_OMP_CRITICAL case of switch
	statement.
---
 gcc/coretypes.h           |  4 ++++
 gcc/gimple-pretty-print.c |  7 ++++---
 gcc/gimple-walk.c         |  5 +++--
 gcc/gimple.c              | 10 ++++++----
 gcc/gimple.h              | 34 ++++++++++++++++++++--------------
 gcc/omp-low.c             | 26 +++++++++++++++-----------
 gcc/tree-inline.c         |  6 ++++--
 7 files changed, 56 insertions(+), 36 deletions(-)

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index e2ad76e..f527da6 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -159,6 +159,10 @@ struct gimple_statement_omp_continue;
 typedef struct gimple_statement_omp_continue *gimple_omp_continue;
 typedef const struct gimple_statement_omp_continue *const_gimple_omp_continue;
 
+struct gimple_statement_omp_critical;
+typedef struct gimple_statement_omp_critical *gimple_omp_critical;
+typedef const struct gimple_statement_omp_critical *const_gimple_omp_critical;
+
 union section;
 typedef union section section;
 struct gcc_options;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 3de01d0..8248c67 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1435,8 +1435,8 @@ dump_gimple_omp_block (pretty_printer *buffer, gimple gs, int spc, int flags)
 /* Dump a GIMPLE_OMP_CRITICAL tuple on the pretty_printer BUFFER.  */
 
 static void
-dump_gimple_omp_critical (pretty_printer *buffer, gimple gs, int spc,
-			  int flags)
+dump_gimple_omp_critical (pretty_printer *buffer, gimple_omp_critical gs,
+			  int spc, int flags)
 {
   if (flags & TDF_RAW)
     dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
@@ -2202,7 +2202,8 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
       break;
 
     case GIMPLE_OMP_CRITICAL:
-      dump_gimple_omp_critical (buffer, gs, spc, flags);
+      dump_gimple_omp_critical (buffer, gs->as_a_gimple_omp_critical (), spc,
+				flags);
       break;
 
     case GIMPLE_CATCH:
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index f286748..ae43f45 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -313,8 +313,9 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
       break;
 
     case GIMPLE_OMP_CRITICAL:
-      ret = walk_tree (gimple_omp_critical_name_ptr (stmt), callback_op, wi,
-		       pset);
+      ret = walk_tree (gimple_omp_critical_name_ptr (
+			 stmt->as_a_gimple_omp_critical ()),
+		       callback_op, wi, pset);
       if (ret)
 	return ret;
       break;
diff --git a/gcc/gimple.c b/gcc/gimple.c
index a0fa31e..3b40884 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -815,10 +815,11 @@ gimple_build_debug_source_bind_stat (tree var, tree value,
    BODY is the sequence of statements for which only one thread can execute.
    NAME is optional identifier for this critical block.  */
 
-gimple
+gimple_omp_critical
 gimple_build_omp_critical (gimple_seq body, tree name)
 {
-  gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
+  gimple_omp_critical p =
+    gimple_alloc (GIMPLE_OMP_CRITICAL, 0)->as_a_gimple_omp_critical ();
   gimple_omp_critical_set_name (p, name);
   if (body)
     gimple_omp_set_body (p, body);
@@ -1736,8 +1737,9 @@ gimple_copy (gimple stmt)
 	  goto copy_omp_body;
 
 	case GIMPLE_OMP_CRITICAL:
-	  t = unshare_expr (gimple_omp_critical_name (stmt));
-	  gimple_omp_critical_set_name (copy, t);
+	  t = unshare_expr (gimple_omp_critical_name (
+			      stmt->as_a_gimple_omp_critical ()));
+	  gimple_omp_critical_set_name (copy->as_a_gimple_omp_critical (), t);
 	  goto copy_omp_body;
 
 	case GIMPLE_OMP_SECTIONS:
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 5a3626e..525fb7b 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -354,6 +354,12 @@ public:
     return as_a <gimple_statement_omp_continue> (this);
   }
 
+  inline gimple_omp_critical
+  as_a_gimple_omp_critical ()
+  {
+    return as_a <gimple_statement_omp_critical> (this);
+  }
+
   /* Dynamic casting methods, where the cast returns NULL if the
      stmt is not of the required kind.
 
@@ -440,6 +446,12 @@ public:
     return dyn_cast <gimple_statement_phi> (this);
   }
 
+  inline gimple_omp_critical
+  dyn_cast_gimple_omp_critical ()
+  {
+    return dyn_cast <gimple_statement_omp_critical> (this);
+  }
+
 };
 
 
@@ -1582,7 +1594,7 @@ gimple_debug gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
 gimple_debug gimple_build_debug_source_bind_stat (tree, tree, gimple MEM_STAT_DECL);
 #define gimple_build_debug_source_bind(var,val,stmt)			\
   gimple_build_debug_source_bind_stat ((var), (val), (stmt) MEM_STAT_INFO)
-gimple gimple_build_omp_critical (gimple_seq, tree);
+gimple_omp_critical gimple_build_omp_critical (gimple_seq, tree);
 gimple gimple_build_omp_for (gimple_seq, int, tree, size_t, gimple_seq);
 gimple gimple_build_omp_parallel (gimple_seq, tree, tree, tree);
 gimple gimple_build_omp_task (gimple_seq, tree, tree, tree, tree, tree, tree);
@@ -4561,36 +4573,30 @@ gimple_omp_set_body (gimple gs, gimple_seq body)
 }
 
 
-/* Return the name associated with OMP_CRITICAL statement GS.  */
+/* Return the name associated with OMP_CRITICAL statement CRIT_STMT.  */
 
 static inline tree
-gimple_omp_critical_name (const_gimple gs)
+gimple_omp_critical_name (const_gimple_omp_critical crit_stmt)
 {
-  const gimple_statement_omp_critical *omp_critical_stmt =
-    as_a <const gimple_statement_omp_critical> (gs);
-  return omp_critical_stmt->name;
+  return crit_stmt->name;
 }
 
 
 /* Return a pointer to the name associated with OMP critical statement GS.  */
 
 static inline tree *
-gimple_omp_critical_name_ptr (gimple gs)
+gimple_omp_critical_name_ptr (gimple_omp_critical crit_stmt)
 {
-  gimple_statement_omp_critical *omp_critical_stmt =
-    as_a <gimple_statement_omp_critical> (gs);
-  return &omp_critical_stmt->name;
+  return &crit_stmt->name;
 }
 
 
 /* Set NAME to be the name associated with OMP critical statement GS.  */
 
 static inline void
-gimple_omp_critical_set_name (gimple gs, tree name)
+gimple_omp_critical_set_name (gimple_omp_critical crit_stmt, tree name)
 {
-  gimple_statement_omp_critical *omp_critical_stmt =
-    as_a <gimple_statement_omp_critical> (gs);
-  omp_critical_stmt->name = name;
+  crit_stmt->name = name;
 }
 
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 1cd4731..c2ab88a 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2472,16 +2472,20 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
 	  }
       break;
     case GIMPLE_OMP_CRITICAL:
-      for (; ctx != NULL; ctx = ctx->outer)
-	if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
-	    && (gimple_omp_critical_name (stmt)
-		== gimple_omp_critical_name (ctx->stmt)))
-	  {
-	    error_at (gimple_location (stmt),
-		      "critical region may not be nested inside a critical "
-		      "region with the same name");
-	    return false;
-	  }
+      {
+	tree this_stmt_name =
+	  gimple_omp_critical_name (stmt->as_a_gimple_omp_critical ());
+	for (; ctx != NULL; ctx = ctx->outer)
+	  if (gimple_omp_critical other_crit =
+	      ctx->stmt->dyn_cast_gimple_omp_critical ())
+	    if (this_stmt_name == gimple_omp_critical_name (other_crit))
+	      {
+		error_at (gimple_location (stmt),
+			  "critical region may not be nested inside a critical "
+			  "region with the same name");
+		return false;
+	      }
+      }
       break;
     case GIMPLE_OMP_TEAMS:
       if (ctx == NULL
@@ -8799,7 +8803,7 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 {
   tree block;
   tree name, lock, unlock;
-  gimple stmt = gsi_stmt (*gsi_p);
+  gimple_omp_critical stmt = gsi_stmt (*gsi_p)->as_a_gimple_omp_critical ();
   gimple_bind bind;
   location_t loc = gimple_location (stmt);
   gimple_seq tbody;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index f1d2791..34c399a 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1411,8 +1411,10 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
 
 	case GIMPLE_OMP_CRITICAL:
 	  s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
-	  copy
-	    = gimple_build_omp_critical (s1, gimple_omp_critical_name (stmt));
+	  copy =
+	    gimple_build_omp_critical (s1,
+				       gimple_omp_critical_name (
+				         stmt->as_a_gimple_omp_critical ()));
 	  break;
 
 	case GIMPLE_TRANSACTION:
-- 
1.8.5.3

