[GSoC] commutative patterns

2014-06-19 Thread Prathamesh Kulkarni
Hi,
The attached patch attempts to generate commutative variants for
a given expression.

Example:
For the AST: (PLUS_EXPR (PLUS_EXPR @0 @1) @2),

the commutative variants are:
(PLUS_EXPR (PLUS_EXPR @0 @1 ) @2 )
(PLUS_EXPR (PLUS_EXPR @1 @0 ) @2 )
(PLUS_EXPR @2 (PLUS_EXPR @0 @1 ) )
(PLUS_EXPR @2 (PLUS_EXPR @1 @0 ) )


* Basic Idea:
Consider expression e with two operands o0, and o1,
and expr-code denoting expression's code (plus/mult, etc.)

Commutative variants are stored in vector (vec).

vec
commutative (e)
{
  if (e is not commutative)
return [e];  // vector with only one expression

  v1 = commutative (o0);
  v2 = commutative (o1);
  ret = []

  for i = 0 ... v1.length ()
for j = 0 ... v2.length ()
  {
ne = new expr with  and operands: v1[i], v2[j];
append ne to ret;
  }

  for i = 0 ... v2.length ()
for j = 0 ... v1.length ()
  {
ne = new expr with  and operand: v2[i], v1[j];
append ne to ret
  }

  return ret;
}

Example:
(plus (plus @0 @1) (plus @2 @3))
generates following commutative variants:

(PLUS_EXPR (PLUS_EXPR @0 @1 ) (PLUS_EXPR @0 @3 ) )
(PLUS_EXPR (PLUS_EXPR @0 @1 ) (PLUS_EXPR @3 @0 ) )
(PLUS_EXPR (PLUS_EXPR @1 @0 ) (PLUS_EXPR @0 @3 ) )
(PLUS_EXPR (PLUS_EXPR @1 @0 ) (PLUS_EXPR @3 @0 ) )
(PLUS_EXPR (PLUS_EXPR @0 @3 ) (PLUS_EXPR @0 @1 ) )
(PLUS_EXPR (PLUS_EXPR @0 @3 ) (PLUS_EXPR @1 @0 ) )
(PLUS_EXPR (PLUS_EXPR @3 @0 ) (PLUS_EXPR @0 @1 ) )
(PLUS_EXPR (PLUS_EXPR @3 @0 ) (PLUS_EXPR @1 @0 ) )


* Decide which operators are commutative.
Currently I assume all PLUS_EXPR and MULT_EXPR are true.
Maybe we should add syntax to mark a particular operator as commutative ?

* Cloning AST nodes
While creating another AST that represents one of
the commutative variants, should we clone the AST nodes,
so that all commutative variants have distinct AST nodes ?
That's not done currently, and AST nodes are shared amongst
different commutative expressions, and we end up with a DAG,
for a set of commutative expressions.

