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] GS_COND, GS_GOTO, GS_LABEL


In the spirit of, let's get these patches in before Diego causes me
conflicts...

Here is a patch implementing gotos, labels, and cond_exprs.

One interesting bit...  Previously we were checking for side effects to
determine if an arm of a COND_EXPR was present or not so we could
reverse its format.  The simplest alternative I found was to have
gimplify_stmt() return true if we actually added any statements, and use
that instead.

However... since GS_COND is a lowered version of GS_COND_EXPR, I would
much rather not swap GS_COND labels, and rip this code out.  Does this
really matter, or do we need to canonicalize GS_COND or something?

Anyways... no regressions.  Committing to branch.  I'll be optimizing
the GS_COND predicates, and getting the push/pop_context business
working.

Aldy

	* testsuite/gcc.dg/gimple/gs_goto.c: New.
	* testsuite/gcc.dg/gimple/gs_cond.c: New.
	* tree-gimple.h (gimplify_stmt): Return bool.
	* gimple-pretty-print.c (INDENT): New.
	(newline_and_indent): New.
	(op_gs_cond): New.
	(dump_gs_cond): New.
	(dump_gimple_stmt): New.
	* gimple-ir.c (gs_cond_invert): New.
	* gimple-ir.h (enum gs_cond): Add comment.
	(gs_cond_invert): Protoize.
	* gimplify.c (gimplify_cond_expr): Rewrite for tuples.
	(gimplify_stmt): Return true if we added a statement to the queue.
	(gimplify_expr): Enable gimplify_cond_expr.
	Build tuples for GOTO_EXPRs and LABEL_EXPRs.

Index: testsuite/gcc.dg/gimple/gs_goto.c
===================================================================
--- testsuite/gcc.dg/gimple/gs_goto.c	(revision 0)
+++ testsuite/gcc.dg/gimple/gs_goto.c	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+/* Test GS_GOTO.  */
+
+void yanory()
+{
+hotdog:
+  goto hotdog;
+}
+
+/* { dg-final { scan-tree-dump-times "gimpleir: goto hotdog" 1 "gimple"} } */
+/* { dg-final { scan-tree-dump-times "gimpleir: hotdog:" 1 "gimple"} } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
Index: testsuite/gcc.dg/gimple/gs_cond.c
===================================================================
--- testsuite/gcc.dg/gimple/gs_cond.c	(revision 0)
+++ testsuite/gcc.dg/gimple/gs_cond.c	(revision 0)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+/* Test GS_COND.  */
+
+int res, a, b, c;
+
+void foo()
+{
+    res = a > 5 ? b : c;
+}
+
+/* { dg-final { scan-tree-dump-times "gimpleir: GS_COND tuple" 1 "gimple"} } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
Index: tree-gimple.h
===================================================================
--- tree-gimple.h	(revision 126065)
+++ tree-gimple.h	(working copy)
@@ -115,7 +115,7 @@ extern enum gimplify_status gimplify_exp
 					   bool (*) (tree), fallback_t);
 extern void gimplify_type_sizes (tree, gs_seq);
 extern void gimplify_one_sizepos (tree *, gs_seq);
-extern void gimplify_stmt (tree *, gs_seq);
+extern bool gimplify_stmt (tree *, gs_seq);
 extern void gimplify_to_stmt_list (tree *);
 extern void gimplify_body (tree *, gs_seq, tree, bool);
 extern void push_gimplify_context (void);
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 126065)
+++ gimple-pretty-print.c	(working copy)
@@ -34,6 +34,8 @@ Software Foundation, 51 Franklin Street,
 #include "tree-pass.h"
 #include "gimple-ir.h"
 
+#define INDENT(SPACE) do { \
+  int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
 
 static pretty_printer buffer;
 static bool initialized = false;
@@ -63,6 +65,14 @@ maybe_init_pretty_print (FILE *file)
   buffer.buffer->stream = file;
 }
 
+static void
+newline_and_indent (pretty_printer *buffer, int spc)
+{
+  pp_newline (buffer);
+  pp_string (buffer, "gimpleir: ");
+  INDENT (spc);
+}
+
 void
 debug_gimple_stmt (gimple gs)
 {
@@ -187,6 +197,57 @@ dump_gs_call (pretty_printer *buffer, gi
 }
 
 
+/* Return the symbol associated with the GS_COND predicate PRED.  */
+
+static const char *
+op_gs_cond (enum gs_cond pred)
+{
+  /* These must be in sync with enum gs_cond.  */
+  static const char *table[] =
+    { "<", ">", "<=", ">=", "==", "!=" };
+
+  return table[(int) pred];
+}
+
+
+/* Dump the gimple conditional GS.  BUFFER, SPC and FLAGS are as in
+   dump_gimple_stmt.  */
+
+static void
+dump_gs_cond (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  /* This stupid line is here so we can scan for it in the testsuite.  */
+  pp_string (buffer, "GS_COND tuple");
+
+  newline_and_indent (buffer, spc);
+  pp_string (buffer, "if (");
+  dump_generic_node (buffer, gs_cond_lhs (gs), spc, flags, false);
+  pp_space (buffer);
+  pp_string (buffer, op_gs_cond (GS_SUBCODE_FLAGS (gs)));
+  pp_space (buffer);
+  dump_generic_node (buffer, gs_cond_rhs (gs), spc, flags, false);
+  pp_character (buffer, ')');
+  newline_and_indent (buffer, spc + 2);
+  pp_character (buffer, '{');
+  newline_and_indent (buffer, spc + 4);
+  pp_string (buffer, "goto ");
+  dump_generic_node (buffer, gs_cond_true_label (gs), spc, flags, false);
+  pp_character (buffer, ';');
+  newline_and_indent (buffer, spc + 2);
+  pp_character (buffer, '}');
+  newline_and_indent (buffer, spc);
+  pp_string (buffer, "else");
+  newline_and_indent (buffer, spc + 2);
+  pp_character (buffer, '{');
+  newline_and_indent (buffer, spc + 4);
+  pp_string (buffer, "goto ");
+  dump_generic_node (buffer, gs_cond_false_label (gs), spc, flags, false);
+  pp_character (buffer, ';');
+  newline_and_indent (buffer, spc + 2);
+  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).  */
@@ -211,6 +272,20 @@ dump_gimple_stmt (pretty_printer *buffer
       dump_gs_call (buffer, gs, spc, flags);
       break;
 
+    case GS_LABEL:
+      dump_generic_node (buffer, gs_label_label (gs), spc, flags, false);
+      pp_character (buffer, ':');
+      break;
+
+    case GS_GOTO:
+      pp_string (buffer, "goto ");
+      dump_generic_node (buffer, gs_goto_dest (gs), spc, flags, false);
+      break;
+
+    case GS_COND:
+      dump_gs_cond (buffer, gs, spc, flags);
+      break;
+
     default:
       GS_NIY;
     }
