On Wed, 13 Mar 2019, Richard Biener wrote:

> On Wed, 13 Mar 2019, Bin.Cheng wrote:
> 
> > On Wed, Mar 13, 2019 at 3:58 AM Richard Biener <rguent...@suse.de> wrote:
> > >
> > >
> > > This makes an attempt at fixing the most annoying parts of the GIMPLE
> > > FE unit testing - the lack of proper CFG preservation and hoops you
> > > need to jump through to make the CFG and SSA builders happy.
> > >
> > > Due to this the __GIMPLE specifiers takes two new flags, "cfg"
> > > for GIMPLE-with-a-CFG and "ssa" for GIMPLE-with-a-CFG-and-SSA.
> > > When there is a CFG you need to start basic-block boundaries with
> > >
> > > __BB(index):
> > >
> > > where 'index' is the basic-block index.  That implicitely defines
> > > a label __BBindex for use in goto stmts and friends (but doesn't
> > > actually add a GIMPLE_LABEL).
> > >
> > > The parsing code isn't defensive right now so you need to watch
> > > out to not use index 0 or 1 (entry and exit block) which are
> > > only implicitely present.
> > >
> > > As a proof of concept I added one BB annotation - loop_header(num)
> > > where "num" is the loop number.  This means you can now also
> > > have loop structures preserved (to some extent - the loop tree is
> > > not explicitely represented nor are loop fathers, both are re-built
> > > via fixup).
> > >
> > > I've not yet adjusted -gimple dumping.
> > >
> > > I've adjusted all testcases I could find.
> > >
> > > The CFG build inside the frontend is a bit awkward (spread out...),
> > > likewise some functionality is asking for split-out.
> > >
> > > This is mainly a RFC for whether you think this is forward looking
> > > enough.  Future enhancements would include EH and abnormal edges
> > > via stmt annotations:
> > Thanks very much for doing this.  Do we have a centralized
> > wiki/document on the formal definition?  It would be very helpful even
> > it's still evolving, otherwise we would need to dig into messages for
> > fragmented clues.
> 
> Earlier this week I transformed the old 
> https://gcc.gnu.org/wiki/GimpleFrontEnd page into one documenting
> the current state but this doesn't yet include any kind of documentation.
> 
> I suppose special syntax documentation should go into our texinfo
> docs, I guess into a new section in the internals manual.  Currently
> we only have documentation for the -fgimple switch.
> 
> Note that I view -gimple dumping as the thing that should give you
> a clue about expected syntax.  I hope to spend a little more time
> on the patch to make it ready for GCC9.

I've settled on another change, forcing explicit gotos for fallthru
edges to the next block.

Otherwise I've cleaned up the patch and removed no longer necessary
support for IFN_PHI from the middle-end.  During cleanup I introduced
a gimple_parser class to hold the extra parsing state and I added
some extra error handling.

Bootstrapped on x86_64-unknown-linux-gnu, testing is still in progress.

I will commit this to make testcase extraction to GIMPLE more feasible
for GCC 9+ (we could even backport the GIMPLE FE changes to GCC 8 if 
needed I guess).  At least it will give me motivation to do further
required changes when I run into the next big LTO testcase running
into a loop optimizer issue... (non-loop passes should work fine
already).

Richard.

>From 5cbec540caa8e86f2167ac980159dbe6933717c4 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguent...@suse.de>
Date: Wed, 13 Mar 2019 13:58:10 +0100
Subject: [PATCH] gimplefe-cfg-ssa

2019-03-12  Richard Biener  <rguent...@suse.de>

        c/
        * c-tree.h (enum c_declspec_il): New.
        (struct c_declspecs): Merge gimple_p and rtl_p into declspec_il
        enum bitfield.
        * c-parser.c (c_parser_declaration_or_fndef): Adjust accordingly.
        Pass start pass and declspec_il to c_parser_parse_gimple_body.
        (c_parser_declspecs): Adjust.
        * gimple-parser.c: Include cfg.h, cfghooks.h, cfganal.h, tree-cfg.h,
        gimple-iterator.h, cfgloop.h, tree-phinodes.h, tree-into-ssa.h
        and bitmap.h.
        (struct gimple_parser): New.
        (gimple_parser::push_edge): New method.
        (c_parser_gimple_parse_bb_spec): New helper.
        (c_parser_parse_gimple_body): Get start pass and IL specification.
        Initialize SSA and CFG.
        (c_parser_gimple_compound_statement): Handle CFG and SSA build.
        Build a gimple_parser parsing state and pass it along.
        (c_parser_gimple_statement): Change intermittend __PHI internal
        function argument for the edge.
        (c_parser_gimple_or_rtl_pass_list): Handle ssa, cfg flags.
        (c_parser_gimple_goto_stmt): Record edges to build.
        (c_parser_gimple_if_stmt): Likewise.
        * gimple-parser.h (c_parser_parse_gimple_body): Adjust.
        (c_parser_gimple_or_rtl_pass_list): Likewise.
        * gimple-pretty-print.c: Include cfgloop.h.
        (dump_gimple_phi): Adjust.
        (dump_gimple_bb_header): Dump loop header for GIMPLE.
        (pp_cfg_jump): Adjust.
        (dump_implicit_edges): Dump fallthru to next block for GIMPLE as well.
        * tree-cfg.c (build_gimple_cfg): Remove lower_phi_internal_fn call.
        (lower_phi_internal_fn): Remove.
        (verify_gimple_call): Remove IFN_PHI special-casing.
        (dump_function_to_file): Dump IL state.
        * tree-into-ssa.c (rewrite_add_phi_arguments): Revert changes
        done to deal with PHI nodes being present in non-SSA state.

        * gcc.dg/gimplefe-13.c: Adjust.
        * gcc.dg/gimplefe-14.c: Likewise.
        * gcc.dg/gimplefe-17.c: Likewise.
        * gcc.dg/gimplefe-18.c: Likewise.
        * gcc.dg/gimplefe-7.c: Likewise.
        * gcc.dg/torture/pr89595.c: Likewise.
        * gcc.dg/tree-ssa/cunroll-13.c: Likewise.
        * gcc.dg/tree-ssa/ivopt_mult_1g.c: Likewise.
        * gcc.dg/tree-ssa/ivopt_mult_2g.c: Likewise.
        * gcc.dg/tree-ssa/scev-3.c: Likewise.
        * gcc.dg/tree-ssa/scev-4.c: Likewise.
        * gcc.dg/tree-ssa/scev-5.c: Likewise.
        * gcc.dg/vect/vect-cond-arith-2.c: Likewise.
        * gcc.target/aarch64/sve/loop_add_6.c: Likewise.

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5134e95a921..741d172ff30 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2324,19 +2324,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
 
-      /* If the definition was marked with __GIMPLE then parse the
-         function body as GIMPLE.  */
-      if (specs->gimple_p)
-       {
-         cfun->pass_startwith = specs->gimple_or_rtl_pass;
-         bool saved = in_late_binary_op;
-         in_late_binary_op = true;
-         c_parser_parse_gimple_body (parser);
-         in_late_binary_op = saved;
-       }
-      /* Similarly, if it was marked with __RTL, use the RTL parser now,
+      /* If the definition was marked with __RTL, use the RTL parser now,
         consuming the function body.  */
-      else if (specs->rtl_p)
+      if (specs->declspec_il == cdil_rtl)
        {
          c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
 
@@ -2350,6 +2340,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
          finish_function ();
          return;
        }
+      /* If the definition was marked with __GIMPLE then parse the
+         function body as GIMPLE.  */
+      else if (specs->declspec_il != cdil_none)
+       {
+         bool saved = in_late_binary_op;
+         in_late_binary_op = true;
+         c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
+                                     specs->declspec_il);
+         in_late_binary_op = saved;
+       }
       else
        fnbody = c_parser_compound_statement (parser);
       tree fndecl = current_function_decl;
@@ -2372,8 +2372,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
            add_stmt (fnbody);
          finish_function ();
        }
-      /* Get rid of the empty stmt list for GIMPLE.  */
-      if (specs->gimple_p)
+      /* Get rid of the empty stmt list for GIMPLE/RTL.  */
+      if (specs->declspec_il != cdil_none)
        DECL_SAVED_TREE (fndecl) = NULL_TREE;
 
       break;