Thanks and Regards,
Prathamesh
Index: gcc/genmatch.c
===
--- gcc/genmatch.c	(revision 211732)
+++ gcc/genmatch.c	(working copy)
@@ -293,14 +293,14 @@ e_operation::e_operation (const char *id
 
 struct simplify {
   simplify (const char *name_,
-	struct operand *match_, source_location match_location_,
+	vec matchers_, source_location match_location_,
 	struct operand *ifexpr_, source_location ifexpr_location_,
 	struct operand *result_, source_location result_location_)
-  : name (name_), match (match_), match_location (match_location_),
+  : name (name_), matchers (matchers_), match_location (match_location_),
   ifexpr (ifexpr_), ifexpr_location (ifexpr_location_),
   result (result_), result_location (result_location_) {}
   const char *name;
-  struct operand *match;
+  vec matchers;  // vector to hold commutative expressions
   source_location match_location;
   struct operand *ifexpr;
   source_location ifexpr_location;
@@ -308,7 +308,108 @@ struct simplify {
   source_location result_location;
 };
 
+void
+print_operand (operand *o, FILE *f = stderr) 
+{
+  if (o->type == operand::OP_CAPTURE)
+fprintf (f, "@%s", (static_cast (o))->where);
+
+  else if (o->type == operand::OP_PREDICATE)
+fprintf (f, "%s", (static_cast (o))->ident);
+
+  else if (o->type == operand::OP_C_EXPR)
+fprintf (f, "c_expr");
+
+  else if (o->type == operand::OP_EXPR)
+{
+  expr *e = static_cast (o);
+  fprintf (f, "(%s ", e->operation->op->id);
+
+  for (unsigned i = 0; i < e->ops.length (); ++i)
+	{
+	  print_operand (e->ops[i], f);
+	  putc (' ', f);
+	}
+
+  putc (')', f);
+}
+
+  else
+gcc_unreachable ();
+}
+
+void
+print_matches (struct simplify *s, FILE *f = stderr)
+{
+  if (s->matchers.length () == 1)
+return;
+
+  fprintf (f, "for expression: ");
+  print_operand (s->matchers[0], f);  // s->matchers[0] is equivalent to original expression
+  putc ('\n', f);
+
+  fprintf (f, "commutative expressions:\n");
+  for (unsigned i = 0; i < s->matchers.length (); ++i)
+{
+  print_operand (s->matchers[i], f);
+  putc ('\n', f);
+}
+}
+
+bool
+is_commutative (operand *op)
+{
+  if (op->type != operand::OP_EXPR)
+return false;
+
+  expr *e = static_cast (op);
+  operator_id *op_id = static_cast  (e->operation->op);
+  enum tree_code code = op_id->code;
 
+  if (code == PLUS_EXPR || code == MULT_EXPR)
+return true;
+
+  return false;
+}
+
+vec
+commutate (operand *op)
+{
+  vec ret = vNULL;
+
+  if (!is_commutative (op))
+{
+  ret.safe_push (op);  // FIXME: should we clone op ? ret.safe_push (op->clone()) 
+  return ret;
+}
+
+  expr *e = static_cast (op);
+
+  vec v1 = commutate (e->ops[0]);
+  vec v2 = commutate (e->ops[1]);
+
+  unsigned i, j;
+
+  for (i = 0; i < v1.length (); ++i)
+for (j = 0; j < v2.length (); ++j)
+  {
+	expr *ne = new expr (e->operation);  // FIXM

Re: [GSoC] commutative patterns

2014-06-19 Thread Prathamesh Kulkarni
On Fri, Jun 20, 2014 at 2:53 AM, Prathamesh Kulkarni
 wrote:
> Hi,
> The attached patch attempts to generate commutative variants for
> a given expression.
>
> Example:
> For the AST: (PLUS_EXPR (PLUS_EXPR @0 @1) @2),
>
> the commutative variants are:
> (PLUS_EXPR (PLUS_EXPR @0 @1 ) @2 )
> (PLUS_EXPR (PLUS_EXPR @1 @0 ) @2 )
> (PLUS_EXPR @2 (PLUS_EXPR @0 @1 ) )
> (PLUS_EXPR @2 (PLUS_EXPR @1 @0 ) )
>
>
> * Basic Idea:
> Consider expression e with two operands o0, and o1,
> and expr-code denoting expression's code (plus/mult, etc.)
>
> Commutative variants are stored in vector (vec).
>
> vec
> commutative (e)
> {
>   if (e is not commutative)
> return [e];  // vector with only one expression
>
>   v1 = commutative (o0);
>   v2 = commutative (o1);
>   ret = []
>
>   for i = 0 ... v1.length ()
> for j = 0 ... v2.length ()
>   {
> ne = new expr with  and operands: v1[i], v2[j];
> append ne to ret;
>   }
>
>   for i = 0 ... v2.length ()
> for j = 0 ... v1.length ()
>   {
> ne = new expr with  and operand: v2[i], v1[j];
> append ne to ret
>   }
>
>   return ret;
> }
>
> Example:
> (plus (plus @0 @1) (plus @2 @3))
> generates following commutative variants:
oops.
the pattern given to genmatch was (bogus):
(plus (plus @0 @1) (plus @0 @3))
>
> (PLUS_EXPR (PLUS_EXPR @0 @1 ) (PLUS_EXPR @0 @3 ) )
> (PLUS_EXPR (PLUS_EXPR @0 @1 ) (PLUS_EXPR @3 @0 ) )
> (PLUS_EXPR (PLUS_EXPR @1 @0 ) (PLUS_EXPR @0 @3 ) )
> (PLUS_EXPR (PLUS_EXPR @1 @0 ) (PLUS_EXPR @3 @0 ) )
> (PLUS_EXPR (PLUS_EXPR @0 @3 ) (PLUS_EXPR @0 @1 ) )
> (PLUS_EXPR (PLUS_EXPR @0 @3 ) (PLUS_EXPR @1 @0 ) )
> (PLUS_EXPR (PLUS_EXPR @3 @0 ) (PLUS_EXPR @0 @1 ) )
> (PLUS_EXPR (PLUS_EXPR @3 @0 ) (PLUS_EXPR @1 @0 ) )
>
>
> * Decide which operators are commutative.
> Currently I assume all PLUS_EXPR and MULT_EXPR are true.
s/true/commutative
> Maybe we should add syntax to mark a particular operator as commutative ?
>
> * Cloning AST nodes
> While creating another AST that represents one of
> the commutative variants, should we clone the AST nodes,
> so that all commutative variants have distinct AST nodes ?
> That's not done currently, and AST nodes are shared amongst
> different commutative expressions, and we end up with a DAG,
> for a set of commutative expressions.
>
> Thanks and Regards,
> Prathamesh


gcc-4.8-20140619 is now available

2014-06-19 Thread gccadmin
Snapshot gcc-4.8-20140619 is now available on
  ftp://gcc.gnu.org/pub/gcc/snapshots/4.8-20140619/
and on various mirrors, see http://gcc.gnu.org/mirrors.html for details.

This snapshot has been generated from the GCC 4.8 SVN branch
with the following options: svn://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch 
revision 211828

You'll find:

 gcc-4.8-20140619.tar.bz2 Complete GCC

  MD5=bdb46d0c39714ca1a3f616956c05c7f3
  SHA1=1db5302a7f769a36355019de528ebad79a875670

Diffs from 4.8-20140612 are available in the diffs/ subdirectory.

When a particular snapshot is ready for public consumption the LATEST-4.8
link is updated and a message is sent to the gcc list.  Please do not use
a snapshot before it has been announced that way.


Re: regs_used estimation in IVOPTS seriously flawed

2014-06-19 Thread Bin.Cheng
On Tue, Jun 17, 2014 at 10:59 PM, Bingfeng Mei  wrote:
> Hi,
> I am looking at a performance regression in our code. A big loop produces
> and uses a lot of temporary variables inside the loop body. The problem
> appears that IVOPTS pass creates even more induction variables (from original
> 2 to 27). It causes a lot of register spilling later and performance
Do you have a simplified case which can be posted here?  I guess it
affects some other targets too.

> take a severe hit. I looked into tree-ssa-loop-ivopts.c, it does call
> estimate_reg_pressure_cost function to take # of registers into
> consideration. The second parameter passed as data->regs_used is supposed
> to represent old register usage before IVOPTS.
>
>   return size + estimate_reg_pressure_cost (size, data->regs_used, 
> data->speed,
> data->body_includes_call);
>
> In this case, it is mere 2 by following calculation. Essentially, it only 
> counts
> all loop invariant registers, ignoring all registers produced/used inside the 
> loop.
There are two kinds of registers produced/used inside the loop.  One
is induction variable irrelevant, it includes non-linear uses as
mentioned by Richard.  The other kind relates to induction variable
rewrite, and one issue with this kind is expression generated during
iv use rewriting is not reflecting the estimated one in ivopt very
well.

Thanks,
bin
>
>   n = 0;
>   for (psi = gsi_start_phis (loop->header); !gsi_end_p (psi); gsi_next (&psi))
> {
>   phi = gsi_stmt (psi);
>   op = PHI_RESULT (phi);
>
>   if (virtual_operand_p (op))
> continue;
>
>   if (get_iv (data, op))
> continue;
>
>   n++;
> }
>
>   EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi)
> {
>   struct version_info *info = ver_info (data, j);
>
>   if (info->inv_id && info->has_nonlin_use)
> n++;
> }
>
>   data->regs_used = n;
>
> I believe how regs_used is calculated is seriously flawed,
> or estimate_reg_pressure_cost is problematic if n_old is
> only supposed to be loop invariant registers. Either way,
> it affects how IVOPTS makes decision and could result in
> worse code. What do you think? Any idea on how to improve
> this?
>
>
> Thanks,
> Bingfeng
>



-- 
Best Regards.