Index: gimple-ir.c
===================================================================
--- gimple-ir.c	(revision 126065)
+++ gimple-ir.c	(working copy)
@@ -211,6 +211,18 @@ gs_build_cond (enum gs_cond pred, tree l
   return p;
 }
 
+/* Invert the condition of a GS_COND by swapping its labels.  */
+
+void
+gs_cond_invert (gimple g)
+{
+  tree tmp;
+
+  tmp = gs_cond_true_label (g);
+  gs_cond_set_true_label (g, gs_cond_false_label (g));
+  gs_cond_set_false_label (g, tmp);
+}
+
 /* Construct a GS_LABEL statement for LABEL.  */
 
 gimple
Index: gimple-ir.h
===================================================================
--- gimple-ir.h	(revision 126065)
+++ gimple-ir.h	(working copy)
@@ -287,6 +287,7 @@ struct gimple_statement_omp_for GTY(())
 
 /* Predicate for conds. */
 enum gs_cond {
+  /* These must be in sync with op_gs_cond().  */
   GS_COND_LT, GS_COND_GT, GS_COND_LE, GS_COND_GE, GS_COND_EQ, GS_COND_NE
 };
 
@@ -371,6 +372,7 @@ extern gimple gs_build_assign (tree, tre
 extern gimple gs_build_call_vec (tree, VEC(tree, gc) *);
 extern gimple gs_build_call (tree, size_t, ...);
 extern gimple gs_build_cond (enum gs_cond, tree, tree, tree, tree);
+extern void gs_cond_invert (gimple);
 extern gimple gs_build_label (tree label);
 extern gimple gs_build_goto (tree dest);
 extern gimple gs_build_nop (void);
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 126065)
+++ gimplify.c	(working copy)
@@ -337,6 +337,7 @@ append_to_statement_list_force (tree t, 
     append_to_statement_list_1 (t, list_p);
 }
 
