+#ifndef FIRST_PSEUDO_REGISTER
+#define NULL 0
+#include "config.h"
+#include "rtl.h"
+#include "tree.h"
+#include "insn-flags.h"
+#endif
+
+/* Functions and data structures for expanding case statements. */
+
+/* Case label structure, used to hold info on labels within case
+ statements. We handle "range" labels; for a single-value label
+ as in C, the high and low limits are the same. */
+
+struct case_node
+{
+ struct case_node *left;
+ struct case_node *right;
+ struct case_node *parent;
+ tree low;
+ tree high;
+ tree test_label;
+ tree code_label;
+};
+
+typedef struct case_node case_node;
+typedef struct case_node *case_node_ptr;
+
+void balance_case_nodes ();
+void emit_case_nodes ();
+void group_case_nodes ();
+void emit_jump_if_reachable ();
+
+/* Generate code to jump to LABEL if OP1 and OP2 are equal. */
+
+static void
+do_jump_if_equal (op1, op2, label, unsignedp)
+ rtx op1, op2, label;
+ int unsignedp;
+{
+ if (GET_CODE (op1) == CONST_INT
+ && GET_CODE (op2) == CONST_INT)
+ {
+ if (INTVAL (op1) == INTVAL (op2))
+ emit_jump (label);
+ }
+ else
+ {
+ emit_cmp_insn (op1, op2, 0, unsignedp, 0);
+ emit_jump_insn (gen_beq (label));
+ }
+}
+\f
+/* Not all case values are encountered equally. This function
+ uses a heuristic to weight case labels, in cases where that
+ looks like a reasonable thing to do.
+
+ Right now, all we try to guess is text, and we establish the
+ following weights:
+
+ chars above space: 16
+ digits: 16
+ default: 12
+ space, punct: 8
+ tab: 4
+ newline: 2
+ other "\" chars: 1
+ remaining chars: 0
+
+ Under this weighting, ranges are automagically taken care of. */
+
+#include <ctype.h>
+static char *cost_table;
+static int use_cost_table;
+
+void
+estimate_case_costs (node, default_label)
+ case_node_ptr node;
+ rtx default_label;
+{
+ tree min_ascii = build_int_2 (-1, -1);
+ tree max_ascii = convert (TREE_TYPE (node->high), build_int_2 (127, 0));
+ case_node_ptr n;
+ use_cost_table = 0;
+
+ /* If the user is running without default, who are we
+ to guess where values are likely to land? */
+ if (default_label == 0)
+ return;
+
+ /* See if all the case expressions look like text. It is text if the lowest
+ constant is >= -1 and the highest constant is <= 127. If the case
+ expression is unsigned, suppress the test for >= -1, since it would always
+ be true. */
+ for (n = node; n; n = n->right)
+ if ((! TREE_UNSIGNED (TREE_TYPE (n->low))
+ && tree_int_cst_lt (n->low, min_ascii))
+ || tree_int_cst_lt (max_ascii, n->high))
+ return;
+
+ /* All interesting values with within the range of
+ interesting ASCII characters. */
+ if (cost_table == NULL)
+ {
+ int i;
+ cost_table = ((char *)malloc (129)) + 1;
+ bzero (cost_table-1, 128);
+ for (i = 0; i < 128; i++)
+ {
+ if (isalnum (i))
+ cost_table[i] = 16;
+ else if (ispunct (i))
+ cost_table[i] = 8;
+ else if (iscntrl (i))
+ cost_table[i] = -1;
+ }
+ cost_table[' '] = 8;
+ cost_table['\t'] = 4;
+ cost_table['\0'] = 4;
+ cost_table['\n'] = 2;
+ cost_table['\f'] = 1;
+ cost_table['\v'] = 1;
+ cost_table['\b'] = 1;
+ }
+ use_cost_table = 1;
+}
+\f
+/* Scan an ordered list of case nodes
+ combining those with consecutive values or ranges.
+
+ Eg. three separate entries 1: 2: 3: become one entry 1..3: */
+
+void
+group_case_nodes (head)
+ case_node_ptr head;
+{
+ case_node_ptr node = head;
+
+ while (node)
+ {
+ rtx lb = next_real_insn (label_rtx (node->code_label));
+ case_node_ptr np = node;
+
+ /* Try to group the successors of NODE with NODE. */
+ while (((np = np->right) != 0)
+ /* Do they jump to the same place? */
+ && next_real_insn (label_rtx (np->code_label)) == lb
+ /* Are their ranges consecutive? */
+ && tree_int_cst_equal (np->low,
+ combine (PLUS_EXPR, node->high,
+ integer_one_node)))
+ {
+ node->high = np->high;
+ }
+ /* NP is the first node after NODE which can't be grouped with it.
+ Delete the nodes in between, and move on to that node. */
+ node->right = np;
+ node = np;
+ }
+}
+
+/* Take an ordered list of case nodes
+ and transform them into a near optimal binary tree,
+ on the assumtion 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 is then transformed recursively. */
+
+void
+balance_case_nodes (head, parent)
+ case_node_ptr *head;
+ case_node_ptr parent;
+{
+ register case_node_ptr np;
+
+ np = *head;
+ if (np)
+ {
+ int cost = 0;
+ int i = 0;
+ int ranges = 0;
+ register case_node_ptr *npp;
+ case_node_ptr left;
+
+ /* Count the number of entries on branch.
+ Also count the ranges. */
+ while (np)
+ {
+ if (!tree_int_cst_equal (np->low, np->high))
+ {
+ ranges++;
+ if (use_cost_table)
+ {
+ int hi_cost = cost_table[TREE_INT_CST_LOW (np->high)];
+ if (hi_cost < 0)
+ use_cost_table = 0;
+ else
+ cost += hi_cost;
+ }
+ }
+ if (use_cost_table)
+ {
+ int lo_cost = cost_table[TREE_INT_CST_LOW (np->low)];
+ if (lo_cost < 0)
+ use_cost_table = 0;
+ else
+ cost += lo_cost;
+ }
+ else
+ cost += 1;
+ i++;
+ np = np->right;
+ }
+ if (i > 2)
+ {
+ /* Split this list if it is long enough for that to help. */
+ npp = head;
+ left = *npp;
+ if (use_cost_table)
+ {
+ /* Find the place in the list that bisects the list's total cost,
+ Here I gets half the total cost. */
+ int n_moved = 0;
+ i = (cost + 1) / 2;
+ while (1)
+ {
+ /* Skip nodes while their cost does not reach that amount. */
+ if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
+ i -= cost_table[TREE_INT_CST_LOW ((*npp)->high)];
+ i -= cost_table[TREE_INT_CST_LOW ((*npp)->low)];
+ if (i <= 0)
+ break;
+ npp = &(*npp)->right;
+ n_moved += 1;
+ }
+ if (n_moved == 0)
+ {
+ /* Leave this branch lopsided, but optimize left-hand
+ side and fill in `parent' fields for right-hand side. */
+ np = *head;
+ np->parent = parent;
+ balance_case_nodes (&np->left, np);
+ for (; np->right; np = np->right)
+ np->right->parent = np;
+ return;
+ }
+ }
+ /* If there are just three nodes, split at the middle one. */
+ else if (i == 3)
+ npp = &(*npp)->right;
+ else
+ {
+ /* Find the place in the list that bisects the list's total cost,
+ where ranges count as 2.
+ Here I gets half the total cost. */
+ i = (i + ranges + 1) / 2;
+ while (1)
+ {
+ /* Skip nodes while their cost does not reach that amount. */
+ if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
+ i--;
+ i--;
+ if (i <= 0)
+ break;
+ npp = &(*npp)->right;
+ }
+ }
+ *head = np = *npp;
+ *npp = 0;
+ np->parent = parent;
+ np->left = left;
+
+ /* Optimize each of the two split parts. */
+ balance_case_nodes (&np->left, np);
+ balance_case_nodes (&np->right, np);
+ }
+ else
+ {
+ /* Else leave this branch as one level,
+ but fill in `parent' fields. */
+ np = *head;
+ np->parent = parent;
+ for (; np->right; np = np->right)
+ np->right->parent = np;
+ }
+ }
+}
+\f
+/* Search the parent sections of the case node tree
+ to see if a test for the lower bound of NODE would be redundant.
+
+ The instructions to synthesis the case decision tree are
+ output in the same order as nodes are processed so it is
+ known that if a parent node checks the range of the current
+ node minus one that the current node is bounded at its lower
+ span. Thus the test would be redundant. */
+
+static int
+node_has_low_bound (node)
+ case_node_ptr node;
+{
+ tree low_minus_one;
+ case_node_ptr pnode;
+
+ if (node->left)
+ {
+ low_minus_one = combine (MINUS_EXPR, node->low, integer_one_node);
+ /* Avoid the screw case of overflow where low_minus_one is > low. */
+ if (tree_int_cst_lt (low_minus_one, node->low))
+ for (pnode = node->parent; pnode; pnode = pnode->parent)
+ {
+ if (tree_int_cst_equal (low_minus_one, pnode->high))
+ return 1;
+ /* If a parent node has a left branch we know that none
+ of its parents can have a high bound of our target
+ minus one so we abort the search. */
+ if (node->left)
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Search the parent sections of the case node tree
+ to see if a test for the upper bound of NODE would be redundant.
+
+ The instructions to synthesis the case decision tree are
+ output in the same order as nodes are processed so it is
+ known that if a parent node checks the range of the current
+ node plus one that the current node is bounded at its upper
+ span. Thus the test would be redundant. */
+
+static int
+node_has_high_bound (node)
+ case_node_ptr node;
+{
+ tree high_plus_one;
+ case_node_ptr pnode;
+
+ if (node->right == 0)
+ {
+ high_plus_one = combine (PLUS_EXPR, node->high, integer_one_node);
+ /* Avoid the screw case of overflow where high_plus_one is > high. */
+ if (tree_int_cst_lt (node->high, high_plus_one))
+ for (pnode = node->parent; pnode; pnode = pnode->parent)
+ {
+ if (tree_int_cst_equal (high_plus_one, pnode->low))
+ return 1;
+ /* If a parent node has a right branch we know that none
+ of its parents can have a low bound of our target
+ plus one so we abort the search. */
+ if (node->right)
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Search the parent sections of the
+ case node tree to see if both tests for the upper and lower
+ bounds of NODE would be redundant. */
+
+static int
+node_is_bounded (node)
+ case_node_ptr node;
+{
+ if (node->left || node->right)
+ return 0;
+ return node_has_low_bound (node) && node_has_high_bound (node);
+}
+
+/* Emit an unconditional jump to LABEL unless it would be dead code. */
+
+void
+emit_jump_if_reachable (label)
+ rtx label;
+{
+ rtx last_insn;
+
+ if (GET_CODE (get_last_insn ()) != BARRIER)
+ emit_jump (label);
+}
+\f
+/* 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.
+ UNSIGNEDP is nonzero if we should do unsigned comparisons.
+
+ Care is taken to prune redundant tests from the decision tree
+ by detecting any boundary conditions already checked by
+ emitted rtx. (See node_has_high_bound, node_has_low_bound
+ and node_is_bounded, above.)
+
+ Where the test conditions can be shown to be redundant we emit
+ an unconditional jump to the target code. As a further
+ optimization, the subordinates of a tree node are examined to
+ check for bounded nodes. In this case conditional and/or
+ unconditional jumps as a result of the boundary check for the
+ current node are arranged to target the subordinates associated
+ code for out of bound conditions on the current node node. */
+
+void
+emit_case_nodes (index, node, default_label, unsignedp)
+ rtx index;
+ case_node_ptr node;
+ rtx default_label;
+ int unsignedp;
+{
+ /* If INDEX has an unsigned type, we must make unsigned branches. */
+ typedef rtx rtx_function ();
+ rtx_function *gen_bgt_pat = unsignedp ? gen_bgtu : gen_bgt;
+ rtx_function *gen_bge_pat = unsignedp ? gen_bgeu : gen_bge;
+ rtx_function *gen_blt_pat = unsignedp ? gen_bltu : gen_blt;
+ rtx_function *gen_ble_pat = unsignedp ? gen_bleu : gen_ble;
+ int defaulted_left = 0;
+ int defaulted_right = 0;
+
+ if (node->test_label)
+ {
+ /* If this test node requires a label it follows that
+ it must be preceeded by an unconditional branch.
+ If control can pass to this point we can assume that
+ a "br default" is in order. */
+ emit_jump_if_reachable (default_label);
+ expand_label (node->test_label);
+ }
+ if (tree_int_cst_equal (node->low, node->high))
+ {
+ /* Node is single valued. */
+ do_jump_if_equal (index, expand_expr (node->low, 0, VOIDmode, 0),
+ label_rtx (node->code_label), unsignedp);
+ if (node->right)
+ {
+ if (node->left)
+ {
+ /* This node has children on either side. */
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+
+ if (node_is_bounded (node->right))
+ {
+ emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label)));
+ if (node_is_bounded (node->left))
+ emit_jump (label_rtx (node->left->code_label));
+ else
+ emit_case_nodes (index, node->left,
+ default_label, unsignedp);
+ }
+ else
+ {
+ if (node_is_bounded (node->left))
+ emit_jump_insn ((*gen_blt_pat) (label_rtx (node->left->code_label)));
+ else
+ {
+ node->right->test_label =
+ build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->test_label)));
+ emit_case_nodes (index, node->left,
+ default_label, unsignedp);
+ }
+ emit_case_nodes (index, node->right,
+ default_label, unsignedp);
+ }
+ }
+ else
+ {
+ /* Here we have a right child but no left
+ so we issue conditional branch to default
+ and process the right child. */
+
+ /* Omit the conditional branch to default
+ if we it avoid only one right child;
+ it costs too much space to save so little time. */
+ if (node->right->right && !node_has_low_bound (node))
+ {
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_blt_pat) (default_label));
+ }
+ if (node_is_bounded (node->right))
+ emit_jump (label_rtx (node->right->code_label));
+ else
+ emit_case_nodes (index, node->right, default_label, unsignedp);
+ }
+ }
+ else if (node->left)
+ {
+ if (use_cost_table
+ && ! defaulted_right
+ && cost_table[TREE_INT_CST_LOW (node->high)] < 12)
+ {
+ /* If our "most probably entry" is less probable
+ than the default label, emit a jump to
+ the default label using condition codes
+ already lying around. With no right branch,
+ a branch-greater-than will get us to the default
+ label correctly. */
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bgt_pat) (default_label));
+ /* No sense doing this too often. */
+ defaulted_right = 1;
+ }
+ if (node_is_bounded (node->left))
+ emit_jump (label_rtx (node->left->code_label));
+ else
+ emit_case_nodes (index, node->left, default_label, unsignedp);
+ }
+ }
+ else
+ {
+ /* Node is a range. */
+ if (node->right)
+ {
+ if (node->left)
+ {
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ if (node_is_bounded (node->right))
+ {
+ /* Right hand node is fully bounded so we can
+ eliminate any testing and branch directly
+ to the target code. */
+ emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->code_label)));
+ }
+ else
+ {
+ /* Right hand node requires testing so create
+ a label to put on the cmp code. */
+ node->right->test_label =
+ build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+ emit_jump_insn ((*gen_bgt_pat) (label_rtx (node->right->test_label)));
+ }
+ emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
+ if (node_is_bounded (node->left))
+ {
+ /* Left hand node is fully bounded so we can
+ eliminate any testing and branch directly
+ to the target code. */
+ emit_jump (label_rtx (node->left->code_label));
+ }
+ else
+ emit_case_nodes (index, node->left, default_label, unsignedp);
+ /* If right node has been given a test label above
+ we must process it now. */
+ if (node->right->test_label)
+ emit_case_nodes (index, node->right, default_label, unsignedp);
+ }
+ else
+ {
+ if (!node_has_low_bound (node))
+ {
+ emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_blt_pat) (default_label));
+ }
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_ble_pat) (label_rtx (node->code_label)));
+ if (node_is_bounded (node->right))
+ {
+ /* Right hand node is fully bounded so we can
+ eliminate any testing and branch directly
+ to the target code. */
+ emit_jump (label_rtx (node->right->code_label));
+ }
+ else
+ emit_case_nodes (index, node->right, default_label, unsignedp);
+ }
+ }
+ else if (node->left)
+ {
+ if (!node_has_high_bound (node))
+ {
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bgt_pat) (default_label));
+ }
+ emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
+ if (node_is_bounded (node->left))
+ {
+ /* Left hand node is fully bounded so we can
+ eliminate any testing and branch directly
+ to the target code. */
+ emit_jump (label_rtx (node->left->code_label));
+ }
+ else
+ emit_case_nodes (index, node->left, default_label, unsignedp);
+ }
+ else
+ {
+ /* Node has no children so we check low and
+ high bounds to remove redundant tests. In practice
+ only one of the limits may be bounded or the parent
+ node will have emmited a jump to our target code. */
+ if (!node_has_high_bound (node))
+ {
+ emit_cmp_insn (index, expand_expr (node->high, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bgt_pat) (default_label));
+ }
+ if (!node_has_low_bound (node))
+ {
+ emit_cmp_insn (index, expand_expr (node->low, 0, VOIDmode, 0), 0, unsignedp, 0);
+ emit_jump_insn ((*gen_bge_pat) (label_rtx (node->code_label)));
+ }
+ /* We allow the default case to drop through since
+ it will picked up by calls to `jump_if_reachable'
+ either on the next test label or at the end of
+ the decision tree emission. */
+ }
+ }
+}
+