Successfully identified regression in *gcc* in CI configuration 
tcwg_gcc_bootstrap/master-arm-bootstrap.  So far, this commit has regressed CI 
configurations:
 - tcwg_gcc_bootstrap/master-arm-bootstrap

Culprit:
<cut>
commit e4f16e9f357a38ec702fb69a0ffab9d292a6af9b
Author: Thomas Schwinge <tho...@codesourcery.com>
Date:   Fri Aug 13 17:53:12 2021 +0200

    Add more self-tests for 'hash_map' with Value type with non-trivial 
constructor/destructor
    
    ... to document the current behavior.
    
            gcc/
            * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor): Extend.
            (test_map_of_type_with_ctor_and_dtor_expand): Add function.
            (hash_map_tests_c_tests): Call it.
</cut>

Results regressed to (for first_bad == e4f16e9f357a38ec702fb69a0ffab9d292a6af9b)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
# 00:02:51 cc1: internal compiler error: in fail, at selftest.c:47
# 00:02:51 cc1plus: internal compiler error: in fail, at selftest.c:47
# 00:02:51 make[3]: *** [s-selftest-c] Error 1
# 00:02:51 make[3]: *** [s-selftest-c++] Error 1
# 00:02:51 make[2]: *** [all-stage1-gcc] Error 2
# 00:02:51 make[1]: *** [stage1-bubble] Error 2
# 00:02:51 make: *** [all] Error 2

from (for last_good == 602fca427df6c5f7452677cfcdd16a5b9a3ca86a)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe bootstrap:
2

Artifacts of last_good build: 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/build-602fca427df6c5f7452677cfcdd16a5b9a3ca86a/
Artifacts of first_bad build: 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/build-e4f16e9f357a38ec702fb69a0ffab9d292a6af9b/
Build top page/logs: 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/

Configuration details:


Reproduce builds:
<cut>
mkdir investigate-gcc-e4f16e9f357a38ec702fb69a0ffab9d292a6af9b
cd investigate-gcc-e4f16e9f357a38ec702fb69a0ffab9d292a6af9b

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

mkdir -p artifacts/manifests
curl -o artifacts/manifests/build-baseline.sh 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/manifests/build-baseline.sh
 --fail
curl -o artifacts/manifests/build-parameters.sh 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/manifests/build-parameters.sh
 --fail
curl -o artifacts/test.sh 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/test.sh
 --fail
chmod +x artifacts/test.sh

# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_gnu-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 e4f16e9f357a38ec702fb69a0ffab9d292a6af9b
../artifacts/test.sh

# Reproduce last_good build
git checkout --detach 602fca427df6c5f7452677cfcdd16a5b9a3ca86a
../artifacts/test.sh

cd ..
</cut>

History of pending regressions and results: 
https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/ci/tcwg_gcc_bootstrap/master-arm-bootstrap

Artifacts: 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/artifact/artifacts/
Build log: 
https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap/1/consoleText

Full commit (up to 1000 lines):
<cut>
commit e4f16e9f357a38ec702fb69a0ffab9d292a6af9b
Author: Thomas Schwinge <tho...@codesourcery.com>
Date:   Fri Aug 13 17:53:12 2021 +0200

    Add more self-tests for 'hash_map' with Value type with non-trivial 
constructor/destructor
    
    ... to document the current behavior.
    
            gcc/
            * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor): Extend.
            (test_map_of_type_with_ctor_and_dtor_expand): Add function.
            (hash_map_tests_c_tests): Call it.
---
 gcc/hash-map-tests.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 152 insertions(+)

diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c
index 5b6b192cd28..257f2be0c26 100644
--- a/gcc/hash-map-tests.c
+++ b/gcc/hash-map-tests.c
@@ -278,6 +278,156 @@ test_map_of_type_with_ctor_and_dtor ()
 
     ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
   }
