This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tuples] Adding switch support to the gimplifier


First stab at adding switch statement support to the gimplifier.  The
code is slightly convoluted because of the lack of the high and low
cases in gs_label, so for now we set gs_label's label to the
case_label_expr which has the high and low values.  It might be
necessary to make a gs_case_label to deal with this in a more
reasonable way.   I'll start on that next unless someone has a better
idea?

2007-07-10 Chris Matthews <chrismatthews@google.com>

	* tree-pretty-print.c (dump_generic_node): Removed space before default
	label colon.
	* tree.h (sort_case_labels): Changed type to gimple vector.
	* gimplify.c (gimplify_ctx): Changed to a gimple vector.
	(compare_case_labels): Changed to work with gimpe statement labels with
	CASE_LABEL_EXPRs inside.
	(sort_case_labels): Same.
	(gimplify_switch_expr): Initial implementation with tuples.
	(gimplify_expr): Changed gimplify_case_label_expr parameter.
	(gimplify_case_label_expr): Added a gs_seq parameter, and put cases in that.
	* gimple-vec.h: Added.
	* gimple-pretty-print.c (dump_gimple_expr): Added.
	(dump_gimple_stmt): Changed to a wrapper for dump_gimple_expr.
	(dump_gs_label):  Refactored from dump_gimple_stmt, and added better colon
	logic, and support for gimple case labels.
	(dump_gs_switch): Added.
	* gimple-ir.h (gs_switch_default_label): Changed to use gimples.
	(gs_switch_label): Same.
	(gs_switch_set_default_label): Same.
	(gs_switch_set_label): Same.
	(gs_build_switch_vec): Added.
	* gimple-ir.c (gs_build_switch_1): Added.
	(gs_build_switch): Refactored to use gs_build_switch_1.
	(gs_build_switch_vec): Added.
	* gs_switch.c: New test case.
	* gs_switch1.c: New test case.
	* gs_switch2.c: New test case.
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 126400)
+++ tree-pretty-print.c	(working copy)
@@ -1644,7 +1644,7 @@ dump_generic_node (pretty_printer *buffe
 	  dump_generic_node (buffer, CASE_LOW (node), spc, flags, false);
 	}
       else
-	pp_string (buffer, "default ");
+	pp_string (buffer, "default");
       pp_character (buffer, ':');
       break;
 
Index: tree.h
===================================================================
--- tree.h	(revision 126527)
+++ tree.h	(working copy)
@@ -28,6 +28,7 @@ Software Foundation, 51 Franklin Street,
 #include "statistics.h"
 #include "vec.h"
 #include "double-int.h"
+#include "gimple-vec.h"
 
 /* Codes of tree nodes */
 
@@ -4740,7 +4741,7 @@ extern tree create_artificial_label (voi
 extern struct gs_sequence gimplify_function_tree (tree);
 extern const char *get_name (tree);
 extern tree unshare_expr (tree);
-extern void sort_case_labels (tree);
+extern void sort_case_labels (VEC(gimple,heap)*);
 
 /* Interface of the DWARF2 unwind info support.  */
 
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 126400)
+++ gimple-pretty-print.c	(working copy)
@@ -34,6 +34,8 @@ Software Foundation, 51 Franklin Street,
 #include "tree-pass.h"
 #include "gimple-ir.h"
 
+void dump_gimple_expr (pretty_printer *, gimple, int, int, bool);
+
 #define INDENT(SPACE) do { \
   int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
 
@@ -213,6 +215,28 @@ dump_gs_call (pretty_printer *buffer, gi
   pp_string (buffer, ")");
 }
 