@@ -2882,15 +2882,15 @@ c_parser_declspecs (c_parser *parser, struct 
c_declspecs *specs,
          if (! flag_gimple)
            error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
          c_parser_consume_token (parser);
-         specs->gimple_p = true;
+         specs->declspec_il = cdil_gimple;
          specs->locations[cdw_gimple] = loc;
-         specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+         c_parser_gimple_or_rtl_pass_list (parser, specs);
          break;
        case RID_RTL:
          c_parser_consume_token (parser);
-         specs->rtl_p = true;
+         specs->declspec_il = cdil_rtl;
          specs->locations[cdw_rtl] = loc;
-         specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+         c_parser_gimple_or_rtl_pass_list (parser, specs);
          break;
        default:
          goto out;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index b69ef3377fd..d6e345afb37 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -288,6 +288,14 @@ enum c_declspec_word {
                            enumerator.  */
 };
 
+enum c_declspec_il {
+  cdil_none,
+  cdil_gimple,         /* __GIMPLE  */
+  cdil_gimple_cfg,     /* __GIMPLE(cfg)  */
+  cdil_gimple_ssa,     /* __GIMPLE(ssa)  */
+  cdil_rtl             /* __RTL  */
+};
+
 /* A sequence of declaration specifiers in C.  When a new declaration
    specifier is added, please update the enum c_declspec_word above
    accordingly.  */
@@ -326,6 +334,7 @@ struct c_declspecs {
   /* The kind of type specifier if one has been seen, ctsk_none
      otherwise.  */
   ENUM_BITFIELD (c_typespec_kind) typespec_kind : 3;
+  ENUM_BITFIELD (c_declspec_il) declspec_il : 3;
   /* Whether any expressions in typeof specifiers may appear in
      constant expressions.  */
   BOOL_BITFIELD expr_const_operands : 1;
@@ -381,10 +390,6 @@ struct c_declspecs {
   /* Whether any alignment specifier (even with zero alignment) was
      specified.  */
   BOOL_BITFIELD alignas_p : 1;
-  /* Whether any __GIMPLE specifier was specified.  */
-  BOOL_BITFIELD gimple_p : 1;
-  /* Whether any __RTL specifier was specified.  */
-  BOOL_BITFIELD rtl_p : 1;
   /* The address space that the declaration belongs to.  */
   addr_space_t address_space;
 };
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index c67b96641eb..5aa906c0b7e 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -54,45 +54,133 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-ssa.h"
 #include "tree-dfa.h"
 #include "internal-fn.h"
+#include "cfg.h"
+#include "cfghooks.h"
+#include "cfganal.h"
+#include "tree-cfg.h"
+#include "gimple-iterator.h"
+#include "cfgloop.h"
+#include "tree-phinodes.h"
+#include "tree-into-ssa.h"
+#include "bitmap.h"
+
+
+/* GIMPLE parser state.  */
+
+struct gimple_parser
+{
+  gimple_parser (c_parser *p) : parser (p), edges(), current_bb(NULL) {}
+  /* c_parser is not visible here, use composition and fake inheritance
+     via a conversion operator.  */
+  operator c_parser *() { return parser; }
+  c_parser *parser;
+
+  /* CFG build state.  */
+  struct gimple_parser_edge
+  {
+    int src;
+    int dest;
+    int flags;
+  };
+  auto_vec<gimple_parser_edge> edges;
+  basic_block current_bb;
+
+  void push_edge (int, int, int);
+};
+
+void
+gimple_parser::push_edge (int src, int dest, int flags)
+{
+  gimple_parser_edge e;
+  e.src = src;
+  e.dest = dest;
+  e.flags = flags;
+  edges.safe_push (e);
+}
 
 
 /* Gimple parsing functions.  */
-static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
-static void c_parser_gimple_label (c_parser *, gimple_seq *);
-static void c_parser_gimple_statement (c_parser *, gimple_seq *);
-static struct c_expr c_parser_gimple_binary_expression (c_parser *);
-static struct c_expr c_parser_gimple_unary_expression (c_parser *);
-static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
-static struct c_expr c_parser_gimple_postfix_expression_after_primary 
(c_parser *,
-                                                                      
location_t,
-                                                                      struct 
c_expr);
-static void c_parser_gimple_declaration (c_parser *);
-static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
-static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
-static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
-static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
+static bool c_parser_gimple_compound_statement (gimple_parser &, gimple_seq *);
+static void c_parser_gimple_label (gimple_parser &, gimple_seq *);
+static void c_parser_gimple_statement (gimple_parser &, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (gimple_parser &);
+static struct c_expr c_parser_gimple_unary_expression (gimple_parser &);
+static struct c_expr c_parser_gimple_postfix_expression (gimple_parser &);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary
+                       (gimple_parser &, location_t, struct c_expr);
+static void c_parser_gimple_declaration (gimple_parser &);
+static void c_parser_gimple_goto_stmt (gimple_parser &, location_t,
+                                      tree, gimple_seq *);
+static void c_parser_gimple_if_stmt (gimple_parser &, gimple_seq *);
+static void c_parser_gimple_switch_stmt (gimple_parser &, gimple_seq *);
+static void c_parser_gimple_return_stmt (gimple_parser &, gimple_seq *);
 static void c_finish_gimple_return (location_t, tree);
-static tree c_parser_gimple_paren_condition (c_parser *);
-static void c_parser_gimple_expr_list (c_parser *, vec<tree> *);
+static tree c_parser_gimple_paren_condition (gimple_parser &);
+static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
 
 
+/* See if VAL is an identifier matching __BB<num> and return <num>
+   in *INDEX.  Return true if so.  */
+
+static bool
+c_parser_gimple_parse_bb_spec (tree val, int *index)
+{
+  if (strncmp (IDENTIFIER_POINTER (val), "__BB", 4) != 0)
+    return false;
+  for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p)
+    if (!ISDIGIT (*p))
+      return false;
+  *index = atoi (IDENTIFIER_POINTER (val) + 4);
+  return *index > 0;
+}
+
 /* Parse the body of a function declaration marked with "__GIMPLE".  */
 
 void
-c_parser_parse_gimple_body (c_parser *parser)
+c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
+                           enum c_declspec_il cdil)
 {
+  gimple_parser parser (cparser);
   gimple_seq seq = NULL;
   gimple_seq body = NULL;
   tree stmt = push_stmt_list ();
   push_scope ();
   location_t loc1 = c_parser_peek_token (parser)->location;
 
+  cfun->pass_startwith = gimple_pass;
   init_tree_ssa (cfun);
 
-  if (! c_parser_gimple_compound_statement (parser, &seq))
+  if (cdil == cdil_gimple)
+    /* While we have SSA names in the IL we do not have a CFG built yet
+       and PHIs are represented using a PHI internal function.  We do
+       have lowered control flow and exception handling (well, we do not
+       have parser support for EH yet).  But as we still have BINDs
+       we have to go through lowering again.  */
+    cfun->curr_properties = PROP_gimple_any;
+  else
+    {
+      /* We have at least cdil_gimple_cfg.  */
+      gimple_register_cfg_hooks ();
+      init_empty_tree_cfg ();
+      /* Initialize the bare loop structure - we are going to only
+         mark headers and leave the rest to fixup.  */
+      set_loops_for_fn (cfun, ggc_cleared_alloc<struct loops> ());
+      init_loops_structure (cfun, loops_for_fn (cfun), 1);
+      loops_state_set (cfun, LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
+      cfun->curr_properties
+       |= PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_loops;
+      if (cdil == cdil_gimple_ssa)
+       {
+         init_ssa_operands (cfun);
+         cfun->curr_properties |= PROP_ssa;
+       }
+    }
+
+  if (! c_parser_gimple_compound_statement (parser, &seq)
+      && cdil == cdil_gimple)
     {
       gimple *ret = gimple_build_return (NULL);
-      gimple_seq_add_stmt (&seq, ret);
+      gimple_seq_add_stmt_without_update (&seq, ret);
     }
 
   tree block = pop_scope ();
@@ -104,18 +192,87 @@ c_parser_parse_gimple_body (c_parser *parser)
   BLOCK_CHAIN (block) = NULL_TREE;
   TREE_ASM_WRITTEN (block) = 1;
 
-  gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
-                                       BIND_EXPR_BLOCK (stmt));
-  gimple_bind_set_body (bind_stmt, seq);
-  gimple_seq_add_stmt (&body, bind_stmt);
-  gimple_set_body (current_function_decl, body);
+  if (cdil == cdil_gimple)
+    {
+      gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+                                           BIND_EXPR_BLOCK (stmt));
+      gimple_bind_set_body (bind_stmt, seq);
+      gimple_seq_add_stmt_without_update (&body, bind_stmt);
+      gimple_set_body (current_function_decl, body);
+    }
+  else
+    {
+      /* Control-flow and binds are lowered, record local decls.  */
+      for (tree var = BIND_EXPR_VARS (stmt); var; var = DECL_CHAIN (var))
+       if (VAR_P (var)
+           && !DECL_EXTERNAL (var))
+         add_local_decl (cfun, var);
+      /* We have a CFG.  Build the edges.  */
+      for (unsigned i = 0; i < parser.edges.length (); ++i)
+       make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
+                  BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
+                  parser.edges[i].flags);
+      /* Add edges for case labels.  */
+      basic_block bb;
+      FOR_EACH_BB_FN (bb, cfun)
+       if (EDGE_COUNT (bb->succs) == 0)
+         {
+           gimple *last = last_stmt (bb);
+           if (gswitch *sw = safe_dyn_cast <gswitch *> (last))
+             for (unsigned i = 0; i < gimple_switch_num_labels (sw); ++i)
+               {
+                 basic_block label_bb = gimple_switch_label_bb (cfun, sw, i);
+                 make_edge (bb, label_bb, 0);
+               }
+         }
+      /* Need those for loop fixup.  */
+      calculate_dominance_info (CDI_DOMINATORS);
+      /* With SSA lower PHIs parsed as internal function calls and
+        update stmts.  */
+      if (cdil == cdil_gimple_ssa)
+       {
+         /* Create PHI nodes, they are parsed into __PHI internal calls.  */
+         FOR_EACH_BB_FN (bb, cfun)
+           for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+                !gsi_end_p (gsi);)
+             {
+               gimple *stmt = gsi_stmt (gsi);
+               if (!gimple_call_internal_p (stmt, IFN_PHI))
+                 break;
 
-  /* While we have SSA names in the IL we do not have a CFG built yet
-     and PHIs are represented using a PHI internal function.  We do
-     have lowered control flow and exception handling (well, we do not
-     have parser support for EH yet).  But as we still have BINDs
-     we have to go through lowering again.  */
-  cfun->curr_properties = PROP_gimple_any;
+               gphi *phi = create_phi_node (gimple_call_lhs (stmt), bb);
+               for (unsigned i = 0; i < gimple_call_num_args (stmt); i += 2)
+                 {
+                   int srcidx = TREE_INT_CST_LOW (gimple_call_arg (stmt, i));
+                   edge e = find_edge (BASIC_BLOCK_FOR_FN (cfun, srcidx), bb);
+                   if (!e)
+                     c_parser_error (parser, "edge not found");
+                   else
+                     add_phi_arg (phi, gimple_call_arg (stmt, i + 1), e,
+                                  UNKNOWN_LOCATION);
+                 }
+               gsi_remove (&gsi, false);
+             }
+         /* Fill SSA name gaps, putting them on the freelist.  */
+         for (unsigned i = 0; i < num_ssa_names; ++i)
+           if (!ssa_name (i))
+             {
+               tree name = make_ssa_name_fn (cfun, integer_type_node, NULL, i);
+               release_ssa_name_fn (cfun, name);
+             }
+         /* No explicit virtual operands (yet).  */
+         bitmap_obstack_initialize (NULL);
+         update_ssa (TODO_update_ssa_only_virtuals);
+         bitmap_obstack_release (NULL);
+         /* ???  By flushing the freelist after virtual operand SSA rewrite
+            we keep the gaps available for re-use like needed for the
+            PR89595 testcase but then usually virtual operands would have
+            taken most of them.  The fix is obviously to make virtual
+            operands explicit in the SSA IL.  */
+         flush_ssaname_freelist ();
+       }
+      fix_loop_structure (NULL);
+    }
 
   dump_function (TDI_gimple, current_function_decl);
 }
