[TCWG CI] Regression caused by gcc: tree-optimization/102570 - teach VN about 
internal functions:
commit 55a3be2f5255d69e740d61b2c5aaba1ccbc643b8
Author: Richard Biener <rguent...@suse.de>

    tree-optimization/102570 - teach VN about internal functions

Results regressed to
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
18360
# First few build errors in logs:
# 00:01:21 ./include/linux/arm-smccc.h:460:40: error: ‘res.a0’ is used 
uninitialized [-Werror=uninitialized]
# 00:01:21 ./include/linux/arm-smccc.h:460:40: error: ‘res.a0’ is used 
uninitialized [-Werror=uninitialized]
# 00:01:21 ./include/linux/arm-smccc.h:460:40: error: ‘res.a0’ is used 
uninitialized [-Werror=uninitialized]
# 00:01:21 make[2]: *** [scripts/Makefile.build:288: 
arch/arm64/hyperv/hv_core.o] Error 1
# 00:01:22 crypto/asymmetric_keys/asymmetric_type.c:481:15: error: 
‘restrict_method’ is used uninitialized [-Werror=uninitialized]
# 00:01:22 make[2]: *** [scripts/Makefile.build:288: 
crypto/asymmetric_keys/asymmetric_type.o] Error 1
# 00:01:22 ./include/trace/perf.h:38:25: error: ‘entry’ is used uninitialized 
[-Werror=uninitialized]
# 00:01:22 ./include/trace/perf.h:44:13: error: ‘__entry_size’ is used 
uninitialized [-Werror=uninitialized]
# 00:01:23 security/keys/encrypted-keys/encrypted.c:660:19: error: ‘mkey’ is 
used uninitialized [-Werror=uninitialized]
# 00:01:23 security/keys/encrypted-keys/encrypted.c:905:19: error: ‘epayload’ 
is used uninitialized [-Werror=uninitialized]

from
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
21404

THIS IS THE END OF INTERESTING STUFF.  BELOW ARE LINKS TO BUILDS, REPRODUCTION 
INSTRUCTIONS, AND THE RAW COMMIT.

This commit has regressed these CI configurations:
 - tcwg_kernel/gnu-master-aarch64-next-allmodconfig

First_bad build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/build-55a3be2f5255d69e740d61b2c5aaba1ccbc643b8/
Last_good build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/build-22d34a2a50651d01669b6fbcdb9677c18d2197c5/
Baseline build: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/build-baseline/
Even more details: 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/

Reproduce builds:
<cut>
mkdir investigate-gcc-55a3be2f5255d69e740d61b2c5aaba1ccbc643b8
cd investigate-gcc-55a3be2f5255d69e740d61b2c5aaba1ccbc643b8

# Fetch scripts
git clone https://git.linaro.org/toolchain/jenkins-scripts

# Fetch manifests and test.sh script
mkdir -p artifacts/manifests
curl -o artifacts/manifests/build-baseline.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/manifests/build-baseline.sh
 --fail
curl -o artifacts/manifests/build-parameters.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/manifests/build-parameters.sh
 --fail
curl -o artifacts/test.sh 
https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-aarch64-next-allmodconfig/28/artifact/artifacts/test.sh
 --fail
chmod +x artifacts/test.sh

# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_kernel-build.sh @@ artifacts/manifests/build-baseline.sh

# Save baseline build state (which is then restored in artifacts/test.sh)
mkdir -p ./bisect
rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ 
--exclude /gcc/ ./ ./bisect/baseline/

cd gcc

# Reproduce first_bad build
git checkout --detach 55a3be2f5255d69e740d61b2c5aaba1ccbc643b8
../artifacts/test.sh

# Reproduce last_good build
git checkout --detach 22d34a2a50651d01669b6fbcdb9677c18d2197c5
../artifacts/test.sh

cd ..
</cut>

