[patch] stmt.c (emit_case_nodes): Fix optimization/9707.
Kazu Hirata
kazu@cs.umass.edu
Thu Mar 25 04:45:00 GMT 2004
Hi,
Attached is a patch to fix PR optimization/9707.
Consider:
int
f (int r)
{
switch (r)
{
case 1:
return 11;
case 2:
return 12;
case 3:
return 13;
}
}
Without this patch, the above switch statement is expanded like so:
if (r == 2) goto case2;
if (r > 2) goto rhs;
if (r == 1) goto case1;
goto default_label;
rhs:
if (r == 3) goto case3;
goto default_label;
With this patch, gcc outputs
if (r == 2) goto case2;
if (r == 3) goto case3;
if (r == 1) goto case1;
goto default_label;
Note that the comparison r > 2 is now gone.
The patch implements this optimization by adding a special case to
emit_case_nodes() so that if we see a node with both of its children
being single-valued equality comparisons, we emit equality comparisons
and don't recurse any further.
This optimization triggers several times within GCC itself.
Tested on i686-pc-linux-gnu. OK to apply?
Kazu Hirata
2004-03-24 Kazu Hirata <kazu@cs.umass.edu>
PR optimization/9707.
* stmt.c (emit_case_nodes): Emit equality comparisons instead
of recursing if both children are single-valued cases with no
children.
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.350
diff -u -p -r1.350 stmt.c
--- stmt.c 14 Mar 2004 22:26:10 -0000 1.350
+++ stmt.c 24 Mar 2004 21:48:16 -0000
@@ -6200,6 +6200,42 @@ emit_case_nodes (rtx index, case_node_pt
emit_case_nodes (index, node->right, default_label, index_type);
}
+ /* If both children are single-valued cases with no
+ children, finish up all the work. This way, we can save
+ one ordered comparison. */
+ else if (tree_int_cst_equal (node->right->low, node->right->high)
+ && node->right->left == 0
+ && node->right->right == 0
+ && tree_int_cst_equal (node->left->low, node->left->high)
+ && node->left->left == 0
+ && node->left->right == 0)
+ {
+ /* Neither node is bounded. First distinguish the two sides;
+ then emit the code for one side at a time. */
+
+ /* See if the value matches what the right hand side
+ wants. */
+ do_jump_if_equal (index,
+ convert_modes (mode, imode,
+ expand_expr (node->right->low,
+ NULL_RTX,
+ VOIDmode, 0),
+ unsignedp),
+ label_rtx (node->right->code_label),
+ unsignedp);
+
+ /* See if the value matches what the left hand side
+ wants. */
+ do_jump_if_equal (index,
+ convert_modes (mode, imode,
+ expand_expr (node->left->low,
+ NULL_RTX,
+ VOIDmode, 0),
+ unsignedp),
+ label_rtx (node->left->code_label),
+ unsignedp);
+ }
+
else
{
/* Neither node is bounded. First distinguish the two sides;
More information about the Gcc-patches
mailing list