This adjusts the PR70251 fix as discussed in the PR audit trail
and fixes a bug in genmatch required (bah, stupid GENERIC comparisons in
GIMPLE operands...).

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2016-03-22  Richard Biener  <rguent...@suse.de>

        PR middle-end/70251
        * genmatch.c (gen_transform): Adjust last parameter to a three-state
        int...
        (capture::gen_transform): ... to change behavior when substituting
        a condition into cond or not-cond expr context.
        (dt_simplify::gen_1): Adjust.
        * gimple-match-head.c: Include gimplify.h for unshare_expr.
        * match.pd (A + (B vcmp C ? 1 : 0) -> A - (B vcmp C)): Revert
        last change and instead change to
        A + (B vcmp C ? 1 : 0) -> A - (B vcmp C ? -1 : 0).
        (A - (B vcmp C ? 1 : 0) -> A + (B vcmp C)): Likewise.

        * g++.dg/torture/pr70251.C: New testcase.

Index: gcc/genmatch.c
===================================================================
*** gcc/genmatch.c      (revision 234394)
--- gcc/genmatch.c      (working copy)
*************** struct operand {
*** 548,554 ****
    virtual void gen_transform (FILE *, int, const char *, bool, int,
                              const char *, capture_info *,
                              dt_operand ** = 0,
!                             bool = true)
      { gcc_unreachable  (); }
  };
  
--- 548,554 ----
    virtual void gen_transform (FILE *, int, const char *, bool, int,
                              const char *, capture_info *,
                              dt_operand ** = 0,
!                             int = 0)
      { gcc_unreachable  (); }
  };
  
*************** struct expr : public operand
*** 590,596 ****
    bool force_single_use;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, bool = true);
  };
  
  /* An operator that is represented by native C code.  This is always
--- 590,596 ----
    bool force_single_use;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, int = 0);
  };
  
  /* An operator that is represented by native C code.  This is always
*************** struct c_expr : public operand
*** 622,628 ****
    vec<id_tab> ids;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, bool = true);
  };
  
  /* A wrapper around another operand that captures its value.  */
--- 622,628 ----
    vec<id_tab> ids;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, int = 0);
  };
  
  /* A wrapper around another operand that captures its value.  */
*************** struct capture : public operand
*** 637,643 ****
    operand *what;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, bool = true);
  };
  
  /* if expression.  */
--- 637,643 ----
    operand *what;
    virtual void gen_transform (FILE *f, int, const char *, bool, int,
                              const char *, capture_info *,
!                             dt_operand ** = 0, int = 0);
  };
  
  /* if expression.  */
*************** get_operand_type (id_base *op, const cha
*** 2149,2155 ****
  void
  expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
                     int depth, const char *in_type, capture_info *cinfo,
!                    dt_operand **indexes, bool)
  {
    id_base *opr = operation;
    /* When we delay operator substituting during lowering of fors we
--- 2149,2155 ----
  void
  expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
                     int depth, const char *in_type, capture_info *cinfo,
!                    dt_operand **indexes, int)
  {
    id_base *opr = operation;
    /* When we delay operator substituting during lowering of fors we
*************** expr::gen_transform (FILE *f, int indent
*** 2213,2221 ****
                            i == 0 ? NULL : op0type);
        ops[i]->gen_transform (f, indent, dest, gimple, depth + 1, optype,
                             cinfo, indexes,
!                            ((!(*opr == COND_EXPR)
!                              && !(*opr == VEC_COND_EXPR))
!                             || i != 0));
      }
  
    const char *opr_name;
--- 2213,2220 ----
                            i == 0 ? NULL : op0type);
        ops[i]->gen_transform (f, indent, dest, gimple, depth + 1, optype,
                             cinfo, indexes,
!                            (*opr == COND_EXPR
!                             || *opr == VEC_COND_EXPR) && i == 0 ? 1 : 2);
      }
  
    const char *opr_name;
*************** expr::gen_transform (FILE *f, int indent
*** 2306,2312 ****
  void
  c_expr::gen_transform (FILE *f, int indent, const char *dest,
                       bool, int, const char *, capture_info *,
!                      dt_operand **, bool)
  {
    if (dest && nr_stmts == 1)
      fprintf_indent (f, indent, "%s = ", dest);
--- 2305,2311 ----
  void
  c_expr::gen_transform (FILE *f, int indent, const char *dest,
                       bool, int, const char *, capture_info *,
!                      dt_operand **, int)
  {
    if (dest && nr_stmts == 1)
      fprintf_indent (f, indent, "%s = ", dest);
*************** c_expr::gen_transform (FILE *f, int inde
*** 2378,2384 ****
  void
  capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
                        int depth, const char *in_type, capture_info *cinfo,
!                       dt_operand **indexes, bool expand_compares)
  {
    if (what && is_a<expr *> (what))
      {
--- 2377,2383 ----
  void
  capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
                        int depth, const char *in_type, capture_info *cinfo,
!                       dt_operand **indexes, int cond_handling)
  {
    if (what && is_a<expr *> (what))
      {
*************** capture::gen_transform (FILE *f, int ind
*** 2394,2413 ****
    fprintf_indent (f, indent, "%s = captures[%u];\n", dest, where);
  
    /* ???  Stupid tcc_comparison GENERIC trees in COND_EXPRs.  Deal
!      with substituting a capture of that.
!      ???  Returning false here will also not allow any other patterns
!      to match.  */
!   if (gimple && expand_compares
        && cinfo->info[where].cond_expr_cond_p)
      {
!       fprintf_indent (f, indent, "if (COMPARISON_CLASS_P (%s))\n", dest);
!       fprintf_indent (f, indent, "  {\n");
!       fprintf_indent (f, indent, "    if (!seq) return false;\n");
!       fprintf_indent (f, indent, "    %s = gimple_build (seq, TREE_CODE (%s),"
!                                " TREE_TYPE (%s), TREE_OPERAND (%s, 0),"
!                                " TREE_OPERAND (%s, 1));\n",
!                                dest, dest, dest, dest, dest);
!       fprintf_indent (f, indent, "  }\n");
      }
  }
  
