[PATCH][match-and-simplify] Refactor GIMPLE code-gen

Richard Biener rguenther@suse.de
Wed Aug 20 11:14:00 GMT 2014


This refactors GIMPLE code-gen to use switch ()es similar to
the GENERIC version.  This should provide all of the
backtracking avoidance we need (I think so at least).

Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu.

Richard.

2014-08-20  Richard Biener  <rguenther@suse.de>

	* genmatch.c (dt_node::get_expr_code, dt_node::is_gimple_expr,
	dt_node::is_gimple_fn): Remove.
	(dt_operand::kids_type, dt_operand::gtok_kids,
	dt_operand::gen_generic_expr_expr, dt_operand::gen_generic_expr_fn):
	Likewise.
	(dt_operand::gen_gimple_expr_expr, dt_operand::gen_gimple_expr_fn):
	Merge into ...
	(dt_operand::gen_gimple_expr): ... this new function.
	(is_a_helper): More specializations.
	(expr::gen_transform): Add missing newline.
	(dt_operand::gen_gimple_kids): Rewrite to use switch statements.
	(dt_operand::gen_generic_expr): Adjust.
	(dt_operand::gen_gimple): Likewise.

Index: gcc/genmatch.c
===================================================================
*** gcc/genmatch.c.orig	2014-08-19 16:50:02.426224137 +0200
--- gcc/genmatch.c	2014-08-20 12:55:55.647242705 +0200
*************** struct dt_node
*** 414,423 ****
  
    virtual void gen_gimple (FILE *) {}
    virtual void gen_generic (FILE *) {}
-   
-   bool get_expr_code (enum tree_code&);
-   bool is_gimple_expr ();
-   bool is_gimple_fn ();
  };
  
  struct dt_operand: public dt_node
--- 414,419 ----
*************** struct dt_operand: public dt_node
*** 426,460 ****
    dt_operand *match_dop;
    dt_operand *parent;
    unsigned pos;
- 
-   struct kids_type {
-     vec<dt_node *> gimple_exprs;
-     vec<dt_node *> fns;
-     vec<dt_node *> others;
-     dt_node *true_operand;
-   
-     kids_type (): gimple_exprs (vNULL), fns (vNULL), others (vNULL), true_operand (0) {}
-   };
   
    dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_, dt_operand *parent_ = 0, unsigned pos_ = 0)
! 	: dt_node (type), op (op_), match_dop (match_dop_), parent (parent_), pos (pos_) {} 
  
    virtual void gen_gimple (FILE *);
    virtual void gen_generic (FILE *);
    unsigned gen_predicate (FILE *, const char *);
    unsigned gen_match_op (FILE *, const char *);
  
!   unsigned gen_gimple_expr_expr (FILE *); 
!   unsigned gen_gimple_expr_fn (FILE *);
! 
!   unsigned gen_generic_expr (FILE *, const char *, bool);
!   void gen_generic_expr_expr (FILE *, expr *, const char *, bool);
!   void gen_generic_expr_fn (FILE *, expr *, const char *, bool);
  
    char *get_name (char *);
    void gen_opname (char *, unsigned);
  
-   void grok_kids(kids_type&);
    void gen_gimple_kids (FILE *);
    void gen_generic_kids (FILE *);
  };
--- 422,442 ----
    dt_operand *match_dop;
    dt_operand *parent;
    unsigned pos;
   
    dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_, dt_operand *parent_ = 0, unsigned pos_ = 0)
! 	: dt_node (type), op (op_), match_dop (match_dop_), parent (parent_), pos (pos_) {}
  
    virtual void gen_gimple (FILE *);
    virtual void gen_generic (FILE *);
    unsigned gen_predicate (FILE *, const char *);
    unsigned gen_match_op (FILE *, const char *);
  
!   unsigned gen_gimple_expr (FILE *);
!   unsigned gen_generic_expr (FILE *, const char *);
  
    char *get_name (char *);
    void gen_opname (char *, unsigned);
  
    void gen_gimple_kids (FILE *);
    void gen_generic_kids (FILE *);
  };
*************** struct dt_simplify: public dt_node
*** 479,484 ****
--- 461,474 ----
    virtual void gen_generic (FILE *f);
  };
  