@@ -135,7 +292,7 @@ c_parser_parse_gimple_body (c_parser *parser)
 */
 
 static bool
-c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
 {
   bool return_p = false;
 
@@ -180,7 +337,7 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
                c_parser_consume_token (parser);
                if (c_parser_next_token_is (parser, CPP_NAME))
                  {
-                   c_parser_gimple_goto_stmt (loc,
+                   c_parser_gimple_goto_stmt (parser, loc,
                                               c_parser_peek_token
                                               (parser)->value,
                                               seq);
@@ -197,6 +354,8 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
              if (! c_parser_require (parser, CPP_SEMICOLON,
                                      "expected %<;%>"))
                return return_p;
+             if (cfun->curr_properties & PROP_cfg)
+               parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0);
              break;
            default:
              goto expr_stmt;
@@ -208,6 +367,142 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
              c_parser_gimple_label (parser, seq);
              break;
            }
+         /* Basic block specification.
+            __BB (index, ...)  */
+         if ((cfun->curr_properties & PROP_cfg)
+             && !strcmp (IDENTIFIER_POINTER
+                           (c_parser_peek_token (parser)->value), "__BB"))
+           {
+             c_parser_consume_token (parser);
+             if (! c_parser_require (parser, CPP_OPEN_PAREN,
+                                     "expected %<(%>"))
+               return return_p;
+             if (c_parser_next_token_is_not (parser, CPP_NUMBER))
+               {
+                 c_parser_error (parser, "expected block index");
+                 return return_p;
+               }
+             tree tnum = c_parser_peek_token (parser)->value;
+             if (TREE_CODE (tnum) != INTEGER_CST)
+               {
+                 c_parser_error (parser, "expected block index");
+                 return return_p;
+               }
+             int index = TREE_INT_CST_LOW (tnum);
+             if (index < NUM_FIXED_BLOCKS
+                 || (index < last_basic_block_for_fn (cfun)
+                     && BASIC_BLOCK_FOR_FN (cfun, index) != NULL))
+               {
+                 c_parser_error (parser, "invalid block index");
+                 return return_p;
+               }
+             int is_loop_header_of = -1;
+             c_parser_consume_token (parser);
+             while (c_parser_next_token_is (parser, CPP_COMMA))
+               {
+                 c_parser_consume_token (parser);
+                 if (! c_parser_next_token_is (parser, CPP_NAME))
+                   {
+                     c_parser_error (parser, "expected block specifier");
+                     return return_p;
+                   }
+                 /* loop_header (NUM)  */
+                 if (!strcmp (IDENTIFIER_POINTER
+                                (c_parser_peek_token (parser)->value),
+                              "loop_header"))
+                   {
+                     c_parser_consume_token (parser);
+                     if (! c_parser_require (parser, CPP_OPEN_PAREN,
+                                             "expected %<(%>"))
+                       return return_p;
+                     tree loop_num;
+                     if (! c_parser_next_token_is (parser, CPP_NUMBER)
+                         || TREE_CODE (loop_num
+                                         = c_parser_peek_token (parser)->value)
+                              != INTEGER_CST)
+                       {
+                         c_parser_error (parser, "expected loop number");
+                         return return_p;
+                       }
+                     c_parser_consume_token (parser);
+                     is_loop_header_of = TREE_INT_CST_LOW (loop_num);
+                     if (! c_parser_require (parser, CPP_CLOSE_PAREN,
+                                             "expected %<)%>"))
+                       return return_p;
+                   }
+                 else
+                   {
+                     c_parser_error (parser, "unknown block specifier");
+                     return return_p;
+                   }
+               }
+             if (! c_parser_require (parser, CPP_CLOSE_PAREN,
+                                     "expected %<)%>")
+                 || ! c_parser_require (parser, CPP_COLON,
+                                        "expected %<:%>"))
+               return return_p;
+
+             /* Put stmts parsed in the current block.  */
+             if (!gimple_seq_empty_p (*seq))
+               {
+                 if (!parser.current_bb)
+                   c_parser_error (parser, "stmts without block");
+                 else
+                   {
+                     gimple_stmt_iterator gsi
+                       = gsi_start_bb (parser.current_bb);
+                     gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING);
+                   }
+                 *seq = NULL;
+               }
+
+             /* Build an empty block with specified index, linking them
+                in source order.  */
+             basic_block bb = alloc_block ();
+             bb->index = index;
+             link_block (bb, (parser.current_bb ? parser.current_bb
+                              : ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+             if (basic_block_info_for_fn (cfun)->length () <= (size_t)index)
+               vec_safe_grow_cleared (basic_block_info_for_fn (cfun),
+                                      index + 1);
+             SET_BASIC_BLOCK_FOR_FN (cfun, index, bb);
+             if (last_basic_block_for_fn (cfun) <= index)
+               last_basic_block_for_fn (cfun) = index + 1;
+             n_basic_blocks_for_fn (cfun)++;
+             if (!parser.current_bb)
+               parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU);
+
+             /* We leave the proper setting to fixup.  */
+             struct loop *loop_father = loops_for_fn (cfun)->tree_root;
+             /* If the new block is a loop header, allocate a loop
+                struct.  Fixup will take care of proper placement within
+                the loop tree.  */
+             if (is_loop_header_of != -1)
+               {
+                 if (number_of_loops (cfun) > (unsigned)is_loop_header_of
+                     && get_loop (cfun, is_loop_header_of) != NULL)
+                   {
+                     c_parser_error (parser, "duplicate loop header");
+                   }
+                 else
+                   {
+                     struct loop *loop = alloc_loop ();
+                     loop->num = is_loop_header_of;
+                     loop->header = bb;
+                     vec_safe_grow_cleared (loops_for_fn (cfun)->larray,
+                                            is_loop_header_of + 1);
+                     (*loops_for_fn (cfun)->larray)[is_loop_header_of] = loop;
+                     flow_loop_tree_node_add (loops_for_fn (cfun)->tree_root,
+                                              loop);
+                   }
+                 loop_father = get_loop (cfun, is_loop_header_of);
+               }
+             bb->loop_father = loop_father;
+
+             /* Stmts now go to the new block.  */
+             parser.current_bb = bb;
+             break;
+           }
          goto expr_stmt;
 
        case CPP_SEMICOLON:
@@ -217,7 +512,7 @@ c_parser_gimple_compound_statement (c_parser *parser, 
gimple_seq *seq)
            c_parser_consume_token (parser);
            gimple *nop = gimple_build_nop ();
            gimple_set_location (nop, loc);
-           gimple_seq_add_stmt (seq, nop);
+           gimple_seq_add_stmt_without_update (seq, nop);
            break;
          }
 