+/* FIXME tuples: This function is obsolete.  Use gimplify_stmt instead.  */
 /* Both gimplify the statement T and append it to SEQ.  */
 
 void
@@ -2462,19 +2463,18 @@ gimple_boolify (tree expr)
 
     The second form is used when *EXPR_P is of type void.
 
-    TARGET is the tree for T1 above.
-
     PRE_P points to the list where side effects that must happen before
       *EXPR_P should be stored.  */
 
-#if 0
-/* FIXME tuples */
 static enum gimplify_status
 gimplify_cond_expr (tree *expr_p, gs_seq pre_p, fallback_t fallback)
 {
   tree expr = *expr_p;
-  tree tmp, tmp2, type;
+  tree tmp, type;
   enum gimplify_status ret;
+  tree label_true, label_false, label_cont;
+  bool have_then_clause_p, have_else_clause_p;
+  gimple gs_cond;
 
   type = TREE_TYPE (expr);
 
@@ -2485,10 +2485,7 @@ gimplify_cond_expr (tree *expr_p, gs_seq
       tree result;
 
       if ((fallback & fb_lvalue) == 0)
-	{
-	  result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
-	  ret = GS_ALL_DONE;
-	}
+	result = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
       else
 	{
 	  tree type = build_pointer_type (TREE_TYPE (expr));
@@ -2501,13 +2498,12 @@ gimplify_cond_expr (tree *expr_p, gs_seq
 	    TREE_OPERAND (expr, 2) =
 	      build_fold_addr_expr (TREE_OPERAND (expr, 2));
 	  
-	  tmp2 = tmp = create_tmp_var (type, "iftmp");
+	  tmp = create_tmp_var (type, "iftmp");
 
 	  expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (expr, 0),
 			 TREE_OPERAND (expr, 1), TREE_OPERAND (expr, 2));
 
 	  result = build_fold_indirect_ref (tmp);
-	  ret = GS_ALL_DONE;
 	}
 
       /* Build the then clause, 't1 = a;'.  But don't build an assignment
@@ -2519,16 +2515,16 @@ gimplify_cond_expr (tree *expr_p, gs_seq
       /* Build the else clause, 't1 = b;'.  */
       if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
 	TREE_OPERAND (expr, 2)
-	  = build_gimple_modify_stmt (tmp2, TREE_OPERAND (expr, 2));
+	  = build_gimple_modify_stmt (tmp, TREE_OPERAND (expr, 2));
 
       TREE_TYPE (expr) = void_type_node;
       recalculate_side_effects (expr);
 
       /* Move the COND_EXPR to the prequeue.  */
-      gimplify_and_add (expr, pre_p);
+      gimplify_stmt (expr_p, pre_p);
 
       *expr_p = result;
-      return ret;
+      return GS_ALL_DONE;
     }
 
   /* Make sure the condition has BOOLEAN_TYPE.  */
@@ -2548,49 +2544,68 @@ gimplify_cond_expr (tree *expr_p, gs_seq
 	     form properly, as cleanups might cause the target labels to be
 	     wrapped in a TRY_FINALLY_EXPR.  To prevent that, we need to
 	     set up a conditional context.  */
+	  /* FIXME tuples
 	  gimple_push_condition ();
-	  gimplify_stmt (expr_p);
+	  */
+	  gimplify_stmt (expr_p, pre_p);
+	  /* FIXME tuples
 	  gimple_pop_condition (pre_p);
+	  */
 
 	  return GS_ALL_DONE;
 	}
     }
 
   /* Now do the normal gimplification.  */
-  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
+
+  /* Gimplify condition.  */
+  ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL, false,
 		       is_gimple_condexpr, fb_rvalue);
+  gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
 
+  /* FIXME tuples
   gimple_push_condition ();
+  */
 