Full commit (up to 1000 lines):
<cut>
commit 55a3be2f5255d69e740d61b2c5aaba1ccbc643b8
Author: Richard Biener <rguent...@suse.de>
Date:   Mon Oct 4 10:57:45 2021 +0200

    tree-optimization/102570 - teach VN about internal functions
    
    We're now using internal functions for a lot of stuff but there's
    still missing VN support out of laziness.  The following instantiates
    support and adds testcases for FRE and PRE (hoisting).
    
    2021-10-04  Richard Biener  <rguent...@suse.de>
    
            PR tree-optimization/102570
            * tree-ssa-sccvn.h (vn_reference_op_struct): Document
            we are using clique for the internal function code.
            * tree-ssa-sccvn.c (vn_reference_op_eq): Compare the
            internal function code.
            (print_vn_reference_ops): Print the internal function code.
            (vn_reference_op_compute_hash): Hash it.
            (copy_reference_ops_from_call): Record it.
            (visit_stmt): Remove the restriction around internal function
            calls.
            (fully_constant_vn_reference_p): Use fold_const_call and handle
            internal functions.
            (vn_reference_eq): Compare call return types.
            * tree-ssa-pre.c (create_expression_by_pieces): Handle
            generating calls to internal functions.
            (compute_avail): Remove the restriction around internal function
            calls.
    
            * gcc.dg/tree-ssa/ssa-fre-96.c: New testcase.
            * gcc.dg/tree-ssa/ssa-pre-33.c: Likewise.
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c | 14 +++++
 gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c | 15 +++++
 gcc/tree-ssa-pre.c                         | 27 +++++----
 gcc/tree-ssa-sccvn.c                       | 91 ++++++++++++++++++------------
 gcc/tree-ssa-sccvn.h                       |  3 +-
 5 files changed, 103 insertions(+), 47 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
