Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-switch-conversion.h @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/tree-switch-conversion.h Thu Oct 25 10:21:07 2018 +0900 @@ -0,0 +1,883 @@ +/* Tree switch conversion for GNU compiler. + Copyright (C) 2017 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). */ + +struct cluster +{ + /* Constructor. */ + 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) = 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) + { + tree r = fold_build2 (MINUS_EXPR, TREE_TYPE (low), high, low); + if (!tree_fits_uhwi_p (r)) + return 0; + + return tree_to_uhwi (r) + 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; + +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) +{ +} + +/* Subclass of cluster representing a simple contiguous range + from [low..high]. */ + +struct simple_cluster: public cluster +{ + /* Constructor. */ + simple_cluster (tree low, tree high, tree case_label_expr, + basic_block case_bb, profile_probability prob); + + /* Destructor. */ + ~simple_cluster () + {} + + cluster_type + get_type () + { + return SIMPLE_CASE; + } + + tree + get_low () + { + return m_low; + } + + tree + get_high () + { + return m_high; + } + + void + debug () + { + dump (stderr); + } + + void + dump (FILE *f, bool details ATTRIBUTE_UNUSED = false) + { + 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) + { + gcc_unreachable (); + } + + bool is_single_value_p () + { + return tree_int_cst_equal (get_low (), get_high ()); + } + + /* 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; +}; + +simple_cluster::simple_cluster (tree low, tree high, tree case_label_expr, + basic_block case_bb, profile_probability prob): + cluster (case_label_expr, case_bb, prob, prob), + m_low (low), m_high (high) +{ + 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. */ + +struct group_cluster: public cluster +{ + /* Constructor. */ + group_cluster (vec<cluster *> &clusters, unsigned start, unsigned end); + + /* Destructor. */ + ~group_cluster (); + + tree + get_low () + { + return m_cases[0]->get_low (); + } + + tree + get_high () + { + return m_cases[m_cases.length () - 1]->get_high (); + } + + void + debug () + { + dump (stderr); + } + + void dump (FILE *f, bool details = false); + + /* 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 gernerates a nested switch statement which + is later lowered to a jump table. */ + +struct jump_table_cluster: public group_cluster +{ + /* Constructor. */ + jump_table_cluster (vec<cluster *> &clusters, unsigned start, unsigned end) + : group_cluster (clusters, start, end) + {} + + cluster_type + get_type () + { + return JUMP_TABLE; + } + + void emit (tree index_expr, tree index_type, + tree default_label_expr, basic_block default_bb); + + /* 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. */ + static bool can_be_handled (const vec<cluster *> &clusters, unsigned start, + unsigned end); + + /* 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 bool is_enabled (void); + + /* Max growth ratio for code that is optimized for size. */ + static const unsigned HOST_WIDE_INT max_ratio_for_size = 3; + + /* Max growth ratio for code that is optimized for speed. */ + static const unsigned HOST_WIDE_INT max_ratio_for_speed = 8; +}; + +/* 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 +*/ + +struct bit_test_cluster: public group_cluster +{ + /* 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 () + { + 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); + + /* 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); + + /* 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. */ + +struct min_cluster_item +{ + /* 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. */ + +struct case_tree_node +{ + /* 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_VALUE (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. */ + +struct case_bit_test +{ + wide_int mask; + basic_block target_bb; + tree label; + int bits; + + /* Comparison function for qsort to order bit tests by decreasing + probability of execution. */ + static int cmp (const void *p1, const void *p2); +}; + +struct switch_decision_tree +{ + /* 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); + + /* 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); + + /* 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); + + /* 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 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. */ +struct switch_conversion +{ + /* 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; + + /* The count of the default edge in the replaced switch. */ + profile_count m_default_count; + + /* Combined count of all other (non-default) edges in the replaced switch. */ + profile_count m_other_count; + + /* 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; +} + +} // tree_switch_conversion namespace + +#endif // TREE_SWITCH_CONVERSION_H