+ template<>
+ template<>
+ inline bool
+ is_a_helper <dt_operand *>::test (dt_node *n)
+ {
+   return n->type == dt_node::DT_OPERAND;
+ }
+ 
  struct decision_tree
  {
    dt_node *root;
*************** expr::gen_transform (FILE *f, const char
*** 913,919 ****
        fprintf (f, ");\n");
      }
    fprintf (f, "  %s = res;\n", dest);
!   fprintf (f, "}");
  }
  
  void
--- 903,909 ----
        fprintf (f, ");\n");
      }
    fprintf (f, "  %s = res;\n", dest);
!   fprintf (f, "}\n");
  }
  
  void
*************** dt_operand::gen_match_op (FILE *f, const
*** 1292,1540 ****
  }
  
  unsigned
! dt_operand::gen_gimple_expr_fn (FILE *f) 
  {
    expr *e = static_cast<expr *> (op);
    unsigned n_ops = e->ops.length ();
  
-   fn_id *op = static_cast <fn_id *> (e->operation->op);
-   fprintf (f, "if (gimple_call_builtin_p (def_stmt, %s))\n", op->id);
-   fprintf (f, "{\n");
- 
    for (unsigned i = 0; i < n_ops; ++i)
      {
        char child_opname[20];
        gen_opname (child_opname, i); 
  
!       fprintf (f, "tree %s = gimple_call_arg (def_stmt, %u);\n", child_opname, i);
!       fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
        fprintf (f, "{\n");
!     } 
  
!   return n_ops + 1;
  }
  
  unsigned
! dt_operand::gen_gimple_expr_expr (FILE *f)
  {
    expr *e = static_cast<expr *> (op);
-   unsigned n_ops = e->ops.length (); 
- 
-   operator_id *op_id = static_cast <operator_id *> (e->operation->op);
-   
-   if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR)
-     fprintf (f, " if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))");
-   else
-     fprintf (f, "if (gimple_assign_rhs_code (def_stmt) == %s)\n", op_id->id);
- 
-   fprintf (f, "{\n");
-   
-   for (unsigned i = 0; i < n_ops; ++i)
-     {
-       char child_opname[20];
-       gen_opname (child_opname, i); 
- 
-       fprintf (f, "tree %s = gimple_assign_rhs%u (def_stmt);\n", child_opname, i + 1);
-       fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
-       fprintf (f, "{\n");
-     }      
- 
-   return n_ops + 1;
- } 
- 
- void
- dt_operand::gen_generic_expr_expr (FILE *f, expr *e, const char *opname,
- 				   bool valueize)
- {
-   unsigned n_ops = e->ops.length ();
- 
-   operator_id *op_id = static_cast <operator_id *> (e->operation->op);
- 
-   if (valueize)
-     {
-       if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR)
- 	fprintf (f, "if (CONVERT_EXPR_P (%s))\n", opname);
-       else
- 	fprintf (f, "if (TREE_CODE (%s) == %s)\n", opname, e->operation->op->id);
-       fprintf (f, "{\n");
-     }
- 
-   for (unsigned i = 0; i < n_ops; ++i)
-     {
-       char child_opname[20];
-       gen_opname (child_opname, i);
- 
-       fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n", child_opname, opname, i);
-       if (valueize)
- 	{
- 	  fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
- 	  fprintf (f, "{\n");
- 	}
-     }
- }   
- 
- void
- dt_operand::gen_generic_expr_fn (FILE *f, expr *e, const char *opname, bool valueize)
- {
    unsigned n_ops = e->ops.length ();
-   fn_id *op = static_cast <fn_id *> (e->operation->op);
- 
-   if (valueize)
-     {
-       fprintf (f, "if (TREE_CODE (%s) == CALL_EXPR\n"
- 	       "    && TREE_CODE (CALL_EXPR_FN (%s)) == ADDR_EXPR\n"
- 	       "    && TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) == FUNCTION_DECL\n"
- 	       "    && DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) == BUILT_IN_NORMAL\n"
- 	       "    && DECL_FUNCTION_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) == %s)\n",
- 	       opname, opname, opname, opname, opname, op->id);
-       fprintf (f, "  {\n");
-     }
  
    for (unsigned i = 0; i < n_ops; ++i)
      {
        char child_opname[20];
        gen_opname (child_opname, i);
  
!       fprintf (f, "tree %s = CALL_EXPR_ARG (%s, %u);\n", child_opname, opname, i);
!       if (valueize)
! 	{
! 	  fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
! 	  fprintf (f, "{\n");
! 	}
      }
- }
- 
- unsigned
- dt_operand::gen_generic_expr (FILE *f, const char *opname, bool valueize)
- {
-   expr *e = static_cast<expr *> (op);
-   (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e, opname, valueize) : gen_generic_expr_fn (f, e, opname, valueize);
-   return valueize ? e->ops.length () + 1 : 0;
- }
- 
- bool
- dt_node::get_expr_code (enum tree_code& code)
- {
- 
-   if (type != dt_node::DT_OPERAND)
-     return false;
  
!   dt_operand *dop = static_cast<dt_operand *> (this);
!   
!   if (dop->op->type != operand::OP_EXPR)
!     return false;
! 
!   expr *e = static_cast<expr *> (dop->op);
!   if (e->operation->op->kind != id_base::CODE)
!     return false;
! 
!   operator_id *opr = static_cast<operator_id *> (e->operation->op);
!   if (opr->nargs == 0)
!     return false;
! 
!   code = opr->code;
!   return true;
! }
! 
! bool
! dt_node::is_gimple_expr ()
! {
!   enum tree_code code;
! 
!   if (!get_expr_code (code))
!     return false;
! 
!   if (code == REALPART_EXPR || code == IMAGPART_EXPR
!       || code == BIT_FIELD_REF || code == VIEW_CONVERT_EXPR)
!     return false;
! 
!   dt_operand *dop = static_cast<dt_operand *> (this);
! 
!   if (dop->parent->type != dt_operand::DT_OPERAND)
!     return true;
! 
!   if (dop->parent->get_expr_code (code) && code == COND_EXPR && dop->pos == 0)
!     return false;
! 
!   return true;
! }
! 
! bool
! dt_node::is_gimple_fn ()
! {
!   if (type != dt_node::DT_OPERAND)
!     return false;
!   
!   dt_operand *dop = static_cast<dt_operand *> (this);
!   if (dop->op->type != operand::OP_EXPR)
!     return false;
! 
!   expr *e = static_cast<expr *> (dop->op);
!   return e->operation->op->kind == id_base::FN;
  }
  
  void
