[Patch,tree-optimization]: Add new path Splitting pass on tree ssa
authorAjit Agarwal <ajitkum@xilinx.com>
Fri, 13 Nov 2015 23:31:51 +0000 (23:31 +0000)
committerJeff Law <law@gcc.gnu.org>
Fri, 13 Nov 2015 23:31:51 +0000 (16:31 -0700)
representation

* Makefile.in (OBJS): Add gimple-ssa-split-paths.o
* common.opt (-fsplit-paths): New flag controlling path splitting.
* doc/invoke.texi (fsplit-paths): Document.
* opts.c (default_options_table): Add -fsplit-paths to -O2.
* passes.def: Add split_paths pass.
* timevar.def (TV_SPLIT_PATHS): New timevar.
* tracer.c: Include "tracer.h"
(ignore_bb_p): No longer static.
(transform_duplicate): New function, broken out of tail_duplicate.
(tail_duplicate): Use transform_duplicate.
* tracer.h (ignore_bb_p): Declare
(transform_duplicate): Likewise.
* tree-pass.h (make_pass_split_paths): Declare.
* gimple-ssa-split-paths.c: New file.

* gcc.dg/tree-ssa/split-path-1.c: New test.

Co-Authored-By: Jeff Law <law@redhat.com>
From-SVN: r230364

13 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/common.opt
gcc/doc/invoke.texi
gcc/gimple-ssa-split-paths.c [new file with mode: 0644]
gcc/opts.c
gcc/passes.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c [new file with mode: 0644]
gcc/timevar.def
gcc/tracer.c
gcc/tracer.h [new file with mode: 0644]
gcc/tree-pass.h

index dde26959f14696d27661c49872cff990cc0df7be..a7abe379db80a54a37cc22b3ab4f09fb9e69bc26 100644 (file)
@@ -1,3 +1,21 @@
+2015-11-13  Ajit Agarwal  <ajitkum@xilinx.com>
+           Jeff Law  <law@redhat.com>
+
+       * Makefile.in (OBJS): Add gimple-ssa-split-paths.o
+       * common.opt (-fsplit-paths): New flag controlling path splitting.
+       * doc/invoke.texi (fsplit-paths): Document.
+       * opts.c (default_options_table): Add -fsplit-paths to -O2.
+       * passes.def: Add split_paths pass.
+       * timevar.def (TV_SPLIT_PATHS): New timevar.
+       * tracer.c: Include "tracer.h"
+       (ignore_bb_p): No longer static.
+       (transform_duplicate): New function, broken out of tail_duplicate.
+       (tail_duplicate): Use transform_duplicate.
+       * tracer.h (ignore_bb_p): Declare
+       (transform_duplicate): Likewise.
+       * tree-pass.h (make_pass_split_paths): Declare.
+       * gimple-ssa-split-paths.c: New file.
+
 2015-11-13  Kai Tietz  <ktietz70@googlemail.com>
            Marek Polacek  <polacek@redhat.com>
            Jason Merrill  <jason@redhat.com>
index d3fd5e96442de64a964947ac925f82e2313bb21e..5c294df7b8a901c7dda9c86ff0985c66befed2b0 100644 (file)
@@ -1277,6 +1277,7 @@ OBJS = \
        gimple-pretty-print.o \
        gimple-ssa-backprop.o \
        gimple-ssa-isolate-paths.o \
+       gimple-ssa-split-paths.o \
        gimple-ssa-strength-reduction.o \
        gimple-streamer-in.o \
        gimple-streamer-out.o \
index 757ce85873503326f28fa7d449edea1d8a366ed1..3eb520eaef2e72c2fb67d1df75047cd6956b2f64 100644 (file)
@@ -2403,6 +2403,10 @@ ftree-vrp
 Common Report Var(flag_tree_vrp) Init(0) Optimization
 Perform Value Range Propagation on trees.
 
+fsplit-paths
+Common Report Var(flag_split_paths) Init(0) Optimization
+Split paths leading to loop backedges.
+
 funit-at-a-time
 Common Report Var(flag_unit_at_a_time) Init(1)
 Compile whole compilation unit at a time.
index c18df986f057801816757777324d10386f683080..eeb79e65c0e259267c9f18b2911c54516a0d889e 100644 (file)
@@ -354,6 +354,7 @@ Objective-C and Objective-C++ Dialects}.
 -fdump-tree-fre@r{[}-@var{n}@r{]} @gol
 -fdump-tree-vtable-verify @gol
 -fdump-tree-vrp@r{[}-@var{n}@r{]} @gol