@@ -229,6 +524,21 @@ expr_stmt:
        }
     }
   c_parser_consume_token (parser);
+
+  /* Put stmts parsed in the current block.  */
+  if ((cfun->curr_properties & PROP_cfg)
+      && !gimple_seq_empty_p (*seq))
+    {
+      if (!parser.current_bb)
+       c_parser_error (parser, "stmts without block");
+      else
+       {
+         gimple_stmt_iterator gsi = gsi_start_bb (parser.current_bb);
+         gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING);
+       }
+      *seq = NULL;
+    }
+
   return return_p;
 }
 
@@ -260,7 +570,7 @@ expr_stmt:
 */
 
 static void
-c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq)
 {
   struct c_expr lhs, rhs;
   gimple *assign = NULL;
@@ -278,7 +588,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
     {
       gimple *call;
       call = gimple_build_call_from_tree (lhs.value, NULL);
-      gimple_seq_add_stmt (seq, call);
+      gimple_seq_add_stmt_without_update (seq, call);
       gimple_set_location (call, loc);
       return;
     }
@@ -316,7 +626,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
                   && FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
            code = FIX_TRUNC_EXPR;
          assign = gimple_build_assign (lhs.value, code, rhs.value);
-         gimple_seq_add_stmt (seq, assign);
+         gimple_seq_add_stmt_without_update (seq, assign);
          gimple_set_location (assign, loc);
          return;
        }
@@ -350,7 +660,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
        {
          assign = gimple_build_assign (lhs.value, rhs.value);
          gimple_set_location (assign, loc);
-         gimple_seq_add_stmt (seq, assign);
+         gimple_seq_add_stmt_without_update (seq, assign);
        }
       return;
 
@@ -373,13 +683,14 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
          if (c_parser_next_token_is (parser, CPP_NAME)
              && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
            {
-             arg = lookup_label_for_goto (loc,
-                                          c_parser_peek_token (parser)->value);
+             arg = c_parser_peek_token (parser)->value;
              c_parser_consume_token (parser);
-
              if (c_parser_next_token_is (parser, CPP_COLON))
                c_parser_consume_token (parser);
-             vargs.safe_push (arg);
+             int src_index = -1;
+             if (!c_parser_gimple_parse_bb_spec (arg, &src_index))
+               c_parser_error (parser, "invalid source block specification");
+             vargs.safe_push (size_int (src_index));
            }
          else if (c_parser_next_token_is (parser, CPP_COMMA))
            c_parser_consume_token (parser);
@@ -397,7 +708,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
       gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
       gimple_call_set_lhs (call_stmt, lhs.value);
       gimple_set_location (call_stmt, UNKNOWN_LOCATION);
-      gimple_seq_add_stmt (seq, call_stmt);
+      gimple_seq_add_stmt_without_update (seq, call_stmt);
       return;
     }
 
@@ -412,7 +723,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
        {
          gimple *call = gimple_build_call_from_tree (rhs.value, NULL);
          gimple_call_set_lhs (call, lhs.value);
-         gimple_seq_add_stmt (seq, call);
+         gimple_seq_add_stmt_without_update (seq, call);
          gimple_set_location (call, loc);
        }
       return;
@@ -440,7 +751,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
                                  rhs.value, trueval.value, falseval.value);
        }
       assign = gimple_build_assign (lhs.value, rhs.value);
-      gimple_seq_add_stmt (seq, assign);
+      gimple_seq_add_stmt_without_update (seq, assign);
       gimple_set_location (assign, loc);
     }
   return;
@@ -470,7 +781,7 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq 
*seq)
 */
 
 static c_expr