! dt_operand::grok_kids (kids_type& ktype)
  {
! 
    for (unsigned i = 0; i < kids.length (); ++i)
      {
!       if (kids[i]->is_gimple_expr ())
! 	ktype.gimple_exprs.safe_push (kids[i]);
!       else if (kids[i]->is_gimple_fn ())
! 	ktype.fns.safe_push (kids[i]);
        else if (kids[i]->type == dt_node::DT_TRUE)
! 	ktype.true_operand = kids[i];
        else
! 	ktype.others.safe_push (kids[i]);
      }
- }
- 
- void
- dt_operand::gen_gimple_kids (FILE *f)
- {
-   kids_type ktype;
-   grok_kids (ktype);
  
    char buf[128];
    char *kid_opname = buf;
   
!   unsigned exprs_len = ktype.gimple_exprs.length ();
!   unsigned fns_len = ktype.fns.length ();
  
!   if (exprs_len || fns_len)
      {
        if (exprs_len)
! 	(static_cast<dt_operand *>(ktype.gimple_exprs[0]))->get_name (kid_opname);
        else
! 	(static_cast<dt_operand *>(ktype.fns[0]))->get_name (kid_opname);
  
!       fprintf (f, "if (TREE_CODE (%s) == SSA_NAME)\n", kid_opname);
        fprintf (f, "{\n");
        fprintf (f, "gimple def_stmt = SSA_NAME_DEF_STMT (%s);\n", kid_opname);
  
        if (exprs_len)
  	{
  	  fprintf (f, "if (is_gimple_assign (def_stmt))\n");
! 	  fprintf (f, "{\n");
  	  for (unsigned i = 0; i < exprs_len; ++i)
  	    {
! 	      ktype.gimple_exprs[i]->gen_gimple (f);
  	    }
! 	  fprintf (f, "}\n");
  	}
    
!       for (unsigned i = 0; i < fns_len; ++i) 
! 	ktype.fns[i]->gen_gimple (f);
  
!       fprintf (f, "}\n");
      }
-   
-   for (unsigned i = 0; i < ktype.others.length (); ++i)
-     ktype.others[i]->gen_gimple (f);
  
!   if (ktype.true_operand)
!     ktype.true_operand->gen_gimple (f);
  }
  
  void
