[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