--- 2393,2421 ----
    fprintf_indent (f, indent, "%s = captures[%u];\n", dest, where);
  
    /* ???  Stupid tcc_comparison GENERIC trees in COND_EXPRs.  Deal
!      with substituting a capture of that.  */
!   if (gimple
!       && cond_handling != 0
        && cinfo->info[where].cond_expr_cond_p)
      {
!       /* If substituting into a cond_expr condition, unshare.  */
!       if (cond_handling == 1)
!       fprintf_indent (f, indent, "%s = unshare_expr (%s);\n", dest, dest);
!       /* If substituting elsewhere we might need to decompose it.  */
!       else if (cond_handling == 2)
!       {
!         /* ???  Returning false here will also not allow any other patterns
!            to match unless this generator was split out.  */
!         fprintf_indent (f, indent, "if (COMPARISON_CLASS_P (%s))\n", dest);
!         fprintf_indent (f, indent, "  {\n");
!         fprintf_indent (f, indent, "    if (!seq) return false;\n");
!         fprintf_indent (f, indent, "    %s = gimple_build (seq,"
!                         " TREE_CODE (%s),"
!                         " TREE_TYPE (%s), TREE_OPERAND (%s, 0),"
!                         " TREE_OPERAND (%s, 1));\n",
!                         dest, dest, dest, dest, dest);
!         fprintf_indent (f, indent, "  }\n");
!       }
      }
  }
  
