]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gimple-match-head.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / gimple-match-head.c
index 414007ec1f9ece6ba112387c9383938adce87950..7112c1168357ba3bf9d99e87d3b78f3367304145 100644 (file)
@@ -1,5 +1,5 @@
 /* Preamble and helpers for the autogenerated gimple-match.c file.
-   Copyright (C) 2014-2018 Free Software Foundation, Inc.
+   Copyright (C) 2014-2021 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "ssa.h"
 #include "cgraph.h"
+#include "vec-perm-indices.h"
 #include "fold-const.h"
 #include "fold-const-call.h"
 #include "stor-layout.h"
@@ -41,7 +42,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "optabs-tree.h"
 #include "tree-eh.h"
-
+#include "dbgcnt.h"
+#include "tm.h"
+#include "gimple-range.h"
 
 /* Forward declarations of the private auto-generated matchers.
    They expect valueized operands in canonical order and do not
@@ -56,6 +59,16 @@ static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
                             code_helper, tree, tree, tree, tree, tree);
 static bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
                             code_helper, tree, tree, tree, tree, tree, tree);
+static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *,
+                               tree (*)(tree));
+static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *,
+                               tree (*)(tree));
+static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *,
+                               tree (*)(tree));
+static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *,
+                               tree (*)(tree));
+static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *,
+                               tree (*)(tree));
 
 const unsigned int gimple_match_op::MAX_NUM_OPS;
 
@@ -133,9 +146,21 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
       /* Likewise if the operation would not trap.  */
       bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
                          && TYPE_OVERFLOW_TRAPS (res_op->type));
-      if (!operation_could_trap_p ((tree_code) res_op->code,
-                                  FLOAT_TYPE_P (res_op->type),
-                                  honor_trapv, res_op->op_or_null (1)))
+      tree_code op_code = (tree_code) res_op->code;
+      bool op_could_trap;
+
+      /* COND_EXPR will trap if, and only if, the condition
+        traps and hence we have to check this.  For all other operations, we
+        don't need to consider the operands.  */
+      if (op_code == COND_EXPR)
+       op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
+      else
+       op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
+                                               FLOAT_TYPE_P (res_op->type),
+                                               honor_trapv,
+                                               res_op->op_or_null (1));
+
+      if (!op_could_trap)
        {
          res_op->cond.cond = NULL_TREE;
          return false;
@@ -172,7 +197,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
    RES_OP with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
-bool
+static bool
 gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
                    tree (*valueize)(tree))
 {
@@ -180,7 +205,12 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
     {
       tree tem = NULL_TREE;
       if (res_op->code.is_tree_code ())
-       tem = const_unop (res_op->code, res_op->type, res_op->ops[0]);
+       {
+         tree_code code = res_op->code;
+         if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+             && TREE_CODE_LENGTH (code) == 1)
+           tem = const_unop (res_op->code, res_op->type, res_op->ops[0]);
+       }
       else
        tem = fold_const_call (combined_fn (res_op->code), res_op->type,
                               res_op->ops[0]);
@@ -232,7 +262,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
    RES_OP with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
-bool
+static bool
 gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
                    tree (*valueize)(tree))
 {
@@ -241,8 +271,13 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
     {
       tree tem = NULL_TREE;
       if (res_op->code.is_tree_code ())
-       tem = const_binop (res_op->code, res_op->type,
-                          res_op->ops[0], res_op->ops[1]);
+       {
+         tree_code code = res_op->code;
+         if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+             && TREE_CODE_LENGTH (code) == 2)
+           tem = const_binop (res_op->code, res_op->type,
+                              res_op->ops[0], res_op->ops[1]);
+       }
       else
        tem = fold_const_call (combined_fn (res_op->code), res_op->type,
                               res_op->ops[0], res_op->ops[1]);
@@ -304,7 +339,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
    RES_OP with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
-bool
+static bool
 gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
                    tree (*valueize)(tree))
 {
@@ -314,9 +349,14 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
     {
       tree tem = NULL_TREE;
       if (res_op->code.is_tree_code ())
-       tem = fold_ternary/*_to_constant*/ (res_op->code, res_op->type,
-                                           res_op->ops[0], res_op->ops[1],
-                                           res_op->ops[2]);
+       {
+         tree_code code = res_op->code;
+         if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+             && TREE_CODE_LENGTH (code) == 3)
+           tem = fold_ternary/*_to_constant*/ (res_op->code, res_op->type,
+                                               res_op->ops[0], res_op->ops[1],
+                                               res_op->ops[2]);
+       }
       else
        tem = fold_const_call (combined_fn (res_op->code), res_op->type,
                               res_op->ops[0], res_op->ops[1], res_op->ops[2]);
@@ -375,7 +415,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
    RES_OP with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
-bool
+static bool
 gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
                    tree (*valueize)(tree))
 {
@@ -416,7 +456,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
    RES_OP with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
-bool
+static bool
 gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
                    tree (*valueize)(tree))
 {
@@ -438,6 +478,30 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
   return false;
 }
 
