[PATCH][match-and-simplify] Properly canonicalize operand order for sub-expressions

Richard Biener rguenther@suse.de
Fri Jul 3 10:13:00 GMT 2015


I observed that we fail to match patterns because when valueizing
sub-expression operands we fail to canonicalize operand order
and thus try matching (1 + a) - 1 instead of the canonical
(a + 1) - 1.  The following fixes this at least for commutative
tree codes.  For comparisons which we also canonicalize in the
plumbing (by means of changing the comparison code via
swap_tree_comparison) this isn't that easily done.  I'm thinking
of a proper solution here.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

2015-07-03  Richard Biener  <rguenther@suse.de>

        * genmatch.c (commutative_tree_code, commutative_ternary_tree_code):
        Copy from tree.c
        (dt_operand::gen_gimple_expr): After valueizing operands
        re-canonicalize operand order for commutative tree codes.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 225368)
+++ gcc/genmatch.c	(working copy)
@@ -175,6 +175,62 @@ END_BUILTINS
 };
 #undef DEF_BUILTIN
 
+/* Return true if CODE represents a commutative tree code.  Otherwise
+   return false.  */
+bool
+commutative_tree_code (enum tree_code code)
+{
+  switch (code)
+    {
+    case PLUS_EXPR:
+    case MULT_EXPR:
+    case MULT_HIGHPART_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case BIT_AND_EXPR:
+    case NE_EXPR:
+    case EQ_EXPR:
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_OR_EXPR:
+    case WIDEN_MULT_EXPR:
+    case VEC_WIDEN_MULT_HI_EXPR:
+    case VEC_WIDEN_MULT_LO_EXPR:
+    case VEC_WIDEN_MULT_EVEN_EXPR:
+    case VEC_WIDEN_MULT_ODD_EXPR:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
+/* Return true if CODE represents a ternary tree code for which the
+   first two operands are commutative.  Otherwise return false.  */
+bool
+commutative_ternary_tree_code (enum tree_code code)
+{
+  switch (code)
+    {
+    case WIDEN_MULT_PLUS_EXPR:
+    case WIDEN_MULT_MINUS_EXPR:
+    case DOT_PROD_EXPR:
+    case FMA_EXPR:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
 
 /* Base class for all identifiers the parser knows.  */
 
@@ -1996,6 +2052,25 @@ dt_operand::gen_gimple_expr (FILE *f)
 	       child_opname, child_opname);
       fprintf (f, "{\n");
     }
+  /* While the toplevel operands are canonicalized by the caller
+     after valueizing operands of sub-expressions we have to
+     re-canonicalize operand order.  */
+  if (operator_id *code = dyn_cast <operator_id *> (id))
+    {
+      /* ???  We can't canonicalize tcc_comparison operands here
+         because that requires changing the comparison code which
+	 we already matched...  */
+      if (commutative_tree_code (code->code)
+	  || commutative_ternary_tree_code (code->code))
+	{
+	  char child_opname0[20], child_opname1[20];
+	  gen_opname (child_opname0, 0);
+	  gen_opname (child_opname1, 1);
+	  fprintf (f, "if (tree_swap_operands_p (%s, %s, false))\n"
+		   "  std::swap (%s, %s);\n", child_opname0, child_opname1,
+		   child_opname0, child_opname1);
+	}
+    }
 
   return n_ops;
 }



More information about the Gcc-patches mailing list