aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch811
1 files changed, 0 insertions, 811 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch
deleted file mode 100644
index cf22aaf16f..0000000000
--- a/toolchain-layer/recipes-devtools/gcc/gcc-4.5/linaro/gcc-4.5-linaro-r99468.patch
+++ /dev/null
@@ -1,811 +0,0 @@
-2010-12-13 Tom de Vries <tom@codesourcery.com>
-
- gcc/
- * tree-if-switch-conversion.c: New pass.
- * tree-pass.h (pass_if_to_switch): Declare.
- * common.opt (ftree-if-to-switch-conversion): New switch.
- * opts.c (decode_options): Set flag_tree_if_to_switch_conversion at -O2
- and higher.
- * passes.c (init_optimization_passes): Use new pass.
- * params.def (PARAM_IF_TO_SWITCH_THRESHOLD): New param.
- * doc/invoke.texi (-ftree-if-to-switch-conversion)
- (if-to-switch-threshold): New item.
- * doc/invoke.texi (Optimization Options, option -O2): Add
- -ftree-if-to-switch-conversion.
- * Makefile.in (OBJS-common): Add tree-if-switch-conversion.o.
- * Makefile.in (tree-if-switch-conversion.o): New rule.
-
-=== modified file 'gcc/Makefile.in'
-Index: gcc-4_5-branch/gcc/Makefile.in
-===================================================================
---- gcc-4_5-branch.orig/gcc/Makefile.in
-+++ gcc-4_5-branch/gcc/Makefile.in
-@@ -1354,6 +1354,7 @@ OBJS-common = \
- tree-profile.o \
- tree-scalar-evolution.o \
- tree-sra.o \
-+ tree-if-switch-conversion.o \
- tree-switch-conversion.o \
- tree-ssa-address.o \
- tree-ssa-alias.o \
-@@ -3013,6 +3014,11 @@ tree-sra.o : tree-sra.c $(CONFIG_H) $(SY
- $(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) $(IPA_PROP_H) \
- $(DIAGNOSTIC_H) statistics.h $(TREE_DUMP_H) $(TIMEVAR_H) $(PARAMS_H) \
- $(TARGET_H) $(FLAGS_H) $(EXPR_H) $(TREE_INLINE_H)
-+tree-if-switch-conversion.o : tree-if-switch-conversion.c $(CONFIG_H) \
-+ $(SYSTEM_H) $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) \
-+ $(TREE_INLINE_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
-+ $(GIMPLE_H) $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) output.h \
-+ $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H)
- tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \
- $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
- $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \
-Index: gcc-4_5-branch/gcc/common.opt
-===================================================================
---- gcc-4_5-branch.orig/gcc/common.opt
-+++ gcc-4_5-branch/gcc/common.opt
-@@ -1285,6 +1285,10 @@ ftree-switch-conversion
- Common Report Var(flag_tree_switch_conversion) Optimization
- Perform conversions of switch initializations.
-
-+ftree-if-to-switch-conversion
-+Common Report Var(flag_tree_if_to_switch_conversion) Optimization
-+Perform conversions of chains of ifs into switches.
-+
- ftree-dce
- Common Report Var(flag_tree_dce) Optimization
- Enable SSA dead code elimination optimization on trees
-Index: gcc-4_5-branch/gcc/doc/invoke.texi
-===================================================================
---- gcc-4_5-branch.orig/gcc/doc/invoke.texi
-+++ gcc-4_5-branch/gcc/doc/invoke.texi
-@@ -382,7 +382,8 @@ Objective-C and Objective-C++ Dialects}.
- -fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol
- -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol
- -ftree-copyrename -ftree-dce @gol
---ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-im @gol
-+-ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre @gol
-+-ftree-if-to-switch-conversion -ftree-loop-im @gol
- -ftree-phiprop -ftree-loop-distribution @gol
- -ftree-loop-ivcanon -ftree-loop-linear -ftree-loop-optimize @gol
- -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-pta -ftree-reassoc @gol
-@@ -5798,6 +5799,7 @@ also turns on the following optimization
- -fsched-interblock -fsched-spec @gol
- -fschedule-insns -fschedule-insns2 @gol
- -fstrict-aliasing -fstrict-overflow @gol
-+-ftree-if-to-switch-conversion @gol
- -ftree-switch-conversion @gol
- -ftree-pre @gol
- -ftree-vrp}
-@@ -6634,6 +6636,10 @@ Perform conversion of simple initializat
- initializations from a scalar array. This flag is enabled by default
- at @option{-O2} and higher.
-
-+@item -ftree-if-to-switch-conversion
-+Perform conversion of chains of ifs into switches. This flag is enabled by
-+default at @option{-O2} and higher.
-+
- @item -ftree-dce
- @opindex ftree-dce
- Perform dead code elimination (DCE) on trees. This flag is enabled by
-@@ -8577,6 +8583,12 @@ loop in the loop nest by a given number
- length can be changed using the @option{loop-block-tile-size}
- parameter. The default value is 51 iterations.
-
-+@item if-to-switch-threshold
-+If-chain to switch conversion, enabled by
-+@option{-ftree-if-to-switch-conversion} convert chains of ifs of sufficient
-+length into switches. The parameter @option{if-to-switch-threshold} can be
-+used to set the minimal required length. The default value is 3.
-+
- @end table
- @end table
-
-Index: gcc-4_5-branch/gcc/opts.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/opts.c
-+++ gcc-4_5-branch/gcc/opts.c
-@@ -905,6 +905,7 @@ decode_options (unsigned int argc, const
- flag_tree_builtin_call_dce = opt2;
- flag_tree_pre = opt2;
- flag_tree_switch_conversion = opt2;
-+ flag_tree_if_to_switch_conversion = opt2;
- flag_ipa_cp = opt2;
- flag_ipa_sra = opt2;
- flag_ee = opt2;
-Index: gcc-4_5-branch/gcc/params.def
-===================================================================
---- gcc-4_5-branch.orig/gcc/params.def
-+++ gcc-4_5-branch/gcc/params.def
-@@ -826,6 +826,11 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTO
- "a pointer to an aggregate with",
- 2, 0, 0)
-
-+DEFPARAM (PARAM_IF_TO_SWITCH_THRESHOLD,
-+ "if-to-switch-threshold",
-+ "Threshold for converting an if-chain into a switch",
-+ 3, 0, 0)
-+
- /*
- Local variables:
- mode:c
-Index: gcc-4_5-branch/gcc/passes.c
-===================================================================
---- gcc-4_5-branch.orig/gcc/passes.c
-+++ gcc-4_5-branch/gcc/passes.c
-@@ -788,6 +788,7 @@ init_optimization_passes (void)
- NEXT_PASS (pass_cd_dce);
- NEXT_PASS (pass_early_ipa_sra);
- NEXT_PASS (pass_tail_recursion);
-+ NEXT_PASS (pass_if_to_switch);
- NEXT_PASS (pass_convert_switch);
- NEXT_PASS (pass_cleanup_eh);
- NEXT_PASS (pass_profile);
-@@ -844,6 +845,7 @@ init_optimization_passes (void)
- NEXT_PASS (pass_phiprop);
- NEXT_PASS (pass_fre);
- NEXT_PASS (pass_copy_prop);
-+ NEXT_PASS (pass_if_to_switch);
- NEXT_PASS (pass_merge_phi);
- NEXT_PASS (pass_vrp);
- NEXT_PASS (pass_dce);
-Index: gcc-4_5-branch/gcc/tree-if-switch-conversion.c
-===================================================================
---- /dev/null
-+++ gcc-4_5-branch/gcc/tree-if-switch-conversion.c
-@@ -0,0 +1,643 @@
-+/* Convert a chain of ifs into a switch.
-+ Copyright (C) 2010 Free Software Foundation, Inc.
-+ Contributed by Tom de Vries <tom@codesourcery.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, write to the Free
-+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-+02110-1301, USA. */
-+
-+
-+/* The following pass converts a chain of ifs into a switch.
-+
-+ The if-chain has the following properties:
-+ - all bbs end in a GIMPLE_COND.
-+ - all but the first bb are empty, apart from the GIMPLE_COND.
-+ - the GIMPLE_CONDs compare the same variable against integer constants.
-+ - the true gotos all target the same bb.
-+ - the false gotos target the next in the if-chain.
-+
-+ F.i., consider the following if-chain:
-+ ...
-+ <bb 4>:
-+ ...
-+ if (D.1993_3 == 32)
-+ goto <bb 3>;
-+ else
-+ goto <bb 5>;
-+
-+ <bb 5>:
-+ if (D.1993_3 == 13)
-+ goto <bb 3>;
-+ else
-+ goto <bb 6>;
-+
-+ <bb 6>:
-+ if (D.1993_3 == 10)
-+ goto <bb 3>;
-+ else
-+ goto <bb 7>;
-+
-+ <bb 7>:
-+ if (D.1993_3 == 9)
-+ goto <bb 3>;
-+ else
-+ goto <bb 8>;
-+ ...
-+
-+ The pass will report this if-chain like this:
-+ ...
-+ var: D.1993_3
-+ first: <bb 4>
-+ true: <bb 3>
-+ last: <bb 7>
-+ constants: 9 10 13 32
-+ ...
-+
-+ and then convert the if-chain into a switch:
-+ ...
-+ <bb 4>:
-+ ...
-+ switch (D.1993_3) <default: <L8>,
-+ case 9: <L7>,
-+ case 10: <L7>,
-+ case 13: <L7>,
-+ case 32: <L7>>
-+ ...
-+
-+ The conversion does not happen if the chain is too short. The threshold is
-+ determined by the parameter PARAM_IF_TO_SWITCH_THRESHOLD.
-+
-+ The pass will try to construct a chain for each bb, unless the bb it is
-+ already contained in a chain. This ensures that all chains will be found,
-+ and that no chain will be constructed twice. The pass constructs and
-+ converts the chains one-by-one, rather than first calculating all the chains
-+ and then doing the conversions.
-+
-+ The pass could detect range-checks in analyze_bb as well, and handle them.
-+ Simple ones, like 'c <= 5', and more complex ones, like
-+ '(unsigned char) c + 247 <= 1', which is generated by the C front-end from
-+ code like '(c == 9 || c == 10)' or '(9 <= c && c <= 10)'. */
-+
-+#include "config.h"
-+#include "system.h"
-+#include "coretypes.h"
-+#include "tm.h"
-+
-+#include "params.h"
-+#include "flags.h"
-+#include "tree.h"
-+#include "basic-block.h"
-+#include "tree-flow.h"
-+#include "tree-flow-inline.h"
-+#include "tree-ssa-operands.h"
-+#include "diagnostic.h"
-+#include "tree-pass.h"
-+#include "tree-dump.h"
-+#include "timevar.h"
-+
-+/* Information we've collected about a single bb. */
-+
-+struct ifsc_info
-+{
-+ /* The variable of the bb's ending GIMPLE_COND, NULL_TREE if not present. */
-+ tree var;
-+ /* The cond_code of the bb's ending GIMPLE_COND. */
-+ enum tree_code cond_code;
-+ /* The constant of the bb's ending GIMPLE_COND. */
-+ tree constant;
-+ /* Successor edge of the bb if its GIMPLE_COND is true. */
-+ edge true_edge;
-+ /* Successor edge of the bb if its GIMPLE_COND is false. */
-+ edge false_edge;
-+ /* Set if the bb has valid ifsc_info. */
-+ bool valid;
-+ /* Set if the bb is part of a chain. */
-+ bool chained;
-+};
-+
-+/* Macros to access the fields of struct ifsc_info. */
-+
-+#define BB_IFSC_VAR(bb) (((struct ifsc_info *)bb->aux)->var)
-+#define BB_IFSC_COND_CODE(bb) (((struct ifsc_info *)bb->aux)->cond_code)
-+#define BB_IFSC_CONSTANT(bb) (((struct ifsc_info *)bb->aux)->constant)
-+#define BB_IFSC_TRUE_EDGE(bb) (((struct ifsc_info *)bb->aux)->true_edge)
-+#define BB_IFSC_FALSE_EDGE(bb) (((struct ifsc_info *)bb->aux)->false_edge)
-+#define BB_IFSC_VALID(bb) (((struct ifsc_info *)bb->aux)->valid)
-+#define BB_IFSC_CHAINED(bb) (((struct ifsc_info *)bb->aux)->chained)
-+
-+/* Data-type describing an if-chain. */
-+
-+struct if_chain
-+{
-+ /* First bb in the chain. */
-+ basic_block first;
-+ /* Last bb in the chain. */
-+ basic_block last;
-+ /* Variable that GIMPLE_CONDs of all bbs in chain compare against. */
-+ tree var;
-+ /* bb that all GIMPLE_CONDs jump to if comparison succeeds. */
-+ basic_block true_dest;
-+ /* Constants that GIMPLE_CONDs of all bbs in chain compare var against. */
-+ VEC (tree, heap) *constants;
-+ /* Same as previous, but sorted and with duplicates removed. */
-+ VEC (tree, heap) *unique_constants;
-+};
-+
-+/* Utility macro. */
-+
-+#define SWAP(T, X, Y) do { T tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
-+
-+/* Helper function for sort_constants. */
-+
-+static int
-+compare_constants (const void *p1, const void *p2)
-+{
-+ const_tree const c1 = *(const_tree const*)p1;
-+ const_tree const c2 = *(const_tree const*)p2;
-+
-+ return tree_int_cst_compare (c1, c2);
-+}
-+
-+/* Sort constants in constants and copy to unique_constants, while skipping
-+ duplicates. */
-+
-+static void
-+sort_constants (VEC (tree,heap) *constants, VEC (tree,heap) **unique_constants)
-+{
-+ size_t len = VEC_length (tree, constants);
-+ unsigned int ix;
-+ tree prev = NULL_TREE, constant;
-+
-+ /* Sort constants. */
-+ qsort (VEC_address (tree, constants), len, sizeof (tree),
-+ compare_constants);
-+
-+ /* Copy to unique_constants, while skipping duplicates. */
-+ for (ix = 0; VEC_iterate (tree, constants, ix, constant); ix++)
-+ {
-+ if (prev != NULL_TREE && tree_int_cst_compare (prev, constant) == 0)
-+ continue;
-+ prev = constant;
-+
-+ VEC_safe_push (tree, heap, *unique_constants, constant);
-+ }
-+}
-+
-+/* Get true_edge and false_edge of a bb ending in a conditional jump. */
-+
-+static void
-+get_edges (basic_block bb, edge *true_edge, edge *false_edge)
-+{
-+ edge e0, e1;
-+ int e0_true;
-+ int n = EDGE_COUNT (bb->succs);
-+ gcc_assert (n == 2);
-+
-+ e0 = EDGE_SUCC (bb, 0);
-+ e1 = EDGE_SUCC (bb, 1);
-+
-+ e0_true = e0->flags & EDGE_TRUE_VALUE;
-+
-+ *true_edge = e0_true ? e0 : e1;
-+ *false_edge = e0_true ? e1 : e0;
-+
-+ gcc_assert ((*true_edge)->flags & EDGE_TRUE_VALUE);
-+ gcc_assert ((*false_edge)->flags & EDGE_FALSE_VALUE);
-+
-+ gcc_assert (((*true_edge)->flags & EDGE_FALLTHRU) == 0);
-+ gcc_assert (((*false_edge)->flags & EDGE_FALLTHRU) == 0);
-+}
-+
-+/* Analyze bb and store results in ifsc_info struct. */
-+
-+static void
-+analyze_bb (basic_block bb)
-+{
-+ gimple stmt = last_stmt (bb);
-+ tree lhs, rhs, var, constant;
-+ edge true_edge, false_edge;
-+ enum tree_code cond_code;
-+
-+ /* Don't redo analysis. */
-+ if (BB_IFSC_VALID (bb))
-+ return;
-+ BB_IFSC_VALID (bb) = true;
-+
-+
-+ /* bb needs to end in GIMPLE_COND. */
-+ if (!stmt || gimple_code (stmt) != GIMPLE_COND)
-+ return;
-+
-+ /* bb needs to end in EQ_EXPR or NE_EXPR. */
-+ cond_code = gimple_cond_code (stmt);
-+ if (cond_code != EQ_EXPR && cond_code != NE_EXPR)
-+ return;
-+
-+ lhs = gimple_cond_lhs (stmt);
-+ rhs = gimple_cond_rhs (stmt);
-+
-+ /* GIMPLE_COND needs to compare variable to constant. */
-+ if ((TREE_CONSTANT (lhs) == 0)
-+ == (TREE_CONSTANT (rhs) == 0))
-+ return;
-+
-+ var = TREE_CONSTANT (lhs) ? rhs : lhs;
-+ constant = TREE_CONSTANT (lhs)? lhs : rhs;
-+
-+ /* Switches cannot handle non-integral types. */
-+ if (!INTEGRAL_TYPE_P(TREE_TYPE (var)))
-+ return;
-+
-+ get_edges (bb, &true_edge, &false_edge);
-+
-+ if (cond_code == NE_EXPR)
-+ SWAP (edge, true_edge, false_edge);
-+
-+ /* TODO: loosen this constraint. In principle it's ok if true_edge->dest has
-+ phis, as long as for each phi all the edges coming from the chain have the
-+ same value. */
-+ if (!gimple_seq_empty_p (phi_nodes (true_edge->dest)))
-+ return;
-+
-+ /* Store analysis in ifsc_info struct. */
-+ BB_IFSC_VAR (bb) = var;
-+ BB_IFSC_COND_CODE (bb) = cond_code;
-+ BB_IFSC_CONSTANT (bb) = constant;
-+ BB_IFSC_TRUE_EDGE (bb) = true_edge;
-+ BB_IFSC_FALSE_EDGE (bb) = false_edge;
-+}
-+
-+/* Grow if-chain forward. */
-+
-+static void
-+grow_if_chain_forward (struct if_chain *chain)
-+{
-+ basic_block next_bb;
-+
-+ while (1)
-+ {
-+ next_bb = BB_IFSC_FALSE_EDGE (chain->last)->dest;
-+
-+ /* next_bb is already part of another chain. */
-+ if (BB_IFSC_CHAINED (next_bb))
-+ break;
-+
-+ /* next_bb needs to be dominated by the last bb. */
-+ if (!single_pred_p (next_bb))
-+ break;
-+
-+ analyze_bb (next_bb);
-+
-+ /* Does next_bb fit in chain? */
-+ if (BB_IFSC_VAR (next_bb) != chain->var
-+ || BB_IFSC_TRUE_EDGE (next_bb)->dest != chain->true_dest)
-+ break;
-+
-+ /* We can only add empty bbs at the end of the chain. */
-+ if (first_stmt (next_bb) != last_stmt (next_bb))
-+ break;
-+
-+ /* Add next_bb at end of chain. */
-+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (next_bb));
-+ BB_IFSC_CHAINED (next_bb) = true;
-+ chain->last = next_bb;
-+ }
-+}
-+
-+/* Grow if-chain backward. */
-+
-+static void
-+grow_if_chain_backward (struct if_chain *chain)
-+{
-+ basic_block prev_bb;
-+
-+ while (1)
-+ {
-+ /* First bb is not empty, cannot grow backwards. */
-+ if (first_stmt (chain->first) != last_stmt (chain->first))
-+ break;
-+
-+ /* First bb has no single predecessor, cannot grow backwards. */
-+ if (!single_pred_p (chain->first))
-+ break;
-+
-+ prev_bb = single_pred (chain->first);
-+
-+ /* prev_bb is already part of another chain. */
-+ if (BB_IFSC_CHAINED (prev_bb))
-+ break;
-+
-+ analyze_bb (prev_bb);
-+
-+ /* Does prev_bb fit in chain? */
-+ if (BB_IFSC_VAR (prev_bb) != chain->var
-+ || BB_IFSC_TRUE_EDGE (prev_bb)->dest != chain->true_dest)
-+ break;
-+
-+ /* Add prev_bb at beginning of chain. */
-+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (prev_bb));
-+ BB_IFSC_CHAINED (prev_bb) = true;
-+ chain->first = prev_bb;
-+ }
-+}
-+
-+/* Grow if-chain containing bb. */
-+
-+static void
-+grow_if_chain (basic_block bb, struct if_chain *chain)
-+{
-+ /* Initialize chain to empty. */
-+ VEC_truncate (tree, chain->constants, 0);
-+ VEC_truncate (tree, chain->unique_constants, 0);
-+
-+ /* bb is already part of another chain. */
-+ if (BB_IFSC_CHAINED (bb))
-+ return;
-+
-+ analyze_bb (bb);
-+
-+ /* bb is not fit to be part of a chain. */
-+ if (BB_IFSC_VAR (bb) == NULL_TREE)
-+ return;
-+
-+ /* Set bb as initial part of the chain. */
-+ VEC_safe_push (tree, heap, chain->constants, BB_IFSC_CONSTANT (bb));
-+ chain->first = chain->last = bb;
-+ chain->var = BB_IFSC_VAR (bb);
-+ chain->true_dest = BB_IFSC_TRUE_EDGE (bb)->dest;
-+
-+ /* bb is part of a chain now. */
-+ BB_IFSC_CHAINED (bb) = true;
-+
-+ /* Grow chain to its maximum size. */
-+ grow_if_chain_forward (chain);
-+ grow_if_chain_backward (chain);
-+
-+ /* Sort constants and skip duplicates. */
-+ sort_constants (chain->constants, &chain->unique_constants);
-+}
-+
-+static void
-+dump_tree_vector (VEC (tree, heap) *vec)
-+{
-+ unsigned int ix;
-+ tree constant;
-+
-+ for (ix = 0; VEC_iterate (tree, vec, ix, constant); ix++)
-+ {
-+ if (ix != 0)
-+ fprintf (dump_file, " ");
-+ print_generic_expr (dump_file, constant, 0);
-+ }
-+ fprintf (dump_file, "\n");
-+}
-+
-+/* Dump if-chain to dump_file. */
-+
-+static void
-+dump_if_chain (struct if_chain *chain)
-+{
-+ if (!dump_file)
-+ return;
-+
-+ fprintf (dump_file, "var: ");
-+ print_generic_expr (dump_file, chain->var, 0);
-+ fprintf (dump_file, "\n");
-+ fprintf (dump_file, "first: <bb %d>\n", chain->first->index);
-+ fprintf (dump_file, "true: <bb %d>\n", chain->true_dest->index);
-+ fprintf (dump_file, "last: <bb %d>\n",chain->last->index);
-+
-+ fprintf (dump_file, "constants: ");
-+ dump_tree_vector (chain->constants);
-+
-+ if (VEC_length (tree, chain->unique_constants)
-+ != VEC_length (tree, chain->constants))
-+ {
-+ fprintf (dump_file, "unique_constants: ");
-+ dump_tree_vector (chain->unique_constants);
-+ }
-+}
-+
-+/* Remove redundant bbs and edges. */
-+
-+static void
-+remove_redundant_bbs_and_edges (struct if_chain *chain, int *false_prob)
-+{
-+ basic_block bb, next;
-+ edge true_edge, false_edge;
-+
-+ for (bb = chain->first;; bb = next)
-+ {
-+ true_edge = BB_IFSC_TRUE_EDGE (bb);
-+ false_edge = BB_IFSC_FALSE_EDGE (bb);
-+
-+ /* Determine next, before we delete false_edge. */
-+ next = false_edge->dest;
-+
-+ /* Accumulate probability. */
-+ *false_prob = (*false_prob * false_edge->probability) / REG_BR_PROB_BASE;
-+
-+ /* Don't remove the new true_edge. */
-+ if (bb != chain->first)
-+ remove_edge (true_edge);
-+
-+ /* Don't remove the new false_edge. */
-+ if (bb != chain->last)
-+ remove_edge (false_edge);
-+
-+ /* Don't remove the first bb. */
-+ if (bb != chain->first)
-+ delete_basic_block (bb);
-+
-+ /* Stop after last. */
-+ if (bb == chain->last)
-+ break;
-+ }
-+}
-+
-+/* Update control flow graph. */
-+
-+static void
-+update_cfg (struct if_chain *chain)
-+{
-+ edge true_edge, false_edge;
-+ int false_prob;
-+ int flags_mask = ~(EDGE_FALLTHRU|EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
-+
-+ /* We keep these 2 edges, and remove the rest. We need this specific
-+ false_edge, because a phi in chain->last->dest might reference (the index
-+ of) this edge. For true_edge, we could pick any of them. */
-+ true_edge = BB_IFSC_TRUE_EDGE (chain->first);
-+ false_edge = BB_IFSC_FALSE_EDGE (chain->last);
-+
-+ /* Update true edge. */
-+ true_edge->flags &= flags_mask;
-+
-+ /* Update false edge. */
-+ redirect_edge_pred (false_edge, chain->first);
-+ false_edge->flags &= flags_mask;
-+
-+ false_prob = REG_BR_PROB_BASE;
-+ remove_redundant_bbs_and_edges (chain, &false_prob);
-+
-+ /* Repair probabilities. */
-+ true_edge->probability = REG_BR_PROB_BASE - false_prob;
-+ false_edge->probability = false_prob;
-+
-+ /* Force recalculation of dominance info. */
-+ free_dominance_info (CDI_DOMINATORS);
-+ free_dominance_info (CDI_POST_DOMINATORS);
-+}
-+
-+/* Create switch statement. Borrows from gimplify_switch_expr. */
-+
-+static void
-+convert_if_chain_to_switch (struct if_chain *chain)
-+{
-+ tree label_decl_true, label_decl_false;
-+ gimple label_true, label_false, gimple_switch;
-+ gimple_stmt_iterator gsi;
-+ tree default_case, other_case, constant;
-+ unsigned int ix;
-+ VEC (tree, heap) *labels;
-+
-+ labels = VEC_alloc (tree, heap, 8);
-+
-+ /* Create and insert true jump label. */
-+ label_decl_true = create_artificial_label (UNKNOWN_LOCATION);
-+ label_true = gimple_build_label (label_decl_true);
-+ gsi = gsi_start_bb (chain->true_dest);
-+ gsi_insert_before (&gsi, label_true, GSI_SAME_STMT);
-+
-+ /* Create and insert false jump label. */
-+ label_decl_false = create_artificial_label (UNKNOWN_LOCATION);
-+ label_false = gimple_build_label (label_decl_false);
-+ gsi = gsi_start_bb (BB_IFSC_FALSE_EDGE (chain->last)->dest);
-+ gsi_insert_before (&gsi, label_false, GSI_SAME_STMT);
-+
-+ /* Create default case label. */
-+ default_case = build3 (CASE_LABEL_EXPR, void_type_node,
-+ NULL_TREE, NULL_TREE,
-+ label_decl_false);
-+
-+ /* Create case labels. */
-+ for (ix = 0; VEC_iterate (tree, chain->unique_constants, ix, constant); ix++)
-+ {
-+ /* TODO: use ranges, as in gimplify_switch_expr. */
-+ other_case = build3 (CASE_LABEL_EXPR, void_type_node,
-+ constant, NULL_TREE,
-+ label_decl_true);
-+ VEC_safe_push (tree, heap, labels, other_case);
-+ }
-+
-+ /* Create and insert switch. */
-+ gimple_switch = gimple_build_switch_vec (chain->var, default_case, labels);
-+ gsi = gsi_for_stmt (last_stmt (chain->first));
-+ gsi_insert_before (&gsi, gimple_switch, GSI_SAME_STMT);
-+
-+ /* Remove now obsolete if. */
-+ gsi_remove (&gsi, true);
-+
-+ VEC_free (tree, heap, labels);
-+}
-+
-+/* Allocation and initialization. */
-+
-+static void
-+init_pass (struct if_chain *chain)
-+{
-+ alloc_aux_for_blocks (sizeof (struct ifsc_info));
-+
-+ chain->constants = VEC_alloc (tree, heap, 8);
-+ chain->unique_constants = VEC_alloc (tree, heap, 8);
-+}
-+
-+/* Deallocation. */
-+
-+static void
-+finish_pass (struct if_chain *chain)
-+{
-+ free_aux_for_blocks ();
-+
-+ VEC_free (tree, heap, chain->constants);
-+ VEC_free (tree, heap, chain->unique_constants);
-+}
-+
-+/* Find if-chains and convert them to switches. */
-+
-+static unsigned int
-+do_if_to_switch (void)
-+{
-+ basic_block bb;
-+ struct if_chain chain;
-+ unsigned int convert_threshold = PARAM_VALUE (PARAM_IF_TO_SWITCH_THRESHOLD);
-+
-+ init_pass (&chain);
-+
-+ for (bb = cfun->cfg->x_entry_block_ptr->next_bb;
-+ bb != cfun->cfg->x_exit_block_ptr;)
-+ {
-+ grow_if_chain (bb, &chain);
-+
-+ do
-+ bb = bb->next_bb;
-+ while (BB_IFSC_CHAINED (bb));
-+
-+ /* Determine if the chain is long enough. */
-+ if (VEC_length (tree, chain.unique_constants) < convert_threshold)
-+ continue;
-+
-+ dump_if_chain (&chain);
-+
-+ convert_if_chain_to_switch (&chain);
-+
-+ update_cfg (&chain);
-+ }
-+
-+ finish_pass (&chain);
-+
-+ return 0;
-+}
-+
-+/* The pass gate. */
-+
-+static bool
-+if_to_switch_gate (void)
-+{
-+ return flag_tree_if_to_switch_conversion;
-+}
-+
-+/* The pass definition. */
-+
-+struct gimple_opt_pass pass_if_to_switch =
-+{
-+ {
-+ GIMPLE_PASS,
-+ "iftoswitch", /* name */
-+ if_to_switch_gate, /* gate */
-+ do_if_to_switch, /* execute */
-+ NULL, /* sub */
-+ NULL, /* next */
-+ 0, /* static_pass_number */
-+ TV_TREE_SWITCH_CONVERSION, /* tv_id */
-+ PROP_cfg | PROP_ssa, /* properties_required */
-+ 0, /* properties_provided */
-+ 0, /* properties_destroyed */
-+ 0, /* todo_flags_start */
-+ TODO_update_ssa | TODO_dump_func
-+ | TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
-+ }
-+};
-Index: gcc-4_5-branch/gcc/tree-pass.h
-===================================================================
---- gcc-4_5-branch.orig/gcc/tree-pass.h
-+++ gcc-4_5-branch/gcc/tree-pass.h
-@@ -560,6 +560,7 @@ extern struct gimple_opt_pass pass_inlin
- extern struct gimple_opt_pass pass_all_early_optimizations;
- extern struct gimple_opt_pass pass_update_address_taken;
- extern struct gimple_opt_pass pass_convert_switch;
-+extern struct gimple_opt_pass pass_if_to_switch;
-
- /* The root of the compilation pass tree, once constructed. */
- extern struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,