*************** dt_simplify::gen_1 (FILE *f, int indent,
*** 3043,3060 ****
                                    "type", e->expr_type,
                                    j == 0 ? NULL : "TREE_TYPE (res_ops[0])");
              /* We need to expand GENERIC conditions we captured from
!                COND_EXPRs.  */
!             bool expand_generic_cond_exprs_p
!               = (!is_predicate
!                  /* But avoid doing that if the GENERIC condition is
!                     valid - which it is in the first operand of COND_EXPRs
!                     and VEC_COND_EXRPs.  */
!                  && ((!(*opr == COND_EXPR)
!                       && !(*opr == VEC_COND_EXPR))
!                      || j != 0));
              e->ops[j]->gen_transform (f, indent, dest, true, 1, optype,
!                                       &cinfo,
!                                       indexes, expand_generic_cond_exprs_p);
            }
  
          /* Re-fold the toplevel result.  It's basically an embedded
--- 3051,3064 ----
                                    "type", e->expr_type,
                                    j == 0 ? NULL : "TREE_TYPE (res_ops[0])");
              /* We need to expand GENERIC conditions we captured from
!                COND_EXPRs and we need to unshare them when substituting
!                into COND_EXPRs.  */
!             int cond_handling = 0;
!             if (!is_predicate)
!               cond_handling = ((*opr == COND_EXPR
!                                 || *opr == VEC_COND_EXPR) && j == 0) ? 1 : 2;
              e->ops[j]->gen_transform (f, indent, dest, true, 1, optype,
!                                       &cinfo, indexes, cond_handling);
            }
  
          /* Re-fold the toplevel result.  It's basically an embedded
*************** dt_simplify::gen_1 (FILE *f, int indent,
*** 3068,3074 ****
               || result->type == operand::OP_C_EXPR)
        {
          result->gen_transform (f, indent, "res_ops[0]", true, 1, "type",
!                                &cinfo, indexes, false);
          fprintf_indent (f, indent, "*res_code = TREE_CODE (res_ops[0]);\n");
          if (is_a <capture *> (result)
              && cinfo.info[as_a <capture *> (result)->where].cond_expr_cond_p)
--- 3072,3078 ----
               || result->type == operand::OP_C_EXPR)
        {
          result->gen_transform (f, indent, "res_ops[0]", true, 1, "type",
!                                &cinfo, indexes);
          fprintf_indent (f, indent, "*res_code = TREE_CODE (res_ops[0]);\n");
          if (is_a <capture *> (result)
              && cinfo.info[as_a <capture *> (result)->where].cond_expr_cond_p)
Index: gcc/gimple-match-head.c
===================================================================
*** gcc/gimple-match-head.c     (revision 234394)
--- gcc/gimple-match-head.c     (working copy)
*************** along with GCC; see the file COPYING3.
*** 38,43 ****
--- 38,44 ----
  #include "tree-pass.h"
  #include "internal-fn.h"
  #include "case-cfn-macros.h"
+ #include "gimplify.h"
  
  
  /* Forward declarations of the private auto-generated matchers.
Index: gcc/match.pd
===================================================================
*** gcc/match.pd        (revision 234394)
--- gcc/match.pd        (working copy)
*************** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
*** 1752,1779 ****
    (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
    (cnd @0 @2 @1)))
  
! /* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C), since vector comparisons
!    return all-1 or all-0 results.  */
  /* ??? We could instead convert all instances of the vec_cond to negate,
     but that isn't necessarily a win on its own.  */
  (simplify
!  (plus:c @3 (view_convert? (vec_cond @0 integer_each_onep@1 integer_zerop@2)))
   (if (VECTOR_TYPE_P (type)
-       && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (@0)))
        && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
        && (TYPE_MODE (TREE_TYPE (type))
            == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
!   (minus @3 (view_convert @0))))
  
! /* ... likewise A - (B vcmp C ? 1 : 0) -> A + (B vcmp C).  */
  (simplify
!  (minus @3 (view_convert? (vec_cond @0 integer_each_onep@1 integer_zerop@2)))
   (if (VECTOR_TYPE_P (type)
-       && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (@0)))
        && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
        && (TYPE_MODE (TREE_TYPE (type))
            == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
!   (plus @3 (view_convert @0))))
  
  
  /* Simplifications of comparisons.  */
--- 1752,1777 ----
    (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
    (cnd @0 @2 @1)))
  
! /* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C ? -1 : 0), since vector comparisons
!    return all -1 or all 0 results.  */
  /* ??? We could instead convert all instances of the vec_cond to negate,
     but that isn't necessarily a win on its own.  */
  (simplify
!  (plus:c @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 
integer_zerop@2)))
   (if (VECTOR_TYPE_P (type)
        && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
        && (TYPE_MODE (TREE_TYPE (type))
            == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
!   (minus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
  
! /* ... likewise A - (B vcmp C ? 1 : 0) -> A + (B vcmp C ? -1 : 0).  */
  (simplify
!  (minus @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 
integer_zerop@2)))
   (if (VECTOR_TYPE_P (type)
        && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
        && (TYPE_MODE (TREE_TYPE (type))
            == TYPE_MODE (TREE_TYPE (TREE_TYPE (@0)))))
!   (plus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
  
  
  /* Simplifications of comparisons.  */
Index: gcc/testsuite/g++.dg/torture/pr70251.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr70251.C      (revision 0)
--- gcc/testsuite/g++.dg/torture/pr70251.C      (working copy)
***************
*** 0 ****
--- 1,11 ----
+ // { dg-do compile }
+ // { dg-additional-options "-w -Wno-psabi" }
+ 
+ typedef int vec __attribute__((vector_size(64)));
+ vec f(vec x,vec y,vec z)
+ {
+   vec zero={};
+   vec one=zero+1;
+   vec c=x<y;
+   return z+(c?one:zero);
+ }

Reply via email to