+
+
+  /* Verify basic construction and destruction of Value objects.  */
+  {
+    /* Configure, arbitrary.  */
+    const size_t N_init = 0;
+    const int N_elem = 28;
+
+    void *a[N_elem];
+    for (size_t i = 0; i < N_elem; ++i)
+      a[i] = &a[i];
+
+    val_t::ndefault = 0;
+    val_t::ncopy = 0;
+    val_t::nassign = 0;
+    val_t::ndtor = 0;
+    Map m (N_init);
+    ASSERT_EQ (val_t::ndefault
+              + val_t::ncopy
+              + val_t::nassign
+              + val_t::ndtor, 0);
+
+    for (int i = 0; i < N_elem; ++i)
+      {
+       m.get_or_insert (a[i]);
+       ASSERT_EQ (val_t::ndefault, 1 + i);
+       ASSERT_EQ (val_t::ncopy, 0);
+       ASSERT_EQ (val_t::nassign, 0);
+       ASSERT_EQ (val_t::ndtor, i);
+
+       m.remove (a[i]);
+       ASSERT_EQ (val_t::ndefault, 1 + i);
+       ASSERT_EQ (val_t::ncopy, 0);
+       ASSERT_EQ (val_t::nassign, 0);
+       ASSERT_EQ (val_t::ndtor, 1 + i);
+      }
+  }
+}
+
+/* Verify aspects of 'hash_table::expand'.  */
+
+static void
+test_map_of_type_with_ctor_and_dtor_expand (bool remove_some_inline)
+{
+  /* Configure, so that hash table expansion triggers a few times.  */
+  const size_t N_init = 0;
+  const int N_elem = 70;
+  size_t expand_c_expected = 4;
+  size_t expand_c = 0;
+
+  void *a[N_elem];
+  for (size_t i = 0; i < N_elem; ++i)
+    a[i] = &a[i];
+
+  typedef hash_map <void *, val_t> Map;
+
+  /* Note that we are starting with a fresh 'Map'.  Even if an existing one has
+     been cleared out completely, there remain 'deleted' elements, and these
+     would disturb the following logic, where we don't have access to the
+     actual 'm_n_deleted' value.  */
+  size_t m_n_deleted = 0;
+
+  val_t::ndefault = 0;
+  val_t::ncopy = 0;
+  val_t::nassign = 0;
+  val_t::ndtor = 0;
+  Map m (N_init);
+
+  /* In the following, in particular related to 'expand', we're adapting from
+     the internal logic of 'hash_table', glossing over "some details" not
+     relevant for this testing here.  */
+
+  /* Per 'hash_table::hash_table'.  */
+  size_t m_size;
+  {
+    unsigned int size_prime_index_ = hash_table_higher_prime_index (N_init);
+    m_size = prime_tab[size_prime_index_].prime;
+  }
+
+  int n_expand_moved = 0;
+
+  for (int i = 0; i < N_elem; ++i)
+    {
+      size_t elts = m.elements ();
+
+      /* Per 'hash_table::find_slot_with_hash'.  */
+      size_t m_n_elements = elts + m_n_deleted;
+      bool expand = m_size * 3 <= m_n_elements * 4;
+
+      m.get_or_insert (a[i]);
+      if (expand)
+       {
+         ++expand_c;
+
+         /* Per 'hash_table::expand'.  */
+         {
+           unsigned int nindex = hash_table_higher_prime_index (elts * 2);
+           m_size = prime_tab[nindex].prime;
+         }
+         m_n_deleted = 0;
+
+         /* All non-deleted elements have been moved.  */
+         n_expand_moved += i;
+         if (remove_some_inline)
+           n_expand_moved -= (i + 2) / 3;
+       }
+
+      ASSERT_EQ (val_t::ndefault, 1 + i);
+      ASSERT_EQ (val_t::ncopy, n_expand_moved);
+      ASSERT_EQ (val_t::nassign, 0);
+      if (remove_some_inline)
+       ASSERT_EQ (val_t::ndtor, (i + 2) / 3);
+      else
+       ASSERT_EQ (val_t::ndtor, 0);
+
+      /* Remove some inline.  This never triggers an 'expand' here, but via
+        'm_n_deleted' does influence any following one.  */
+      if (remove_some_inline
+         && !(i % 3))
+       {
+         m.remove (a[i]);
+         /* Per 'hash_table::remove_elt_with_hash'.  */
+         m_n_deleted++;
+
+         ASSERT_EQ (val_t::ndefault, 1 + i);
+         ASSERT_EQ (val_t::ncopy, n_expand_moved);
+         ASSERT_EQ (val_t::nassign, 0);
+         ASSERT_EQ (val_t::ndtor, 1 + (i + 2) / 3);
+       }
+    }
+  ASSERT_EQ (expand_c, expand_c_expected);
+
+  int ndefault = val_t::ndefault;
+  int ncopy = val_t::ncopy;
+  int nassign = val_t::nassign;
+  int ndtor = val_t::ndtor;
+
+  for (int i = 0; i < N_elem; ++i)
+    {
+      if (remove_some_inline
+         && !(i % 3))
+       continue;
+
+      m.remove (a[i]);
+      ++ndtor;
+      ASSERT_EQ (val_t::ndefault, ndefault);
+      ASSERT_EQ (val_t::ncopy, ncopy);
+      ASSERT_EQ (val_t::nassign, nassign);
+      ASSERT_EQ (val_t::ndtor, ndtor);
+    }
 }
 
 /* Test calling empty on a hash_map that has a key type with non-zero
@@ -309,6 +459,8 @@ hash_map_tests_c_tests ()
   test_map_of_strings_to_int ();
   test_map_of_int_to_strings ();
   test_map_of_type_with_ctor_and_dtor ();
+  test_map_of_type_with_ctor_and_dtor_expand (false);
+  test_map_of_type_with_ctor_and_dtor_expand (true);
   test_nonzero_empty_key ();
 }
 
</cut>
_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to