genmatch.c (struct expr): Add force_single_use flag.
authorRichard Biener <rguenther@suse.de>
Thu, 9 Jul 2015 12:23:22 +0000 (12:23 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 9 Jul 2015 12:23:22 +0000 (12:23 +0000)
2015-07-09  Richard Biener  <rguenther@suse.de>

* genmatch.c (struct expr): Add force_single_use flag.
(expr::expr): Add copy constructor.
(capture_info::walk_match): Gather force_single_use captures.
(expr::gen_transform): Use possibly NULLified sequence.
(dt_simplify::gen): Apply single-use restrictions by NULLifying
seq if any constrained expr is not single-use.
(parser::parse_expr): Refactor to allow multiple flags.  Handle
's' flag to force an expression have a single-use if the pattern
simplifies to more than one statement.
* match.pd: Convert most single_use conditionals to :s flags.

From-SVN: r225610

gcc/ChangeLog
gcc/genmatch.c
gcc/match.pd

index 4e81e8cce047fd1920bbe1cc5a44e218a28dfe4c..8e05c427c45050e7df16063bb23f7541c3cf9f5e 100644 (file)
@@ -1,3 +1,16 @@
+2015-07-09  Richard Biener  <rguenther@suse.de>
+
+       * genmatch.c (struct expr): Add force_single_use flag.
+       (expr::expr): Add copy constructor.
+       (capture_info::walk_match): Gather force_single_use captures.
+       (expr::gen_transform): Use possibly NULLified sequence.
+       (dt_simplify::gen): Apply single-use restrictions by NULLifying
+       seq if any constrained expr is not single-use.
+       (parser::parse_expr): Refactor to allow multiple flags.  Handle
+       's' flag to force an expression have a single-use if the pattern
+       simplifies to more than one statement.
+       * match.pd: Convert most single_use conditionals to :s flags.
+
 2015-07-09  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/i386/iamcu.h (ASM_OUTPUT_ALIGNED_BSS): New.
index 7ee6fb5b50f9ec9254cb13fcce6fe9d4d392c89b..15ce1f591bd8b8f191aaf2bb5cb21322d0242d06 100644 (file)
@@ -491,7 +491,11 @@ struct expr : public operand
   expr (id_base *operation_, bool is_commutative_ = false)
     : operand (OP_EXPR), operation (operation_),
       ops (vNULL), expr_type (NULL), is_commutative (is_commutative_),
-      is_generic (false) {}
+      is_generic (false), force_single_use (false) {}
+  expr (expr *e)
+    : operand (OP_EXPR), operation (e->operation),
+      ops (vNULL), expr_type (e->expr_type), is_commutative (e->is_commutative),
+      is_generic (e->is_generic), force_single_use (e->force_single_use) {}
   void append_op (operand *op) { ops.safe_push (op); }
   /* The operator and its operands.  */
   id_base *operation;
@@ -503,6 +507,9 @@ struct expr : public operand
   bool is_commutative;
   /* Whether the expression is expected to be in GENERIC form.  */
   bool is_generic;
+  /* Whether pushing any stmt to the sequence should be conditional
+     on this expression having a single-use.  */
+  bool force_single_use;
   virtual void gen_transform (FILE *f, const char *, bool, int,
                              const char *, capture_info *,
                              dt_operand ** = 0, bool = true);
@@ -747,7 +754,8 @@ commutate (operand *op)
 
   for (unsigned i = 0; i < result.length (); ++i)
     {
-      expr *ne = new expr (e->operation);
+      expr *ne = new expr (e);
+      ne->is_commutative = false;
       for (unsigned j = 0; j < result[i].length (); ++j)
        ne->append_op (result[i][j]);
       ret.safe_push (ne);
@@ -758,7 +766,8 @@ commutate (operand *op)
 
   for (unsigned i = 0; i < result.length (); ++i)
     {
-      expr *ne = new expr (e->operation);
+      expr *ne = new expr (e);
+      ne->is_commutative = false;
       // result[i].length () is 2 since e->operation is binary
       for (unsigned j = result[i].length (); j; --j)
        ne->append_op (result[i][j-1]);
@@ -809,14 +818,15 @@ lower_opt_convert (operand *o, enum tree_code oper,
       if (strip)
        return lower_opt_convert (e->ops[0], oper, to_oper, strip);
 
-      expr *ne = new expr (to_oper == CONVERT_EXPR
-                          ? get_operator ("CONVERT_EXPR")
-                          : get_operator ("VIEW_CONVERT_EXPR"));
+      expr *ne = new expr (e);
+      ne->operation = (to_oper == CONVERT_EXPR
+                      ? get_operator ("CONVERT_EXPR")
+                      : get_operator ("VIEW_CONVERT_EXPR"));
       ne->append_op (lower_opt_convert (e->ops[0], oper, to_oper, strip));
       return ne;
     }
 
-  expr *ne = new expr (e->operation, e->is_commutative);
+  expr *ne = new expr (e);
   for (unsigned i = 0; i < e->ops.length (); ++i)
     ne->append_op (lower_opt_convert (e->ops[i], oper, to_oper, strip));
 
@@ -951,7 +961,7 @@ lower_cond (operand *o)
 
   for (unsigned i = 0; i < result.length (); ++i)
     {
-      expr *ne = new expr (e->operation);
+      expr *ne = new expr (e);
       for (unsigned j = 0; j < result[i].length (); ++j)
        ne->append_op (result[i][j]);
       ro.safe_push (ne);
@@ -968,13 +978,13 @@ lower_cond (operand *o)
              || (is_a <expr *> (e->ops[0])
                  && as_a <expr *> (e->ops[0])->ops.length () == 2)))
        {
-         expr *ne = new expr (e->operation);
+         expr *ne = new expr (e);
          for (unsigned j = 0; j < result[i].length (); ++j)
            ne->append_op (result[i][j]);
          if (capture *c = dyn_cast <capture *> (ne->ops[0]))
            {
              expr *ocmp = as_a <expr *> (c->what);
-             expr *cmp = new expr (ocmp->operation);
+             expr *cmp = new expr (ocmp);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
@@ -983,7 +993,7 @@ lower_cond (operand *o)
          else
            {
              expr *ocmp = as_a <expr *> (ne->ops[0]);
-             expr *cmp = new expr (ocmp->operation);
+             expr *cmp = new expr (ocmp);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
@@ -1027,9 +1037,9 @@ replace_id (operand *o, user_id *id, id_base *with)
     }
   else if (expr *e = dyn_cast<expr *> (o))
     {
-      expr *ne = new expr (e->operation == id ? with : e->operation,
-                          e->is_commutative);
-      ne->expr_type = e->expr_type;
+      expr *ne = new expr (e);
+      if (e->operation == id)
+       ne->operation = with;
       for (unsigned i = 0; i < e->ops.length (); ++i)
        ne->append_op (replace_id (e->ops[i], id, with));
       return ne;
@@ -1513,6 +1523,7 @@ struct capture_info
       bool expr_p;
       bool cse_p;
       bool force_no_side_effects_p;
+      bool force_single_use;
       bool cond_expr_cond_p;
       unsigned long toplevel_msk;
       int result_use_count;
@@ -1566,10 +1577,12 @@ capture_info::walk_match (operand *o, unsigned toplevel_arg,
       info[c->where].force_no_side_effects_p |= conditional_p;
       info[c->where].cond_expr_cond_p |= cond_expr_cond_p;
       /* Mark expr (non-leaf) captures and recurse.  */
+      expr *e;
       if (c->what
-         && is_a <expr *> (c->what))
+         && (e = dyn_cast <expr *> (c->what)))
        {
          info[c->where].expr_p = true;
+         info[c->where].force_single_use |= e->force_single_use;
          walk_match (c->what, toplevel_arg, conditional_p, false);
        }
     }
@@ -1808,9 +1821,9 @@ expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
       for (unsigned i = 0; i < ops.length (); ++i)
        fprintf (f, "ops%d[%u]%s", depth, i,
                 i == ops.length () - 1 ? " };\n" : ", ");
-      fprintf (f, "  gimple_resimplify%d (seq, &tem_code, %s, tem_ops, valueize);\n",
+      fprintf (f, "  gimple_resimplify%d (lseq, &tem_code, %s, tem_ops, valueize);\n",
               ops.length (), type);
-      fprintf (f, "  res = maybe_push_res_to_seq (tem_code, %s, tem_ops, seq);\n"
+      fprintf (f, "  res = maybe_push_res_to_seq (tem_code, %s, tem_ops, lseq);\n"
               "  if (!res) return false;\n", type);
       if (*operation == CONVERT_EXPR)
         fprintf (f, "  }\n"
@@ -2449,27 +2462,52 @@ dt_simplify::gen (FILE *f, bool gimple)
      that cover cases we cannot handle.  */
   capture_info cinfo (s);
   expr *e;
-  if (!gimple
-      && s->result
+  if (s->result
       && !((e = dyn_cast <expr *> (s->result))
           && is_a <predicate_id *> (e->operation)))
     {
-      for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i)
-       if (cinfo.force_no_side_effects & (1 << i))
-         fprintf (f, "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n", i);
-      for (int i = 0; i <= s->capture_max; ++i)
-       if (cinfo.info[i].cse_p)
-         ;
-       else if (cinfo.info[i].force_no_side_effects_p
-                && (cinfo.info[i].toplevel_msk
-                    & cinfo.force_no_side_effects) == 0)
-         fprintf (f, "if (TREE_SIDE_EFFECTS (captures[%d])) "
-                  "return NULL_TREE;\n", i);
-       else if ((cinfo.info[i].toplevel_msk
-                 & cinfo.force_no_side_effects) != 0)
-         /* Mark capture as having no side-effects if we had to verify
-            that via forced toplevel operand checks.  */
-         cinfo.info[i].force_no_side_effects_p = true;
+      if (!gimple)
+       {
+         for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i)
+           if (cinfo.force_no_side_effects & (1 << i))
+             fprintf (f, "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n", i);
+         for (int i = 0; i <= s->capture_max; ++i)
+           if (cinfo.info[i].cse_p)
+             ;
+           else if (cinfo.info[i].force_no_side_effects_p
+                    && (cinfo.info[i].toplevel_msk
+                        & cinfo.force_no_side_effects) == 0)
+             fprintf (f, "if (TREE_SIDE_EFFECTS (captures[%d])) "
+                      "return NULL_TREE;\n", i);
+           else if ((cinfo.info[i].toplevel_msk
+                     & cinfo.force_no_side_effects) != 0)
+             /* Mark capture as having no side-effects if we had to verify
+                that via forced toplevel operand checks.  */
+             cinfo.info[i].force_no_side_effects_p = true;
+       }
+      if (gimple)
+       {
+         /* Force single-use restriction by only allowing simple
+            results via setting seq to NULL.  */
+         fprintf (f, "gimple_seq *lseq = seq;\n");
+         bool first_p = true;
+         for (int i = 0; i <= s->capture_max; ++i)
+           if (cinfo.info[i].force_single_use)
+             {
+               if (first_p)
+                 {
+                   fprintf (f, "if (lseq\n"
+                            "&& (");
+                   first_p = false;
+                 }
+               else
+                 fprintf (f, "\n|| ");
+               fprintf (f, "!single_use (captures[%d])", i);
+             }
+         if (!first_p)
+           fprintf (f, "))\n"
+                    "lseq = NULL;\n");
+       }
     }
 
   fprintf (f, "if (dump_file && (dump_flags & TDF_DETAILS)) "
@@ -2524,7 +2562,7 @@ dt_simplify::gen (FILE *f, bool gimple)
          /* Re-fold the toplevel result.  It's basically an embedded
             gimple_build w/o actually building the stmt.  */
          if (!is_predicate)
-           fprintf (f, "gimple_resimplify%d (seq, res_code, type, "
+           fprintf (f, "gimple_resimplify%d (lseq, res_code, type, "
                     "res_ops, valueize);\n", e->ops.length ());
        }
       else if (result->type == operand::OP_CAPTURE
@@ -3051,6 +3089,7 @@ parser::parse_expr ()
   const cpp_token *token = peek ();
   operand *op;
   bool is_commutative = false;
+  bool force_capture = false;
   const char *expr_type = NULL;
 
   if (token->type == CPP_COLON
@@ -3062,22 +3101,25 @@ parser::parse_expr ()
          && !(token->flags & PREV_WHITE))
        {
          const char *s = get_ident ();
-         if (s[0] == 'c' && !s[1])
-           {
-             if (!parsing_match_operand)
-               fatal_at (token,
-                         "flag 'c' can only be used in match expression");
-             is_commutative = true;
-           }
-         else if (s[1] != '\0')
+         if (!parsing_match_operand)
+           expr_type = s;
+         else
            {
-             if (parsing_match_operand)
-               fatal_at (token, "type can only be used in result expression");
-             expr_type = s;
+             const char *sp = s;
+             while (*sp)
+               {
+                 if (*sp == 'c')
+                   is_commutative = true;
+                 else if (*sp == 's')
+                   {
+                     e->force_single_use = true;
+                     force_capture = true;
+                   }
+                 else
+                   fatal_at (token, "flag %c not recognized", *sp);
+                 sp++;
+               }
            }
-         else
-           fatal_at (token, "flag %s not recognized", s);
-
          token = peek ();
        }
       else
@@ -3087,6 +3129,17 @@ parser::parse_expr ()
   if (token->type == CPP_ATSIGN
       && !(token->flags & PREV_WHITE))
     op = parse_capture (e);
+  else if (force_capture)
+    {
+      unsigned num = capture_ids->elements ();
+      char id[8];
+      bool existed;
+      sprintf (id, "__%u", num);
+      capture_ids->get_or_insert (xstrdup (id), &existed);
+      if (existed)
+       fatal_at (token, "reserved capture id '%s' already used", id);
+      op = new capture (num, e);
+    }
   else
     op = e;
   do
index 5e8fd32ed22638d5a6b0264c009094cb7e7dec40..b28f107be90bb764298e2964dc6db3227eb3ff1d 100644 (file)
@@ -334,17 +334,15 @@ along with GCC; see the file COPYING3.  If not see
 
 /* x + (x & 1) -> (x + 1) & ~1 */
 (simplify
- (plus:c @0 (bit_and@2 @0 integer_onep@1))
- (if (single_use (@2))
-  (bit_and (plus @0 @1) (bit_not @1))))
+ (plus:c @0 (bit_and:s @0 integer_onep@1))
+ (bit_and (plus @0 @1) (bit_not @1)))
 
 /* x & ~(x & y) -> x & ~y */
 /* x | ~(x | y) -> x | ~y  */
 (for bitop (bit_and bit_ior)
  (simplify
-  (bitop:c @0 (bit_not (bitop:c@2 @0 @1)))
-   (if (single_use (@2))
-    (bitop @0 (bit_not @1)))))
+  (bitop:c @0 (bit_not (bitop:cs @0 @1)))
+  (bitop @0 (bit_not @1))))
 
 /* (x | y) & ~x -> y & ~x */
 /* (x & y) | ~x -> y | ~x */
@@ -633,17 +631,14 @@ along with GCC; see the file COPYING3.  If not see
 
 /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */
 (simplify
-  (bit_ior:c (bit_and:c@3 @0 (bit_not @2)) (bit_and:c@4 @1 @2))
-  (if (single_use (@3) && single_use (@4))
-   (bit_xor (bit_and (bit_xor @0 @1) @2) @0)))
+ (bit_ior:c (bit_and:cs @0 (bit_not @2)) (bit_and:cs @1 @2))
+ (bit_xor (bit_and (bit_xor @0 @1) @2) @0))
 
 
 /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)).  */
 (simplify
-  (pointer_plus (pointer_plus@2 @0 @1) @3)
-  (if (single_use (@2)
-       || (TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@3) == INTEGER_CST))
-   (pointer_plus @0 (plus @1 @3))))
+  (pointer_plus (pointer_plus:s @0 @1) @3)
+  (pointer_plus @0 (plus @1 @3)))
 
 /* Pattern match
      tem1 = (long) ptr1;
@@ -913,7 +908,8 @@ along with GCC; see the file COPYING3.  If not see
    if the new mask might be further optimized.  */
 (for shift (lshift rshift)
  (simplify
-  (bit_and (convert?@4 (shift@5 (convert1?@3 @0) INTEGER_CST@1)) INTEGER_CST@2)
+  (bit_and (convert?:s@4 (shift:s@5 (convert1?@3 @0) INTEGER_CST@1))
+           INTEGER_CST@2)
    (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5))
        && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT
        && tree_fits_uhwi_p (@1)
@@ -993,8 +989,7 @@ along with GCC; see the file COPYING3.  If not see
         (with
          { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); }
          (if (!tree_int_cst_equal (newmaskt, @2))
-          (if (shift_type != TREE_TYPE (@3)
-               && single_use (@4) && single_use (@5))
+          (if (shift_type != TREE_TYPE (@3))
            (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; }))
           (if (shift_type == TREE_TYPE (@3))
            (bit_and @4 { newmaskt; }))))))))))))