+-fdump-tree-split-paths@r{[}-@var{n}@r{]} @gol
 -fdump-tree-storeccp@r{[}-@var{n}@r{]} @gol
 -fdump-final-insns=@var{file} @gol
 -fcompare-debug@r{[}=@var{opts}@r{]}  -fcompare-debug-second @gol
@@ -448,6 +449,7 @@ Objective-C and Objective-C++ Dialects}.
 -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol
 -fsemantic-interposition -fshrink-wrap -fsignaling-nans @gol
 -fsingle-precision-constant -fsplit-ivs-in-unroller @gol
+-fsplit-paths @gol
 -fsplit-wide-types -fssa-backprop -fssa-phiopt @gol
 -fstack-protector -fstack-protector-all -fstack-protector-strong @gol
 -fstack-protector-explicit -fstdarg-opt -fstrict-aliasing @gol
@@ -7171,6 +7173,11 @@ output on to @file{stderr}. If two conflicting dump filenames are
 given for the same pass, then the latter option overrides the earlier
 one.
 
+@item split-paths
+@opindex fdump-tree-split-paths
+Dump each function after splitting paths to loop backedges.  The file
+name is made by appending @file{.split-paths} to the source file name.
+
 @item all
 Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
 and @option{lineno}.
@@ -7808,6 +7815,7 @@ also turns on the following optimization flags:
 -frerun-cse-after-loop  @gol
 -fsched-interblock  -fsched-spec @gol
 -fschedule-insns  -fschedule-insns2 @gol
+-fsplit-paths @gol
 -fstrict-aliasing -fstrict-overflow @gol
 -ftree-builtin-call-dce @gol
 -ftree-switch-conversion -ftree-tail-merge @gol
@@ -8821,7 +8829,7 @@ currently enabled, but may be enabled by @option{-O2} in the future.
 
 @item -ftree-sink
 @opindex ftree-sink
-Perform forward store motion  on trees.  This flag is
+Perform forward store motion on trees.  This flag is
 enabled by default at @option{-O} and higher.
 
 @item -ftree-bit-ccp
@@ -9127,6 +9135,12 @@ enabled by default at @option{-O2} and higher.  Null pointer check
 elimination is only done if @option{-fdelete-null-pointer-checks} is
 enabled.
 
+@item -fsplit-paths
+@opindex fsplit-paths
+Split paths leading to loop backedges.  This can improve dead code
+elimination and common subexpression elimination.  This is enabled by
+default at @option{-O2} and above.
+
 @item -fsplit-ivs-in-unroller
 @opindex fsplit-ivs-in-unroller
 Enables expression of values of induction variables in later iterations