+/* Match and simplify the toplevel valueized operation THIS.
+   Replaces THIS with a simplified and/or canonicalized result and
+   returns whether any change was made.  */
+
+bool
+gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
+{
+  switch (num_ops)
+    {
+    case 1:
+      return gimple_resimplify1 (seq, this, valueize);
+    case 2:
+      return gimple_resimplify2 (seq, this, valueize);
+    case 3:
+      return gimple_resimplify3 (seq, this, valueize);
+    case 4:
+      return gimple_resimplify4 (seq, this, valueize);
+    case 5:
+      return gimple_resimplify5 (seq, this, valueize);
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* If in GIMPLE the operation described by RES_OP should be single-rhs,
    build a GENERIC tree for that expression and update RES_OP accordingly.  */
 
@@ -445,16 +509,20 @@ void
 maybe_build_generic_op (gimple_match_op *res_op)
 {
   tree_code code = (tree_code) res_op->code;
+  tree val;
   switch (code)
     {
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case VIEW_CONVERT_EXPR:
-      res_op->set_value (build1 (code, res_op->type, res_op->ops[0]));
+      val = build1 (code, res_op->type, res_op->ops[0]);
+      res_op->set_value (val);
       break;
     case BIT_FIELD_REF:
-      res_op->set_value (build3 (code, res_op->type, res_op->ops[0],
-                                res_op->ops[1], res_op->ops[2]));
+      val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
+                   res_op->ops[2]);
+      REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
+      res_op->set_value (val);
       break;
     default:;
     }
@@ -798,8 +866,8 @@ try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
   gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
                                              res_op->ops[num_ops - 1]),
                           op, res_op->type, num_ops - 2);
-  for (unsigned int i = 1; i < num_ops - 1; ++i)
-    cond_op.ops[i - 1] = res_op->ops[i];
+
+  memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
   switch (num_ops - 2)
     {
     case 2:
@@ -853,7 +921,10 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
                op0 = do_valueize (op0, top_valueize, valueized);
                res_op->set_op (code, type, op0,
                                TREE_OPERAND (rhs1, 1),
-                               TREE_OPERAND (rhs1, 2));
+                               TREE_OPERAND (rhs1, 2),
+                               REF_REVERSE_STORAGE_ORDER (rhs1));
+               if (res_op->reverse)
+                 return valueized;
                return (gimple_resimplify3 (seq, res_op, valueize)
                        || valueized);
              }
@@ -892,10 +963,9 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
            {
              bool valueized = false;
              tree rhs1 = gimple_assign_rhs1 (stmt);
-             /* If this is a [VEC_]COND_EXPR first try to simplify an
+             /* If this is a COND_EXPR first try to simplify an
                 embedded GENERIC condition.  */
-             if (code == COND_EXPR
-                 || code == VEC_COND_EXPR)
+             if (code == COND_EXPR)
                {
                  if (COMPARISON_CLASS_P (rhs1))
                    {
@@ -1089,6 +1159,16 @@ canonicalize_math_after_vectorization_p ()
   return !cfun || (cfun->curr_properties & PROP_gimple_lvec) != 0;
 }
 
+/* Return true if we can still perform transformations that may introduce
+   vector operations that are not supported by the target. Vector lowering
+   normally handles those, but after that pass, it becomes unsafe.  */
+
+static inline bool
+optimize_vectors_before_lowering_p ()
+{
+  return !cfun || (cfun->curr_properties & PROP_gimple_lvec) == 0;
+}
+
 /* Return true if pow(cst, x) should be optimized into exp(log(cst) * x).
    As a workaround for SPEC CPU2017 628.pop2_s, don't do it if arg0
    is an exact integer, arg1 = phi_res +/- cst1 and phi_res = PHI <cst2, ...>
@@ -1156,3 +1236,27 @@ optimize_pow_to_exp (tree arg0, tree arg1)
     return false;
   return true;
 }
+
+/* Return true if a division INNER_DIV / DIVISOR where INNER_DIV
+   is another division can be optimized.  Don't optimize if INNER_DIV
+   is used in a TRUNC_MOD_EXPR with DIVISOR as second operand.  */
+
+static bool
+optimize_successive_divisions_p (tree divisor, tree inner_div)
+{
+  if (!gimple_in_ssa_p (cfun))
+    return false;
+
+  imm_use_iterator imm_iter;
+  use_operand_p use_p;
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, inner_div)
+    {
+      gimple *use_stmt = USE_STMT (use_p);
+      if (!is_gimple_assign (use_stmt)
+         || gimple_assign_rhs_code (use_stmt) != TRUNC_MOD_EXPR
+         || !operand_equal_p (gimple_assign_rhs2 (use_stmt), divisor, 0))
+       continue;
+      return false;
+    }
+  return true;
+}