On Wed, 8 Jul 2015, Richard Biener wrote:

> 
> This introduces a :s flag to match expressions which enforces
> the expression to have a single-use if(!) the simplified
> expression is larger than one statement.
> 
> Thus with that we for example allow
> 
>   tem = a + 1;
>   x = tem - 3;
>   foo (tem);
> 
> to simplify to
> 
>   tem = a + 1;
>   x = a - 2;
>   foo (tem);
> 
> and more importantly not require "hacks" like
> 
>   /* 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))))
> 
> to allow the simplification if (plus @1 @3) will simplify further.
> 
> The trick is that generated code is changed like
> 
>  tree captures[4] ATTRIBUTE_UNUSED = {};
>  captures[0] = op0;
>  captures[1] = o20;
>  captures[2] = o21;
>  captures[3] = op1;
> -/* #line 659 "/space/rguenther/tramp3d/trunk/gcc/match.pd" */
> -if (single_use (captures[0]) || (TREE_CODE (captures[2]) == INTEGER_CST 
> && TREE
> _CODE (captures[3]) == INTEGER_CST))
> -{
> +gimple_seq *lseq = seq;
> +if (!single_use (captures[0])) lseq = NULL;
> ...
> 
> so in particular it disables all single-use restrictions if seq is NULL
> anyway (that is enough of a restriction already).
> 
> Bootstrap / regtest running on x86_64-unknown-linux-gnu.

The following is what I will apply soon.  I have changed code-generation
to use

  gimple_seq *lseq = seq;
  if (lseq
      && (!single_use (captures[0])
          || !single_use (captures[2])))
    lseq = NULL;

to short-cut the single_use checks completely if they would have no
effect.  I've also cleaned up genmatch by adding a kind-of 
copy-constructor to expr (verified that doesn't change generated code).

I've also changed all but one pattern to the new style.  The single
non-changed one is

/* Transform comparisons of the form X - Y CMP 0 to X CMP Y.
...
(for cmp (eq ne)
 (simplify
  (cmp (minus@2 @0 @1) integer_zerop)
  (if (single_use (@2))
   (cmp @0 @1))))

which is the one regressing DOM.  The issue with conditionals
if not appearing as the RHS of an assignment is that their
value is not available, so it isn't just a no-op change
regarding to surrounding code.

I've once attempted to "fix" that by forcing predicate computation
out of GIMPLE_CONDs but never finished that (doing this for
[VEC_]COND_EXPRs on RHS of assignments is still on my list of
things to do though).

Richard.

2015-07-09  Richard Biener  <rguent...@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.

Index: gcc/genmatch.c
===================================================================
*** gcc/genmatch.c      (revision 225600)
--- gcc/genmatch.c      (working copy)
*************** struct expr : public operand
*** 491,497 ****
    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) {}
    void append_op (operand *op) { ops.safe_push (op); }
    /* The operator and its operands.  */
    id_base *operation;
--- 491,501 ----
    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), 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;
*************** struct expr : public operand
*** 503,508 ****
--- 507,515 ----
    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);
*************** commutate (operand *op)
*** 747,753 ****
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       expr *ne = new expr (e->operation);
        for (unsigned j = 0; j < result[i].length (); ++j)
        ne->append_op (result[i][j]);
        ret.safe_push (ne);
--- 754,761 ----
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       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);
*************** commutate (operand *op)
*** 758,764 ****
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       expr *ne = new expr (e->operation);
        // 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]);
--- 766,773 ----
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       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]);
*************** lower_opt_convert (operand *o, enum tree
*** 809,822 ****
        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"));
        ne->append_op (lower_opt_convert (e->ops[0], oper, to_oper, strip));
        return ne;
      }
  
!   expr *ne = new expr (e->operation, e->is_commutative);
    for (unsigned i = 0; i < e->ops.length (); ++i)
      ne->append_op (lower_opt_convert (e->ops[i], oper, to_oper, strip));
  
--- 818,832 ----
        if (strip)
        return lower_opt_convert (e->ops[0], oper, to_oper, strip);
  
!       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);
    for (unsigned i = 0; i < e->ops.length (); ++i)
      ne->append_op (lower_opt_convert (e->ops[i], oper, to_oper, strip));
  
*************** lower_cond (operand *o)
*** 951,957 ****
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       expr *ne = new expr (e->operation);
        for (unsigned j = 0; j < result[i].length (); ++j)
        ne->append_op (result[i][j]);
        ro.safe_push (ne);
--- 961,967 ----
  
    for (unsigned i = 0; i < result.length (); ++i)
      {
!       expr *ne = new expr (e);
        for (unsigned j = 0; j < result[i].length (); ++j)
        ne->append_op (result[i][j]);
        ro.safe_push (ne);
*************** lower_cond (operand *o)
*** 968,980 ****
              || (is_a <expr *> (e->ops[0])
                  && as_a <expr *> (e->ops[0])->ops.length () == 2)))
        {
!         expr *ne = new expr (e->operation);
          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);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
--- 978,990 ----
              || (is_a <expr *> (e->ops[0])
                  && as_a <expr *> (e->ops[0])->ops.length () == 2)))
        {
!         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);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
*************** lower_cond (operand *o)
*** 983,989 ****
          else
            {
              expr *ocmp = as_a <expr *> (ne->ops[0]);
!             expr *cmp = new expr (ocmp->operation);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
--- 993,999 ----
          else
            {
              expr *ocmp = as_a <expr *> (ne->ops[0]);
!             expr *cmp = new expr (ocmp);
              for (unsigned j = 0; j < ocmp->ops.length (); ++j)
                cmp->append_op (ocmp->ops[j]);
              cmp->is_generic = true;
*************** replace_id (operand *o, user_id *id, id_
*** 1027,1035 ****
      }
    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;
        for (unsigned i = 0; i < e->ops.length (); ++i)
        ne->append_op (replace_id (e->ops[i], id, with));
        return ne;
--- 1037,1045 ----
      }
    else if (expr *e = dyn_cast<expr *> (o))
      {
!       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;
*************** struct capture_info
*** 1513,1518 ****
--- 1523,1529 ----
        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;
*************** capture_info::walk_match (operand *o, un
*** 1566,1575 ****
        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.  */
        if (c->what
!         && is_a <expr *> (c->what))
        {
          info[c->where].expr_p = true;
          walk_match (c->what, toplevel_arg, conditional_p, false);
        }
      }
--- 1577,1588 ----
        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
!         && (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);
        }
      }
