Hi!

I've bootstrapped/regtested on x86_64-linux and i686-linux
following backports and committed them to 4.8 branch.

        Jakub
2015-06-03  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2015-02-18  Jakub Jelinek  <ja...@redhat.com>

        PR gcov-profile/64634
        * tree-eh.c (frob_into_branch_around): Fix up typos
        in function comment.
        (lower_catch): Put eh_seq resulting from EH lowering of
        the cleanup sequence after the cleanup rather than before
        it.

        * g++.dg/gcov/gcov-15.C: New test.

--- gcc/tree-eh.c       (revision 220800)
+++ gcc/tree-eh.c       (revision 220801)
@@ -884,10 +884,10 @@ eh_region_may_contain_throw (eh_region r
 /* We want to transform
        try { body; } catch { stuff; }
    to
-       normal_seqence:
+       normal_sequence:
          body;
          over:
-       eh_seqence:
+       eh_sequence:
          landing_pad:
          stuff;
          goto over;
@@ -1813,6 +1813,12 @@ lower_catch (struct leh_state *state, gt
   this_state.cur_region = state->cur_region;
   this_state.ehp_region = try_region;
 
+  /* Add eh_seq from lowering EH in the cleanup sequence after the cleanup
+     itself, so that e.g. for coverage purposes the nested cleanups don't
+     appear before the cleanup body.  See PR64634 for details.  */
+  gimple_seq old_eh_seq = eh_seq;
+  eh_seq = NULL;
+
   out_label = NULL;
   cleanup = gimple_try_cleanup (tp);
   for (gsi = gsi_start (cleanup);
@@ -1849,7 +1855,11 @@ lower_catch (struct leh_state *state, gt
 
   gimple_try_set_cleanup (tp, new_seq);
 
-  return frob_into_branch_around (tp, try_region, out_label);
+  gimple_seq new_eh_seq = eh_seq;
+  eh_seq = old_eh_seq;
+  gimple_seq ret_seq = frob_into_branch_around (tp, try_region, out_label);
+  gimple_seq_add_seq (&eh_seq, new_eh_seq);
+  return ret_seq;
 }
 
 /* A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with a
--- gcc/testsuite/g++.dg/gcov/gcov-15.C (revision 0)
+++ gcc/testsuite/g++.dg/gcov/gcov-15.C (revision 220801)
@@ -0,0 +1,26 @@
+// PR gcov-profile/64634
+// { dg-options "-fprofile-arcs -ftest-coverage" }
+// { dg-do run { target native } }
+
+void catchEx ()                // count(1)
+{
+  __builtin_exit (0);  // count(1)
+  try
+  {}
+  catch (int)
+  {}
+}
+
+int main ()            // count(1)
+{
+  try
+  {
+    throw 5;           // count(1)
+  }
+  catch (...)          // count(1)
+  {
+    catchEx ();                // count(1)
+  }
+}
+
+// { dg-final { run-gcov gcov-15.C } }
2015-06-03  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2015-03-10  Jakub Jelinek  <ja...@redhat.com>

        PR target/65368
        * config/i386/i386.md (bmi2_bzhi_<mode>3): Removed define_insn,
        new define_expand.
        (*bmi2_bzhi_<mode>3, *bmi2_bzhi_<mode>3_1): New define_insns.

        * gcc.target/i386/bmi2-bzhi-2.c: New test.

--- gcc/config/i386/i386.md     (revision 221334)
+++ gcc/config/i386/i386.md     (revision 221335)
@@ -12172,17 +12172,51 @@
    (set_attr "mode" "<MODE>")])
 
 ;; BMI2 instructions.
-(define_insn "bmi2_bzhi_<mode>3"
+(define_expand "bmi2_bzhi_<mode>3"
+  [(parallel
+    [(set (match_operand:SWI48 0 "register_operand")
+         (zero_extract:SWI48
+           (match_operand:SWI48 1 "nonimmediate_operand")
+           (umin:SWI48
+             (and:SWI48 (match_operand:SWI48 2 "register_operand")
+                        (const_int 255))
+             (match_dup 3))
+           (const_int 0)))
+     (clobber (reg:CC FLAGS_REG))])]
+  "TARGET_BMI2"
+  "operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
+
+(define_insn "*bmi2_bzhi_<mode>3"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
-       (and:SWI48 (lshiftrt:SWI48 (const_int -1)
-                                  (match_operand:SWI48 2 "register_operand" 
"r"))
-                  (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
+       (zero_extract:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+         (umin:SWI48
+           (and:SWI48 (match_operand:SWI48 2 "register_operand" "r")
+                      (const_int 255))
+           (match_operand:SWI48 3 "const_int_operand" "n"))
+         (const_int 0)))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_BMI2"
+  "TARGET_BMI2 && INTVAL (operands[3]) == GET_MODE_BITSIZE (<MODE>mode)"
   "bzhi\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "bitmanip")
    (set_attr "prefix" "vex")
    (set_attr "mode" "<MODE>")])
+
+(define_mode_attr k [(SI "k") (DI "q")])
+(define_insn "*bmi2_bzhi_<mode>3_1"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+       (zero_extract:SWI48
+         (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+         (umin:SWI48
+           (zero_extend:SWI48 (match_operand:QI 2 "register_operand" "r"))
+           (match_operand:SWI48 3 "const_int_operand" "n"))
+         (const_int 0)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_BMI2 && INTVAL (operands[3]) == GET_MODE_BITSIZE (<MODE>mode)"
+  "bzhi\t{%<k>2, %1, %0|%0, %1, %<k>2}"
+  [(set_attr "type" "bitmanip")
+   (set_attr "prefix" "vex")
+   (set_attr "mode" "<MODE>")])
 
 (define_insn "bmi2_pdep_<mode>3"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
--- gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c (revision 0)
+++ gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c (revision 221335)
@@ -0,0 +1,67 @@
+/* PR target/65368 */
+/* { dg-do assemble { target bmi2 } } */
+/* { dg-options "-O2 -mbmi2" } */
+
+#include <x86intrin.h>
+#include "bmi2-check.h"
+
+unsigned int a;
+unsigned long long b;
+
+#define A __attribute__((noinline, noclone))
+
+A unsigned int f1 (void) { return _bzhi_u32 (a, 0); }
+A unsigned int f2 (unsigned int x) { return _bzhi_u32 (x, 0); }
+A unsigned int f3 (void) { return _bzhi_u32 (a, 5); }
+A unsigned int f4 (unsigned int x) { return _bzhi_u32 (x, 5); }
+A unsigned int f5 (void) { return _bzhi_u32 (a, 31); }
+A unsigned int f6 (unsigned int x) { return _bzhi_u32 (x, 31); }
+A unsigned int f7 (void) { return _bzhi_u32 (a, 32); }
+A unsigned int f8 (unsigned int x) { return _bzhi_u32 (x, 32); }
+A unsigned int f9 (void) { return _bzhi_u32 (a, 37); }
+A unsigned int f10 (unsigned int x) { return _bzhi_u32 (x, 37); }
+A unsigned int f11 (void) { return _bzhi_u32 (a, 257); }
+A unsigned int f12 (unsigned int x) { return _bzhi_u32 (x, 257); }
+A unsigned int f13 (void) { return _bzhi_u32 (a, 289); }
+A unsigned int f14 (unsigned int x) { return _bzhi_u32 (x, 289); }
+#ifdef __x86_64__
+A unsigned long long f21 (void) { return _bzhi_u64 (b, 0); }
+A unsigned long long f22 (unsigned long long x) { return _bzhi_u64 (x, 0); }
+A unsigned long long f23 (void) { return _bzhi_u64 (b, 5); }
+A unsigned long long f24 (unsigned long long x) { return _bzhi_u64 (x, 5); }
+A unsigned long long f25 (void) { return _bzhi_u64 (b, 63); }
+A unsigned long long f26 (unsigned long long x) { return _bzhi_u64 (x, 63); }
+A unsigned long long f27 (void) { return _bzhi_u64 (b, 64); }
+A unsigned long long f28 (unsigned long long x) { return _bzhi_u64 (x, 64); }
+A unsigned long long f29 (void) { return _bzhi_u64 (b, 69); }
+A unsigned long long f30 (unsigned long long x) { return _bzhi_u64 (x, 69); }
+A unsigned long long f31 (void) { return _bzhi_u64 (b, 257); }
+A unsigned long long f32 (unsigned long long x) { return _bzhi_u64 (x, 257); }
+A unsigned long long f33 (void) { return _bzhi_u64 (b, 321); }
+A unsigned long long f34 (unsigned long long x) { return _bzhi_u64 (x, 321); }
+#endif
+
+static void
+bmi2_test ()
+{
+  a = -1U;
+  b = -1ULL;
+  if (f1 () != 0 || f2 (-1U) != 0
+      || f3 () != 0x1f || f4 (-1U) != 0x1f
+      || f5 () != 0x7fffffffU || f6 (-1U) != 0x7fffffffU
+      || f7 () != -1U || f8 (-1U) != -1U
+      || f9 () != -1U || f10 (-1U) != -1U
+      || f11 () != 1 || f12 (-1U) != 1
+      || f13 () != -1U || f14 (-1U) != -1U)
+    abort ();
+#ifdef __x86_64__
+  if (f21 () != 0 || f22 (-1ULL) != 0
+      || f23 () != 0x1f || f24 (-1ULL) != 0x1f
+      || f25 () != 0x7fffffffffffffffULL || f26 (-1ULL) != 
0x7fffffffffffffffULL
+      || f27 () != -1ULL || f28 (-1ULL) != -1ULL
+      || f29 () != -1ULL || f30 (-1ULL) != -1ULL
+      || f31 () != 1 || f32 (-1ULL) != 1
+      || f33 () != -1ULL || f34 (-1ULL) != -1ULL)
+    abort ();
+#endif
+}
2015-06-03  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2015-04-07  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/65680
        * expr.c (get_inner_reference): Handle bit_offset that doesn't fit
        into signed HOST_WIDE_INT the same as negative bit_offset.

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

--- gcc/expr.c  (revision 221898)
+++ gcc/expr.c  (revision 221899)
@@ -6873,7 +6873,7 @@ get_inner_reference (tree exp, HOST_WIDE
   if (offset)
     {
       /* Avoid returning a negative bitpos as this may wreak havoc later.  */
-      if (bit_offset.is_negative ())
+      if (bit_offset.is_negative () || !bit_offset.fits_shwi ())
         {
          double_int mask
            = double_int::mask (BITS_PER_UNIT == 8
--- gcc/testsuite/gcc.c-torture/compile/pr65680.c       (revision 0)
+++ gcc/testsuite/gcc.c-torture/compile/pr65680.c       (revision 221899)
@@ -0,0 +1,20 @@
+/* PR middle-end/65680 */
+/* { dg-do compile { target lp64 } } */
+
+struct S
+{
+  int f : 1;
+} a[100000000000000001][3];
+
+void
+foo (void)
+{
+  struct S b = { 0 };
+  a[100000000000000000][0] = b;
+}
+
+void
+bar (void)
+{
+  a[100000000000000000][0].f = 1;
+}
2015-06-03  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2015-05-13  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/66133
        * omp-low.c (expand_omp_taskreg): For GIMPLE_OMP_TASK expansion,
        make sure it is never noreturn, even when the task body does not
        return.
        (lower_omp_taskreg): For GIMPLE_OMP_TASK, emit GIMPLE_OMP_CONTINUE
        right before GIMPLE_OMP_RETURN.
        * tree-cfg.c (make_edges): Accept GIMPLE_OMP_CONTINUE as ->cont
        for GIMPLE_OMP_TASK.  For GIMPLE_OMP_RETURN corresponding to
        GIMPLE_OMP_TASK add an EDGE_ABNORMAL edge from entry to exit.

        * testsuite/libgomp.c/pr66133.c: New test.

--- gcc/omp-low.c       (revision 223519)
+++ gcc/omp-low.c       (revision 223520)
@@ -3487,7 +3487,10 @@ expand_omp_taskreg (struct omp_region *r
   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
 
   entry_bb = region->entry;
-  exit_bb = region->exit;
+  if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
+    exit_bb = region->cont;
+  else
+    exit_bb = region->exit;
 
   if (is_combined_parallel (region))
     ws_args = region->ws_args;
@@ -3536,7 +3539,9 @@ expand_omp_taskreg (struct omp_region *r
         variable.  In which case, we need to keep the assignment.  */
       if (gimple_omp_taskreg_data_arg (entry_stmt))
        {
-         basic_block entry_succ_bb = single_succ (entry_bb);
+         basic_block entry_succ_bb
+           = single_succ_p (entry_bb) ? single_succ (entry_bb)
+                                      : FALLTHRU_EDGE (entry_bb)->dest;
          gimple_stmt_iterator gsi;
          tree arg, narg;
          gimple parcopy_stmt = NULL;
@@ -3625,14 +3630,28 @@ expand_omp_taskreg (struct omp_region *r
       gsi_remove (&gsi, true);
       e = split_block (entry_bb, stmt);
       entry_bb = e->dest;
-      single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+      edge e2 = NULL;
+      if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
+       single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
+      else
+       {
+         e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
+         gcc_assert (e2->dest == region->exit);
+         remove_edge (BRANCH_EDGE (entry_bb));
+         set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
+         gsi = gsi_last_bb (region->exit);
+         gcc_assert (!gsi_end_p (gsi)
+                     && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
+         gsi_remove (&gsi, true);
+       }
 
-      /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR.  */
+      /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR.  */
       if (exit_bb)
        {
          gsi = gsi_last_bb (exit_bb);
          gcc_assert (!gsi_end_p (gsi)
-                     && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
+                     && (gimple_code (gsi_stmt (gsi))
+                         == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
          stmt = gimple_build_return (NULL);
          gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
          gsi_remove (&gsi, true);
@@ -3653,6 +3672,14 @@ expand_omp_taskreg (struct omp_region *r
       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
       if (exit_bb)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+      if (e2)
+       {
+         basic_block dest_bb = e2->dest;
+         if (!exit_bb)
+           make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
+         remove_edge (e2);
+         set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
+       }
 
       /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
       num = vec_safe_length (child_cfun->local_decls);
@@ -7020,6 +7047,10 @@ lower_omp_taskreg (gimple_stmt_iterator
   gimple_seq_add_seq (&new_body, par_body);
   gimple_seq_add_seq (&new_body, par_olist);
   new_body = maybe_catch_exception (new_body);
+  if (gimple_code (stmt) == GIMPLE_OMP_TASK)
+    gimple_seq_add_stmt (&new_body,
+                        gimple_build_omp_continue (integer_zero_node,
+                                                   integer_zero_node));
   gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
   gimple_omp_set_body (stmt, new_body);
 
--- gcc/tree-cfg.c.jj   2014-02-20 21:39:14.000000000 +0100
+++ gcc/tree-cfg.c      2015-06-03 18:59:25.681769246 +0200
@@ -589,6 +589,10 @@ make_edges (void)
                 somewhere other than the next block.  This will be
                 created later.  */
              cur_region->exit = bb;
+             if (cur_region->type == GIMPLE_OMP_TASK)
+               /* Add an edge corresponding to not scheduling the task
+                  immediately.  */
+               make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
              fallthru = cur_region->type != GIMPLE_OMP_SECTION;
              cur_region = cur_region->outer;
              break;
@@ -637,6 +641,10 @@ make_edges (void)
                  }
                  break;
 
+               case GIMPLE_OMP_TASK:
+                 fallthru = true;
+                 break;
+
                default:
                  gcc_unreachable ();
                }
--- libgomp/testsuite/libgomp.c/pr66133.c       (revision 0)
+++ libgomp/testsuite/libgomp.c/pr66133.c       (revision 223520)
@@ -0,0 +1,35 @@
+/* PR middle-end/66133 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp" } */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+volatile int x;
+
+__attribute__((noinline)) void
+foo (void)
+{
+  if (x == 0)
+    {
+      #pragma omp task
+       {
+         usleep (2000);
+         exit (0);
+       }
+    }
+  else
+    abort ();
+}
+
+int
+main ()
+{
+  #pragma omp parallel num_threads (2)
+    {
+      #pragma omp barrier
+      #pragma omp single
+       foo ();
+    }
+  exit (0);
+}

Reply via email to