From c34938a8aa48af61df1835c2c0dab95d4ef6ca1a Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Thu, 12 Jun 2008 13:03:50 +0200
Subject: [PATCH] re PR middle-end/36506 (Broken #pragma omp sections reduction
 (+:x))

	PR middle-end/36506
	* omp-low.c (expand_omp_sections): Handle #pragma omp sections with
	reductions.

	* testsuite/libgomp.c/reduction-5.c: New test.

From-SVN: r136696
---
 gcc/ChangeLog                             |  6 ++
 gcc/omp-low.c                             | 34 +++++++++-
 libgomp/ChangeLog                         |  5 ++
 libgomp/testsuite/libgomp.c/reduction-5.c | 78 +++++++++++++++++++++++
 4 files changed, 121 insertions(+), 2 deletions(-)
 create mode 100644 libgomp/testsuite/libgomp.c/reduction-5.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eb6c434e6ff0..f2c51854bcd6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2008-06-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/36506
+	* omp-low.c (expand_omp_sections): Handle #pragma omp sections with
+	reductions.
+
 2008-06-12  Richard Guenther  <rguenther@suse.de>
 
 	PR tree-optimization/36345
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index e9223b2afb20..85b83332ff80 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -4389,6 +4389,8 @@ expand_omp_sections (struct omp_region *region)
   unsigned i, casei, len;
   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
   block_stmt_iterator si;
+  edge_iterator ei;
+  edge e;
   struct omp_region *inner;
   bool exit_reachable = region->cont != NULL;
 
@@ -4399,10 +4401,30 @@ expand_omp_sections (struct omp_region *region)
   l2_bb = region->exit;
   if (exit_reachable)
     {
-      gcc_assert (single_pred (l2_bb) == l0_bb);
+      if (single_pred (l2_bb) == l0_bb)
+	l2 = tree_block_label (l2_bb);
+      else
+	{
+	  /* This can happen if there are reductions.  */
+	  len = EDGE_COUNT (l0_bb->succs);
+	  gcc_assert (len > 0);
+	  e = EDGE_SUCC (l0_bb, len - 1);
+	  si = bsi_last (e->dest);
+	  if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION)
+	    l2 = tree_block_label (e->dest);
+	  else
+	    FOR_EACH_EDGE (e, ei, l0_bb->succs)
+	      {
+		si = bsi_last (e->dest);
+		if (bsi_end_p (si) || TREE_CODE (bsi_stmt (si)) != OMP_SECTION)
+		  {
+		    l2 = tree_block_label (e->dest);
+		    break;
+		  }
+	      }
+	}
       default_bb = create_empty_bb (l1_bb->prev_bb);
       l1 = tree_block_label (l1_bb);
-      l2 = tree_block_label (l2_bb);
     }
   else
     {
@@ -4480,6 +4502,14 @@ expand_omp_sections (struct omp_region *region)
     {
       basic_block s_entry_bb, s_exit_bb;
 
+      /* Skip optional reduction region.  */
+      if (inner->type == OMP_ATOMIC_LOAD)
+	{
+	  --i;
+	  --casei;
+	  continue;
+	}
+
       s_entry_bb = inner->entry;
       s_exit_bb = inner->exit;
 
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index fb70823cfcc4..ff9ed0374c93 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,8 @@
+2008-06-12  Jakub Jelinek  <jakub@redhat.com>
+
+	PR middle-end/36506
+	* testsuite/libgomp.c/reduction-5.c: New test.
+
 2008-06-11  Jakub Jelinek  <jakub@redhat.com>
 
 	* libgomp.h (struct gomp_task): Add in_tied_task field.
diff --git a/libgomp/testsuite/libgomp.c/reduction-5.c b/libgomp/testsuite/libgomp.c/reduction-5.c
new file mode 100644
index 000000000000..de87d9f6dc89
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/reduction-5.c
@@ -0,0 +1,78 @@
+/* PR middle-end/36506 */
+
+extern void abort (void);
+
+int
+main (void)
+{
+  int sum = 0, prod = 1;
+#pragma omp parallel
+  #pragma omp sections reduction (+:sum)
+    {
+    #pragma omp section
+      sum += 2;
+    #pragma omp section
+      sum += 2;
+    #pragma omp section
+      sum += 2;
+    }
+  if (sum != 6)
+    abort ();
+  sum = 0;
+#pragma omp parallel sections reduction (+:sum)
+  {
+  #pragma omp section
+    sum += 2;
+  #pragma omp section
+    sum += 2;
+  #pragma omp section
+    sum += 2;
+  }
+  if (sum != 6)
+    abort ();
+  sum = 0;
+#pragma omp parallel
+  #pragma omp sections reduction (+:sum) reduction (*:prod)
+    {
+    #pragma omp section
+      {
+	sum += 2;
+	prod *= 2;
+      }
+    #pragma omp section
+      {
+	sum += 2;
+	prod *= 2;
+      }
+    #pragma omp section
+      {
+	sum += 2;
+	prod *= 2;
+      }
+    }
+  if (sum != 6 || prod != 8)
+    abort ();
+  sum = 0;
+  prod = 1;
+#pragma omp parallel sections reduction (+:sum) reduction (*:prod)
+  {
+  #pragma omp section
+    {
+      sum += 2;
+      prod *= 2;
+    }
+  #pragma omp section
+    {
+      sum += 2;
+      prod *= 2;
+    }
+  #pragma omp section
+    {
+      sum += 2;
+      prod *= 2;
+    }
+  }
+  if (sum != 6 || prod != 8)
+    abort ();
+  return 0;
+}
-- 
GitLab