*************** expr::gen_transform (FILE *f, const char
*** 1808,1816 ****
        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",
               ops.length (), type);
!       fprintf (f, "  res = maybe_push_res_to_seq (tem_code, %s, tem_ops, 
seq);\n"
               "  if (!res) return false;\n", type);
        if (*operation == CONVERT_EXPR)
          fprintf (f, "  }\n"
--- 1821,1829 ----
        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 (lseq, &tem_code, %s, tem_ops, 
valueize);\n",
               ops.length (), type);
!       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"
*************** dt_simplify::gen (FILE *f, bool gimple)
*** 2449,2475 ****
       that cover cases we cannot handle.  */
    capture_info cinfo (s);
    expr *e;
!   if (!gimple
!       && 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;
      }
  
    fprintf (f, "if (dump_file && (dump_flags & TDF_DETAILS)) "
--- 2462,2513 ----
       that cover cases we cannot handle.  */
    capture_info cinfo (s);
    expr *e;
!   if (s->result
        && !((e = dyn_cast <expr *> (s->result))
           && is_a <predicate_id *> (e->operation)))
      {
!       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)) "
*************** dt_simplify::gen (FILE *f, bool gimple)
*** 2524,2530 ****
          /* 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, "
                     "res_ops, valueize);\n", e->ops.length ());
        }
        else if (result->type == operand::OP_CAPTURE
--- 2562,2568 ----
          /* 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 (lseq, res_code, type, "
                     "res_ops, valueize);\n", e->ops.length ());
        }
        else if (result->type == operand::OP_CAPTURE
*************** parser::parse_expr ()
*** 3051,3056 ****
--- 3089,3095 ----
    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
*************** parser::parse_expr ()
*** 3062,3083 ****
          && !(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)
!               fatal_at (token, "type can only be used in result expression");
!             expr_type = s;
            }
-         else
-           fatal_at (token, "flag %s not recognized", s);
- 
          token = peek ();
        }
        else
--- 3101,3125 ----
          && !(token->flags & PREV_WHITE))
        {
          const char *s = get_ident ();
!         if (!parsing_match_operand)
!           expr_type = s;
!         else
            {
!             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++;
!               }
            }
          token = peek ();
        }
        else
*************** parser::parse_expr ()
*** 3087,3092 ****
--- 3129,3145 ----
    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: gcc/match.pd
===================================================================
*** gcc/match.pd        (revision 225600)
--- gcc/match.pd        (working copy)
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 334,350 ****
  
  /* 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))))
  
  /* 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)))))
  
  /* (x | y) & ~x -> y & ~x */
  /* (x & y) | ~x -> y | ~x */
--- 334,348 ----
  
  /* x + (x & 1) -> (x + 1) & ~1 */
  (simplify
!  (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:cs @0 @1)))
!   (bitop @0 (bit_not @1))))
  
  /* (x | y) & ~x -> y & ~x */
  /* (x & y) | ~x -> y | ~x */
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 633,649 ****
  
  /* (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)))
  
  
  /* 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))))
  
  /* Pattern match
       tem1 = (long) ptr1;
--- 631,644 ----
  
  /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */
  (simplify
!  (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:s@2 @0 @1) @3)
!   (pointer_plus @0 (plus @1 @3)))
  
  /* Pattern match
       tem1 = (long) ptr1;
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 913,919 ****
     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)
     (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5))
        && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT
        && tree_fits_uhwi_p (@1)
--- 908,915 ----
     if the new mask might be further optimized.  */
  (for shift (lshift rshift)
   (simplify
!   (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)
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 993,1000 ****
         (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))
            (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; 
}))
           (if (shift_type == TREE_TYPE (@3))
            (bit_and @4 { newmaskt; }))))))))))))
--- 989,995 ----
         (with
          { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); }
          (if (!tree_int_cst_equal (newmaskt, @2))
!          (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; }))))))))))))
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 1733,1739 ****
     operation and convert the result to the desired type.  */
  (for op (plus minus)
    (simplify
!     (convert (op@4 (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.  */
--- 1728,1734 ----
     operation and convert the result to the desired type.  */
  (for op (plus minus)
    (simplify
!     (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.  */
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 1750,1757 ****
         /* 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))
        (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (convert (op @0 @1)))
        (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
--- 1745,1751 ----
         /* 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))
        (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (convert (op @0 @1)))
        (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 1764,1770 ****
     arithmetic operation.  */
  (for op (minus plus)
    (simplify
!     (bit_and (op@5 (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.  */
--- 1758,1764 ----
     arithmetic operation.  */
  (for op (minus plus)
    (simplify
!     (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.  */
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 1784,1791 ****
         && (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))
        (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (with { tree ntype = TREE_TYPE (@0); }
          (convert (bit_and (op @0 @1) (convert:ntype @4)))))
--- 1778,1784 ----
         && (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))
        (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
        (with { tree ntype = TREE_TYPE (@0); }
          (convert (bit_and (op @0 @1) (convert:ntype @4)))))

Reply via email to