diff --git a/gcc/gimple-ssa-split-paths.c b/gcc/gimple-ssa-split-paths.c
new file mode 100644 (file)
index 0000000..602e916
--- /dev/null
@@ -0,0 +1,270 @@
+/* Support routines for Splitting Paths to loop backedges
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   Contributed by Ajit Kumar Agarwal <ajitkum@xilinx.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "cfganal.h"
+#include "cfgloop.h"
+#include "gimple-iterator.h"
+#include "tracer.h"
+
+/* Given LATCH, the latch block in a loop, see if the shape of the
+   path reaching LATCH is suitable for being split by duplication.
+   If so, return the block that will be duplicated into its predecessor
+   paths.  Else return NULL.  */
+
+static basic_block
+find_block_to_duplicate_for_splitting_paths (basic_block latch)
+{
+  /* We should have simple latches at this point.  So the latch should
+     have a single successor.  This implies the predecessor of the latch
+     likely has the loop exit.  And it's that predecessor we're most
+     interested in. To keep things simple, we're going to require that
+     the latch have a single predecessor too.  */
+  if (single_succ_p (latch) && single_pred_p (latch))
+    {
+      basic_block bb = get_immediate_dominator (CDI_DOMINATORS, latch);
+      gcc_assert (single_pred_edge (latch)->src == bb);
+
+      /* If BB has been marked as not to be duplicated, then honor that
+        request.  */
+      if (ignore_bb_p (bb))
+       return NULL;
+
+      gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb));
+      /* The immediate dominator of the latch must end in a conditional.  */
+      if (!last || gimple_code (last) != GIMPLE_COND)
+       return NULL;
+
+      /* We're hoping that BB is a join point for an IF-THEN-ELSE diamond
+        region.  Verify that it is.
+
+        First, verify that BB has two predecessors (each arm of the
+        IF-THEN-ELSE) and two successors (the latch and exit).  */
+      if (EDGE_COUNT (bb->preds) == 2 && EDGE_COUNT (bb->succs) == 2)
+       {
+         /* Now verify that BB's immediate dominator ends in a
+            conditional as well.  */
+         basic_block bb_idom = get_immediate_dominator (CDI_DOMINATORS, bb);
+         gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb_idom));
+         if (!last || gimple_code (last) != GIMPLE_COND)
+           return NULL;
+
+         /* And that BB's immediate dominator's successors are the
+            the predecessors of BB.  */
+         if (!find_edge (bb_idom, EDGE_PRED (bb, 0)->src)
+             || !find_edge (bb_idom, EDGE_PRED (bb, 1)->src))
+           return NULL;
+
+         /* So at this point we have a simple diamond for an IF-THEN-ELSE
+            construct starting at BB_IDOM, with a join point at BB.  BB
+            pass control outside the loop or to the loop latch.
+
+            We're going to want to create two duplicates of BB, one for
+            each successor of BB_IDOM.  */
+         return bb;
+       }
+    }
+  return NULL;
+}
+
+/* Return TRUE if BB is a reasonable block to duplicate by examining
+   its size, false otherwise.  BB will always be a loop latch block.
+
+   Should this use the same tests as we do for jump threading?  */
+
+static bool
+is_feasible_trace (basic_block bb)
+{
+  int num_stmt = 0;
+  gimple_stmt_iterator gsi;
+
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple *stmt = gsi_stmt (gsi);
+      if (!is_gimple_debug (stmt))
+       num_stmt++;
+    }
+
+  /* We may want to limit how many statements we copy.  */
+  if (num_stmt > 1)
+    return true;
+
+  return false;
+}
+
+/* If the immediate dominator of the latch of the loop is
+   block with conditional branch, then the loop latch  is
+   duplicated to its predecessors path preserving the SSA
+   semantics.
+
+   CFG before transformation.
+
+              2
+              |
+              |
+        +---->3
+        |    / \
+        |   /   \
+        |  4     5
+        |   \   /
+        |    \ /
+        |     6
+        |    / \
+        |   /   \
+        |  8     7
+        |  |     |
+        ---+     E
+
+
+
+    Block 8 is the latch.  We're going to make copies of block 6 (9 & 10)
+    and wire things up so they look like this:
+
+              2
+              |
+              |
+        +---->3
+        |    / \
+        |   /   \
+        |  4     5
+        |  |     |
+        |  |     |
+        |  9    10
+        |  |\   /|
+        |  | \ / |
+        |  |  7  |
+        |  |  |  |
+        |  |  E  |
+        |  |     |
+        |   \   /
+        |    \ /
+        +-----8
+
+
+    Blocks 9 and 10 will get merged into blocks 4 & 5 respectively which
+    enables CSE, DCE and other optimizations to occur on a larger block
+    of code.   */
+
+static bool
+split_paths ()
+{
+  bool changed = false;
+  loop_p loop;
+
+  loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
+  initialize_original_copy_tables ();
+  calculate_dominance_info (CDI_DOMINATORS);
+
+  FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
+    {
+      /* See if there is a block that we can duplicate to split the
+        path to the loop latch.  */
+      basic_block bb = find_block_to_duplicate_for_splitting_paths (loop->latch);
+
+      /* BB is the merge point for an IF-THEN-ELSE we want to transform.
+
+        Essentially we want to create two duplicates of BB and append
+        a duplicate to the THEN and ELSE clauses.  This will split the
+        path leading to the latch.  BB will be unreachable and removed.  */
+      if (bb && is_feasible_trace (bb))
+       {
+         if (dump_file && (dump_flags & TDF_DETAILS))
+           fprintf (dump_file,
+                    "Duplicating join block %d into predecessor paths\n",
+                    bb->index);
+         basic_block pred0 = EDGE_PRED (bb, 0)->src;
+         basic_block pred1 = EDGE_PRED (bb, 1)->src;
+         transform_duplicate (pred0, bb);
+         transform_duplicate (pred1, bb);
+         changed = true;
+       }
+    }
+
+  loop_optimizer_finalize ();
+  free_original_copy_tables ();
+  return changed;
+}
+
+/* Main entry point for splitting paths.  Returns TODO_cleanup_cfg if any
+   paths where split, otherwise return zero.  */
+
+static unsigned int
+execute_split_paths ()
+{
+  /* If we don't have at least 2 real blocks and backedges in the
+     CFG, then there's no point in trying to perform path splitting.  */
+  if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1
+      || !mark_dfs_back_edges ())
+    return 0;
+
+  bool changed = split_paths();
+  if (changed)
+    free_dominance_info (CDI_DOMINATORS);
+
+  return changed ? TODO_cleanup_cfg : 0;
+}
+
+static bool
+gate_split_paths ()
+{
+  return flag_split_paths;
+}
+
+namespace {
+
+const pass_data pass_data_split_paths =
+{
+  GIMPLE_PASS, /* type */
+  "split-paths", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_SPLIT_PATHS, /* tv_id */
+  PROP_ssa, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_update_ssa, /* todo_flags_finish */
+};
+
+class pass_split_paths : public gimple_opt_pass
+{
+   public:
+    pass_split_paths (gcc::context *ctxt)
+      : gimple_opt_pass (pass_data_split_paths, ctxt)
+    {}
+   /* opt_pass methods: */
+   opt_pass * clone () { return new pass_split_paths (m_ctxt); }
+   virtual bool gate (function *) { return gate_split_paths (); }
+   virtual unsigned int execute (function *) { return execute_split_paths (); }
+
+}; // class pass_split_paths
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_split_paths (gcc::context *ctxt)
+{
+  return new pass_split_paths (ctxt);
+}
index 930ae431157e5fd07e001c2e8d4c34668f0812d5..be04cf5641266a83778eaa8ecd9eea91e10875ba 100644 (file)
@@ -523,6 +523,7 @@ static const struct default_options default_options_table[] =
     { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 },
     { OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },
+    { OPT_LEVELS_2_PLUS, OPT_fsplit_paths, NULL, 1 },
 
     /* -O3 optimizations.  */
     { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
index c0ab6b98e4b1a18ae97629e45d0003b12fe80e89..db822d335971a059bf4cc2c7fc41b1435ef50812 100644 (file)
@@ -274,6 +274,7 @@ along with GCC; see the file COPYING3.  If not see
       POP_INSERT_PASSES ()
       NEXT_PASS (pass_simduid_cleanup);
       NEXT_PASS (pass_lower_vector_ssa);
+      NEXT_PASS (pass_split_paths);
       NEXT_PASS (pass_cse_reciprocals);
       NEXT_PASS (pass_reassoc);
       NEXT_PASS (pass_strength_reduction);
index 33011306f354298406571506b6791ff5a3741847..ee92aaf3275f1b804583a7a961717b17f6a3e40f 100644 (file)
@@ -1,3 +1,8 @@
+2015-11-13  Ajit Agarwal  <ajitkum@xilinx.com>
+            Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/split-path-1.c: New test.
+
 2015-11-13  Nathan Sidwell  <nathan@codesourcery.com>
 
        * c-c++-common/goacc/loop-auto-1.c: New.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-1.c
new file mode 100644 (file)
index 0000000..1239892
--- /dev/null
@@ -0,0 +1,67 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-split-paths-details " } */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define RGBMAX 255
+
+int
+test()
+{
+  int i, Pels;
+  unsigned char sum = 0;
+  unsigned char xr, xg, xb;
+  unsigned char xc, xm, xy, xk;
+  unsigned char *ReadPtr, *EritePtr;
+
+  ReadPtr = ( unsigned char *) malloc (sizeof (unsigned char) * 100);
+  EritePtr = ( unsigned char *) malloc (sizeof (unsigned char) * 100);
+
+  for (i = 0; i < 100;i++)
+     {
+       ReadPtr[i] = 100 - i;
+     }
+
+  for (i = 0; i < 100; i++)
+     {
+       xr = *ReadPtr++;
+       xg = *ReadPtr++;
+       xb = *ReadPtr++;
+
+       xc = (unsigned char) (RGBMAX - xr);
+       xm = (unsigned char) (RGBMAX - xg);
+       xy = (unsigned char) (RGBMAX - xb);
+
+       if (xc < xm)
+         {
+           xk = (unsigned char) (xc < xy ? xc : xy);
+         }
+       else
+        {
+          xk = (unsigned char) (xm < xy ? xm : xy);
+        }
+
+       xc = (unsigned char) (xc - xk);
+       xm = (unsigned char) (xm - xk);
+       xy = (unsigned char) (xy - xk);
+
+       *EritePtr++ = xc;
+       *EritePtr++ = xm;
+       *EritePtr++ = xy;
+       *EritePtr++ = xk;
+       sum += *EritePtr;
+    }
+  return sum;
+}
+
+int
+main()
+{
+  if (test() != 33)
+    abort();
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Duplicating join block" "split-paths" } } */
index b429faf6d5515c23f7864156152b4d2107723b72..45e3b709af1a58499f8e46fd676e94d2a742f8d3 100644 (file)
@@ -252,6 +252,7 @@ DEFTIMEVAR (TV_GCSE_AFTER_RELOAD     , "load CSE after reload")
 DEFTIMEVAR (TV_REE                  , "ree")
 DEFTIMEVAR (TV_THREAD_PROLOGUE_AND_EPILOGUE, "thread pro- & epilogue")
 DEFTIMEVAR (TV_IFCVT2               , "if-conversion 2")
+DEFTIMEVAR (TV_SPLIT_PATHS          , "split paths")
 DEFTIMEVAR (TV_COMBINE_STACK_ADJUST  , "combine stack adjustments")
 DEFTIMEVAR (TV_PEEPHOLE2             , "peephole 2")
 DEFTIMEVAR (TV_RENAME_REGISTERS      , "rename registers")
index 941dc204eee164d9ae44ff07e90d8071a7b20ecb..c2dba4c2503307ede20d9fe7f38ed36b5c5b271d 100644 (file)
@@ -51,9 +51,9 @@
 #include "tree-inline.h"
 #include "cfgloop.h"
 #include "fibonacci_heap.h"
+#include "tracer.h"
 
 static int count_insns (basic_block);
-static bool ignore_bb_p (const_basic_block);
 static bool better_p (const_edge, const_edge);
 static edge find_best_successor (basic_block);
 static edge find_best_predecessor (basic_block);
@@ -85,7 +85,7 @@ bb_seen_p (basic_block bb)
 }
 
 /* Return true if we should ignore the basic block for purposes of tracing.  */
-static bool
+bool
 ignore_bb_p (const_basic_block bb)
 {
   if (bb->index < NUM_FIXED_BLOCKS)
@@ -226,6 +226,24 @@ find_trace (basic_block bb, basic_block *trace)
   return i;
 }
 
+/* Duplicate block BB2, placing it after BB in the CFG.  Return the
+   newly created block.  */
+basic_block
+transform_duplicate (basic_block bb, basic_block bb2)
+{
+  edge e;
+  basic_block copy;
+
+  e = find_edge (bb, bb2);
+
+  copy = duplicate_block (bb2, e, bb);
+  flush_pending_stmts (e);
+
+  add_phi_args_after_copy (&copy, 1, NULL);
+
+  return (copy);
+}
+
 /* Look for basic blocks in frequency order, construct traces and tail duplicate
    if profitable.  */
 
@@ -321,17 +339,8 @@ tail_duplicate (void)
                 entries or at least rotate the loop.  */
              && bb2->loop_father->header != bb2)
            {
-             edge e;
-             basic_block copy;
-
              nduplicated += counts [bb2->index];
-
-             e = find_edge (bb, bb2);
-
-             copy = duplicate_block (bb2, e, bb);
-             flush_pending_stmts (e);
-
-             add_phi_args_after_copy (&copy, 1, NULL);
+             basic_block copy = transform_duplicate (bb, bb2);
 
              /* Reconsider the original copy of block we've duplicated.
                 Removing the most common predecessor may make it to be
diff --git a/gcc/tracer.h b/gcc/tracer.h
new file mode 100644 (file)
index 0000000..cd1792a
--- /dev/null
@@ -0,0 +1,26 @@
+/* Header file for Tracer.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TRACER_H
+#define GCC_TRACER_H
+
+extern basic_block transform_duplicate (basic_block bb, basic_block bb2);
+extern bool ignore_bb_p (const_basic_block bb);
+
+#endif /* GCC_TRACER_H */
index 49e22a9d091247316b7b31074f636c6a87be2dab..da67761782688e0135c5f6373c726b5a82bf7cab 100644 (file)
@@ -390,6 +390,7 @@ extern gimple_opt_pass *make_pass_tree_loop_done (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_ch (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_ch_vect (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_ccp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_split_paths (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_phi_only_cprop (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_build_ssa (gcc::context *ctxt);
 extern gimple_opt_pass *make_pass_build_alias (gcc::context *ctxt);