+/* Dump the switch statement GS.  BUFFER, SPC and FLAGS are as in
+   dump_gimple_stmt.  */
+
+static void
+dump_gs_switch (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  unsigned int i;
+  GS_CHECK (gs, GS_SWITCH);
+  pp_string (buffer, "switch (");
+  dump_generic_node (buffer, gs_switch_index (gs), spc, flags, true);
+  pp_string (buffer, ") labels {");
+  for (i = 0; i< gs_switch_nlabels (gs); i++)
+    {
+      dump_gimple_expr (buffer, gs_switch_label (gs, i), spc, flags, false);
+      if (i < gs_switch_nlabels (gs) - 1)
+        pp_string (buffer, ", ");
+    }
+      dump_gimple_expr (buffer, gs_switch_default_label (gs), spc, flags,
+                        false);
+  
+  pp_string (buffer, "}");
+}
 
 /* Return the symbol associated with the GS_COND predicate PRED.  */
 
@@ -264,6 +288,15 @@ dump_gs_cond (pretty_printer *buffer, gi
   pp_character (buffer, '}');
 }
 
+/* Dump a GS_LABEL tuple.  */
+
+static void
+dump_gs_label (pretty_printer *buffer, gimple gs, int spc, int flags) {
+  tree label = gs_label_label (gs);
+  dump_generic_node (buffer, label, spc, flags, false);
+  if (TREE_CODE (label) != CASE_LABEL_EXPR )
+    pp_string (buffer, ":");
+}
 
 /* Dump a GS_BIND tuple.  */
 
@@ -292,13 +325,13 @@ dump_gs_bind (pretty_printer *buffer, gi
   pp_character (buffer, '}');
 }
 
-
 /* Dump the gimple statement GS on the pretty_printer BUFFER, SPC
    spaces of indent.  FLAGS specifies details to show in the dump (see
-   TDF_* in tree.h).  */
-
+   TDF_* in tree.h).  ISSTMT specifics if there should be a ";" printed
+   after this GS statement.  */
 void
-dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_expr (pretty_printer *buffer, gimple gs, int spc, int flags,
+                  bool isStmt)
 {
   if (!gs)
     return;
@@ -322,8 +355,8 @@ dump_gimple_stmt (pretty_printer *buffer
       break;
 
     case GS_LABEL:
-      dump_generic_node (buffer, gs_label_label (gs), spc, flags, false);
-      pp_character (buffer, ':');
+      dump_gs_label (buffer, gs, spc, flags);
+      isStmt = false;
       break;
 
     case GS_GOTO:
@@ -339,11 +372,25 @@ dump_gimple_stmt (pretty_printer *buffer
       dump_gs_return (buffer, gs, spc, flags);
       break;
 
+    case GS_SWITCH:
+      dump_gs_switch (buffer, gs, spc, flags);
+      break;
+
     default:
       GS_NIY;
     }
-
-  pp_character (buffer, ';');
+  if (isStmt)
+    pp_character (buffer, ';');
   newline_and_indent (buffer, spc);
   pp_write_text_to_stream (buffer);
 }
+
+/* Dump the gimple statement GS on the pretty_printer BUFFER, SPC
+   spaces of indent.  FLAGS specifies details to show in the dump (see
+   TDF_* in tree.h).  */
+
+void
+dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  dump_gimple_expr (buffer, gs, spc, flags, true);
+}
Index: ChangeLog.tuples
===================================================================
--- ChangeLog.tuples	(revision 126400)
+++ ChangeLog.tuples	(working copy)
@@ -1,3 +1,33 @@
+2007-07-10  Chris Matthews  <chrismatthews@google.com> 
+
+	* tree-pretty-print.c (dump_generic_node): Removed space before default
+	label colon.
+	* tree.h (sort_case_labels): Changed type to gimple vector.
+	* gimplify.c (gimplify_ctx): Changed to a gimple vector.
+	(compare_case_labels): Changed to work with gimpe statement labels with 
+	CASE_LABEL_EXPRs inside.
+	(sort_case_labels): Same.
+	(gimplify_switch_expr): Initial implementation with tuples.
+	(gimplify_expr): Changed gimplify_case_label_expr parameter.
+	(gimplify_case_label_expr): Added a gs_seq parameter, and put cases in that.
+	* gimple-vec.h: Added.
+	* gimple-pretty-print.c (dump_gimple_expr): Added.
+	(dump_gimple_stmt): Changed to a wrapper for dump_gimple_expr.
+	(dump_gs_label):  Refactored from dump_gimple_stmt, and added better colon
+	logic, and support for gimple case labels.
+	(dump_gs_switch): Added.
+	* gimple-ir.h (gs_switch_default_label): Changed to use gimples.
+	(gs_switch_label): Same.
+	(gs_switch_set_default_label): Same.
+	(gs_switch_set_label): Same.
+	(gs_build_switch_vec): Added.
+	* gimple-ir.c (gs_build_switch_1): Added.
+	(gs_build_switch): Refactored to use gs_build_switch_1.
+	(gs_build_switch_vec): Added.
+	* gs_switch.c: New test case.
+	* gs_switch1.c: New test case.
+	* gs_switch2.c: New test case.
+	
 2007-07-05  Aldy Hernandez  <aldyh@redhat.com> 
 
 	* gimple-pretty-print.c (dump_gimple_stmt): Alphabetize cases.