-  gimplify_to_stmt_list (&TREE_OPERAND (expr, 1));
-  gimplify_to_stmt_list (&TREE_OPERAND (expr, 2));
-  recalculate_side_effects (expr);
+  label_true = create_artificial_label ();
+  label_false = create_artificial_label ();
+  /* FIXME tuples: We should add smarts to use the other GS_COND predicates
+     when appropriate.  */
+  gs_cond = gs_build_cond (GS_COND_NE,
+			   TREE_OPERAND (expr, 0), boolean_false_node,
+			   label_true, label_false);
+  gs_add (gs_cond, pre_p);
+  gs_add (gs_build_label (label_true), pre_p);
+  have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), pre_p);
+  label_cont = create_artificial_label ();
+  gs_add (gs_build_goto (label_cont), pre_p);
+  gs_add (gs_build_label (label_false), pre_p);
+  have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), pre_p);
+  gs_add (gs_build_label (label_cont), pre_p);
 
+  /* FIXME tuples
   gimple_pop_condition (pre_p);
+  */
 
   if (ret == GS_ERROR)
     ;
-  else if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
+  else if (have_then_clause_p)
     ret = GS_ALL_DONE;
-  else if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2)))
-    /* Rewrite "if (a); else b" to "if (!a) b"  */
+  else if (have_else_clause_p)
     {
-      TREE_OPERAND (expr, 0) = invert_truthvalue (TREE_OPERAND (expr, 0));
-      ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
-			   is_gimple_condexpr, fb_rvalue);
-
-      tmp = TREE_OPERAND (expr, 1);
-      TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 2);
-      TREE_OPERAND (expr, 2) = tmp;
+      /* Rewrite "if (a); else b" into "if (!a) b"  */
+      gs_cond_invert (gs_cond);
     }
   else
-    /* Both arms are empty; replace the COND_EXPR with its predicate.  */
-    expr = TREE_OPERAND (expr, 0);
+    {
+      /* Both arms are empty; replace the COND_EXPR with its predicate.  */
+      expr = TREE_OPERAND (expr, 0);
+      gimplify_stmt (&expr, pre_p);
+    }
 
-  *expr_p = expr;
+  *expr_p = NULL;
   return ret;
 }
-#endif
 
 /* A subroutine of gimplify_modify_expr.  Replace a MODIFY_EXPR with
    a call to __builtin_memcpy.  */
@@ -4368,12 +4383,17 @@ gimplify_target_expr (tree *expr_p, gs_s
 
 /* Gimplification of expression trees.  */
 
-/* Gimplify an expression which appears at statement context into SEQ_P.  */
+/* Gimplify an expression which appears at statement context into SEQ_P.
+   Return true if we actually added a statement to the queue.  */
 
-void
+bool
 gimplify_stmt (tree *stmt_p, gs_seq seq_p)
 {
+  gimple last;
+
+  last = gs_seq_last (seq_p);
   gimplify_expr (stmt_p, seq_p, NULL, true, is_gimple_stmt, fb_none);
+  return last != gs_seq_last (seq_p);
 }
 
 /* Similarly, but force the result to be a STATEMENT_LIST.  */
@@ -5566,9 +5586,7 @@ gimplify_expr (tree *expr_p, gs_seq pre_
 	  break;
 
 	case COND_EXPR:
-#if 0
-/* FIXME tuples */
-	  ret = gimplify_cond_expr (expr_p, seq_p, pre_p, fallback);
+	  ret = gimplify_cond_expr (expr_p, pre_p, fallback);
 	  /* C99 code may assign to an array in a structure value of a
 	     conditional expression, and this has undefined behavior
 	     only on execution, so create a temporary if an lvalue is
@@ -5578,8 +5596,6 @@ gimplify_expr (tree *expr_p, gs_seq pre_
 	      *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p);
 	      lang_hooks.mark_addressable (*expr_p);
 	    }
-#endif
-	  gcc_unreachable();
 	  break;
 
 	case CALL_EXPR:
@@ -5725,12 +5741,14 @@ gimplify_expr (tree *expr_p, gs_seq pre_
 	  if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
 	    ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
 				 NULL, false, is_gimple_val, fb_rvalue);
+	  gs_add (gs_build_goto (GOTO_DESTINATION (*expr_p)), pre_p);
 	  break;
 
 	case LABEL_EXPR:
 	  ret = GS_ALL_DONE;
 	  gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
 		      == current_function_decl);
+	  gs_add (gs_build_label (LABEL_EXPR_LABEL (*expr_p)), pre_p);
 	  break;
 
 	case CASE_LABEL_EXPR:


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