--- 1282,1475 ----
  }
  
  unsigned
! dt_operand::gen_gimple_expr (FILE *f)
  {
    expr *e = static_cast<expr *> (op);
+   id_base *id = e->operation->op;
    unsigned n_ops = e->ops.length ();
  
    for (unsigned i = 0; i < n_ops; ++i)
      {
        char child_opname[20];
        gen_opname (child_opname, i); 
  
!       if (id->kind == id_base::CODE)
! 	{
! 	  if (*id == REALPART_EXPR || *id == IMAGPART_EXPR
! 	      || *id == BIT_FIELD_REF || *id == VIEW_CONVERT_EXPR)
! 	    fprintf (f, "tree %s = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), %i);\n",
! 		     child_opname, i);
! 	  else
! 	    fprintf (f, "tree %s = gimple_assign_rhs%u (def_stmt);\n",
! 		     child_opname, i + 1);
! 	}
!       else
! 	fprintf (f, "tree %s = gimple_call_arg (def_stmt, %u);\n",
! 		 child_opname, i);
!       fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
! 	       child_opname, child_opname);
        fprintf (f, "{\n");
!     }
  
!   return n_ops;
  }
  
  unsigned
! dt_operand::gen_generic_expr (FILE *f, const char *opname)
  {
    expr *e = static_cast<expr *> (op);
    unsigned n_ops = e->ops.length ();
  
    for (unsigned i = 0; i < n_ops; ++i)
      {
        char child_opname[20];
        gen_opname (child_opname, i);
  
!       if (e->operation->op->kind == id_base::CODE)
! 	fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n",
! 		 child_opname, opname, i);
!       else
! 	fprintf (f, "tree %s = CALL_EXPR_ARG (%s, %u);\n",
! 		 child_opname, opname, i);
      }
  
!   return 0;
  }
  
  void