@@ -1733,7 +1728,7 @@ along with GCC; see the file COPYING3.  If not see
    operation and convert the result to the desired type.  */
 (for op (plus minus)
   (simplify
-    (convert (op@4 (convert@2 @0) (convert@3 @1)))
+    (convert (op:s (convert@2 @0) (convert@3 @1)))
     (if (INTEGRAL_TYPE_P (type)
         /* We check for type compatibility between @0 and @1 below,
            so there's no need to check that @1/@3 are integral types.  */
@@ -1750,8 +1745,7 @@ along with GCC; see the file COPYING3.  If not see
         /* The inner conversion must be a widening conversion.  */
         && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
         && types_match (@0, @1)
-        && types_match (@0, type)
-        && single_use (@4))
+        && types_match (@0, type))
       (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (convert (op @0 @1)))
       (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
@@ -1764,7 +1758,7 @@ along with GCC; see the file COPYING3.  If not see
    arithmetic operation.  */
 (for op (minus plus)
   (simplify
-    (bit_and (op@5 (convert@2 @0) (convert@3 @1)) INTEGER_CST@4)
+    (bit_and (op:s (convert@2 @0) (convert@3 @1)) INTEGER_CST@4)
     (if (INTEGRAL_TYPE_P (type)
         /* We check for type compatibility between @0 and @1 below,
            so there's no need to check that @1/@3 are integral types.  */
@@ -1784,8 +1778,7 @@ along with GCC; see the file COPYING3.  If not see
         && (tree_int_cst_min_precision (@4, TYPE_SIGN (TREE_TYPE (@0)))
             <= TYPE_PRECISION (TREE_TYPE (@0)))
         && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
-            || tree_int_cst_sgn (@4) >= 0)
-        && single_use (@5))
+            || tree_int_cst_sgn (@4) >= 0))
       (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (with { tree ntype = TREE_TYPE (@0); }
          (convert (bit_and (op @0 @1) (convert:ntype @4)))))