re PR middle-end/17657 (ICE in expand_case)
PR middle-end/17657 * stmt.c (add_case_node): Add additional type argument. Declare as static to match prototype. Convert the upper and lower bounds to the specified index type. Optimize away case ranges/values that are outside the index type's bounds. Truncate case ranges that span the index type's bounds. (expand_case): Avoid unnessary computation and memory allocation when index type is error_mark_node. Pass index_type as required by change to add_case_node API. No need to convert case range bounds to index_type, this is now done by add_case_node. * gcc.dg/switch-4.c: New test case. From-SVN: r88881
This commit is contained in:
parent
539ed333f6
commit
eb172681f7
@ -1,3 +1,16 @@
|
||||
2004-10-11 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR middle-end/17657
|
||||
* stmt.c (add_case_node): Add additional type argument. Declare
|
||||
as static to match prototype. Convert the upper and lower bounds
|
||||
to the specified index type. Optimize away case ranges/values
|
||||
that are outside the index type's bounds. Truncate case ranges
|
||||
that span the index type's bounds.
|
||||
(expand_case): Avoid unnessary computation and memory allocation
|
||||
when index type is error_mark_node. Pass index_type as required
|
||||
by change to add_case_node API. No need to convert case range
|
||||
bounds to index_type, this is now done by add_case_node.
|
||||
|
||||
2004-10-11 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/s390/s390-protos.h (s390_offset_p): Add prototype.
|
||||
|
104
gcc/stmt.c
104
gcc/stmt.c
@ -122,7 +122,8 @@ static int node_has_low_bound (case_node_ptr, tree);
|
||||
static int node_has_high_bound (case_node_ptr, tree);
|
||||
static int node_is_bounded (case_node_ptr, tree);
|
||||
static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
|
||||
static struct case_node *add_case_node (struct case_node *, tree, tree, tree);
|
||||
static struct case_node *add_case_node (struct case_node *, tree,
|
||||
tree, tree, tree);
|
||||
|
||||
|
||||
/* Return the rtx-label that corresponds to a LABEL_DECL,
|
||||
@ -2115,19 +2116,55 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
|
||||
/* Do the insertion of a case label into case_list. The labels are
|
||||
fed to us in descending order from the sorted vector of case labels used
|
||||
in the tree part of the middle end. So the list we construct is
|
||||
sorted in ascending order. */
|
||||
sorted in ascending order. The bounds on the case range, LOW and HIGH,
|
||||
are converted to case's index type TYPE. */
|
||||
|
||||
struct case_node *
|
||||
add_case_node (struct case_node *head, tree low, tree high, tree label)
|
||||
static struct case_node *
|
||||
add_case_node (struct case_node *head, tree type, tree low, tree high,
|
||||
tree label)
|
||||
{
|
||||
tree min_value, max_value;
|
||||
struct case_node *r;
|
||||
|
||||
gcc_assert (TREE_CODE (low) == INTEGER_CST);
|
||||
gcc_assert (!high || TREE_CODE (high) == INTEGER_CST);
|
||||
|
||||
min_value = TYPE_MIN_VALUE (type);
|
||||
max_value = TYPE_MAX_VALUE (type);
|
||||
|
||||
/* If there's no HIGH value, then this is not a case range; it's
|
||||
just a simple case label. But that's just a degenerate case
|
||||
range.
|
||||
If the bounds are equal, turn this into the one-value case. */
|
||||
if (!high || tree_int_cst_equal (low, high))
|
||||
high = low;
|
||||
{
|
||||
/* If the simple case value is unreachable, ignore it. */
|
||||
if (tree_int_cst_compare (low, min_value) < 0
|
||||
|| tree_int_cst_compare (low, max_value) > 0)
|
||||
return head;
|
||||
low = fold_convert (type, low);
|
||||
high = low;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the entire case range is unreachable, ignore it. */
|
||||
if (tree_int_cst_compare (high, min_value) < 0
|
||||
|| tree_int_cst_compare (low, max_value) > 0)
|
||||
return head;
|
||||
|
||||
/* If the lower bound is less than the index type's minimum
|
||||
value, truncate the range bounds. */
|
||||
if (tree_int_cst_compare (low, min_value) < 0)
|
||||
low = min_value;
|
||||
low = fold_convert (type, low);
|
||||
|
||||
/* If the upper bound is greater than the index type's maximum
|
||||
value, truncate the range bounds. */
|
||||
if (tree_int_cst_compare (high, max_value) > 0)
|
||||
high = max_value;
|
||||
high = fold_convert (type, high);
|
||||
}
|
||||
|
||||
|
||||
/* Add this label to the chain. */
|
||||
r = ggc_alloc (sizeof (struct case_node));
|
||||
@ -2307,7 +2344,7 @@ expand_case (tree exp)
|
||||
rtx table_label;
|
||||
int ncases;
|
||||
rtx *labelvec;
|
||||
int i;
|
||||
int i, fail;
|
||||
rtx before_case, end, lab;
|
||||
|
||||
tree vec = SWITCH_LABELS (exp);
|
||||
@ -2332,34 +2369,36 @@ expand_case (tree exp)
|
||||
gcc_assert (!SWITCH_BODY (exp));
|
||||
gcc_assert (SWITCH_LABELS (exp));
|
||||
|
||||
for (i = TREE_VEC_LENGTH (vec); --i >= 0; )
|
||||
{
|
||||
tree elt = TREE_VEC_ELT (vec, i);
|
||||
|
||||
/* Handle default labels specially. */
|
||||
if (!CASE_HIGH (elt) && !CASE_LOW (elt))
|
||||
{
|
||||
gcc_assert (!default_label_decl);
|
||||
default_label_decl = CASE_LABEL (elt);
|
||||
}
|
||||
else
|
||||
case_list = add_case_node (case_list, CASE_LOW (elt), CASE_HIGH (elt),
|
||||
CASE_LABEL (elt));
|
||||
}
|
||||
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
/* Make sure start points to something that won't need any transformation
|
||||
before the end of this function. */
|
||||
if (!NOTE_P (get_last_insn ()))
|
||||
emit_note (NOTE_INSN_DELETED);
|
||||
|
||||
start = get_last_insn ();
|
||||
|
||||
/* An ERROR_MARK occurs for various reasons including invalid data type. */
|
||||
if (index_type != error_mark_node)
|
||||
{
|
||||
int fail;
|
||||
for (i = TREE_VEC_LENGTH (vec); --i >= 0; )
|
||||
{
|
||||
tree elt = TREE_VEC_ELT (vec, i);
|
||||
|
||||
/* Handle default labels specially. */
|
||||
if (!CASE_HIGH (elt) && !CASE_LOW (elt))
|
||||
{
|
||||
gcc_assert (!default_label_decl);
|
||||
default_label_decl = CASE_LABEL (elt);
|
||||
}
|
||||
else
|
||||
case_list = add_case_node (case_list, index_type,
|
||||
CASE_LOW (elt), CASE_HIGH (elt),
|
||||
CASE_LABEL (elt));
|
||||
}
|
||||
|
||||
|
||||
/* Make sure start points to something that won't need any
|
||||
transformation before the end of this function. */
|
||||
start = get_last_insn ();
|
||||
if (! NOTE_P (start))
|
||||
{
|
||||
emit_note (NOTE_INSN_DELETED);
|
||||
start = get_last_insn ();
|
||||
}
|
||||
|
||||
/* If we don't have a default-label, create one here,
|
||||
after the body of the switch. */
|
||||
@ -2380,13 +2419,6 @@ expand_case (tree exp)
|
||||
count = 0;
|
||||
for (n = case_list; n; n = n->right)
|
||||
{
|
||||
/* Check low and high label values are integers. */
|
||||
gcc_assert (TREE_CODE (n->low) == INTEGER_CST);
|
||||
gcc_assert (TREE_CODE (n->high) == INTEGER_CST);
|
||||
|
||||
n->low = convert (index_type, n->low);
|
||||
n->high = convert (index_type, n->high);
|
||||
|
||||
/* Count the elements and track the largest and smallest
|
||||
of them (treating them as signed even if they are not). */
|
||||
if (count++ == 0)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2004-10-11 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
PR middle-end/17657
|
||||
* gcc.dg/switch-4.c: New test case.
|
||||
|
||||
2004-10-11 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/20041011-1.c: New test.
|
||||
|
24
gcc/testsuite/gcc.dg/switch-4.c
Normal file
24
gcc/testsuite/gcc.dg/switch-4.c
Normal file
@ -0,0 +1,24 @@
|
||||
/* PR middle-end/17657 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
extern signed char foo(int);
|
||||
|
||||
void bar (void)
|
||||
{
|
||||
signed char tmp = foo (0);
|
||||
int t1 = tmp;
|
||||
switch (t1)
|
||||
{
|
||||
case 1: foo (1); break;
|
||||
case 2: foo (2); break;
|
||||
case 3: foo (3); break;
|
||||
case 4: foo (4); break;
|
||||
case 5: foo (5); break;
|
||||
case 6: foo (6); break;
|
||||
case 7: foo (7); break;
|
||||
case 255: foo (8); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user