-c_parser_gimple_binary_expression (c_parser *parser)
+c_parser_gimple_binary_expression (gimple_parser &parser)
 {
   /* Location of the binary operator.  */
   struct c_expr ret, lhs, rhs;
@@ -578,7 +889,7 @@ c_parser_gimple_binary_expression (c_parser *parser)
 */
 
 static c_expr
-c_parser_gimple_unary_expression (c_parser *parser)
+c_parser_gimple_unary_expression (gimple_parser &parser)
 {
   struct c_expr ret, op;
   location_t op_loc = c_parser_peek_token (parser)->location;
@@ -687,7 +998,7 @@ c_parser_parse_ssa_name_id (tree id, unsigned *version, 
unsigned *ver_offset)
    TYPE is the type if the SSA name is being declared.  */
 
 static tree 
-c_parser_parse_ssa_name (c_parser *parser,
+c_parser_parse_ssa_name (gimple_parser &parser,
                         tree id, tree type, unsigned version,
                         unsigned ver_offset)
 {
@@ -752,7 +1063,7 @@ c_parser_parse_ssa_name (c_parser *parser,
      . identifier ( gimple-argument-expression-list[opt] )  */
 
 static struct c_expr
-c_parser_gimple_call_internal (c_parser *parser)
+c_parser_gimple_call_internal (gimple_parser &parser)
 {
   struct c_expr expr;
   expr.set_error ();
@@ -812,7 +1123,7 @@ c_parser_gimple_call_internal (c_parser *parser)
 */
 
 static struct c_expr
-c_parser_gimple_postfix_expression (c_parser *parser)
+c_parser_gimple_postfix_expression (gimple_parser &parser)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   source_range tok_range = c_parser_peek_token (parser)->get_range ();
@@ -1102,7 +1413,7 @@ c_parser_gimple_postfix_expression (c_parser *parser)
    literal.  */
 
 static struct c_expr
-c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser,
                                                  location_t expr_loc,
                                                  struct c_expr expr)
 {
@@ -1245,7 +1556,7 @@ c_parser_gimple_postfix_expression_after_primary 
(c_parser *parser,
  */
 
 static void
-c_parser_gimple_expr_list (c_parser *parser, vec<tree> *ret)
+c_parser_gimple_expr_list (gimple_parser &parser, vec<tree> *ret)
 {
   struct c_expr expr;
 
@@ -1269,7 +1580,7 @@ c_parser_gimple_expr_list (c_parser *parser, vec<tree> 
*ret)
 */
 
 static void
-c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_label (gimple_parser &parser, gimple_seq *seq)
 {
   tree name = c_parser_peek_token (parser)->value;
   location_t loc1 = c_parser_peek_token (parser)->location;
@@ -1278,58 +1589,67 @@ c_parser_gimple_label (c_parser *parser, gimple_seq 
*seq)
   gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
   c_parser_consume_token (parser);
   tree label = define_label (loc1, name);
-  gimple_seq_add_stmt (seq, gimple_build_label (label));
+  gimple_seq_add_stmt_without_update (seq, gimple_build_label (label));
   return;
 }
 
 /* Parse gimple/RTL pass list.
 
    gimple-or-rtl-pass-list:
-     startwith("pass-name")
+     startwith("pass-name")[,{cfg,ssa}]
  */
 
-char *
-c_parser_gimple_or_rtl_pass_list (c_parser *parser)
+void
+c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
 {
   char *pass = NULL;
 
   /* Accept __GIMPLE/__RTL.  */
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
-    return NULL;
+    return;
   c_parser_consume_token (parser);
 
-  if (c_parser_next_token_is (parser, CPP_NAME))
+  while (c_parser_next_token_is (parser, CPP_NAME))
     {
       const char *op = IDENTIFIER_POINTER (c_parser_peek_token 
(parser)->value);
       c_parser_consume_token (parser);
       if (! strcmp (op, "startwith"))
        {
          if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
-           return NULL;
+           return;
          if (c_parser_next_token_is_not (parser, CPP_STRING))
            {
              error_at (c_parser_peek_token (parser)->location,
                        "expected pass name");
-             return NULL;
+             return;
            }
          pass = xstrdup (TREE_STRING_POINTER
                                (c_parser_peek_token (parser)->value));
          c_parser_consume_token (parser);
-         if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-           return NULL;
+         if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>"))
+           return;
        }
+      else if (specs->declspec_il != cdil_gimple)
+       /* Allow only one IL specifier and none on RTL.  */
+       ;
+      else if (! strcmp (op, "cfg"))
+       specs->declspec_il = cdil_gimple_cfg;
+      else if (! strcmp (op, "ssa"))
+       specs->declspec_il = cdil_gimple_ssa;
       else
        {
          error_at (c_parser_peek_token (parser)->location,
                    "invalid operation");
-         return NULL;
+         return;
        }
+     if (c_parser_next_token_is (parser, CPP_COMMA))
+       c_parser_consume_token (parser);
     }
 
   if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
-    return NULL;
+    return;
 
-  return pass;
+  specs->gimple_or_rtl_pass = pass;
 }
 
 /* Parse gimple local declaration.
@@ -1371,7 +1691,7 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser)
  */
 
 static void
-c_parser_gimple_declaration (c_parser *parser)
+c_parser_gimple_declaration (gimple_parser &parser)
 {
   struct c_declarator *declarator;
   struct c_declspecs *specs = build_null_declspecs ();
@@ -1431,11 +1751,21 @@ c_parser_gimple_declaration (c_parser *parser)
 /* Parse gimple goto statement.  */
 
 static void
-c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+c_parser_gimple_goto_stmt (gimple_parser &parser,
+                          location_t loc, tree label, gimple_seq *seq)
 {
+  if (cfun->curr_properties & PROP_cfg)
+    {
+      int dest_index;
+      if (c_parser_gimple_parse_bb_spec (label, &dest_index))
+       {
+         parser.push_edge (parser.current_bb->index, dest_index,
+                           EDGE_FALLTHRU);
+         return;
+       }
+    }
   tree decl = lookup_label_for_goto (loc, label);
-  gimple_seq_add_stmt (seq, gimple_build_goto (decl));
-  return;
+  gimple_seq_add_stmt_without_update (seq, gimple_build_goto (decl));
 }
 
 /* Parse a parenthesized condition.
@@ -1443,7 +1773,7 @@ c_parser_gimple_goto_stmt (location_t loc, tree label, 
gimple_seq *seq)
      ( gimple-binary-expression )    */
 
 static tree
-c_parser_gimple_paren_condition (c_parser *parser)
+c_parser_gimple_paren_condition (gimple_parser &parser)
 {
   if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
     return error_mark_node;
@@ -1462,9 +1792,9 @@ c_parser_gimple_paren_condition (c_parser *parser)
  */
 
 static void
-c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
 {
-  tree t_label, f_label, label;
+  tree t_label = NULL_TREE, f_label = NULL_TREE, label;
   location_t loc;
   c_parser_consume_token (parser);
   tree cond = c_parser_gimple_paren_condition (parser);
@@ -1480,7 +1810,13 @@ c_parser_gimple_if_stmt (c_parser *parser, gimple_seq 
*seq)
        }
       label = c_parser_peek_token (parser)->value;
       c_parser_consume_token (parser);
-      t_label = lookup_label_for_goto (loc, label);
+      int dest_index;
+      if ((cfun->curr_properties & PROP_cfg)
+         && c_parser_gimple_parse_bb_spec (label, &dest_index))
+       parser.push_edge (parser.current_bb->index, dest_index,
+                         EDGE_TRUE_VALUE);
+      else
+       t_label = lookup_label_for_goto (loc, label);
       if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
        return;
     }
@@ -1508,7 +1844,13 @@ c_parser_gimple_if_stmt (c_parser *parser, gimple_seq 
*seq)
          return;
        }
       label = c_parser_peek_token (parser)->value;
-      f_label = lookup_label_for_goto (loc, label);
+      int dest_index;
+      if ((cfun->curr_properties & PROP_cfg)
+         && c_parser_gimple_parse_bb_spec (label, &dest_index))
+       parser.push_edge (parser.current_bb->index, dest_index,
+                         EDGE_FALSE_VALUE);
+      else
+       f_label = lookup_label_for_goto (loc, label);
       c_parser_consume_token (parser);
       if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
        return;
@@ -1520,7 +1862,7 @@ c_parser_gimple_if_stmt (c_parser *parser, gimple_seq 
*seq)
     }
 
   if (cond != error_mark_node)
-    gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+    gimple_seq_add_stmt_without_update (seq, gimple_build_cond_from_tree 
(cond, t_label,
                                                           f_label));
 }
 
@@ -1535,13 +1877,12 @@ c_parser_gimple_if_stmt (c_parser *parser, gimple_seq 
*seq)
 */
 
 static void
-c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_switch_stmt (gimple_parser &parser, gimple_seq *seq)
 {
   c_expr cond_expr;
   tree case_label, label;
   auto_vec<tree> labels;
   tree default_label = NULL_TREE;
-  gimple_seq switch_body = NULL;
   c_parser_consume_token (parser);
 
   if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -1629,32 +1970,8 @@ c_parser_gimple_switch_stmt (c_parser *parser, 
gimple_seq *seq)
              return;
            break;
          }
-       case RID_GOTO:
-         {
-           location_t loc = c_parser_peek_token (parser)->location;
-           c_parser_consume_token (parser);
-           if (c_parser_next_token_is (parser, CPP_NAME))
-             {
-               c_parser_gimple_goto_stmt (loc,
-                                          c_parser_peek_token
-                                          (parser)->value,
-                                          &switch_body);
-               c_parser_consume_token (parser);
-               if (c_parser_next_token_is (parser, CPP_SEMICOLON))
-                 c_parser_consume_token (parser);
-               else
-                 {
-                   c_parser_error (parser, "expected semicolon");
-                   return;
-                 }
-             }
-           else if (! c_parser_require (parser, CPP_NAME,
-                                        "expected label"))
-             return;
-           break;
-         }
        default:
-         c_parser_error (parser, "expected case label or goto statement");
+         c_parser_error (parser, "expected case label");
          return;
        }
 
@@ -1664,16 +1981,15 @@ c_parser_gimple_switch_stmt (c_parser *parser, 
gimple_seq *seq)
 
   if (cond_expr.value != error_mark_node)
     {
-      gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
-                                                    default_label, labels));
-      gimple_seq_add_seq (seq, switch_body);
+      gswitch *s = gimple_build_switch (cond_expr.value, default_label, 
labels);
+      gimple_seq_add_stmt_without_update (seq, s);
     }
 }
 
 /* Parse gimple return statement.  */
 
 static void
-c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+c_parser_gimple_return_stmt (gimple_parser &parser, gimple_seq *seq)
 {
   location_t loc = c_parser_peek_token (parser)->location;
   gimple *ret = NULL;
@@ -1682,7 +1998,7 @@ c_parser_gimple_return_stmt (c_parser *parser, gimple_seq 
*seq)
     {
       c_finish_gimple_return (loc, NULL_TREE);
       ret = gimple_build_return (NULL);
-      gimple_seq_add_stmt (seq, ret);
+      gimple_seq_add_stmt_without_update (seq, ret);
     }
   else
     {
@@ -1692,7 +2008,7 @@ c_parser_gimple_return_stmt (c_parser *parser, gimple_seq 
*seq)
        {
          c_finish_gimple_return (xloc, expr.value);
          ret = gimple_build_return (expr.value);
-         gimple_seq_add_stmt (seq, ret);
+         gimple_seq_add_stmt_without_update (seq, ret);
        }
     }
 }
diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h
index ae912ee4777..383ad768759 100644
--- a/gcc/c/gimple-parser.h
+++ b/gcc/c/gimple-parser.h
@@ -21,7 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_GIMPLE_PARSER_H
 
 /* Gimple parsing functions.  */
-extern void c_parser_parse_gimple_body (c_parser *);
-extern char *c_parser_gimple_or_rtl_pass_list (c_parser *);
+extern void c_parser_parse_gimple_body (c_parser *, char *,
+                                       enum c_declspec_il);
+extern void c_parser_gimple_or_rtl_pass_list (c_parser *, c_declspecs *);
 
 #endif
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 45ef09e8241..69bae0d10d0 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "asan.h"
+#include "cfgloop.h"
 
 #define INDENT(SPACE)                                                  \
   do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0)
@@ -2221,18 +2222,11 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int 
spc, bool comment,
     {
       if ((flags & TDF_LINENO) && gimple_phi_arg_has_location (phi, i))
        dump_location (buffer, gimple_phi_arg_location (phi, i));
+      basic_block src = gimple_phi_arg_edge (phi, i)->src;
       if (flags & TDF_GIMPLE)
        {
-         basic_block src = gimple_phi_arg_edge (phi, i)->src;
-         gimple *stmt = first_stmt (src);
-         if (!stmt || gimple_code (stmt) != GIMPLE_LABEL)
-           {
-             pp_string (buffer, "bb_");
-             pp_decimal_int (buffer, src->index);
-           }
-         else
-           dump_generic_node (buffer, gimple_label_label (as_a <glabel *> 
(stmt)), 0, flags,
-                              false);
+         pp_string (buffer, "__BB");
+         pp_decimal_int (buffer, src->index);
          pp_string (buffer, ": ");
        }
       dump_generic_node (buffer, gimple_phi_arg_def (phi, i), spc, flags,
@@ -2240,7 +2234,7 @@ dump_gimple_phi (pretty_printer *buffer, gphi *phi, int 
spc, bool comment,
       if (! (flags & TDF_GIMPLE))
        {
          pp_left_paren (buffer);
-         pp_decimal_int (buffer, gimple_phi_arg_edge (phi, i)->src->index);
+         pp_decimal_int (buffer, src->index);
          pp_right_paren (buffer);
        }
       if (i < gimple_phi_num_args (phi) - 1)
@@ -2706,7 +2700,12 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int 
indent,
   else
     {
       if (flags & TDF_GIMPLE)
-       fprintf (outf, "%*sbb_%d:\n", indent, "", bb->index);
+       {
+         fprintf (outf, "%*s__BB(%d", indent, "", bb->index);
+         if (bb->loop_father->header == bb)
+           fprintf (outf, ",loop_header(%d)", bb->loop_father->num);
+         fprintf (outf, "):\n");
+       }
       else
        fprintf (outf, "%*s<bb %d> %s:\n",
                 indent, "", bb->index, dump_profile (bb->count));
@@ -2759,7 +2758,7 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t 
flags)
 {
   if (flags & TDF_GIMPLE)
     {
-      pp_string (buffer, "goto bb_");
+      pp_string (buffer, "goto __BB");
       pp_decimal_int (buffer, e->dest->index);
       pp_semicolon (buffer);
     }
@@ -2812,7 +2811,7 @@ dump_implicit_edges (pretty_printer *buffer, basic_block 
bb, int indent,
      goto to the dump.  */
   e = find_fallthru_edge (bb->succs);
 
-  if (e && e->dest != bb->next_bb)
+  if (e && (e->dest != bb->next_bb || (flags & TDF_GIMPLE)))
     {
       INDENT (indent);
 
diff --git a/gcc/testsuite/gcc.dg/gimplefe-13.c 
b/gcc/testsuite/gcc.dg/gimplefe-13.c
index f0af7611fb9..dc326861c0f 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-13.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-13.c
@@ -1,25 +1,26 @@
 /* { dg-do compile } */
 /* { dg-options "-O -fgimple" } */
 
-void __GIMPLE (startwith ("dse2")) foo ()
+void __GIMPLE (ssa,startwith ("dse2")) foo ()
 {
   int a;
 
-bb_2:
-  if (a > 4)
-    goto bb_3;
+__BB(2):
+  if (a_5(D) > 4)
+    goto __BB3;
   else
-    goto bb_4;
+    goto __BB4;
 
-bb_3:
+__BB(3):
   a_2 = 10;
-  goto bb_5;
+  goto __BB5;
 
-bb_4:
+__BB(4):
   a_3 = 20;
+  goto __BB5;
 
-bb_5:
-  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+__BB(5):
+  a_1 = __PHI (__BB3: a_2, __BB4: a_3);
   a_4 = a_1 + 4;
 
 return;
diff --git a/gcc/testsuite/gcc.dg/gimplefe-14.c 
b/gcc/testsuite/gcc.dg/gimplefe-14.c
index 15022297703..a9e9d8141f0 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-14.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-14.c
@@ -1,29 +1,33 @@
 /* { dg-do run } */
 /* { dg-options "-O -fgimple" } */
 
-int __GIMPLE ()
+int __GIMPLE (ssa)
 main (int argc, char * * argv)
 {
   int a;
 
-  bb_2:
+  __BB(2):
   /* Because of PR82114 we need to handle also 0 as base metal can have
      argc == 0.  */
   switch (argc_2(D)) {default: L2; case 0: L0; case 1: L0; case 2: L1; }
 
+  __BB(3):
 L0:
   a_4 = 0;
-  goto bb_6;
+  goto __BB6;
 
+  __BB(4):
 L1:
   a_3 = 3;
-  goto bb_6;
+  goto __BB6;
 
+  __BB(5):
 L2:
   a_5 = -1;
+  goto __BB6;
 
-  bb_6:
-  a_1 = __PHI (L0: a_4, L1: a_3, L2: a_5);
+  __BB(6):
+  a_1 = __PHI (__BB3: a_4, __BB4: a_3, __BB5: a_5);
   return a_1;
 
 }
diff --git a/gcc/testsuite/gcc.dg/gimplefe-17.c 
b/gcc/testsuite/gcc.dg/gimplefe-17.c
index c5633eee34f..eceefd153ef 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-17.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-17.c
@@ -1,26 +1,31 @@
 /* { dg-do compile } */
-/* { dg-options "-fgimple -fdump-tree-ssa" } */
+/* { dg-options "-fgimple -fdump-tree-fixup_cfg2" } */
 
 int 
-__GIMPLE () *
+__GIMPLE (ssa) *
 foo ()
 {
   int _1;
   int j;
   int *b;
+
+__BB(5):
   _1 = 1;
-bb1:
+  goto __BB2;
+
+__BB(2):
   if (_1)
-    goto bb3;
+    goto __BB4;
   else
-    goto bb2;
+    goto __BB3;
 
-bb2:
+__BB(3):
   b_2 = (int *)0;
+  goto __BB4;
 
-bb3:
-  b_4 = __PHI (bb1: b_3(D), bb2: b_2);
+__BB(4):
+  b_4 = __PHI (__BB2: b_3(D), __BB3: b_2);
   return b_4;
 }
 
-/* { dg-final { scan-tree-dump-not "_1_" "ssa" } } */
+/* { dg-final { scan-tree-dump-not "_1_" "fixup_cfg2" } } */
diff --git a/gcc/testsuite/gcc.dg/gimplefe-18.c 
b/gcc/testsuite/gcc.dg/gimplefe-18.c
index ba918b2bc04..18fabbe1e66 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-18.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-18.c
@@ -2,23 +2,28 @@
 /* { dg-options "-fgimple" } */
 
 int
-__GIMPLE () *
+__GIMPLE (ssa) *
 foo ()
 {
   int _1;
   int j;
   int *b;
+
+__BB(2):
   _1 = 1;
-bb1:
+  goto __BB3;
+
+__BB(3):
   if (_1)
-    goto bb3;
+    goto __BB5;
   else
-    goto bb2;
+    goto __BB4;
 
-bb2:
+__BB(4):
   b_2 = (int *)0;
+  goto __BB5;
 
-bb3:
-  b_4 = __PHI (bb1: &j, bb2: b_2);
+__BB(5):
+  b_4 = __PHI (__BB3: &j, __BB4: b_2);
   return b_4;
 }
diff --git a/gcc/testsuite/gcc.dg/gimplefe-7.c 
b/gcc/testsuite/gcc.dg/gimplefe-7.c
index 61255412ab5..ad34e85b502 100644
--- a/gcc/testsuite/gcc.dg/gimplefe-7.c
+++ b/gcc/testsuite/gcc.dg/gimplefe-7.c
@@ -1,25 +1,26 @@
 /* { dg-do compile } */
 /* { dg-options "-fgimple" } */
 
-void __GIMPLE () foo ()
+void __GIMPLE (ssa) foo ()
 {
   int a;
 
-bb_2:
-  if (a > 4)
-    goto bb_3;
+__BB(2):
+  if (a_5(D) > 4)
+    goto __BB3;
   else
-    goto bb_4;
+    goto __BB4;
 
-bb_3:
+__BB(3):
   a_2 = 10;
-  goto bb_5;
+  goto __BB5;
 
-bb_4:
+__BB(4):
   a_3 = 20;
+  goto __BB5;
 
-bb_5:
-  a_1 = __PHI (bb_3: a_2, bb_4: a_3);
+__BB(5):
+  a_1 = __PHI (__BB3: a_2, __BB4: a_3);
   a_4 = a_1 + 4;
 
 return;
diff --git a/gcc/testsuite/gcc.dg/torture/pr89595.c 
b/gcc/testsuite/gcc.dg/torture/pr89595.c
index ebd834f32a4..f45dc98c3f0 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89595.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89595.c
@@ -2,33 +2,35 @@
 /* { dg-additional-options "-fgimple" } */
 
 int __attribute__((noipa))
-__GIMPLE(startwith("dom")) bar(int cond, int val)
+__GIMPLE(ssa,startwith("dom")) bar(int cond, int val)
 {
   int i;
 
+__BB(3):
   if (0 != 0)
-    goto bb_6;
+    goto __BB6;
   else
-    goto bb_2;
+    goto __BB2;
 
-bb_2:
+__BB(2):
   if (cond_5(D) != 0)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_5;
+    goto __BB5;
 
-bb_4:
+__BB(4):
   i_6 = val_2(D);
   i_1 = val_2(D) > 0 ? i_6 : 0;
+  goto __BB5;
 
-bb_5:
-  i_3 = __PHI (bb_4: i_1, bb_2: 0);
+__BB(5):
+  i_3 = __PHI (__BB4: i_1, __BB2: 0);
   return i_3;
 
-bb_6:
+__BB(6):
   i_4 = 1;
   i_9 = 2;
-  goto bb_2;
+  goto __BB2;
 }
 
 int main()
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c 
b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c
index 096380ab5aa..98cb56a8564 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-13.c
@@ -9,7 +9,7 @@ typedef int i32;
 
 struct a {i32 a[8];i32 b;};
 
-void __GIMPLE (startwith("fix_loops"))
+void __GIMPLE (ssa,startwith("fix_loops"))
 t (struct a * a)
 {
   i32 i;
@@ -18,37 +18,37 @@ t (struct a * a)
   i32 _9;
   i32 _11;
 
-bb_2:
+__BB(2):
   _11 = a_6(D)->a[0];
   if (_11 != _Literal (i32) 0)
-    goto bb_6;
+    goto __BB6;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_3:
+__BB(3):
   return;
 
-bb_4:
+__BB(4):
   _1 = _2 + _Literal (i32) 1;
   a_6(D)->a[i_19] = _1;
   i_8 = i_19 + _Literal (i32) 1;
   if (i_8 <= _Literal (i32) 123455)
-    goto bb_5;
+    goto __BB5;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_5:
-  i_19 = __PHI (bb_6: _Literal (i32) 1, bb_4: i_8);
+__BB(5):
+  i_19 = __PHI (__BB6: _Literal (i32) 1, __BB4: i_8);
   _2 = a_6(D)->a[i_19];
   if (_2 != _Literal (i32) 0)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_6:
+__BB(6):
   _9 = _11 + _Literal (i32) 1;
   a_6(D)->a[0] = _9;
-  goto bb_5;
+  goto __BB5;
 }
 
 /* This testcase relies on the fact that we do not eliminate the redundant test
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1g.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1g.c
index ac1346c7663..3f2132b1161 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1g.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1g.c
@@ -15,7 +15,7 @@ foo (long int * p, long int * p2, int N1, int N2)
   long unsigned int _4;
   long int _5;
 
-  bb_2:
+  __BB(2):
   _1 = (long unsigned int) N1_10(D);
   _2 = _1 * 8ul;
   p_limit_12 = p_11(D) + _2;
@@ -23,59 +23,60 @@ foo (long int * p, long int * p2, int N1, int N2)
   _4 = _3 * 8ul;
   p_limit2_15 = p2_14(D) + _4;
   if (p_11(D) <= p_limit_12)
-    goto bb_3;
+    goto __BB3;
   else
-    goto bb_13;
+    goto __BB13;
 
-  bb_13:
+  __BB(13):
+  goto __BB9;
 
-  bb_9:
-  goto bb_6;
+  __BB(9):
+  goto __BB6;
 
-  bb_3:
+  __BB(3):
   p_20 = p_11(D) + 8ul;
   p2_23 = p2_14(D) + 8ul;
   if (p_limit2_15 < p2_23)
-    goto bb_14;
+    goto __BB14;
   else
-    goto bb_7;
+    goto __BB7;
 
-  bb_14:
-  goto bb_9;
+  __BB(14):
+  goto __BB9;
 
-  bb_7:
-  goto bb_5;
+  __BB(7):
+  goto __BB5;
 
-  bb_4:
+  __BB(4):
   p_16 = p_26 + 8ul;
   p2_17 = p2_27 + 8ul;
   if (p_limit2_15 < p2_17)
-    goto bb_11;
+    goto __BB11;
   else
-    goto bb_8;
+    goto __BB8;
 
-  bb_11:
-  goto bb_6;
+  __BB(11):
+  goto __BB6;
 
-  bb_8:
-  ;
+  __BB(8):
+  goto __BB5;
 
-  bb_5:
-  s_24 = __PHI (bb_7: 0l, bb_8: s_19);
-  p_26 = __PHI (bb_7: p_20, bb_8: p_16);
-  p2_27 = __PHI (bb_7: p2_23, bb_8: p2_17);
+  __BB(5):
+  s_24 = __PHI (__BB7: 0l, __BB8: s_19);
+  p_26 = __PHI (__BB7: p_20, __BB8: p_16);
+  p2_27 = __PHI (__BB7: p2_23, __BB8: p2_17);
   _5 = __MEM <long int> (p_26);
   s_19 = _5 + s_24;
   if (p_limit_12 >= p_26)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_12;
+    goto __BB12;
 
-  bb_12:
-  ;
+  __BB(12):
+  goto __BB6;
 
-  bb_6:
-  s_25 = __PHI (bb_12: s_19, bb_11: s_19, bb_9: 0l);
+  __BB(6):
+  s_25 = __PHI (__BB12: s_19, __BB11: s_19, __BB9: 0l);
   return s_25;
 }
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2g.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2g.c
index 38f547657d1..e0c90bdd914 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2g.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2g.c
@@ -3,7 +3,7 @@
 
 /* Exit tests 'i < N1' and 'p2 > p_limit2' can be replaced, so
  * two ivs i and p2 can be eliminate.  */
-long int __GIMPLE (startwith("fix_loops"))
+long int __GIMPLE (ssa,startwith("fix_loops"))
 foo (long int * p, long int * p2, int N1, int N2)
 {
   long int s;
@@ -13,66 +13,67 @@ foo (long int * p, long int * p2, int N1, int N2)
   long unsigned int _2;
   long int _3;
 
-  bb_2:
+  __BB(2):
   _1 = (long unsigned int) N2_9(D);
   _2 = _1 * 8ul;
   p_limit2_11 = p2_10(D) + _2;
   if (N1_13(D) > 0)
-    goto bb_3;
+    goto __BB3;
   else
-    goto bb_13;
+    goto __BB13;
 
-  bb_13:
+  __BB(13):
+  goto __BB9;
 
-  bb_9:
-  goto bb_6;
+  __BB(9):
+  goto __BB6;
 
-  bb_3:
+  __BB(3):
   p_22 = p_12(D) + 8ul;
   p2_23 = p2_10(D) + 8ul;
   if (p_limit2_11 < p2_23)
-    goto bb_14;
+    goto __BB14;
   else
-    goto bb_7;
+    goto __BB7;
 
-  bb_14:
-  goto bb_9;
+  __BB(14):
+  goto __BB9;
 
-  bb_7:
-  goto bb_5;
+  __BB(7):
+  goto __BB5;
 
-  bb_4:
+  __BB(4):
   p_14 = p_27 + 8ul;
   p2_15 = p2_28 + 8ul;
   i_16 = i_29 + 1;
   if (p_limit2_11 < p2_15)
-    goto bb_11;
+    goto __BB11;
   else
-    goto bb_8;
+    goto __BB8;
 
-  bb_11:
-  goto bb_6;
+  __BB(11):
+  goto __BB6;
 
-  bb_8:
-  ;
+  __BB(8):
+  goto __BB8;
 
-  bb_5:
-  s_25 = __PHI (bb_7: 0l, bb_8: s_18);
-  p_27 = __PHI (bb_7: p_22, bb_8: p_14);
-  p2_28 = __PHI (bb_7: p2_23, bb_8: p2_15);
-  i_29 = __PHI (bb_7: 1, bb_8: i_16);
+  __BB(5):
+  s_25 = __PHI (__BB7: 0l, __BB8: s_18);
+  p_27 = __PHI (__BB7: p_22, __BB8: p_14);
+  p2_28 = __PHI (__BB7: p2_23, __BB8: p2_15);
+  i_29 = __PHI (__BB7: 1, __BB8: i_16);
   _3 = __MEM <long int> (p_27);
   s_18 = _3 + s_25;
   if (N1_13(D) > i_29)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_12;
+    goto __BB12;
 
-  bb_12:
-  ;
+  __BB(12):
+  goto __BB6;
 
-  bb_6:
-  s_26 = __PHI (bb_12: s_18, bb_11: s_18, bb_9: 0l);
+  __BB(6):
+  s_26 = __PHI (__BB12: s_18, __BB11: s_18, __BB9: 0l);
   return s_26;
 }
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c 
b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
index fed1011968d..4babd33f5c0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
@@ -4,39 +4,39 @@
 int *a_p;
 int a[1000];
 
-void __GIMPLE (startwith ("loop"))
+void __GIMPLE (ssa,startwith ("loop"))
 f (int k)
 {
   int i;
   int * _1;
 
-bb_2:
+__BB(2):
   i_5 = k_4(D);
   if (i_5 <= 999)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_3:
+__BB(3):
   return;
 
-bb_4:
-  ;
+__BB(4):
+  goto __BB5;
 
-bb_5:
-  i_12 = __PHI (bb_6: i_9, bb_4: i_5);
+__BB(5):
+  i_12 = __PHI (__BB6: i_9, __BB4: i_5);
   _1 = &a[i_12];
   a_p = _1;
   __MEM <int[1000]> ((int *)&a)[i_12] = 100;
   i_9 = i_5 + i_12;
   if (i_9 <= 999)
-    goto bb_6;
+    goto __BB6;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_6:
+__BB(6):
   ;
-  goto bb_5;
+  goto __BB5;
 
 }
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c 
b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
index 94ebfae7b93..57cb0213402 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
@@ -9,39 +9,39 @@ typedef struct {
 int *a_p;
 S a[1000];
 
-void __GIMPLE (startwith ("loop"))
+void __GIMPLE (ssa, startwith ("loop"))
 f (int k)
 {
   int i;
   int * _1;
 
-bb_2:
+__BB(2):
   i_5 = k_4(D);
   if (i_5 <= 999)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_3:
+__BB(3):
   return;
 
-bb_4:
-  ;
+__BB(4):
+  goto __BB5;
 
-bb_5:
-  i_12 = __PHI (bb_6: i_9, bb_4: i_5);
+__BB(5):
+  i_12 = __PHI (__BB6: i_9, __BB4: i_5);
   _1 = &a[i_12].y;
   a_p = _1;
   __MEM <S[1000]> ((int *)&a)[i_12].y = 100;
   i_9 = i_5 + i_12;
   if (i_9 <= 999)
-    goto bb_6;
+    goto __BB6;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_6:
+__BB(6):
   ;
-  goto bb_5;
+  goto __BB5;
 
 }
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c 
b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
index 8cced512e8d..c2feebdfc24 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
@@ -4,39 +4,39 @@
 int *a_p;
 int a[1000];
 
-void __GIMPLE (startwith ("loop"))
+void __GIMPLE (ssa,startwith ("loop"))
 f (int k)
 {
   long long int i;
   int * _1;
 
-bb_2:
+__BB(2):
   i_5 = (long long int) k_4(D);
   if (i_5 <= 999ll)
-    goto bb_4;
+    goto __BB4;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_3:
+__BB(3):
   return;
 
-bb_4:
-  ;
+__BB(4):
+  goto __BB5;
 
-bb_5:
-  i_12 = __PHI (bb_6: i_9, bb_4: i_5);
+__BB(5):
+  i_12 = __PHI (__BB6: i_9, __BB4: i_5);
   _1 = &a[i_12];
   a_p = _1;
   __MEM <int[1000]> ((int *)&a)[i_12] = 100;
   i_9 = i_5 + i_12;
   if (i_9 <= 999ll)
-    goto bb_6;
+    goto __BB6;
   else
-    goto bb_3;
+    goto __BB3;
 
-bb_6:
+__BB(6):
   ;
-  goto bb_5;
+  goto __BB5;
 
 }
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
index 15ec005df26..38994ea82a5 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-arith-2.c
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-additional-options "-fgimple -fdump-tree-optimized -ffast-math" } */
 
-double __GIMPLE (startwith("loop"))
+double __GIMPLE (ssa, startwith("loop"))
 neg_xi (double *x)
 {
   int i;
@@ -13,13 +13,13 @@ neg_xi (double *x)
   double res;
   unsigned int ivtmp;
 
- bb_1:
-  goto bb_2;
+ __BB(5):
+  goto __BB2;
 
- bb_2:
-  res_1 = __PHI (bb_1: 0.0, bb_3: res_2);
-  i_4 = __PHI (bb_1: 0, bb_3: i_5);
-  ivtmp_6 = __PHI (bb_1: 100U, bb_3: ivtmp_7);
+ __BB(2):
+  res_1 = __PHI (__BB5: 0.0, __BB3: res_2);
+  i_4 = __PHI (__BB5: 0, __BB3: i_5);
+  ivtmp_6 = __PHI (__BB5: 100U, __BB3: ivtmp_7);
   index = (long unsigned int) i_4;
   offset = index * 8UL;
   xi_ptr = x_8(D) + offset;
@@ -29,15 +29,15 @@ neg_xi (double *x)
   i_5 = i_4 + 1;
   ivtmp_7 = ivtmp_6 - 1U;
   if (ivtmp_7 != 0U)
-    goto bb_3;
+    goto __BB3;
   else
-    goto bb_4;
+    goto __BB4;
 
- bb_3:
-  goto bb_2;
+ __BB(3):
+  goto __BB2;
 
- bb_4:
-  res_3 = __PHI (bb_2: res_2);
+ __BB(4):
+  res_3 = __PHI (__BB2: res_2);
   return res_3;
 }
 
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/loop_add_6.c 
b/gcc/testsuite/gcc.target/aarch64/sve/loop_add_6.c
index aab5eddddb0..e7416ebcded 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/loop_add_6.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/loop_add_6.c
@@ -1,7 +1,7 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -ftree-vectorize -fgimple -ffast-math" } */
 
-double __GIMPLE (startwith("loop"))
+double __GIMPLE (ssa, startwith("loop"))
 neg_xi (double *x)
 {
   int i;
@@ -13,13 +13,13 @@ neg_xi (double *x)
   double res;
   unsigned int ivtmp;
 
- bb_1:
-  goto bb_2;
+ __BB(5):
+  goto __BB2;
 
- bb_2:
-  res_1 = __PHI (bb_1: 0.0, bb_3: res_2);
-  i_4 = __PHI (bb_1: 0, bb_3: i_5);
-  ivtmp_6 = __PHI (bb_1: 100U, bb_3: ivtmp_7);
+ __BB(2):
+  res_1 = __PHI (__BB5: 0.0, __BB3: res_2);
+  i_4 = __PHI (__BB5: 0, __BB3: i_5);
+  ivtmp_6 = __PHI (__BB5: 100U, __BB3: ivtmp_7);
   index = (long unsigned int) i_4;
   offset = index * 8UL;
   xi_ptr = x_8(D) + offset;
@@ -29,15 +29,15 @@ neg_xi (double *x)
   i_5 = i_4 + 1;
   ivtmp_7 = ivtmp_6 - 1U;
   if (ivtmp_7 != 0U)
-    goto bb_3;
+    goto __BB3;
   else
-    goto bb_4;
+    goto __BB4;
 
- bb_3:
-  goto bb_2;
+ __BB(3):
+  goto __BB2;
 
- bb_4:
-  res_3 = __PHI (bb_2: res_2);
+ __BB(4):
+  res_3 = __PHI (__BB2: res_2);
   return res_3;
 }
 
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 805e8727ce0..0dc94ea41d4 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -171,7 +171,6 @@ static bool gimple_can_merge_blocks_p (basic_block, 
basic_block);
 static void remove_bb (basic_block);
 static edge find_taken_edge_computed_goto (basic_block, tree);
 static edge find_taken_edge_cond_expr (const gcond *, tree);
-static void lower_phi_internal_fn ();
 
 void
 init_empty_tree_cfg_for_function (struct function *fn)
@@ -246,7 +245,6 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = new hash_table<locus_discrim_hasher> (13);
   make_edges ();
   assign_discriminators ();
-  lower_phi_internal_fn ();
   cleanup_dead_labels ();
   delete discriminator_per_locus;
   discriminator_per_locus = NULL;
@@ -359,47 +357,6 @@ replace_loop_annotate (void)
     }
 }
 
-/* Lower internal PHI function from GIMPLE FE.  */
-
-static void
-lower_phi_internal_fn ()
-{
-  basic_block bb, pred = NULL;
-  gimple_stmt_iterator gsi;
-  tree lhs;
-  gphi *phi_node;
-  gimple *stmt;
-
-  /* After edge creation, handle __PHI function from GIMPLE FE.  */
-  FOR_EACH_BB_FN (bb, cfun)
-    {
-      for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi);)
-       {
-         stmt = gsi_stmt (gsi);
-         if (! gimple_call_internal_p (stmt, IFN_PHI))
-           break;
-
-         lhs = gimple_call_lhs (stmt);
-         phi_node = create_phi_node (lhs, bb);
-
-         /* Add arguments to the PHI node.  */
-         for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
-           {
-             tree arg = gimple_call_arg (stmt, i);
-             if (TREE_CODE (arg) == LABEL_DECL)
-               pred = label_to_block (cfun, arg);
-             else
-               {
-                 edge e = find_edge (pred, bb);
-                 add_phi_arg (phi_node, arg, e, UNKNOWN_LOCATION);
-               }
-           }
-
-         gsi_remove (&gsi, true);
-       }
-    }
-}
-
 static unsigned int
 execute_build_cfg (void)
 {
@@ -3337,11 +3294,6 @@ verify_gimple_call (gcall *stmt)
          debug_generic_stmt (fn);
          return true;
        }
-      /* FIXME : for passing label as arg in internal fn PHI from GIMPLE FE*/
-      else if (gimple_call_internal_fn (stmt) == IFN_PHI)
-       {
-         return false;
-       }
     }
   else
     {
@@ -7922,7 +7874,11 @@ dump_function_to_file (tree fndecl, FILE *file, 
dump_flags_t flags)
     {
       print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)),
                          dump_flags | TDF_SLIM);
-      fprintf (file, " __GIMPLE ()\n%s (", function_name (fun));
+      fprintf (file, " __GIMPLE (%s)\n%s (",
+              (fun->curr_properties & PROP_ssa) ? "ssa"
+              : (fun->curr_properties & PROP_cfg) ? "cfg"
+              : "",
+              function_name (fun));
     }
   else
     fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : 
"");
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index dad071df6ee..061521d20d5 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -1436,20 +1436,12 @@ rewrite_add_phi_arguments (basic_block bb)
       for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi);
           gsi_next (&gsi))
        {
-         tree currdef, res, argvar;
+         tree currdef, res;
          location_t loc;
 
          phi = gsi.phi ();
          res = gimple_phi_result (phi);
-         /* If we have pre-existing PHI (via the GIMPLE FE) its args may
-            be different vars than existing vars and they may be constants
-            as well.  Note the following supports partial SSA for PHI args.  */
-         argvar = gimple_phi_arg_def (phi, e->dest_idx);
-         if (argvar && ! DECL_P (argvar))
-           continue;
-         if (!argvar)
-           argvar = SSA_NAME_VAR (res);
-         currdef = get_reaching_def (argvar);
+         currdef = get_reaching_def (SSA_NAME_VAR (res));
          /* Virtual operand PHI args do not need a location.  */
          if (virtual_operand_p (res))
            loc = UNKNOWN_LOCATION;

Reply via email to