summaryrefslogtreecommitdiff
path: root/lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h')
-rw-r--r--lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h927
1 files changed, 927 insertions, 0 deletions
diff --git a/lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h
new file mode 100644
index 0000000..4e97164
--- /dev/null
+++ b/lib/gcc/arm-none-eabi/13.2.1/plugin/include/tree-switch-conversion.h
@@ -0,0 +1,927 @@
+/* Tree switch conversion for GNU compiler.
+ Copyright (C) 2017-2023 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 TREE_SWITCH_CONVERSION_H
+#define TREE_SWITCH_CONVERSION_H
+
+namespace tree_switch_conversion {
+
+/* Type of cluster. */
+
+enum cluster_type
+{
+ SIMPLE_CASE,
+ JUMP_TABLE,
+ BIT_TEST
+};
+
+#define PRINT_CASE(f,c) print_generic_expr (f, c)
+
+/* Abstract base class for representing a cluster of cases.
+
+ Here is the inheritance hierarachy, and the enum_cluster_type
+ values for the concrete subclasses:
+
+ cluster
+ |-simple_cluster (SIMPLE_CASE)
+ `-group_cluster
+ |-jump_table_cluster (JUMP_TABLE)
+ `-bit_test_cluster (BIT_TEST). */
+
+class cluster
+{
+public:
+ /* Constructor. */
+ inline cluster (tree case_label_expr, basic_block case_bb,
+ profile_probability prob, profile_probability subtree_prob);
+
+ /* Destructor. */
+ virtual ~cluster ()
+ {}
+
+ /* Return type. */
+ virtual cluster_type get_type () = 0;
+
+ /* Get low value covered by a cluster. */
+ virtual tree get_low () = 0;
+
+ /* Get high value covered by a cluster. */
+ virtual tree get_high () = 0;
+
+ /* Debug content of a cluster. */
+ virtual void debug () = 0;
+
+ /* Dump content of a cluster. */
+ virtual void dump (FILE *f, bool details = false) = 0;
+
+ /* Emit GIMPLE code to handle the cluster. */
+ virtual void emit (tree, tree, tree, basic_block, location_t) = 0;
+
+ /* Return true if a cluster handles only a single case value and the
+ value is not a range. */
+ virtual bool is_single_value_p ()
+ {
+ return false;
+ }
+
+ /* Return range of a cluster. If value would overflow in type of LOW,
+ then return 0. */
+ static unsigned HOST_WIDE_INT get_range (tree low, tree high)
+ {
+ wide_int w = wi::to_wide (high) - wi::to_wide (low);
+ if (wi::neg_p (w, TYPE_SIGN (TREE_TYPE (low))) || !wi::fits_uhwi_p (w))
+ return 0;
+ return w.to_uhwi () + 1;
+ }
+
+ /* Case label. */
+ tree m_case_label_expr;
+
+ /* Basic block of the case. */
+ basic_block m_case_bb;
+
+ /* Probability of taking this cluster. */
+ profile_probability m_prob;
+
+ /* Probability of reaching subtree rooted at this node. */
+ profile_probability m_subtree_prob;
+
+ /* Probability of default case when reaching the node.
+ It is used by bit-test right now. */
+ profile_probability m_default_prob;
+
+protected:
+ /* Default constructor. */
+ cluster () {}
+};
+
+cluster::cluster (tree case_label_expr, basic_block case_bb,
+ profile_probability prob, profile_probability subtree_prob):
+ m_case_label_expr (case_label_expr), m_case_bb (case_bb), m_prob (prob),
+ m_subtree_prob (subtree_prob),
+ m_default_prob (profile_probability::uninitialized ())
+{
+}
+
+/* Subclass of cluster representing a simple contiguous range
+ from [low..high]. */
+
+class simple_cluster: public cluster
+{
+public:
+ /* Constructor. */
+ inline simple_cluster (tree low, tree high, tree case_label_expr,
+ basic_block case_bb, profile_probability prob,
+ bool has_forward_bb = false);
+
+ /* Destructor. */
+ ~simple_cluster ()
+ {}
+
+ cluster_type
+ get_type () final override
+ {
+ return SIMPLE_CASE;
+ }
+
+ tree
+ get_low () final override
+ {
+ return m_low;
+ }
+
+ tree
+ get_high () final override
+ {
+ return m_high;
+ }
+
+ void set_high (tree high)
+ {
+ m_high = high;
+ }
+
+ void
+ debug () final override
+ {
+ dump (stderr);
+ }
+
+ void
+ dump (FILE *f, bool details ATTRIBUTE_UNUSED = false) final override
+ {
+ PRINT_CASE (f, get_low ());
+ if (get_low () != get_high ())
+ {
+ fprintf (f, "-");
+ PRINT_CASE (f, get_high ());
+ }
+ fprintf (f, " ");
+ }
+
+ void emit (tree, tree, tree, basic_block, location_t) final override
+ {
+ gcc_unreachable ();
+ }
+
+ bool is_single_value_p () final override
+ {
+ return tree_int_cst_equal (get_low (), get_high ());
+ }
+
+ /* Return number of comparisons needed for the case. */
+ unsigned
+ get_comparison_count ()
+ {
+ return m_range_p ? 2 : 1;
+ }
+
+ /* Low value of the case. */
+ tree m_low;
+
+ /* High value of the case. */
+ tree m_high;
+
+ /* True if case is a range. */
+ bool m_range_p;
+
+ /* True if the case will use a forwarder BB. */
+ bool m_has_forward_bb;
+};
+
+simple_cluster::simple_cluster (tree low, tree high, tree case_label_expr,
+ basic_block case_bb, profile_probability prob,
+ bool has_forward_bb):
+ cluster (case_label_expr, case_bb, prob, prob),
+ m_low (low), m_high (high), m_has_forward_bb (has_forward_bb)
+{
+ m_range_p = m_high != NULL;
+ if (m_high == NULL)
+ m_high = m_low;
+}
+
+/* Abstract subclass of jump table and bit test cluster,
+ handling a collection of simple_cluster instances. */
+
+class group_cluster: public cluster
+{
+public:
+ /* Constructor. */
+ group_cluster (vec<cluster *> &clusters, unsigned start, unsigned end);
+
+ /* Destructor. */
+ ~group_cluster ();
+
+ tree
+ get_low () final override
+ {
+ return m_cases[0]->get_low ();
+ }
+
+ tree
+ get_high () final override
+ {
+ return m_cases[m_cases.length () - 1]->get_high ();
+ }
+
+ void
+ debug () final override
+ {
+ dump (stderr);
+ }
+
+ void dump (FILE *f, bool details = false) final override;
+
+ /* List of simple clusters handled by the group. */
+ vec<simple_cluster *> m_cases;
+};
+
+/* Concrete subclass of group_cluster representing a collection
+ of cases to be implemented as a jump table.
+ The "emit" vfunc generates a nested switch statement which
+ is later lowered to a jump table. */
+
+class jump_table_cluster: public group_cluster
+{
+public:
+ /* Constructor. */
+ jump_table_cluster (vec<cluster *> &clusters, unsigned start, unsigned end)
+ : group_cluster (clusters, start, end)
+ {}
+
+ cluster_type
+ get_type () final override
+ {
+ return JUMP_TABLE;
+ }
+
+ void emit (tree index_expr, tree index_type,
+ tree default_label_expr, basic_block default_bb, location_t loc)
+ final override;
+
+ /* Find jump tables of given CLUSTERS, where all members of the vector
+ are of type simple_cluster. New clusters are returned. */
+ static vec<cluster *> find_jump_tables (vec<cluster *> &clusters);
+
+ /* Return true when cluster starting at START and ending at END (inclusive)
+ can build a jump-table. COMPARISON_COUNT is number of comparison
+ operations needed if the clusters are expanded as decision tree.
+ MAX_RATIO tells about the maximum code growth (in percent). */
+ static bool can_be_handled (const vec<cluster *> &clusters, unsigned start,
+ unsigned end, unsigned HOST_WIDE_INT max_ratio,
+ unsigned HOST_WIDE_INT comparison_count);
+
+ /* Return true if cluster starting at START and ending at END (inclusive)
+ is profitable transformation. */
+ static bool is_beneficial (const vec<cluster *> &clusters, unsigned start,
+ unsigned end);
+
+ /* Return the smallest number of different values for which it is best
+ to use a jump-table instead of a tree of conditional branches. */
+ static inline unsigned int case_values_threshold (void);
+
+ /* Return whether jump table expansion is allowed. */
+ static inline bool is_enabled (void);
+};
+
+/* A GIMPLE switch statement can be expanded to a short sequence of bit-wise
+comparisons. "switch(x)" is converted into "if ((1 << (x-MINVAL)) & CST)"
+where CST and MINVAL are integer constants. This is better than a series
+of compare-and-banch insns in some cases, e.g. we can implement:
+
+ if ((x==4) || (x==6) || (x==9) || (x==11))
+
+as a single bit test:
+
+ if ((1<<x) & ((1<<4)|(1<<6)|(1<<9)|(1<<11)))
+
+This transformation is only applied if the number of case targets is small,
+if CST constains at least 3 bits, and "1 << x" is cheap. The bit tests are
+performed in "word_mode".
+
+The following example shows the code the transformation generates:
+
+ int bar(int x)
+ {
+ switch (x)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F':
+ return 1;
+ }
+ return 0;
+ }
+
+==>
+
+ bar (int x)
+ {
+ tmp1 = x - 48;
+ if (tmp1 > (70 - 48)) goto L2;
+ tmp2 = 1 << tmp1;
+ tmp3 = 0b11111100000001111111111;
+ if ((tmp2 & tmp3) != 0) goto L1 ; else goto L2;
+ L1:
+ return 1;
+ L2:
+ return 0;
+ }
+
+TODO: There are still some improvements to this transformation that could
+be implemented:
+
+* A narrower mode than word_mode could be used if that is cheaper, e.g.
+ for x86_64 where a narrower-mode shift may result in smaller code.
+
+* The compounded constant could be shifted rather than the one. The
+ test would be either on the sign bit or on the least significant bit,
+ depending on the direction of the shift. On some machines, the test
+ for the branch would be free if the bit to test is already set by the
+ shift operation.
+
+This transformation was contributed by Roger Sayle, see this e-mail:
+ http://gcc.gnu.org/ml/gcc-patches/2003-01/msg01950.html
+*/
+
+class bit_test_cluster: public group_cluster
+{
+public:
+ /* Constructor. */
+ bit_test_cluster (vec<cluster *> &clusters, unsigned start, unsigned end,
+ bool handles_entire_switch)
+ :group_cluster (clusters, start, end),
+ m_handles_entire_switch (handles_entire_switch)
+ {}
+
+ cluster_type
+ get_type () final override
+ {
+ return BIT_TEST;
+ }
+
+/* Expand a switch statement by a short sequence of bit-wise
+ comparisons. "switch(x)" is effectively converted into
+ "if ((1 << (x-MINVAL)) & CST)" where CST and MINVAL are
+ integer constants.
+
+ INDEX_EXPR is the value being switched on.
+
+ MINVAL is the lowest case value of in the case nodes,
+ and RANGE is highest value minus MINVAL. MINVAL and RANGE
+ are not guaranteed to be of the same type as INDEX_EXPR
+ (the gimplifier doesn't change the type of case label values,
+ and MINVAL and RANGE are derived from those values).
+ MAXVAL is MINVAL + RANGE.
+
+ There *MUST* be max_case_bit_tests or less unique case
+ node targets. */
+ void emit (tree index_expr, tree index_type,
+ tree default_label_expr, basic_block default_bb, location_t loc)
+ final override;
+
+ /* Find bit tests of given CLUSTERS, where all members of the vector
+ are of type simple_cluster. New clusters are returned. */
+ static vec<cluster *> find_bit_tests (vec<cluster *> &clusters);
+
+ /* Return true when RANGE of case values with UNIQ labels
+ can build a bit test. */
+ static bool can_be_handled (unsigned HOST_WIDE_INT range, unsigned uniq);
+
+ /* Return true when cluster starting at START and ending at END (inclusive)
+ can build a bit test. */
+ static bool can_be_handled (const vec<cluster *> &clusters, unsigned start,
+ unsigned end);
+
+ /* Return true when COUNT of cases of UNIQ labels is beneficial for bit test
+ transformation. */
+ static bool is_beneficial (unsigned count, unsigned uniq);
+
+ /* Return true if cluster starting at START and ending at END (inclusive)
+ is profitable transformation. */
+ static bool is_beneficial (const vec<cluster *> &clusters, unsigned start,
+ unsigned end);
+
+/* Split the basic block at the statement pointed to by GSIP, and insert
+ a branch to the target basic block of E_TRUE conditional on tree
+ expression COND.
+
+ It is assumed that there is already an edge from the to-be-split
+ basic block to E_TRUE->dest block. This edge is removed, and the
+ profile information on the edge is re-used for the new conditional
+ jump.
+
+ The CFG is updated. The dominator tree will not be valid after
+ this transformation, but the immediate dominators are updated if
+ UPDATE_DOMINATORS is true.
+
+ Returns the newly created basic block. */
+ static basic_block hoist_edge_and_branch_if_true (gimple_stmt_iterator *gsip,
+ tree cond,
+ basic_block case_bb,
+ profile_probability prob,
+ location_t);
+
+ /* Return whether bit test expansion is allowed. */
+ static inline bool is_enabled (void)
+ {
+ return flag_bit_tests;
+ }
+
+ /* True when the jump table handles an entire switch statement. */
+ bool m_handles_entire_switch;
+
+ /* Maximum number of different basic blocks that can be handled by
+ a bit test. */
+ static const int m_max_case_bit_tests = 3;
+};
+
+/* Helper struct to find minimal clusters. */
+
+class min_cluster_item
+{
+public:
+ /* Constructor. */
+ min_cluster_item (unsigned count, unsigned start, unsigned non_jt_cases):
+ m_count (count), m_start (start), m_non_jt_cases (non_jt_cases)
+ {}
+
+ /* Count of clusters. */
+ unsigned m_count;
+
+ /* Index where is cluster boundary. */
+ unsigned m_start;
+
+ /* Total number of cases that will not be in a jump table. */
+ unsigned m_non_jt_cases;
+};
+
+/* Helper struct to represent switch decision tree. */
+
+class case_tree_node
+{
+public:
+ /* Empty Constructor. */
+ case_tree_node ();
+
+ /* Return true when it has a child. */
+ bool has_child ()
+ {
+ return m_left != NULL || m_right != NULL;
+ }
+
+ /* Left son in binary tree. */
+ case_tree_node *m_left;
+
+ /* Right son in binary tree; also node chain. */
+ case_tree_node *m_right;
+
+ /* Parent of node in binary tree. */
+ case_tree_node *m_parent;
+
+ /* Cluster represented by this tree node. */
+ cluster *m_c;
+};
+
+inline
+case_tree_node::case_tree_node ():
+ m_left (NULL), m_right (NULL), m_parent (NULL), m_c (NULL)
+{
+}
+
+unsigned int
+jump_table_cluster::case_values_threshold (void)
+{
+ unsigned int threshold = param_case_values_threshold;
+
+ if (threshold == 0)
+ threshold = targetm.case_values_threshold ();
+
+ return threshold;
+}
+
+/* Return whether jump table expansion is allowed. */
+bool jump_table_cluster::is_enabled (void)
+{
+ /* If neither casesi or tablejump is available, or flag_jump_tables
+ over-ruled us, we really have no choice. */
+ if (!targetm.have_casesi () && !targetm.have_tablejump ())
+ return false;
+ if (!flag_jump_tables)
+ return false;
+#ifndef ASM_OUTPUT_ADDR_DIFF_ELT
+ if (flag_pic)
+ return false;
+#endif
+
+ return true;
+}
+
+/* A case_bit_test represents a set of case nodes that may be
+ selected from using a bit-wise comparison. HI and LO hold
+ the integer to be tested against, TARGET_EDGE contains the
+ edge to the basic block to jump to upon success and BITS
+ counts the number of case nodes handled by this test,
+ typically the number of bits set in HI:LO. The LABEL field
+ is used to quickly identify all cases in this set without
+ looking at label_to_block for every case label. */
+
+class case_bit_test
+{
+public:
+ wide_int mask;
+ basic_block target_bb;
+ tree label;
+ int bits;
+ profile_probability prob;
+
+ /* Comparison function for qsort to order bit tests by decreasing
+ probability of execution. */
+ static int cmp (const void *p1, const void *p2);
+};
+
+class switch_decision_tree
+{
+public:
+ /* Constructor. */
+ switch_decision_tree (gswitch *swtch): m_switch (swtch), m_phi_mapping (),
+ m_case_bbs (), m_case_node_pool ("struct case_node pool"),
+ m_case_list (NULL)
+ {
+ }
+
+ /* Analyze switch statement and return true when the statement is expanded
+ as decision tree. */
+ bool analyze_switch_statement ();
+
+ /* Attempt to expand CLUSTERS as a decision tree. Return true when
+ expanded. */
+ bool try_switch_expansion (vec<cluster *> &clusters);
+ /* Compute the number of case labels that correspond to each outgoing edge of
+ switch statement. Record this information in the aux field of the edge.
+ */
+ void compute_cases_per_edge ();
+
+ /* Before switch transformation, record all SSA_NAMEs defined in switch BB
+ and used in a label basic block. */
+ void record_phi_operand_mapping ();
+
+ /* Append new operands to PHI statements that were introduced due to
+ addition of new edges to case labels. */
+ void fix_phi_operands_for_edges ();
+
+ /* Generate a decision tree, switching on INDEX_EXPR and jumping to
+ one of the labels in CASE_LIST or to the DEFAULT_LABEL.
+
+ We generate a binary decision tree to select the appropriate target
+ code. */
+ void emit (basic_block bb, tree index_expr,
+ profile_probability default_prob, tree index_type);
+
+ /* Emit step-by-step code to select a case for the value of INDEX.
+ The thus generated decision tree follows the form of the
+ case-node binary tree NODE, whose nodes represent test conditions.
+ DEFAULT_PROB is probability of cases leading to default BB.
+ INDEX_TYPE is the type of the index of the switch. */
+ basic_block emit_case_nodes (basic_block bb, tree index,
+ case_tree_node *node,
+ profile_probability default_prob,
+ tree index_type, location_t);
+
+ /* Take an ordered list of case nodes
+ and transform them into a near optimal binary tree,
+ on the assumption that any target code selection value is as
+ likely as any other.
+
+ The transformation is performed by splitting the ordered
+ list into two equal sections plus a pivot. The parts are
+ then attached to the pivot as left and right branches. Each
+ branch is then transformed recursively. */
+ static void balance_case_nodes (case_tree_node **head,
+ case_tree_node *parent);
+
+ /* Dump ROOT, a list or tree of case nodes, to file F. */
+ static void dump_case_nodes (FILE *f, case_tree_node *root, int indent_step,
+ int indent_level);
+
+ /* Add an unconditional jump to CASE_BB that happens in basic block BB. */
+ static void emit_jump (basic_block bb, basic_block case_bb);
+
+ /* Generate code to compare OP0 with OP1 so that the condition codes are
+ set and to jump to LABEL_BB if the condition is true.
+ COMPARISON is the GIMPLE comparison (EQ, NE, GT, etc.).
+ PROB is the probability of jumping to LABEL_BB. */
+ static basic_block emit_cmp_and_jump_insns (basic_block bb, tree op0,
+ tree op1, tree_code comparison,
+ basic_block label_bb,
+ profile_probability prob,
+ location_t);
+
+ /* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE.
+ PROB is the probability of jumping to LABEL_BB. */
+ static basic_block do_jump_if_equal (basic_block bb, tree op0, tree op1,
+ basic_block label_bb,
+ profile_probability prob,
+ location_t);
+
+ /* Reset the aux field of all outgoing edges of switch basic block. */
+ static inline void reset_out_edges_aux (gswitch *swtch);
+
+ /* Switch statement. */
+ gswitch *m_switch;
+
+ /* Map of PHI nodes that have to be fixed after expansion. */
+ hash_map<tree, tree> m_phi_mapping;
+
+ /* List of basic blocks that belong to labels of the switch. */
+ auto_vec<basic_block> m_case_bbs;
+
+ /* Basic block with default label. */
+ basic_block m_default_bb;
+
+ /* A pool for case nodes. */
+ object_allocator<case_tree_node> m_case_node_pool;
+
+ /* Balanced tree of case nodes. */
+ case_tree_node *m_case_list;
+};
+
+/*
+ Switch initialization conversion
+
+The following pass changes simple initializations of scalars in a switch
+statement into initializations from a static array. Obviously, the values
+must be constant and known at compile time and a default branch must be
+provided. For example, the following code:
+
+ int a,b;
+
+ switch (argc)
+ {
+ case 1:
+ case 2:
+ a_1 = 8;
+ b_1 = 6;
+ break;
+ case 3:
+ a_2 = 9;
+ b_2 = 5;
+ break;
+ case 12:
+ a_3 = 10;
+ b_3 = 4;
+ break;
+ default:
+ a_4 = 16;
+ b_4 = 1;
+ break;
+ }
+ a_5 = PHI <a_1, a_2, a_3, a_4>
+ b_5 = PHI <b_1, b_2, b_3, b_4>
+
+
+is changed into:
+
+ static const int = CSWTCH01[] = {6, 6, 5, 1, 1, 1, 1, 1, 1, 1, 1, 4};
+ static const int = CSWTCH02[] = {8, 8, 9, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 10};
+
+ if (((unsigned) argc) - 1 < 11)
+ {
+ a_6 = CSWTCH02[argc - 1];
+ b_6 = CSWTCH01[argc - 1];
+ }
+ else
+ {
+ a_7 = 16;
+ b_7 = 1;
+ }
+ a_5 = PHI <a_6, a_7>
+ b_b = PHI <b_6, b_7>
+
+There are further constraints. Specifically, the range of values across all
+case labels must not be bigger than param_switch_conversion_branch_ratio
+(default eight) times the number of the actual switch branches.
+
+This transformation was contributed by Martin Jambor, see this e-mail:
+ http://gcc.gnu.org/ml/gcc-patches/2008-07/msg00011.html */
+
+/* The main structure of the pass. */
+class switch_conversion
+{
+public:
+ /* Constructor. */
+ switch_conversion ();
+
+ /* Destructor. */
+ ~switch_conversion ();
+
+ /* The following function is invoked on every switch statement (the current
+ one is given in SWTCH) and runs the individual phases of switch
+ conversion on it one after another until one fails or the conversion
+ is completed. On success, NULL is in m_reason, otherwise points
+ to a string with the reason why the conversion failed. */
+ void expand (gswitch *swtch);
+
+ /* Collection information about SWTCH statement. */
+ void collect (gswitch *swtch);
+
+ /* Checks whether the range given by individual case statements of the switch
+ switch statement isn't too big and whether the number of branches actually
+ satisfies the size of the new array. */
+ bool check_range ();
+
+ /* Checks whether all but the final BB basic blocks are empty. */
+ bool check_all_empty_except_final ();
+
+ /* This function checks whether all required values in phi nodes in final_bb
+ are constants. Required values are those that correspond to a basic block
+ which is a part of the examined switch statement. It returns true if the
+ phi nodes are OK, otherwise false. */
+ bool check_final_bb ();
+
+ /* The following function allocates default_values, target_{in,out}_names and
+ constructors arrays. The last one is also populated with pointers to
+ vectors that will become constructors of new arrays. */
+ void create_temp_arrays ();
+
+ /* Populate the array of default values in the order of phi nodes.
+ DEFAULT_CASE is the CASE_LABEL_EXPR for the default switch branch
+ if the range is non-contiguous or the default case has standard
+ structure, otherwise it is the first non-default case instead. */
+ void gather_default_values (tree default_case);
+
+ /* The following function populates the vectors in the constructors array with
+ future contents of the static arrays. The vectors are populated in the
+ order of phi nodes. */
+ void build_constructors ();
+
+ /* If all values in the constructor vector are products of a linear function
+ a * x + b, then return true. When true, COEFF_A and COEFF_B and
+ coefficients of the linear function. Note that equal values are special
+ case of a linear function with a and b equal to zero. */
+ bool contains_linear_function_p (vec<constructor_elt, va_gc> *vec,
+ wide_int *coeff_a, wide_int *coeff_b);
+
+ /* Return type which should be used for array elements, either TYPE's
+ main variant or, for integral types, some smaller integral type
+ that can still hold all the constants. */
+ tree array_value_type (tree type, int num);
+
+ /* Create an appropriate array type and declaration and assemble a static
+ array variable. Also create a load statement that initializes
+ the variable in question with a value from the static array. SWTCH is
+ the switch statement being converted, NUM is the index to
+ arrays of constructors, default values and target SSA names
+ for this particular array. ARR_INDEX_TYPE is the type of the index
+ of the new array, PHI is the phi node of the final BB that corresponds
+ to the value that will be loaded from the created array. TIDX
+ is an ssa name of a temporary variable holding the index for loads from the
+ new array. */
+ void build_one_array (int num, tree arr_index_type,
+ gphi *phi, tree tidx);
+
+ /* Builds and initializes static arrays initialized with values gathered from
+ the switch statement. Also creates statements that load values from
+ them. */
+ void build_arrays ();
+
+ /* Generates and appropriately inserts loads of default values at the position
+ given by GSI. Returns the last inserted statement. */
+ gassign *gen_def_assigns (gimple_stmt_iterator *gsi);
+
+ /* Deletes the unused bbs and edges that now contain the switch statement and
+ its empty branch bbs. BBD is the now dead BB containing
+ the original switch statement, FINAL is the last BB of the converted
+ switch statement (in terms of succession). */
+ void prune_bbs (basic_block bbd, basic_block final, basic_block default_bb);
+
+ /* Add values to phi nodes in final_bb for the two new edges. E1F is the edge
+ from the basic block loading values from an array and E2F from the basic
+ block loading default values. BBF is the last switch basic block (see the
+ bbf description in the comment below). */
+ void fix_phi_nodes (edge e1f, edge e2f, basic_block bbf);
+
+ /* Creates a check whether the switch expression value actually falls into the
+ range given by all the cases. If it does not, the temporaries are loaded
+ with default values instead. */
+ void gen_inbound_check ();
+
+ /* Switch statement for which switch conversion takes place. */
+ gswitch *m_switch;
+
+ /* The expression used to decide the switch branch. */
+ tree m_index_expr;
+
+ /* The following integer constants store the minimum and maximum value
+ covered by the case labels. */
+ tree m_range_min;
+ tree m_range_max;
+
+ /* The difference between the above two numbers. Stored here because it
+ is used in all the conversion heuristics, as well as for some of the
+ transformation, and it is expensive to re-compute it all the time. */
+ tree m_range_size;
+
+ /* Basic block that contains the actual GIMPLE_SWITCH. */
+ basic_block m_switch_bb;
+
+ /* Basic block that is the target of the default case. */
+ basic_block m_default_bb;
+
+ /* The single successor block of all branches out of the GIMPLE_SWITCH,
+ if such a block exists. Otherwise NULL. */
+ basic_block m_final_bb;
+
+ /* The probability of the default edge in the replaced switch. */
+ profile_probability m_default_prob;
+
+ /* Number of phi nodes in the final bb (that we'll be replacing). */
+ int m_phi_count;
+
+ /* Constructors of new static arrays. */
+ vec<constructor_elt, va_gc> **m_constructors;
+
+ /* Array of default values, in the same order as phi nodes. */
+ tree *m_default_values;
+
+ /* Array of ssa names that are initialized with a value from a new static
+ array. */
+ tree *m_target_inbound_names;
+
+ /* Array of ssa names that are initialized with the default value if the
+ switch expression is out of range. */
+ tree *m_target_outbound_names;
+
+ /* VOP SSA_NAME. */
+ tree m_target_vop;
+
+ /* The first load statement that loads a temporary from a new static array.
+ */
+ gimple *m_arr_ref_first;
+
+ /* The last load statement that loads a temporary from a new static array. */
+ gimple *m_arr_ref_last;
+
+ /* String reason why the case wasn't a good candidate that is written to the
+ dump file, if there is one. */
+ const char *m_reason;
+
+ /* True if default case is not used for any value between range_min and
+ range_max inclusive. */
+ bool m_contiguous_range;
+
+ /* True if default case does not have the required shape for other case
+ labels. */
+ bool m_default_case_nonstandard;
+
+ /* Number of uniq labels for non-default edges. */
+ unsigned int m_uniq;
+
+ /* Count is number of non-default edges. */
+ unsigned int m_count;
+
+ /* True if CFG has been changed. */
+ bool m_cfg_altered;
+};
+
+void
+switch_decision_tree::reset_out_edges_aux (gswitch *swtch)
+{
+ basic_block bb = gimple_bb (swtch);
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ e->aux = (void *) 0;
+}
+
+/* Release CLUSTERS vector and destruct all dynamically allocated items. */
+
+inline void
+release_clusters (vec<cluster *> &clusters)
+{
+ for (unsigned i = 0; i < clusters.length (); i++)
+ delete clusters[i];
+ clusters.release ();
+}
+
+} // tree_switch_conversion namespace
+
+#endif // TREE_SWITCH_CONVERSION_H