new file mode 100644
index 00000000000..fd1d5713b5f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-96.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res)
+{
+    _Bool t = __builtin_add_overflow(x, y, res);
+    unsigned res1;
+    _Bool t1 = __builtin_add_overflow(x, y, &res1);
+    *res -= res1;
+    return t==t1;
+}
+
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "fre1" } } */
+/* { dg-final { scan-tree-dump "return 1;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
new file mode 100644
index 00000000000..3b3bd629bc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-33.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre" } */
+
+_Bool f1(unsigned x, unsigned y, unsigned *res, int flag, _Bool *t)
+{
+  if (flag)
+    *t = __builtin_add_overflow(x, y, res);
+  unsigned res1;
+  _Bool t1 = __builtin_add_overflow(x, y, &res1);
+  *res -= res1;
+  return *t==t1;
+}
+
+/* We should hoist the .ADD_OVERFLOW to before the check.  */
+/* { dg-final { scan-tree-dump-times "ADD_OVERFLOW" 1 "pre" } } */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 08755847f66..1cc1aae694f 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2855,9 +2855,13 @@ create_expression_by_pieces (basic_block block, pre_expr 
expr,
          unsigned int operand = 1;
          vn_reference_op_t currop = &ref->operands[0];
          tree sc = NULL_TREE;
-         tree fn  = find_or_generate_expression (block, currop->op0, stmts);
-         if (!fn)
-           return NULL_TREE;
+         tree fn = NULL_TREE;
+         if (currop->op0)
+           {
+             fn = find_or_generate_expression (block, currop->op0, stmts);
+             if (!fn)
+               return NULL_TREE;
+           }
          if (currop->op1)
            {
              sc = find_or_generate_expression (block, currop->op1, stmts);
@@ -2873,12 +2877,19 @@ create_expression_by_pieces (basic_block block, 
pre_expr expr,
                return NULL_TREE;
              args.quick_push (arg);
            }
-         gcall *call = gimple_build_call_vec (fn, args);
+         gcall *call;
+         if (currop->op0)
+           {
+             call = gimple_build_call_vec (fn, args);
+             gimple_call_set_fntype (call, currop->type);
+           }
+         else
+           call = gimple_build_call_internal_vec ((internal_fn)currop->clique,
+                                                  args);
          gimple_set_location (call, expr->loc);
-         gimple_call_set_fntype (call, currop->type);
          if (sc)
            gimple_call_set_chain (call, sc);
-         tree forcedname = make_ssa_name (TREE_TYPE (currop->type));
+         tree forcedname = make_ssa_name (ref->type);
          gimple_call_set_lhs (call, forcedname);
          /* There's no CCP pass after PRE which would re-compute alignment
             information so make sure we re-materialize this here.  */
@@ -4004,10 +4015,6 @@ compute_avail (function *fun)
                vn_reference_s ref1;
                pre_expr result = NULL;
 
-               /* We can value number only calls to real functions.  */
-               if (gimple_call_internal_p (stmt))
-                 continue;
-
                vn_reference_lookup_call (as_a <gcall *> (stmt), &ref, &ref1);
                /* There is no point to PRE a call without a value.  */
                if (!ref || !ref->result)
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 416a5252144..0d942218279 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-loop-niter.h"
 #include "builtins.h"
+#include "fold-const-call.h"
 #include "tree-ssa-sccvn.h"
 
 /* This algorithm is based on the SCC algorithm presented by Keith
@@ -212,7 +213,8 @@ vn_reference_op_eq (const void *p1, const void *p2)
                                         TYPE_MAIN_VARIANT (vro2->type))))
          && expressions_equal_p (vro1->op0, vro2->op0)
          && expressions_equal_p (vro1->op1, vro2->op1)
-         && expressions_equal_p (vro1->op2, vro2->op2));
+         && expressions_equal_p (vro1->op2, vro2->op2)
+         && (vro1->opcode != CALL_EXPR || vro1->clique == vro2->clique));
 }
 
 /* Free a reference operation structure VP.  */
@@ -264,15 +266,18 @@ print_vn_reference_ops (FILE *outfile, const 
vec<vn_reference_op_s> ops)
          && TREE_CODE_CLASS (vro->opcode) != tcc_declaration)
        {
          fprintf (outfile, "%s", get_tree_code_name (vro->opcode));
-         if (vro->op0)
+         if (vro->op0 || vro->opcode == CALL_EXPR)
            {
              fprintf (outfile, "<");
              closebrace = true;
            }
        }
-      if (vro->op0)
+      if (vro->op0 || vro->opcode == CALL_EXPR)
        {
-         print_generic_expr (outfile, vro->op0);
+         if (!vro->op0)
+           fprintf (outfile, internal_fn_name ((internal_fn)vro->clique));
+         else
+           print_generic_expr (outfile, vro->op0);
          if (vro->op1)
            {
              fprintf (outfile, ",");
@@ -684,6 +689,8 @@ static void
 vn_reference_op_compute_hash (const vn_reference_op_t vro1, inchash::hash 
&hstate)
 {
   hstate.add_int (vro1->opcode);
+  if (vro1->opcode == CALL_EXPR && !vro1->op0)
+    hstate.add_int (vro1->clique);
   if (vro1->op0)
     inchash::add_expr (vro1->op0, hstate);
   if (vro1->op1)
@@ -769,11 +776,16 @@ vn_reference_eq (const_vn_reference_t const vr1, 
const_vn_reference_t const vr2)
       if (vr1->type != vr2->type)
        return false;
     }
+  else if (vr1->type == vr2->type)
+    ;
   else if (COMPLETE_TYPE_P (vr1->type) != COMPLETE_TYPE_P (vr2->type)
           || (COMPLETE_TYPE_P (vr1->type)
               && !expressions_equal_p (TYPE_SIZE (vr1->type),
                                        TYPE_SIZE (vr2->type))))
     return false;
+  else if (vr1->operands[0].opcode == CALL_EXPR
+          && !types_compatible_p (vr1->type, vr2->type))
+    return false;
   else if (INTEGRAL_TYPE_P (vr1->type)
           && INTEGRAL_TYPE_P (vr2->type))
     {
@@ -1270,6 +1282,8 @@ copy_reference_ops_from_call (gcall *call,
   temp.type = gimple_call_fntype (call);
   temp.opcode = CALL_EXPR;
   temp.op0 = gimple_call_fn (call);
+  if (gimple_call_internal_p (call))
+    temp.clique = gimple_call_internal_fn (call);
   temp.op1 = gimple_call_chain (call);
   if (stmt_could_throw_p (cfun, call) && (lr = lookup_stmt_eh_lp (call)) > 0)
     temp.op2 = size_int (lr);
@@ -1459,9 +1473,11 @@ fully_constant_vn_reference_p (vn_reference_t ref)
      a call to a builtin function with at most two arguments.  */
   op = &operands[0];
   if (op->opcode == CALL_EXPR
-      && TREE_CODE (op->op0) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
-      && fndecl_built_in_p (TREE_OPERAND (op->op0, 0))
+      && (!op->op0
+         || (TREE_CODE (op->op0) == ADDR_EXPR
+             && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
+             && fndecl_built_in_p (TREE_OPERAND (op->op0, 0),
+                                   BUILT_IN_NORMAL)))
       && operands.length () >= 2
       && operands.length () <= 3)
     {
@@ -1481,13 +1497,17 @@ fully_constant_vn_reference_p (vn_reference_t ref)
        anyconst = true;
       if (anyconst)
        {
-         tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
-                                        arg1 ? 2 : 1,
-                                        arg0->op0,
-                                        arg1 ? arg1->op0 : NULL);
-         if (folded
-             && TREE_CODE (folded) == NOP_EXPR)
-           folded = TREE_OPERAND (folded, 0);
+         combined_fn fn;
+         if (op->op0)
+           fn = as_combined_fn (DECL_FUNCTION_CODE
+                                       (TREE_OPERAND (op->op0, 0)));
+         else
+           fn = as_combined_fn ((internal_fn) op->clique);
+         tree folded;
+         if (arg1)
+           folded = fold_const_call (fn, ref->type, arg0->op0, arg1->op0);
+         else
+           folded = fold_const_call (fn, ref->type, arg0->op0);
          if (folded
              && is_gimple_min_invariant (folded))
            return folded;
@@ -5648,28 +5668,27 @@ visit_stmt (gimple *stmt, bool backedges_varying_p = 
false)
              && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
            extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
        }
-      if (!gimple_call_internal_p (call_stmt)
-         && (/* Calls to the same function with the same vuse
-                and the same operands do not necessarily return the same
-                value, unless they're pure or const.  */
-             ((gimple_call_flags (call_stmt) | extra_fnflags)
-              & (ECF_PURE | ECF_CONST))
-             /* If calls have a vdef, subsequent calls won't have
-                the same incoming vuse.  So, if 2 calls with vdef have the
-                same vuse, we know they're not subsequent.
-                We can value number 2 calls to the same function with the
-                same vuse and the same operands which are not subsequent
-                the same, because there is no code in the program that can
-                compare the 2 values...  */
-             || (gimple_vdef (call_stmt)
-                 /* ... unless the call returns a pointer which does
-                    not alias with anything else.  In which case the
-                    information that the values are distinct are encoded
-                    in the IL.  */
-                 && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
-                 /* Only perform the following when being called from PRE
-                    which embeds tail merging.  */
-                 && default_vn_walk_kind == VN_WALK)))
+      if (/* Calls to the same function with the same vuse
+            and the same operands do not necessarily return the same
+            value, unless they're pure or const.  */
+         ((gimple_call_flags (call_stmt) | extra_fnflags)
+          & (ECF_PURE | ECF_CONST))
+         /* If calls have a vdef, subsequent calls won't have
+            the same incoming vuse.  So, if 2 calls with vdef have the
+            same vuse, we know they're not subsequent.
+            We can value number 2 calls to the same function with the
+            same vuse and the same operands which are not subsequent
+            the same, because there is no code in the program that can
+            compare the 2 values...  */
+         || (gimple_vdef (call_stmt)
+             /* ... unless the call returns a pointer which does
+                not alias with anything else.  In which case the
+                information that the values are distinct are encoded
+                in the IL.  */
+             && !(gimple_call_return_flags (call_stmt) & ERF_NOALIAS)
+             /* Only perform the following when being called from PRE
+                which embeds tail merging.  */
+             && default_vn_walk_kind == VN_WALK))
        changed = visit_reference_op_call (lhs, call_stmt);
       else
        changed = defs_to_varying (call_stmt);
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 96100596d2e..8a1b649c726 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -106,7 +106,8 @@ typedef const struct vn_phi_s *const_vn_phi_t;
 typedef struct vn_reference_op_struct
 {
   ENUM_BITFIELD(tree_code) opcode : 16;
-  /* Dependence info, used for [TARGET_]MEM_REF only.  */
+  /* Dependence info, used for [TARGET_]MEM_REF only.  For internal
+     function calls clique is also used for the internal function code.  */
   unsigned short clique;
   unsigned short base;
   unsigned reverse : 1;
</cut>
_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to