! dt_operand::gen_gimple_kids (FILE *f)
  {
!   vec<dt_operand *> gimple_exprs = vNULL;
!   vec<dt_operand *> generic_exprs = vNULL;
!   vec<dt_operand *> fns = vNULL;
!   vec<dt_node *> others = vNULL;
!   dt_node *true_operand = NULL;
    for (unsigned i = 0; i < kids.length (); ++i)
      {
!       if (dt_operand *op = dyn_cast <dt_operand *> (kids[i]))
! 	{
! 	  if (expr *e = dyn_cast <expr *> (op->op))
! 	    {
! 	      if (e->ops.length () == 0)
! 		generic_exprs.safe_push (op);
! 	      else if (e->operation->op->kind == id_base::FN)
! 		fns.safe_push (op);
! 	      else
! 		gimple_exprs.safe_push (op);
! 	    }
! 	  else if (op->op->type == operand::OP_PREDICATE)
! 	    others.safe_push (kids[i]);
! 	  else
! 	    gcc_unreachable ();
! 	}
!       else if (kids[i]->type == dt_node::DT_MATCH
! 	       || kids[i]->type == dt_node::DT_SIMPLIFY)
! 	others.safe_push (kids[i]);
        else if (kids[i]->type == dt_node::DT_TRUE)
! 	true_operand = kids[i];
        else
! 	gcc_unreachable ();
      }
  
    char buf[128];
    char *kid_opname = buf;
   
!   unsigned exprs_len = gimple_exprs.length ();
!   unsigned gexprs_len = generic_exprs.length ();
!   unsigned fns_len = fns.length ();
  
!   if (exprs_len || fns_len || gexprs_len)
      {
        if (exprs_len)
! 	gimple_exprs[0]->get_name (kid_opname);
!       else if (fns_len)
! 	fns[0]->get_name (kid_opname);
        else
! 	generic_exprs[0]->get_name (kid_opname);
  
!       fprintf (f, "switch (TREE_CODE (%s))\n"
! 	       "{\n", kid_opname);
!     }
! 
!   if (exprs_len || fns_len)
!     {
!       fprintf (f, "case SSA_NAME:\n");
        fprintf (f, "{\n");
        fprintf (f, "gimple def_stmt = SSA_NAME_DEF_STMT (%s);\n", kid_opname);
  
        if (exprs_len)
  	{
  	  fprintf (f, "if (is_gimple_assign (def_stmt))\n");
! 	  fprintf (f, "switch (gimple_assign_rhs_code (def_stmt))\n"
! 		   "{\n");
  	  for (unsigned i = 0; i < exprs_len; ++i)
  	    {
! 	      expr *e = as_a <expr *> (gimple_exprs[i]->op);
! 	      id_base *op = e->operation->op;
! 	      if (*op == CONVERT_EXPR || *op == NOP_EXPR)
! 		fprintf (f, "CASE_CONVERT:\n");
! 	      else
! 		fprintf (f, "case %s:\n", op->id);
! 	      fprintf (f, "{\n");
! 	      gimple_exprs[i]->gen_gimple (f);
! 	      fprintf (f, "break;\n"
! 		       "}\n");
  	    }
! 	  fprintf (f, "default:;\n"
! 		   "}\n");
  	}
    
!       if (fns_len)
! 	{
! 	  if (exprs_len)
! 	    fprintf (f, "else ");
  
! 	  fprintf (f, "if (gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL))\n"
! 		   "{\n"
! 		   "tree fndecl = gimple_call_fndecl (def_stmt);\n"
! 		   "switch (DECL_FUNCTION_CODE (fndecl))\n"
! 		   "{\n");
! 
! 	  for (unsigned i = 0; i < fns_len; ++i)
! 	    {
! 	      expr *e = as_a <expr *>(fns[i]->op);
! 	      fprintf (f, "case %s:\n"
! 		       "{\n", e->operation->op->id);
! 	      fns[i]->gen_gimple (f);
! 	      fprintf (f, "break;\n"
! 		       "}\n");
! 	    }
! 
! 	  fprintf (f, "default:;\n"
! 		   "}\n"
! 		   "}\n");
! 	}
! 
!       fprintf (f, "break;\n"
! 	       "}\n");
      }
  
!   for (unsigned i = 0; i < generic_exprs.length (); ++i)
!     {
!       expr *e = as_a <expr *>(generic_exprs[i]->op);
!       fprintf (f, "case %s:\n"
! 	       "{\n", e->operation->op->id);
! 
!       generic_exprs[i]->gen_gimple (f);
!       fprintf (f, "break;\n"
! 	       "}\n");
!     }
! 
!   /* Close switch (TREE_CODE ()).  */
!   if (exprs_len || fns_len || gexprs_len)
!     fprintf (f, "default:;\n"
! 	     "}\n");
! 
!   for (unsigned i = 0; i < others.length (); ++i)
!     others[i]->gen_gimple (f);
! 
!   if (true_operand)
!     true_operand->gen_gimple (f);
  }
  
  void
*************** dt_operand::gen_gimple (FILE *f)
*** 1553,1564 ****
  	  break;
  
  	case operand::OP_EXPR:
! 	  if (is_gimple_expr ())
! 	    n_braces = gen_gimple_expr_expr (f);
! 	  else if (is_gimple_fn ())
! 	    n_braces = gen_gimple_expr_fn (f);
! 	  else
! 	    n_braces = gen_generic_expr (f, opname, true);
  	  break;
  
  	default:
--- 1488,1494 ----
  	  break;
  
  	case operand::OP_EXPR:
! 	  n_braces = gen_gimple_expr (f);
  	  break;
  
  	default:
*************** dt_operand::gen_generic (FILE *f)
*** 1594,1600 ****
  	  break;
  
  	case operand::OP_EXPR:
! 	  n_braces = gen_generic_expr (f, opname, false);
  	  break;
  
  	default:
--- 1524,1530 ----
  	  break;
  
  	case operand::OP_EXPR:
! 	  n_braces = gen_generic_expr (f, opname);
  	  break;
  
  	default:
*************** decision_tree::gen_gimple (FILE *f)
*** 1879,1885 ****
  		     e->operation->op->id);
  	  fprintf (f, "{\n");
  	  dop->gen_gimple_kids (f); 
! 	  fprintf (f, "  break;\n");
  	  fprintf (f, "}\n");
  	}
        fprintf (f, "default:;\n"
--- 1809,1815 ----
  		     e->operation->op->id);
  	  fprintf (f, "{\n");
  	  dop->gen_gimple_kids (f); 
! 	  fprintf (f, "break;\n");
  	  fprintf (f, "}\n");
  	}
        fprintf (f, "default:;\n"



More information about the Gcc-patches mailing list