Index: gimple-ir.c
===================================================================
--- gimple-ir.c	(revision 126400)
+++ gimple-ir.c	(working copy)
@@ -27,6 +27,7 @@ Software Foundation, 51 Franklin Street,
 #include "ggc.h"
 #include "errors.h"
 #include "tree-gimple.h"
+#include "gimple-vec.h"
 #include "gimple-ir.h"
 
 #define DEFGSCODE(SYM, NAME)	NAME,
@@ -425,19 +426,12 @@ gs_build_resx (int region)
   gs_resx_set_region (p, region);
   return p;
 }
+/*  The helper for constructing a gimple switch statement.  */
 
-/* Construct a GS_SWITCH statement.
-
-   INDEX is the switch's index.
-   NLABLES is the number of labels in the switch excluding the default. 
-   ... are the labels excluding the default.  */
-
-gimple 
-gs_build_switch (unsigned int nlabels, tree index, tree default_label, ...)
+static inline gimple 
+gs_build_switch_1 (unsigned int nlabels, tree index, gimple default_label)
 {
   gimple p;
-  unsigned int i;
-  va_list al;
   
   /* nlables + 1 default - 1 extra from struct */ 
   p = ggc_alloc_cleared ( sizeof (struct gimple_statement_switch)
@@ -447,10 +441,46 @@ gs_build_switch (unsigned int nlabels, t
   gs_switch_set_nlabels (p, nlabels);
   gs_switch_set_index (p, index);
   gs_switch_set_default_label (p, default_label);
+  
+  return p;
+}
+/* Construct a GS_SWITCH statement.
+
+   INDEX is the switch's index.
+   NLABLES is the number of labels in the switch excluding the default. 
+   ... are the labels excluding the default.  */
+
+gimple 
+gs_build_switch (unsigned int nlabels, tree index, gimple default_label, ...)
+{
+  va_list al;
+  unsigned int i;
+
+  gimple p = gs_build_switch_1 (nlabels, index, default_label);
   va_start (al, default_label);
   for (i = 0; i < nlabels; i++)
-    gs_switch_set_label (p, i, va_arg (al, tree));
+    gs_switch_set_label (p, i, va_arg (al, gimple));
   va_end (al);
+
+  return p;
+}
+
+/* Construct a GS_SWITCH statement.
+
+   INDEX is the switch's index.
+   NLABLES is the number of labels in the switch excluding the default. 
+   ARGS is a vector of labels excluding the default.  */
+
+gimple
+gs_build_switch_vec (tree index, gimple default_label, VEC(gimple, heap) *args)
+{
+  size_t i;
+  size_t nlabels = VEC_length (gimple, args);
+  gimple p = gs_build_switch_1 (nlabels, index, default_label);
+
+  for (i = 0; i < nlabels; i++)
+    gs_switch_set_label (p, i, VEC_index (gimple, args, i));
+
   return p;
 }
 
Index: gimple-ir.h
===================================================================
--- gimple-ir.h	(revision 126400)
+++ gimple-ir.h	(working copy)
@@ -38,6 +38,8 @@ enum gs_code {
 #define GS_LOCUS_EMPTY_P(G)	(GS_LOCUS ((G)).file == NULL \
 				 && GS_LOCUS ((G)).line == 0)
 
+#include "gimple-vec.h"
+
 /* A sequences of gimple statements.  */
 struct gs_sequence
 {
@@ -383,7 +385,8 @@ extern gimple gs_build_eh_filter (tree, 
 extern gimple gs_build_try (gimple, gimple, bool, bool);
 extern gimple gs_build_phi (unsigned, unsigned, tree, ...);
 extern gimple gs_build_resx (int);
-extern gimple gs_build_switch (unsigned int, tree, tree, ...);
+extern gimple gs_build_switch (unsigned int, tree, gimple, ...);
+extern gimple gs_build_switch_vec (tree, gimple, VEC(gimple,heap)*);
 extern gimple gs_omp_build_parallel (struct gs_sequence, tree, tree, tree);
 extern gimple gs_omp_build_for (struct gs_sequence, tree, tree, tree, tree,
     				tree, struct gs_sequence, enum gs_cond);
@@ -1047,34 +1050,34 @@ gs_switch_set_index (gimple gs, tree ind
   gs->gs_switch.index = index;
 }
 
-static inline tree
+static inline gimple
 gs_switch_default_label (gimple gs)
 {
   GS_CHECK (gs, GS_SWITCH);
-  return gs->gs_switch.labels[0];
+  return (gimple)gs->gs_switch.labels[0];
 }
 
 static inline void
-gs_switch_set_default_label (gimple gs, tree label)
+gs_switch_set_default_label (gimple gs, gimple label)
 {
   GS_CHECK (gs, GS_SWITCH);
-  gs->gs_switch.labels[0] = label;
+  gs->gs_switch.labels[0] = (tree) label;
 }
 
-static inline tree
+static inline gimple
 gs_switch_label (gimple gs, int index)
 {
   GS_CHECK (gs, GS_SWITCH);
   gcc_assert ((unsigned)index <= gs->gs_switch.nlabels);
-  return gs->gs_switch.labels[index + 1];
+  return (gimple) gs->gs_switch.labels[index + 1];
 }
 
 static inline void
-gs_switch_set_label (gimple gs, int index, tree label)
+gs_switch_set_label (gimple gs, int index, gimple label)
 {
   GS_CHECK (gs, GS_SWITCH);
   gcc_assert ((unsigned)index <= gs->gs_switch.nlabels);
-  gs->gs_switch.labels[index + 1] = label;
+  gs->gs_switch.labels[index + 1] = (tree) label;
 }
 
 /* GS_OMP_* accessors. */
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 126400)
+++ gimplify.c	(working copy)
@@ -50,8 +50,9 @@ Software Foundation, 51 Franklin Street,
 #include "optabs.h"
 #include "pointer-set.h"
 #include "splay-tree.h"
-#include "gimple-ir.h"
 #include "vec.h"
+#include "gimple-vec.h"
+#include "gimple-ir.h"
 
 
 enum gimplify_omp_var_data
@@ -90,7 +91,7 @@ struct gimplify_ctx
   tree exit_label;
   tree return_temp;
   
-  VEC(tree,heap) *case_labels;
+  VEC(gimple,heap) *case_labels;
   /* The formal temporary table.  Should this be persistent?  */
   htab_t temp_htab;
 
@@ -119,6 +120,7 @@ static enum gimplify_status gimplify_com
 static bool cpt_same_type (tree a, tree b);
 #endif
 
+static enum gimplify_status gimplify_statement_list (tree *, gs_seq);
 
 /* Return a hash value for a formal temporary table entry.  */
 
@@ -1324,21 +1326,22 @@ gimplify_loop_expr (tree *expr_p, gs_seq
 static int
 compare_case_labels (const void *p1, const void *p2)
 {
-  tree case1 = *(tree *)p1;
-  tree case2 = *(tree *)p2;
+  gimple case1 = *(gimple *)p1;
+  gimple case2 = *(gimple *)p2;
 
-  return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
+  return tree_int_cst_compare (CASE_LOW (gs_label_label (case1)),
+                               CASE_LOW (gs_label_label (case2)));
 }
 
 /* Sort the case labels in LABEL_VEC in place in ascending order.  */
 
 void
-sort_case_labels (tree label_vec)
+sort_case_labels (VEC(gimple,heap)* label_vec)
 {
-  size_t len = TREE_VEC_LENGTH (label_vec);
-  tree default_case = TREE_VEC_ELT (label_vec, len - 1);
+  size_t len = VEC_length (gimple, label_vec);
+  gimple default_case = VEC_index (gimple, label_vec, len - 1);
 
-  if (CASE_LOW (default_case))
+  if (CASE_LOW (gs_label_label (default_case)))
     {
       size_t i;
 
@@ -1346,18 +1349,19 @@ sort_case_labels (tree label_vec)
          but it is not.  */
       for (i = 0; i < len; ++i)
 	{
-	  tree t = TREE_VEC_ELT (label_vec, i);
-	  if (!CASE_LOW (t))
+	  gimple t = VEC_index (gimple, label_vec, i);
+	  if (!CASE_LOW (gs_label_label (t)))
 	    {
 	      default_case = t;
-	      TREE_VEC_ELT (label_vec, i) = TREE_VEC_ELT (label_vec, len - 1);
-	      TREE_VEC_ELT (label_vec, len - 1) = default_case;
+	      gimple index = VEC_index (gimple, label_vec, len - 1);
+	      VEC_replace (gimple, label_vec, i, index);
+	      VEC_replace (gimple, label_vec, len - 1, default_case);
 	      break;
 	    }
 	}
     }
 
-  qsort (&TREE_VEC_ELT (label_vec, 0), len - 1, sizeof (tree),
+  qsort (VEC_address (gimple, label_vec), len - 1, sizeof (tree),
 	 compare_case_labels);
 }
 
@@ -1369,39 +1373,44 @@ gimplify_switch_expr (tree *expr_p, gs_s
 {
   tree switch_expr = *expr_p;
   enum gimplify_status ret;
-
-  ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, false,
-		       is_gimple_val, fb_rvalue);
-
+  gs_seq switch_body_seq = ggc_alloc (sizeof (struct gs_sequence));
+  
+  gs_seq_init (switch_body_seq);
+  gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, false, is_gimple_val,
+                 fb_rvalue);
+  
   if (SWITCH_BODY (switch_expr))
     {
-      VEC(tree,heap) *labels, *saved_labels;
-      tree label_vec, default_case = NULL_TREE;
+      VEC (gimple,heap) *labels;
+      VEC (gimple,heap) *saved_labels;
+      gimple default_case = NULL;
       size_t i, len;
-
+      gimple gs_switch;
+      
       /* If someone can be bothered to fill in the labels, they can
 	 be bothered to null out the body too.  */
       gcc_assert (!SWITCH_LABELS (switch_expr));
 
+      /* save old labels, get new ones from body, then restore the old 
+         labels.  Save all the things from the switch body to append after.  */
       saved_labels = gimplify_ctxp->case_labels;
-      gimplify_ctxp->case_labels = VEC_alloc (tree, heap, 8);
-
-      gimplify_to_stmt_list (&SWITCH_BODY (switch_expr));
+      gimplify_ctxp->case_labels = VEC_alloc (gimple, heap, 8);
 
+      gimplify_statement_list (&SWITCH_BODY (switch_expr), switch_body_seq);
       labels = gimplify_ctxp->case_labels;
       gimplify_ctxp->case_labels = saved_labels;
-
+ 
       i = 0;
-      while (i < VEC_length (tree, labels))
+      while (i < VEC_length (gimple, labels))
 	{
-	  tree elt = VEC_index (tree, labels, i);
-	  tree low = CASE_LOW (elt);
+	  gimple elt = VEC_index (gimple, labels, i);
+	  tree low = CASE_LOW (gs_label_label (elt));
 	  bool remove_element = FALSE;
 
 	  if (low)
 	    {
 	      /* Discard empty ranges.  */
-	      tree high = CASE_HIGH (elt);
+	      tree high = CASE_HIGH (gs_label_label (elt));
 	      if (high && INT_CST_LT (high, low))
 	        remove_element = TRUE;
 	    }
@@ -1414,49 +1423,36 @@ gimplify_switch_expr (tree *expr_p, gs_s
 	    }
 
 	  if (remove_element)
-	    VEC_ordered_remove (tree, labels, i);
+	    VEC_ordered_remove (gimple, labels, i);
 	  else
 	    i++;
 	}
       len = i;
 
-      label_vec = make_tree_vec (len + 1);
-      SWITCH_LABELS (*expr_p) = label_vec;
-      gimplify_and_add (switch_expr, pre_p);
-
       if (! default_case)
 	{
 	  /* If the switch has no default label, add one, so that we jump
 	     around the switch body.  */
-	  default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
-				 NULL_TREE, create_artificial_label ());
-	  gimplify_and_add (SWITCH_BODY (switch_expr), pre_p);
-	  *expr_p = build1 (LABEL_EXPR, void_type_node,
-			    CASE_LABEL (default_case));
+	  gimple new_default = gs_build_label (build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
+				 NULL_TREE, create_artificial_label ()));
+	  gs_add (new_default, switch_body_seq);
+	  default_case = new_default;
 	}
-      else
-	*expr_p = SWITCH_BODY (switch_expr);
-
-      for (i = 0; i < len; ++i)
-	TREE_VEC_ELT (label_vec, i) = VEC_index (tree, labels, i);
-      TREE_VEC_ELT (label_vec, len) = default_case;
-
-      VEC_free (tree, heap, labels);
 
-      sort_case_labels (label_vec);
-
-      SWITCH_BODY (switch_expr) = NULL;
+      sort_case_labels (labels);
+      gs_switch = gs_build_switch_vec (SWITCH_COND (switch_expr), default_case , labels);
+      gs_add (gs_switch, pre_p);
+      gs_seq_append (switch_body_seq, pre_p);
+      VEC_free(gimple, heap, labels);
     }
   else
     gcc_assert (SWITCH_LABELS (switch_expr));
-
   return ret;
 }
 
 static enum gimplify_status
-gimplify_case_label_expr (tree *expr_p)
+gimplify_case_label_expr (tree *expr_p, gs_seq pre_p)
 {
-  tree expr = *expr_p;
   struct gimplify_ctx *ctxp;
 
   /* Invalid OpenMP programs can play Duff's Device type games with
@@ -1466,8 +1462,10 @@ gimplify_case_label_expr (tree *expr_p)
     if (ctxp->case_labels)
       break;
 
-  VEC_safe_push (tree, heap, ctxp->case_labels, expr);
-  *expr_p = build1 (LABEL_EXPR, void_type_node, CASE_LABEL (expr));
+  gimple gs_label = gs_build_label (*expr_p);
+  VEC_safe_push (gimple, heap, ctxp->case_labels, gs_label);
+  gs_add (gs_label, pre_p);
+
   return GS_ALL_DONE;
 }
 
@@ -5763,7 +5761,7 @@ gimplify_expr (tree *expr_p, gs_seq pre_
 	  break;
 
 	case CASE_LABEL_EXPR:
-	  ret = gimplify_case_label_expr (expr_p);
+	  ret = gimplify_case_label_expr (expr_p, pre_p);
 	  break;
 
 	case RETURN_EXPR:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]