After gcc commit c416c52bcdb120db5e8c53a51bd78c4360daf79b
Author: Nathan Sidwell <nathan(a)acm.org>
c++ ICE with nested requirement as default tpl parm[PR94827]
the following benchmarks slowed down by more than 2%:
- 456.hmmer slowed down by 4%
Benchmark:
Toolchain: GCC + Glibc + GNU Linker
Version: all components were built from their latest release branch
Target: aarch64-linux-gnu
Compiler flags: -O3 -flto
Hardware: NVidia TX1 4x Cortex-A57
This commit has regressed these CI configurations:
- tcwg_bmk_gnu_tx1/gnu-release-aarch64-spec2k6-O3_LTO
First_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Baseline build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Even more details: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a…
Reproduce builds:
<cut>
mkdir investigate-gcc-c416c52bcdb120db5e8c53a51bd78c4360daf79b
cd investigate-gcc-c416c52bcdb120db5e8c53a51bd78c4360daf79b
# 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_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-a… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 c416c52bcdb120db5e8c53a51bd78c4360daf79b
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach b1983f4582bbe060b7da83578acb9ed653681fc8
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit c416c52bcdb120db5e8c53a51bd78c4360daf79b
Author: Nathan Sidwell <nathan(a)acm.org>
Date: Thu Apr 30 08:23:16 2020 -0700
c++ ICE with nested requirement as default tpl parm[PR94827]
Template headers are not incrementally updated as we parse its parameters.
We maintain a dummy level until the closing > when we replace the dummy with
a real parameter set. requires processing was expecting a properly populated
arg_vec in current_template_parms, and then creates a self-mapping of parameters
from that. But we don't need to do that, just teach map_arguments to look at
TREE_VALUE when args is NULL.
* constraint.cc (map_arguments): If ARGS is null, it's a
self-mapping of parms.
(finish_nested_requirement): Do not pass argified
current_template_parms to normalization.
(tsubst_nested_requirement): Don't assert no template parms.
---
gcc/cp/ChangeLog | 10 ++++++++++
gcc/cp/constraint.cc | 27 ++++++++++++++++-----------
gcc/testsuite/g++.dg/concepts/pr94827.C | 15 +++++++++++++++
3 files changed, 41 insertions(+), 11 deletions(-)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1fa0e123cb1..3c57945cecf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2020-04-30 Jason Merrill <jason(a)redhat.com>
+ Nathan Sidwell <nathan(a)acm.org>
+
+ PR c++/94827
+ * constraint.cc (map_arguments): If ARGS is null, it's a
+ self-mapping of parms.
+ (finish_nested_requirement): Do not pass argified
+ current_template_parms to normalization.
+ (tsubst_nested_requirement): Don't assert no template parms.
+
2020-04-30 Iain Sandoe <iain(a)sandoe.co.uk>
PR c++/94886
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 866b0f51b05..85513fecf43 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -546,12 +546,16 @@ static tree
map_arguments (tree parms, tree args)
{
for (tree p = parms; p; p = TREE_CHAIN (p))
- {
- int level;
- int index;
- template_parm_level_and_index (TREE_VALUE (p), &level, &index);
- TREE_PURPOSE (p) = TMPL_ARG (args, level, index);
- }
+ if (args)
+ {
+ int level;
+ int index;
+ template_parm_level_and_index (TREE_VALUE (p), &level, &index);
+ TREE_PURPOSE (p) = TMPL_ARG (args, level, index);
+ }
+ else
+ TREE_PURPOSE (p) = TREE_VALUE (p);
+
return parms;
}
@@ -2005,8 +2009,6 @@ tsubst_compound_requirement (tree t, tree args, subst_info info)
static tree
tsubst_nested_requirement (tree t, tree args, subst_info info)
{
- gcc_assert (!uses_template_parms (args));
-
/* Ensure that we're in an evaluation context prior to satisfaction. */
tree norm = TREE_VALUE (TREE_TYPE (t));
tree result = satisfy_constraint (norm, args, info);
@@ -2953,12 +2955,15 @@ finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept
tree
finish_nested_requirement (location_t loc, tree expr)
{
+ /* Currently open template headers have dummy arg vectors, so don't
+ pass into normalization. */
+ tree norm = normalize_constraint_expression (expr, NULL_TREE, false);
+ tree args = current_template_parms
+ ? template_parms_to_args (current_template_parms) : NULL_TREE;
+
/* Save the normalized constraint and complete set of normalization
arguments with the requirement. We keep the complete set of arguments
around for re-normalization during diagnostics. */
- tree args = current_template_parms
- ? template_parms_to_args (current_template_parms) : NULL_TREE;
- tree norm = normalize_constraint_expression (expr, args, false);
tree info = build_tree_list (args, norm);
/* Build the constraint, saving its normalization as its type. */
diff --git a/gcc/testsuite/g++.dg/concepts/pr94827.C b/gcc/testsuite/g++.dg/concepts/pr94827.C
new file mode 100644
index 00000000000..f14ec2551a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr94827.C
@@ -0,0 +1,15 @@
+// PR 94287 ICE looking inside open template-parm level
+// { dg-do run { target c++17 } }
+// { dg-options -fconcepts }
+
+template <typename T,
+ bool X = requires { requires (sizeof(T)==1); } >
+ int foo(T) { return X; }
+
+int main() {
+ if (!foo('4'))
+ return 1;
+ if (foo (4))
+ return 2;
+ return 0;
+}
</cut>
After llvm commit f17d60d620283b5d53286056ceeaeb8c27b6530a
Author: Bjorn Pettersson <bjorn.a.pettersson(a)ericsson.com>
Inform pass manager when child loops are deleted
Below reproducer instructions can be used to re-build both "first_bad" and "last_good" cross-toolchains used in this bisection. Naturally, the scripts will fail when triggerring benchmarking jobs if you don't have access to Linaro TCWG CI.
This commit has regressed these CI configurations:
- tcwg_bmk_llvm_tx1/llvm-release-aarch64-spec2k6-O2
First_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release…
Last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release…
Baseline build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release…
Even more details: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release…
Reproduce builds:
<cut>
mkdir investigate-llvm-f17d60d620283b5d53286056ceeaeb8c27b6530a
cd investigate-llvm-f17d60d620283b5d53286056ceeaeb8c27b6530a
# 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_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-release… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 /llvm/ ./ ./bisect/baseline/
cd llvm
# Reproduce first_bad build
git checkout --detach f17d60d620283b5d53286056ceeaeb8c27b6530a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach f56129fe78d5c849971017976c71333b6b1a27c6
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit f17d60d620283b5d53286056ceeaeb8c27b6530a
Author: Bjorn Pettersson <bjorn.a.pettersson(a)ericsson.com>
Date: Fri Sep 3 20:50:33 2021 +0200
Inform pass manager when child loops are deleted
As part of the nontrivial unswitching we could end up removing child
loops. This patch add a notification to the pass manager when
that happens (using the markLoopAsDeleted callback).
Without this there could be stale LoopAccessAnalysis results cached
in the analysis manager. Those analysis results are cached based on
a Loop* as key. Since the BumpPtrAllocator used to allocate
Loop objects could be resetted between different runs of for
example the loop-distribute pass (running on different functions),
a new Loop object could be created using the same Loop pointer.
And then when requiring the LoopAccessAnalysis for the loop we
got the stale (corrupt) result from the destroyed loop.
Reviewed By: aeubanks
Differential Revision: https://reviews.llvm.org/D109257
(fixes PR51754)
(cherry-picked from commit 0f0344dd1e3b53387bb396070916e67f4c426da6)
---
llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp | 43 +++++++++----
.../nontrivial-unswitch-markloopasdeleted.ll | 71 ++++++++++++++++++++++
2 files changed, 102 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index b9cccc2af309..b1c105258027 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -1587,10 +1587,12 @@ deleteDeadClonedBlocks(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
BB->eraseFromParent();
}
-static void deleteDeadBlocksFromLoop(Loop &L,
- SmallVectorImpl<BasicBlock *> &ExitBlocks,
- DominatorTree &DT, LoopInfo &LI,
- MemorySSAUpdater *MSSAU) {
+static void
+deleteDeadBlocksFromLoop(Loop &L,
+ SmallVectorImpl<BasicBlock *> &ExitBlocks,
+ DominatorTree &DT, LoopInfo &LI,
+ MemorySSAUpdater *MSSAU,
+ function_ref<void(Loop &, StringRef)> DestroyLoopCB) {
// Find all the dead blocks tied to this loop, and remove them from their
// successors.
SmallSetVector<BasicBlock *, 8> DeadBlockSet;
@@ -1640,6 +1642,7 @@ static void deleteDeadBlocksFromLoop(Loop &L,
}) &&
"If the child loop header is dead all blocks in the child loop must "
"be dead as well!");
+ DestroyLoopCB(*ChildL, ChildL->getName());
LI.destroy(ChildL);
return true;
});
@@ -1980,6 +1983,8 @@ static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
ParentL->removeChildLoop(llvm::find(*ParentL, &L));
else
LI.removeLoop(llvm::find(LI, &L));
+ // markLoopAsDeleted for L should be triggered by the caller (it is typically
+ // done by using the UnswitchCB callback).
LI.destroy(&L);
return false;
}
@@ -2019,7 +2024,8 @@ static void unswitchNontrivialInvariants(
SmallVectorImpl<BasicBlock *> &ExitBlocks, IVConditionInfo &PartialIVInfo,
DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
function_ref<void(bool, bool, ArrayRef<Loop *>)> UnswitchCB,
- ScalarEvolution *SE, MemorySSAUpdater *MSSAU) {
+ ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
+ function_ref<void(Loop &, StringRef)> DestroyLoopCB) {
auto *ParentBB = TI.getParent();
BranchInst *BI = dyn_cast<BranchInst>(&TI);
SwitchInst *SI = BI ? nullptr : cast<SwitchInst>(&TI);
@@ -2319,7 +2325,7 @@ static void unswitchNontrivialInvariants(
// Now that our cloned loops have been built, we can update the original loop.
// First we delete the dead blocks from it and then we rebuild the loop
// structure taking these deletions into account.
- deleteDeadBlocksFromLoop(L, ExitBlocks, DT, LI, MSSAU);
+ deleteDeadBlocksFromLoop(L, ExitBlocks, DT, LI, MSSAU, DestroyLoopCB);
if (MSSAU && VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
@@ -2670,7 +2676,8 @@ static bool unswitchBestCondition(
Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
AAResults &AA, TargetTransformInfo &TTI,
function_ref<void(bool, bool, ArrayRef<Loop *>)> UnswitchCB,
- ScalarEvolution *SE, MemorySSAUpdater *MSSAU) {
+ ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
+ function_ref<void(Loop &, StringRef)> DestroyLoopCB) {
// Collect all invariant conditions within this loop (as opposed to an inner
// loop which would be handled when visiting that inner loop).
SmallVector<std::pair<Instruction *, TinyPtrVector<Value *>>, 4>
@@ -2958,7 +2965,7 @@ static bool unswitchBestCondition(
<< "\n");
unswitchNontrivialInvariants(L, *BestUnswitchTI, BestUnswitchInvariants,
ExitBlocks, PartialIVInfo, DT, LI, AC,
- UnswitchCB, SE, MSSAU);
+ UnswitchCB, SE, MSSAU, DestroyLoopCB);
return true;
}
@@ -2988,7 +2995,8 @@ unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
AAResults &AA, TargetTransformInfo &TTI, bool Trivial,
bool NonTrivial,
function_ref<void(bool, bool, ArrayRef<Loop *>)> UnswitchCB,
- ScalarEvolution *SE, MemorySSAUpdater *MSSAU) {
+ ScalarEvolution *SE, MemorySSAUpdater *MSSAU,
+ function_ref<void(Loop &, StringRef)> DestroyLoopCB) {
assert(L.isRecursivelyLCSSAForm(DT, LI) &&
"Loops must be in LCSSA form before unswitching.");
@@ -3036,7 +3044,8 @@ unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
// Try to unswitch the best invariant condition. We prefer this full unswitch to
// a partial unswitch when possible below the threshold.
- if (unswitchBestCondition(L, DT, LI, AC, AA, TTI, UnswitchCB, SE, MSSAU))
+ if (unswitchBestCondition(L, DT, LI, AC, AA, TTI, UnswitchCB, SE, MSSAU,
+ DestroyLoopCB))
return true;
// No other opportunities to unswitch.
@@ -3083,6 +3092,10 @@ PreservedAnalyses SimpleLoopUnswitchPass::run(Loop &L, LoopAnalysisManager &AM,
U.markLoopAsDeleted(L, LoopName);
};
+ auto DestroyLoopCB = [&U](Loop &L, StringRef Name) {
+ U.markLoopAsDeleted(L, Name);
+ };
+
Optional<MemorySSAUpdater> MSSAU;
if (AR.MSSA) {
MSSAU = MemorySSAUpdater(AR.MSSA);
@@ -3091,7 +3104,8 @@ PreservedAnalyses SimpleLoopUnswitchPass::run(Loop &L, LoopAnalysisManager &AM,
}
if (!unswitchLoop(L, AR.DT, AR.LI, AR.AC, AR.AA, AR.TTI, Trivial, NonTrivial,
UnswitchCB, &AR.SE,
- MSSAU.hasValue() ? MSSAU.getPointer() : nullptr))
+ MSSAU.hasValue() ? MSSAU.getPointer() : nullptr,
+ DestroyLoopCB))
return PreservedAnalyses::all();
if (AR.MSSA && VerifyMemorySSA)
@@ -3179,12 +3193,17 @@ bool SimpleLoopUnswitchLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) {
LPM.markLoopAsDeleted(*L);
};
+ auto DestroyLoopCB = [&LPM](Loop &L, StringRef /* Name */) {
+ LPM.markLoopAsDeleted(L);
+ };
+
if (MSSA && VerifyMemorySSA)
MSSA->verifyMemorySSA();
bool Changed =
unswitchLoop(*L, DT, LI, AC, AA, TTI, true, NonTrivial, UnswitchCB, SE,
- MSSAU.hasValue() ? MSSAU.getPointer() : nullptr);
+ MSSAU.hasValue() ? MSSAU.getPointer() : nullptr,
+ DestroyLoopCB);
if (MSSA && VerifyMemorySSA)
MSSA->verifyMemorySSA();
diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-markloopasdeleted.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-markloopasdeleted.ll
new file mode 100644
index 000000000000..455a38535576
--- /dev/null
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-markloopasdeleted.ll
@@ -0,0 +1,71 @@
+; RUN: opt < %s -enable-loop-distribute -passes='loop-distribute,loop-mssa(simple-loop-unswitch<nontrivial>),loop-distribute' -o /dev/null -S -debug-pass-manager=verbose 2>&1 | FileCheck %s
+
+
+; Running loop-distribute will result in LoopAccessAnalysis being required and
+; cached in the LoopAnalysisManagerFunctionProxy.
+;
+; CHECK: Running analysis: LoopAccessAnalysis on Loop at depth 2 containing: %loop_a_inner<header><latch><exiting>
+
+
+; Then simple-loop-unswitch is removing/replacing some loops (resulting in
+; Loop objects used as key in the analyses cache is destroyed). So here we
+; want to see that any analysis results cached on the destroyed loop is
+; cleared. A special case here is that loop_a_inner is destroyed when
+; unswitching the parent loop.
+;
+; The bug solved and verified by this test case was related to the
+; SimpleLoopUnswitch not marking the Loop as removed, so we missed clearing
+; the analysis caches.
+;
+; CHECK: Running pass: SimpleLoopUnswitchPass on Loop at depth 1 containing: %loop_begin<header>,%loop_b,%loop_b_inner,%loop_b_inner_exit,%loop_a,%loop_a_inner,%loop_a_inner_exit,%latch<latch><exiting>
+; CHECK-NEXT: Clearing all analysis results for: loop_a_inner
+
+
+; When running loop-distribute the second time we can see that loop_a_inner
+; isn't analysed because the loop no longer exists (instead we find a new loop,
+; loop_a_inner.us). This kind of verifies that it was correct to remove the
+; loop_a_inner related analysis above.
+;
+; CHECK: Running analysis: LoopAccessAnalysis on Loop at depth 2 containing: %loop_a_inner.us<header><latch><exiting>
+
+
+define i32 @test6(i1* %ptr, i1 %cond1, i32* %a.ptr, i32* %b.ptr) {
+entry:
+ br label %loop_begin
+
+loop_begin:
+ %v = load i1, i1* %ptr
+ br i1 %cond1, label %loop_a, label %loop_b
+
+loop_a:
+ br label %loop_a_inner
+
+loop_a_inner:
+ %va = load i1, i1* %ptr
+ %a = load i32, i32* %a.ptr
+ br i1 %va, label %loop_a_inner, label %loop_a_inner_exit
+
+loop_a_inner_exit:
+ %a.lcssa = phi i32 [ %a, %loop_a_inner ]
+ br label %latch
+
+loop_b:
+ br label %loop_b_inner
+
+loop_b_inner:
+ %vb = load i1, i1* %ptr
+ %b = load i32, i32* %b.ptr
+ br i1 %vb, label %loop_b_inner, label %loop_b_inner_exit
+
+loop_b_inner_exit:
+ %b.lcssa = phi i32 [ %b, %loop_b_inner ]
+ br label %latch
+
+latch:
+ %ab.phi = phi i32 [ %a.lcssa, %loop_a_inner_exit ], [ %b.lcssa, %loop_b_inner_exit ]
+ br i1 %v, label %loop_begin, label %loop_exit
+
+loop_exit:
+ %ab.lcssa = phi i32 [ %ab.phi, %latch ]
+ ret i32 %ab.lcssa
+}
</cut>
Identified regression caused by *gcc:76b75018b3d053a890ebe155e47814de14b3c9fb*:
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
c++: implement C++17 hardware interference size
Results regressed to (for first_bad == 76b75018b3d053a890ebe155e47814de14b3c9fb)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe stage1:
2
# build_abe linux:
3
# build_abe glibc:
4
# First few build errors in logs:
from (for last_good == 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe stage1:
2
# build_abe linux:
3
# build_abe glibc:
4
# build_abe stage2:
5
# build_abe gdb:
6
# build_abe qemu:
7
This commit has regressed these CI configurations:
- tcwg_gnu_cross_build/master-aarch64
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/2/arti…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/2/arti…
Even more details: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/2/arti…
Reproduce builds:
<cut>
mkdir investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
cd investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
# 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_gnu_cross_build-bisect-master-aarch64/2/arti… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/2/arti… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/2/arti… --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 76b75018b3d053a890ebe155e47814de14b3c9fb
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
Date: Thu Jul 15 15:30:17 2021 -0400
c++: implement C++17 hardware interference size
The last missing piece of the C++17 standard library is the hardware
intereference size constants. Much of the delay in implementing these has
been due to uncertainty about what the right values are, and even whether
there is a single constant value that is suitable; the destructive
interference size is intended to be used in structure layout, so program
ABIs will depend on it.
In principle, both of these values should be the same as the target's L1
cache line size. When compiling for a generic target that is intended to
support a range of target CPUs with different cache line sizes, the
constructive size should probably be the minimum size, and the destructive
size the maximum, unless you are constrained by ABI compatibility with
previous code.
From discussion on gcc-patches, I've come to the conclusion that the
solution to the difficulty of choosing stable values is to give up on it,
and instead encourage only uses where ABI stability is unimportant: in
particular, uses where the ABI is shared at most between translation units
built at the same time with the same flags.
To that end, I've added a warning for any use of the constant value of
std::hardware_destructive_interference_size in a header or module export.
Appropriate uses within a project can disable the warning.
A previous iteration of this patch included an -finterference-tune flag to
make the value vary with -mtune; this iteration makes that the default
behavior, which should be appropriate for all reasonable uses of the
variable. The previous default of "stable-ish" seems to me likely to have
been more of an attractive nuisance; since we can't promise actual
stability, we should instead make proper uses more convenient.
JF Bastien's implementation proposal is summarized at
https://github.com/itanium-cxx-abi/cxx-abi/issues/74
I implement this by adding new --params for the two sizes. Targets can
override these values in targetm.target_option.override() to support a range
of values for the generic target; otherwise, both will default to the L1
cache line size.
64 bytes still seems correct for all x86.
I'm not sure why he proposed 64/64 for generic 32-bit ARM, since the Cortex
A9 has a 32-byte cache line, so I'd think 32/64 would make more sense.
He proposed 64/128 for generic AArch64, but since the A64FX now has a 256B
cache line, I've changed that to 64/256.
Other arch maintainers are invited to set ranges for their generic targets
if that seems better than using the default cache line size for both values.
With the above choice to reject stability as a goal, getting these values
"right" is now just a matter of what we want the default optimization to be,
and we can feel free to adjust them as CPUs with different cache lines
become more and less common.
gcc/ChangeLog:
* params.opt: Add destructive-interference-size and
constructive-interference-size.
* doc/invoke.texi: Document them.
* config/aarch64/aarch64.c (aarch64_override_options_internal):
Set them.
* config/arm/arm.c (arm_option_override): Set them.
* config/i386/i386-options.c (ix86_option_override_internal):
Set them.
gcc/c-family/ChangeLog:
* c.opt: Add -Winterference-size.
* c-cppbuiltin.c (cpp_atomic_builtins): Add __GCC_DESTRUCTIVE_SIZE
and __GCC_CONSTRUCTIVE_SIZE.
gcc/cp/ChangeLog:
* constexpr.c (maybe_warn_about_constant_value):
Complain about std::hardware_destructive_interference_size.
(cxx_eval_constant_expression): Call it.
* decl.c (cxx_init_decl_processing): Check
--param *-interference-size values.
libstdc++-v3/ChangeLog:
* include/std/version: Define __cpp_lib_hardware_interference_size.
* libsupc++/new: Define hardware interference size variables.
gcc/testsuite/ChangeLog:
* g++.dg/warn/Winterference.H: New file.
* g++.dg/warn/Winterference.C: New test.
* g++.target/aarch64/interference.C: New test.
* g++.target/arm/interference.C: New test.
* g++.target/i386/interference.C: New test.
---
gcc/c-family/c-cppbuiltin.c | 14 ++++++
gcc/c-family/c.opt | 5 ++
gcc/config/aarch64/aarch64.c | 22 +++++++++
gcc/config/arm/arm.c | 22 +++++++++
gcc/config/i386/i386-options.c | 6 +++
gcc/cp/constexpr.c | 33 +++++++++++++
gcc/cp/decl.c | 32 ++++++++++++
gcc/doc/invoke.texi | 65 +++++++++++++++++++++++++
gcc/params.opt | 16 ++++++
gcc/testsuite/g++.dg/warn/Winterference-2.C | 14 ++++++
gcc/testsuite/g++.dg/warn/Winterference.C | 6 +++
gcc/testsuite/g++.dg/warn/Winterference.H | 7 +++
gcc/testsuite/g++.target/aarch64/interference.C | 9 ++++
gcc/testsuite/g++.target/arm/interference.C | 9 ++++
gcc/testsuite/g++.target/i386/interference.C | 8 +++
libstdc++-v3/include/std/version | 3 ++
libstdc++-v3/libsupc++/new | 10 +++-
17 files changed, 279 insertions(+), 2 deletions(-)
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 48cbefd8bf8..ce88e707127 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -741,6 +741,20 @@ cpp_atomic_builtins (cpp_reader *pfile)
builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
targetm.atomic_test_and_set_trueval);
+ /* Macros for C++17 hardware interference size constants. Either both or
+ neither should be set. */
+ gcc_assert (!param_destruct_interfere_size
+ == !param_construct_interfere_size);
+ if (param_destruct_interfere_size)
+ {
+ /* FIXME The way of communicating these values to the library should be
+ part of the C++ ABI, whether macro or builtin. */
+ builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
+ param_destruct_interfere_size);
+ builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
+ param_construct_interfere_size);
+ }
+
/* ptr_type_node can't be used here since ptr_mode is only set when
toplev calls backend_init which is not done with -E or pch. */
psize = POINTER_SIZE_UNITS;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c5fe90003f2..9c151d19870 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -722,6 +722,11 @@ Winit-list-lifetime
C++ ObjC++ Var(warn_init_list) Warning Init(1)
Warn about uses of std::initializer_list that can result in dangling pointers.
+Winterference-size
+C++ ObjC++ Var(warn_interference_size) Warning Init(1)
+Warn about nonsensical values of --param destructive-interference-size or
+constructive-interference-size.
+
Wimplicit
C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
Warn about implicit declarations.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 30d9a0b7a3d..36519ccc5a5 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -16540,6 +16540,28 @@ aarch64_override_options_internal (struct gcc_options *opts)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l1_cache_line_size,
aarch64_tune_params.prefetch->l1_cache_line_size);
+
+ if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic AArch64 target, cover the current range of cache line
+ sizes. */
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ 256);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ 64);
+ }
+
if (aarch64_tune_params.prefetch->l2_cache_size >= 0)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l2_cache_size,
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f1e628253d0..6c6e77fab66 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3669,6 +3669,28 @@ arm_option_override (void)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_line_size,
current_tune->prefetch.l1_cache_line_size);
+ if (current_tune->prefetch.l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic ARM target, JF Bastien proposed using 64 for both. */
+ /* ??? Cortex A9 has a 32-byte cache line, so why not 32 for
+ constructive? */
+ /* More recent Cortex chips have a 64-byte cache line, but are marked
+ ARM_PREFETCH_NOT_BENEFICIAL, so they get these defaults. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+ }
+
if (current_tune->prefetch.l1_cache_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_size,
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 2cb87cedec0..c0006b3674b 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -2579,6 +2579,12 @@ ix86_option_override_internal (bool main_args_p,
SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
ix86_tune_cost->l2_cache_size);
+ /* 64B is the accepted value for these for all x86. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+
/* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */
if (opts->x_flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7772fe62d95..0c2498aee22 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6075,6 +6075,37 @@ inline_asm_in_constexpr_error (location_t loc)
"%<constexpr%> function in C++20");
}
+/* We're getting the constant value of DECL in a manifestly constant-evaluated
+ context; maybe complain about that. */
+
+static void
+maybe_warn_about_constant_value (location_t loc, tree decl)
+{
+ static bool explained = false;
+ if (cxx_dialect >= cxx17
+ && warn_interference_size
+ && !global_options_set.x_param_destruct_interfere_size
+ && DECL_CONTEXT (decl) == std_node
+ && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size")
+ && (LOCATION_FILE (input_location) != main_input_filename
+ || module_exporting_p ())
+ && warning_at (loc, OPT_Winterference_size, "use of %qD", decl)
+ && !explained)
+ {
+ explained = true;
+ inform (loc, "its value can vary between compiler versions or "
+ "with different %<-mtune%> or %<-mcpu%> flags");
+ inform (loc, "if this use is part of a public ABI, change it to "
+ "instead use a constant variable you define");
+ inform (loc, "the default value for the current CPU tuning "
+ "is %d bytes", param_destruct_interfere_size);
+ inform (loc, "you can stabilize this value with %<--param "
+ "hardware_destructive_interference_size=%d%>, or disable "
+ "this warning with %<-Wno-interference-size%>",
+ param_destruct_interfere_size);
+ }
+}
+
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -6219,6 +6250,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = *p;
break;
}
+ if (ctx->manifestly_const_eval)
+ maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bce62ad202a..c2065027369 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4752,6 +4752,38 @@ cxx_init_decl_processing (void)
/* Show we use EH for cleanups. */
if (flag_exceptions)
using_eh_for_cleanups ();
+
+ /* Check that the hardware interference sizes are at least
+ alignof(max_align_t), as required by the standard. */
+ const int max_align = max_align_t_align () / BITS_PER_UNIT;
+ if (param_destruct_interfere_size)
+ {
+ if (param_destruct_interfere_size < max_align)
+ error ("%<--param destructive-interference-size=%d%> is less than "
+ "%d", param_destruct_interfere_size, max_align);
+ else if (param_destruct_interfere_size < param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param destructive-interference-size=%d%> "
+ "is less than %<--param l1-cache-line-size=%d%>",
+ param_destruct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_destruct_interfere_size = param_l1_cache_line_size;
+ /* else leave it unset. */
+
+ if (param_construct_interfere_size)
+ {
+ if (param_construct_interfere_size < max_align)
+ error ("%<--param constructive-interference-size=%d%> is less than "
+ "%d", param_construct_interfere_size, max_align);
+ else if (param_construct_interfere_size > param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param constructive-interference-size=%d%> "
+ "is greater than %<--param l1-cache-line-size=%d%>",
+ param_construct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_construct_interfere_size = param_l1_cache_line_size;
}
/* Enter an abi node in global-module context. returns a cookie to
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23cc68f92b5..78cfc100ac2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9018,6 +9018,43 @@ that has already been done in the current function. Therefore,
seemingly insignificant changes in the source program can cause the
warnings produced by @option{-Winline} to appear or disappear.
+@item -Winterference-size
+@opindex Winterference-size
+Warn about use of C++17 @code{std::hardware_destructive_interference_size}
+without specifying its value with @option{--param destructive-interference-size}.
+Also warn about questionable values for that option.
+
+This variable is intended to be used for controlling class layout, to
+avoid false sharing in concurrent code:
+
+@smallexample
+struct independent_fields @{
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
+@};
+@end smallexample
+
+Here @samp{one} and @samp{two} are intended to be far enough apart
+that stores to one won't require accesses to the other to reload the
+cache line.
+
+By default, @option{--param destructive-interference-size} and
+@option{--param constructive-interference-size} are set based on the
+current @option{-mtune} option, typically to the L1 cache line size
+for the particular target CPU, sometimes to a range if tuning for a
+generic target. So all translation units that depend on ABI
+compatibility for the use of these variables must be compiled with
+the same @option{-mtune} (or @option{-mcpu}).
+
+If ABI stability is important, such as if the use is in a header for a
+library, you should probably not use the hardware interference size
+variables at all. Alternatively, you can force a particular value
+with @option{--param}.
+
+If you are confident that your use of the variable does not affect ABI
+outside a single build of your project, you can turn off the warning
+with @option{-Wno-interference-size}.
+
@item -Wint-in-bool-context
@opindex Wint-in-bool-context
@opindex Wno-int-in-bool-context
@@ -13938,6 +13975,34 @@ prefetch hints can be issued for any constant stride.
This setting is only useful for strides that are known and constant.
+@item destructive-interference-size
+@item constructive-interference-size
+The values for the C++17 variables
+@code{std::hardware_destructive_interference_size} and
+@code{std::hardware_constructive_interference_size}. The destructive
+interference size is the minimum recommended offset between two
+independent concurrently-accessed objects; the constructive
+interference size is the maximum recommended size of contiguous memory
+accessed together. Typically both will be the size of an L1 cache
+line for the target, in bytes. For a generic target covering a range of L1
+cache line sizes, typically the constructive interference size will be
+the small end of the range and the destructive size will be the large
+end.
+
+The destructive interference size is intended to be used for layout,
+and thus has ABI impact. The default value is not expected to be
+stable, and on some targets varies with @option{-mtune}, so use of
+this variable in a context where ABI stability is important, such as
+the public interface of a library, is strongly discouraged; if it is
+used in that context, users can stabilize the value using this
+option.
+
+The constructive interference size is less sensitive, as it is
+typically only used in a @samp{static_assert} to make sure that a type
+fits within a cache line.
+
+See also @option{-Winterference-size}.
+
@item loop-interchange-max-num-stmts
The maximum number of stmts in a loop to be interchanged.
diff --git a/gcc/params.opt b/gcc/params.opt
index 3a701e22c46..658ca028851 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -361,6 +361,22 @@ The maximum code size growth ratio when expanding into a jump table (in percent)
Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
The size of L1 cache line.
+-param=destructive-interference-size=
+Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
+The minimum recommended offset between two concurrently-accessed objects to
+avoid additional performance degradation due to contention introduced by the
+implementation. Typically the L1 cache line size, but can be larger to
+accommodate a variety of target processors with different cache line sizes.
+C++17 code might use this value in structure layout, but is strongly
+discouraged from doing so in public ABIs.
+
+-param=constructive-interference-size=
+Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
+The maximum recommended size of contiguous memory occupied by two objects
+accessed with temporal locality by concurrent threads. Typically the L1 cache
+line size, but can be smaller to accommodate a variety of target processors with
+different cache line sizes.
+
-param=l1-cache-size=
Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
The size of L1 cache.
diff --git a/gcc/testsuite/g++.dg/warn/Winterference-2.C b/gcc/testsuite/g++.dg/warn/Winterference-2.C
new file mode 100644
index 00000000000..2af75c63f83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference-2.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fmodules-ts }
+
+module ;
+
+#include <new>
+
+export module foo;
+
+export {
+ struct A {
+ alignas(std::hardware_destructive_interference_size) int x; // { dg-warning Winterference-size }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.C b/gcc/testsuite/g++.dg/warn/Winterference.C
new file mode 100644
index 00000000000..57c001bc032
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.C
@@ -0,0 +1,6 @@
+// Test that we warn about use of std::hardware_destructive_interference_size
+// in a header.
+// { dg-do compile { target c++17 } }
+
+// { dg-warning Winterference-size "" { target *-*-* } 0 }
+#include "Winterference.H"
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.H b/gcc/testsuite/g++.dg/warn/Winterference.H
new file mode 100644
index 00000000000..36f0ad5f6d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.H
@@ -0,0 +1,7 @@
+#include <new>
+
+struct A
+{
+ alignas(std::hardware_destructive_interference_size) int i;
+ alignas(std::hardware_destructive_interference_size) int j;
+};
diff --git a/gcc/testsuite/g++.target/aarch64/interference.C b/gcc/testsuite/g++.target/aarch64/interference.C
new file mode 100644
index 00000000000..0fc01655223
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Most AArch64 CPUs have an L1 cache line size of 64, but some recent ones use
+// 128 or even 256.
+static_assert(std::hardware_destructive_interference_size == 256);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/arm/interference.C b/gcc/testsuite/g++.target/arm/interference.C
new file mode 100644
index 00000000000..34fe8a52bff
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Recent ARM CPUs have a cache line size of 64. Older ones have
+// a size of 32, but I guess they're old enough that we don't care?
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/i386/interference.C b/gcc/testsuite/g++.target/i386/interference.C
new file mode 100644
index 00000000000..c7b910e3ada
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/interference.C
@@ -0,0 +1,8 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// It is generally agreed that these are the right values for all x86.
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index f950bf0f0db..f41004b5911 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -140,6 +140,9 @@
#define __cpp_lib_filesystem 201703
#define __cpp_lib_gcd 201606
#define __cpp_lib_gcd_lcm 201606
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+#endif
#define __cpp_lib_hypot 201603
#define __cpp_lib_invoke 201411L
#define __cpp_lib_lcm 201606
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 3349b13fd1b..7bc67a6cb02 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -183,9 +183,9 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
} // extern "C++"
#if __cplusplus >= 201703L
-#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
namespace std
{
+#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
#define __cpp_lib_launder 201606
/// Pointer optimization barrier [ptr.launder]
template<typename _Tp>
@@ -205,8 +205,14 @@ namespace std
void launder(const void*) = delete;
void launder(volatile void*) = delete;
void launder(const volatile void*) = delete;
-}
#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
+
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+ inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE;
+ inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE;
+#endif // __GCC_DESTRUCTIVE_SIZE
+}
#endif // C++17
#if __cplusplus > 201703L
</cut>
Identified regression caused by *gcc:76b75018b3d053a890ebe155e47814de14b3c9fb*:
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
c++: implement C++17 hardware interference size
Results regressed to (for first_bad == 76b75018b3d053a890ebe155e47814de14b3c9fb)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
from (for last_good == 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe bootstrap:
2
This commit has regressed these CI configurations:
- tcwg_gcc_bootstrap/master-aarch64-bootstrap
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstra…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstra…
Even more details: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstra…
Reproduce builds:
<cut>
mkdir investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
cd investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
# 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_gcc_bootstrap-bisect-master-aarch64-bootstra… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstra… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-aarch64-bootstra… --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 76b75018b3d053a890ebe155e47814de14b3c9fb
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
Date: Thu Jul 15 15:30:17 2021 -0400
c++: implement C++17 hardware interference size
The last missing piece of the C++17 standard library is the hardware
intereference size constants. Much of the delay in implementing these has
been due to uncertainty about what the right values are, and even whether
there is a single constant value that is suitable; the destructive
interference size is intended to be used in structure layout, so program
ABIs will depend on it.
In principle, both of these values should be the same as the target's L1
cache line size. When compiling for a generic target that is intended to
support a range of target CPUs with different cache line sizes, the
constructive size should probably be the minimum size, and the destructive
size the maximum, unless you are constrained by ABI compatibility with
previous code.
From discussion on gcc-patches, I've come to the conclusion that the
solution to the difficulty of choosing stable values is to give up on it,
and instead encourage only uses where ABI stability is unimportant: in
particular, uses where the ABI is shared at most between translation units
built at the same time with the same flags.
To that end, I've added a warning for any use of the constant value of
std::hardware_destructive_interference_size in a header or module export.
Appropriate uses within a project can disable the warning.
A previous iteration of this patch included an -finterference-tune flag to
make the value vary with -mtune; this iteration makes that the default
behavior, which should be appropriate for all reasonable uses of the
variable. The previous default of "stable-ish" seems to me likely to have
been more of an attractive nuisance; since we can't promise actual
stability, we should instead make proper uses more convenient.
JF Bastien's implementation proposal is summarized at
https://github.com/itanium-cxx-abi/cxx-abi/issues/74
I implement this by adding new --params for the two sizes. Targets can
override these values in targetm.target_option.override() to support a range
of values for the generic target; otherwise, both will default to the L1
cache line size.
64 bytes still seems correct for all x86.
I'm not sure why he proposed 64/64 for generic 32-bit ARM, since the Cortex
A9 has a 32-byte cache line, so I'd think 32/64 would make more sense.
He proposed 64/128 for generic AArch64, but since the A64FX now has a 256B
cache line, I've changed that to 64/256.
Other arch maintainers are invited to set ranges for their generic targets
if that seems better than using the default cache line size for both values.
With the above choice to reject stability as a goal, getting these values
"right" is now just a matter of what we want the default optimization to be,
and we can feel free to adjust them as CPUs with different cache lines
become more and less common.
gcc/ChangeLog:
* params.opt: Add destructive-interference-size and
constructive-interference-size.
* doc/invoke.texi: Document them.
* config/aarch64/aarch64.c (aarch64_override_options_internal):
Set them.
* config/arm/arm.c (arm_option_override): Set them.
* config/i386/i386-options.c (ix86_option_override_internal):
Set them.
gcc/c-family/ChangeLog:
* c.opt: Add -Winterference-size.
* c-cppbuiltin.c (cpp_atomic_builtins): Add __GCC_DESTRUCTIVE_SIZE
and __GCC_CONSTRUCTIVE_SIZE.
gcc/cp/ChangeLog:
* constexpr.c (maybe_warn_about_constant_value):
Complain about std::hardware_destructive_interference_size.
(cxx_eval_constant_expression): Call it.
* decl.c (cxx_init_decl_processing): Check
--param *-interference-size values.
libstdc++-v3/ChangeLog:
* include/std/version: Define __cpp_lib_hardware_interference_size.
* libsupc++/new: Define hardware interference size variables.
gcc/testsuite/ChangeLog:
* g++.dg/warn/Winterference.H: New file.
* g++.dg/warn/Winterference.C: New test.
* g++.target/aarch64/interference.C: New test.
* g++.target/arm/interference.C: New test.
* g++.target/i386/interference.C: New test.
---
gcc/c-family/c-cppbuiltin.c | 14 ++++++
gcc/c-family/c.opt | 5 ++
gcc/config/aarch64/aarch64.c | 22 +++++++++
gcc/config/arm/arm.c | 22 +++++++++
gcc/config/i386/i386-options.c | 6 +++
gcc/cp/constexpr.c | 33 +++++++++++++
gcc/cp/decl.c | 32 ++++++++++++
gcc/doc/invoke.texi | 65 +++++++++++++++++++++++++
gcc/params.opt | 16 ++++++
gcc/testsuite/g++.dg/warn/Winterference-2.C | 14 ++++++
gcc/testsuite/g++.dg/warn/Winterference.C | 6 +++
gcc/testsuite/g++.dg/warn/Winterference.H | 7 +++
gcc/testsuite/g++.target/aarch64/interference.C | 9 ++++
gcc/testsuite/g++.target/arm/interference.C | 9 ++++
gcc/testsuite/g++.target/i386/interference.C | 8 +++
libstdc++-v3/include/std/version | 3 ++
libstdc++-v3/libsupc++/new | 10 +++-
17 files changed, 279 insertions(+), 2 deletions(-)
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 48cbefd8bf8..ce88e707127 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -741,6 +741,20 @@ cpp_atomic_builtins (cpp_reader *pfile)
builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
targetm.atomic_test_and_set_trueval);
+ /* Macros for C++17 hardware interference size constants. Either both or
+ neither should be set. */
+ gcc_assert (!param_destruct_interfere_size
+ == !param_construct_interfere_size);
+ if (param_destruct_interfere_size)
+ {
+ /* FIXME The way of communicating these values to the library should be
+ part of the C++ ABI, whether macro or builtin. */
+ builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
+ param_destruct_interfere_size);
+ builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
+ param_construct_interfere_size);
+ }
+
/* ptr_type_node can't be used here since ptr_mode is only set when
toplev calls backend_init which is not done with -E or pch. */
psize = POINTER_SIZE_UNITS;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c5fe90003f2..9c151d19870 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -722,6 +722,11 @@ Winit-list-lifetime
C++ ObjC++ Var(warn_init_list) Warning Init(1)
Warn about uses of std::initializer_list that can result in dangling pointers.
+Winterference-size
+C++ ObjC++ Var(warn_interference_size) Warning Init(1)
+Warn about nonsensical values of --param destructive-interference-size or
+constructive-interference-size.
+
Wimplicit
C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
Warn about implicit declarations.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 30d9a0b7a3d..36519ccc5a5 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -16540,6 +16540,28 @@ aarch64_override_options_internal (struct gcc_options *opts)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l1_cache_line_size,
aarch64_tune_params.prefetch->l1_cache_line_size);
+
+ if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic AArch64 target, cover the current range of cache line
+ sizes. */
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ 256);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ 64);
+ }
+
if (aarch64_tune_params.prefetch->l2_cache_size >= 0)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l2_cache_size,
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f1e628253d0..6c6e77fab66 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3669,6 +3669,28 @@ arm_option_override (void)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_line_size,
current_tune->prefetch.l1_cache_line_size);
+ if (current_tune->prefetch.l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic ARM target, JF Bastien proposed using 64 for both. */
+ /* ??? Cortex A9 has a 32-byte cache line, so why not 32 for
+ constructive? */
+ /* More recent Cortex chips have a 64-byte cache line, but are marked
+ ARM_PREFETCH_NOT_BENEFICIAL, so they get these defaults. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+ }
+
if (current_tune->prefetch.l1_cache_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_size,
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 2cb87cedec0..c0006b3674b 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -2579,6 +2579,12 @@ ix86_option_override_internal (bool main_args_p,
SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
ix86_tune_cost->l2_cache_size);
+ /* 64B is the accepted value for these for all x86. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+
/* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */
if (opts->x_flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7772fe62d95..0c2498aee22 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6075,6 +6075,37 @@ inline_asm_in_constexpr_error (location_t loc)
"%<constexpr%> function in C++20");
}
+/* We're getting the constant value of DECL in a manifestly constant-evaluated
+ context; maybe complain about that. */
+
+static void
+maybe_warn_about_constant_value (location_t loc, tree decl)
+{
+ static bool explained = false;
+ if (cxx_dialect >= cxx17
+ && warn_interference_size
+ && !global_options_set.x_param_destruct_interfere_size
+ && DECL_CONTEXT (decl) == std_node
+ && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size")
+ && (LOCATION_FILE (input_location) != main_input_filename
+ || module_exporting_p ())
+ && warning_at (loc, OPT_Winterference_size, "use of %qD", decl)
+ && !explained)
+ {
+ explained = true;
+ inform (loc, "its value can vary between compiler versions or "
+ "with different %<-mtune%> or %<-mcpu%> flags");
+ inform (loc, "if this use is part of a public ABI, change it to "
+ "instead use a constant variable you define");
+ inform (loc, "the default value for the current CPU tuning "
+ "is %d bytes", param_destruct_interfere_size);
+ inform (loc, "you can stabilize this value with %<--param "
+ "hardware_destructive_interference_size=%d%>, or disable "
+ "this warning with %<-Wno-interference-size%>",
+ param_destruct_interfere_size);
+ }
+}
+
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -6219,6 +6250,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = *p;
break;
}
+ if (ctx->manifestly_const_eval)
+ maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bce62ad202a..c2065027369 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4752,6 +4752,38 @@ cxx_init_decl_processing (void)
/* Show we use EH for cleanups. */
if (flag_exceptions)
using_eh_for_cleanups ();
+
+ /* Check that the hardware interference sizes are at least
+ alignof(max_align_t), as required by the standard. */
+ const int max_align = max_align_t_align () / BITS_PER_UNIT;
+ if (param_destruct_interfere_size)
+ {
+ if (param_destruct_interfere_size < max_align)
+ error ("%<--param destructive-interference-size=%d%> is less than "
+ "%d", param_destruct_interfere_size, max_align);
+ else if (param_destruct_interfere_size < param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param destructive-interference-size=%d%> "
+ "is less than %<--param l1-cache-line-size=%d%>",
+ param_destruct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_destruct_interfere_size = param_l1_cache_line_size;
+ /* else leave it unset. */
+
+ if (param_construct_interfere_size)
+ {
+ if (param_construct_interfere_size < max_align)
+ error ("%<--param constructive-interference-size=%d%> is less than "
+ "%d", param_construct_interfere_size, max_align);
+ else if (param_construct_interfere_size > param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param constructive-interference-size=%d%> "
+ "is greater than %<--param l1-cache-line-size=%d%>",
+ param_construct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_construct_interfere_size = param_l1_cache_line_size;
}
/* Enter an abi node in global-module context. returns a cookie to
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23cc68f92b5..78cfc100ac2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9018,6 +9018,43 @@ that has already been done in the current function. Therefore,
seemingly insignificant changes in the source program can cause the
warnings produced by @option{-Winline} to appear or disappear.
+@item -Winterference-size
+@opindex Winterference-size
+Warn about use of C++17 @code{std::hardware_destructive_interference_size}
+without specifying its value with @option{--param destructive-interference-size}.
+Also warn about questionable values for that option.
+
+This variable is intended to be used for controlling class layout, to
+avoid false sharing in concurrent code:
+
+@smallexample
+struct independent_fields @{
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
+@};
+@end smallexample
+
+Here @samp{one} and @samp{two} are intended to be far enough apart
+that stores to one won't require accesses to the other to reload the
+cache line.
+
+By default, @option{--param destructive-interference-size} and
+@option{--param constructive-interference-size} are set based on the
+current @option{-mtune} option, typically to the L1 cache line size
+for the particular target CPU, sometimes to a range if tuning for a
+generic target. So all translation units that depend on ABI
+compatibility for the use of these variables must be compiled with
+the same @option{-mtune} (or @option{-mcpu}).
+
+If ABI stability is important, such as if the use is in a header for a
+library, you should probably not use the hardware interference size
+variables at all. Alternatively, you can force a particular value
+with @option{--param}.
+
+If you are confident that your use of the variable does not affect ABI
+outside a single build of your project, you can turn off the warning
+with @option{-Wno-interference-size}.
+
@item -Wint-in-bool-context
@opindex Wint-in-bool-context
@opindex Wno-int-in-bool-context
@@ -13938,6 +13975,34 @@ prefetch hints can be issued for any constant stride.
This setting is only useful for strides that are known and constant.
+@item destructive-interference-size
+@item constructive-interference-size
+The values for the C++17 variables
+@code{std::hardware_destructive_interference_size} and
+@code{std::hardware_constructive_interference_size}. The destructive
+interference size is the minimum recommended offset between two
+independent concurrently-accessed objects; the constructive
+interference size is the maximum recommended size of contiguous memory
+accessed together. Typically both will be the size of an L1 cache
+line for the target, in bytes. For a generic target covering a range of L1
+cache line sizes, typically the constructive interference size will be
+the small end of the range and the destructive size will be the large
+end.
+
+The destructive interference size is intended to be used for layout,
+and thus has ABI impact. The default value is not expected to be
+stable, and on some targets varies with @option{-mtune}, so use of
+this variable in a context where ABI stability is important, such as
+the public interface of a library, is strongly discouraged; if it is
+used in that context, users can stabilize the value using this
+option.
+
+The constructive interference size is less sensitive, as it is
+typically only used in a @samp{static_assert} to make sure that a type
+fits within a cache line.
+
+See also @option{-Winterference-size}.
+
@item loop-interchange-max-num-stmts
The maximum number of stmts in a loop to be interchanged.
diff --git a/gcc/params.opt b/gcc/params.opt
index 3a701e22c46..658ca028851 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -361,6 +361,22 @@ The maximum code size growth ratio when expanding into a jump table (in percent)
Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
The size of L1 cache line.
+-param=destructive-interference-size=
+Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
+The minimum recommended offset between two concurrently-accessed objects to
+avoid additional performance degradation due to contention introduced by the
+implementation. Typically the L1 cache line size, but can be larger to
+accommodate a variety of target processors with different cache line sizes.
+C++17 code might use this value in structure layout, but is strongly
+discouraged from doing so in public ABIs.
+
+-param=constructive-interference-size=
+Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
+The maximum recommended size of contiguous memory occupied by two objects
+accessed with temporal locality by concurrent threads. Typically the L1 cache
+line size, but can be smaller to accommodate a variety of target processors with
+different cache line sizes.
+
-param=l1-cache-size=
Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
The size of L1 cache.
diff --git a/gcc/testsuite/g++.dg/warn/Winterference-2.C b/gcc/testsuite/g++.dg/warn/Winterference-2.C
new file mode 100644
index 00000000000..2af75c63f83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference-2.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fmodules-ts }
+
+module ;
+
+#include <new>
+
+export module foo;
+
+export {
+ struct A {
+ alignas(std::hardware_destructive_interference_size) int x; // { dg-warning Winterference-size }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.C b/gcc/testsuite/g++.dg/warn/Winterference.C
new file mode 100644
index 00000000000..57c001bc032
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.C
@@ -0,0 +1,6 @@
+// Test that we warn about use of std::hardware_destructive_interference_size
+// in a header.
+// { dg-do compile { target c++17 } }
+
+// { dg-warning Winterference-size "" { target *-*-* } 0 }
+#include "Winterference.H"
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.H b/gcc/testsuite/g++.dg/warn/Winterference.H
new file mode 100644
index 00000000000..36f0ad5f6d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.H
@@ -0,0 +1,7 @@
+#include <new>
+
+struct A
+{
+ alignas(std::hardware_destructive_interference_size) int i;
+ alignas(std::hardware_destructive_interference_size) int j;
+};
diff --git a/gcc/testsuite/g++.target/aarch64/interference.C b/gcc/testsuite/g++.target/aarch64/interference.C
new file mode 100644
index 00000000000..0fc01655223
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Most AArch64 CPUs have an L1 cache line size of 64, but some recent ones use
+// 128 or even 256.
+static_assert(std::hardware_destructive_interference_size == 256);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/arm/interference.C b/gcc/testsuite/g++.target/arm/interference.C
new file mode 100644
index 00000000000..34fe8a52bff
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Recent ARM CPUs have a cache line size of 64. Older ones have
+// a size of 32, but I guess they're old enough that we don't care?
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/i386/interference.C b/gcc/testsuite/g++.target/i386/interference.C
new file mode 100644
index 00000000000..c7b910e3ada
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/interference.C
@@ -0,0 +1,8 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// It is generally agreed that these are the right values for all x86.
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index f950bf0f0db..f41004b5911 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -140,6 +140,9 @@
#define __cpp_lib_filesystem 201703
#define __cpp_lib_gcd 201606
#define __cpp_lib_gcd_lcm 201606
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+#endif
#define __cpp_lib_hypot 201603
#define __cpp_lib_invoke 201411L
#define __cpp_lib_lcm 201606
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 3349b13fd1b..7bc67a6cb02 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -183,9 +183,9 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
} // extern "C++"
#if __cplusplus >= 201703L
-#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
namespace std
{
+#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
#define __cpp_lib_launder 201606
/// Pointer optimization barrier [ptr.launder]
template<typename _Tp>
@@ -205,8 +205,14 @@ namespace std
void launder(const void*) = delete;
void launder(volatile void*) = delete;
void launder(const volatile void*) = delete;
-}
#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
+
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+ inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE;
+ inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE;
+#endif // __GCC_DESTRUCTIVE_SIZE
+}
#endif // C++17
#if __cplusplus > 201703L
</cut>
Identified regression caused by *gcc:76b75018b3d053a890ebe155e47814de14b3c9fb*:
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
c++: implement C++17 hardware interference size
Results regressed to (for first_bad == 76b75018b3d053a890ebe155e47814de14b3c9fb)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
from (for last_good == 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe gcc:
2
# build_abe linux:
4
# build_abe glibc:
5
# build_abe gdb:
6
This commit has regressed these CI configurations:
- tcwg_gnu_native_build/master-arm
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/2/artifac…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/2/artifac…
Even more details: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/2/artifac…
Reproduce builds:
<cut>
mkdir investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
cd investigate-gcc-76b75018b3d053a890ebe155e47814de14b3c9fb
# 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_gnu_native_build-bisect-master-arm/2/artifac… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/2/artifac… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/2/artifac… --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 76b75018b3d053a890ebe155e47814de14b3c9fb
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 8ea292591e42aa4d52b4b7a00b86335bfd2e2e85
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit 76b75018b3d053a890ebe155e47814de14b3c9fb
Author: Jason Merrill <jason(a)redhat.com>
Date: Thu Jul 15 15:30:17 2021 -0400
c++: implement C++17 hardware interference size
The last missing piece of the C++17 standard library is the hardware
intereference size constants. Much of the delay in implementing these has
been due to uncertainty about what the right values are, and even whether
there is a single constant value that is suitable; the destructive
interference size is intended to be used in structure layout, so program
ABIs will depend on it.
In principle, both of these values should be the same as the target's L1
cache line size. When compiling for a generic target that is intended to
support a range of target CPUs with different cache line sizes, the
constructive size should probably be the minimum size, and the destructive
size the maximum, unless you are constrained by ABI compatibility with
previous code.
From discussion on gcc-patches, I've come to the conclusion that the
solution to the difficulty of choosing stable values is to give up on it,
and instead encourage only uses where ABI stability is unimportant: in
particular, uses where the ABI is shared at most between translation units
built at the same time with the same flags.
To that end, I've added a warning for any use of the constant value of
std::hardware_destructive_interference_size in a header or module export.
Appropriate uses within a project can disable the warning.
A previous iteration of this patch included an -finterference-tune flag to
make the value vary with -mtune; this iteration makes that the default
behavior, which should be appropriate for all reasonable uses of the
variable. The previous default of "stable-ish" seems to me likely to have
been more of an attractive nuisance; since we can't promise actual
stability, we should instead make proper uses more convenient.
JF Bastien's implementation proposal is summarized at
https://github.com/itanium-cxx-abi/cxx-abi/issues/74
I implement this by adding new --params for the two sizes. Targets can
override these values in targetm.target_option.override() to support a range
of values for the generic target; otherwise, both will default to the L1
cache line size.
64 bytes still seems correct for all x86.
I'm not sure why he proposed 64/64 for generic 32-bit ARM, since the Cortex
A9 has a 32-byte cache line, so I'd think 32/64 would make more sense.
He proposed 64/128 for generic AArch64, but since the A64FX now has a 256B
cache line, I've changed that to 64/256.
Other arch maintainers are invited to set ranges for their generic targets
if that seems better than using the default cache line size for both values.
With the above choice to reject stability as a goal, getting these values
"right" is now just a matter of what we want the default optimization to be,
and we can feel free to adjust them as CPUs with different cache lines
become more and less common.
gcc/ChangeLog:
* params.opt: Add destructive-interference-size and
constructive-interference-size.
* doc/invoke.texi: Document them.
* config/aarch64/aarch64.c (aarch64_override_options_internal):
Set them.
* config/arm/arm.c (arm_option_override): Set them.
* config/i386/i386-options.c (ix86_option_override_internal):
Set them.
gcc/c-family/ChangeLog:
* c.opt: Add -Winterference-size.
* c-cppbuiltin.c (cpp_atomic_builtins): Add __GCC_DESTRUCTIVE_SIZE
and __GCC_CONSTRUCTIVE_SIZE.
gcc/cp/ChangeLog:
* constexpr.c (maybe_warn_about_constant_value):
Complain about std::hardware_destructive_interference_size.
(cxx_eval_constant_expression): Call it.
* decl.c (cxx_init_decl_processing): Check
--param *-interference-size values.
libstdc++-v3/ChangeLog:
* include/std/version: Define __cpp_lib_hardware_interference_size.
* libsupc++/new: Define hardware interference size variables.
gcc/testsuite/ChangeLog:
* g++.dg/warn/Winterference.H: New file.
* g++.dg/warn/Winterference.C: New test.
* g++.target/aarch64/interference.C: New test.
* g++.target/arm/interference.C: New test.
* g++.target/i386/interference.C: New test.
---
gcc/c-family/c-cppbuiltin.c | 14 ++++++
gcc/c-family/c.opt | 5 ++
gcc/config/aarch64/aarch64.c | 22 +++++++++
gcc/config/arm/arm.c | 22 +++++++++
gcc/config/i386/i386-options.c | 6 +++
gcc/cp/constexpr.c | 33 +++++++++++++
gcc/cp/decl.c | 32 ++++++++++++
gcc/doc/invoke.texi | 65 +++++++++++++++++++++++++
gcc/params.opt | 16 ++++++
gcc/testsuite/g++.dg/warn/Winterference-2.C | 14 ++++++
gcc/testsuite/g++.dg/warn/Winterference.C | 6 +++
gcc/testsuite/g++.dg/warn/Winterference.H | 7 +++
gcc/testsuite/g++.target/aarch64/interference.C | 9 ++++
gcc/testsuite/g++.target/arm/interference.C | 9 ++++
gcc/testsuite/g++.target/i386/interference.C | 8 +++
libstdc++-v3/include/std/version | 3 ++
libstdc++-v3/libsupc++/new | 10 +++-
17 files changed, 279 insertions(+), 2 deletions(-)
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 48cbefd8bf8..ce88e707127 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -741,6 +741,20 @@ cpp_atomic_builtins (cpp_reader *pfile)
builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
targetm.atomic_test_and_set_trueval);
+ /* Macros for C++17 hardware interference size constants. Either both or
+ neither should be set. */
+ gcc_assert (!param_destruct_interfere_size
+ == !param_construct_interfere_size);
+ if (param_destruct_interfere_size)
+ {
+ /* FIXME The way of communicating these values to the library should be
+ part of the C++ ABI, whether macro or builtin. */
+ builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
+ param_destruct_interfere_size);
+ builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
+ param_construct_interfere_size);
+ }
+
/* ptr_type_node can't be used here since ptr_mode is only set when
toplev calls backend_init which is not done with -E or pch. */
psize = POINTER_SIZE_UNITS;
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c5fe90003f2..9c151d19870 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -722,6 +722,11 @@ Winit-list-lifetime
C++ ObjC++ Var(warn_init_list) Warning Init(1)
Warn about uses of std::initializer_list that can result in dangling pointers.
+Winterference-size
+C++ ObjC++ Var(warn_interference_size) Warning Init(1)
+Warn about nonsensical values of --param destructive-interference-size or
+constructive-interference-size.
+
Wimplicit
C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
Warn about implicit declarations.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 30d9a0b7a3d..36519ccc5a5 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -16540,6 +16540,28 @@ aarch64_override_options_internal (struct gcc_options *opts)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l1_cache_line_size,
aarch64_tune_params.prefetch->l1_cache_line_size);
+
+ if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ aarch64_tune_params.prefetch->l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic AArch64 target, cover the current range of cache line
+ sizes. */
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_destruct_interfere_size,
+ 256);
+ SET_OPTION_IF_UNSET (opts, &global_options_set,
+ param_construct_interfere_size,
+ 64);
+ }
+
if (aarch64_tune_params.prefetch->l2_cache_size >= 0)
SET_OPTION_IF_UNSET (opts, &global_options_set,
param_l2_cache_size,
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index f1e628253d0..6c6e77fab66 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -3669,6 +3669,28 @@ arm_option_override (void)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_line_size,
current_tune->prefetch.l1_cache_line_size);
+ if (current_tune->prefetch.l1_cache_line_size >= 0)
+ {
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size,
+ current_tune->prefetch.l1_cache_line_size);
+ }
+ else
+ {
+ /* For a generic ARM target, JF Bastien proposed using 64 for both. */
+ /* ??? Cortex A9 has a 32-byte cache line, so why not 32 for
+ constructive? */
+ /* More recent Cortex chips have a 64-byte cache line, but are marked
+ ARM_PREFETCH_NOT_BENEFICIAL, so they get these defaults. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+ }
+
if (current_tune->prefetch.l1_cache_size >= 0)
SET_OPTION_IF_UNSET (&global_options, &global_options_set,
param_l1_cache_size,
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index 2cb87cedec0..c0006b3674b 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -2579,6 +2579,12 @@ ix86_option_override_internal (bool main_args_p,
SET_OPTION_IF_UNSET (opts, opts_set, param_l2_cache_size,
ix86_tune_cost->l2_cache_size);
+ /* 64B is the accepted value for these for all x86. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_destruct_interfere_size, 64);
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_construct_interfere_size, 64);
+
/* Enable sw prefetching at -O3 for CPUS that prefetching is helpful. */
if (opts->x_flag_prefetch_loop_arrays < 0
&& HAVE_prefetch
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7772fe62d95..0c2498aee22 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6075,6 +6075,37 @@ inline_asm_in_constexpr_error (location_t loc)
"%<constexpr%> function in C++20");
}
+/* We're getting the constant value of DECL in a manifestly constant-evaluated
+ context; maybe complain about that. */
+
+static void
+maybe_warn_about_constant_value (location_t loc, tree decl)
+{
+ static bool explained = false;
+ if (cxx_dialect >= cxx17
+ && warn_interference_size
+ && !global_options_set.x_param_destruct_interfere_size
+ && DECL_CONTEXT (decl) == std_node
+ && id_equal (DECL_NAME (decl), "hardware_destructive_interference_size")
+ && (LOCATION_FILE (input_location) != main_input_filename
+ || module_exporting_p ())
+ && warning_at (loc, OPT_Winterference_size, "use of %qD", decl)
+ && !explained)
+ {
+ explained = true;
+ inform (loc, "its value can vary between compiler versions or "
+ "with different %<-mtune%> or %<-mcpu%> flags");
+ inform (loc, "if this use is part of a public ABI, change it to "
+ "instead use a constant variable you define");
+ inform (loc, "the default value for the current CPU tuning "
+ "is %d bytes", param_destruct_interfere_size);
+ inform (loc, "you can stabilize this value with %<--param "
+ "hardware_destructive_interference_size=%d%>, or disable "
+ "this warning with %<-Wno-interference-size%>",
+ param_destruct_interfere_size);
+ }
+}
+
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -6219,6 +6250,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = *p;
break;
}
+ if (ctx->manifestly_const_eval)
+ maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bce62ad202a..c2065027369 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4752,6 +4752,38 @@ cxx_init_decl_processing (void)
/* Show we use EH for cleanups. */
if (flag_exceptions)
using_eh_for_cleanups ();
+
+ /* Check that the hardware interference sizes are at least
+ alignof(max_align_t), as required by the standard. */
+ const int max_align = max_align_t_align () / BITS_PER_UNIT;
+ if (param_destruct_interfere_size)
+ {
+ if (param_destruct_interfere_size < max_align)
+ error ("%<--param destructive-interference-size=%d%> is less than "
+ "%d", param_destruct_interfere_size, max_align);
+ else if (param_destruct_interfere_size < param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param destructive-interference-size=%d%> "
+ "is less than %<--param l1-cache-line-size=%d%>",
+ param_destruct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_destruct_interfere_size = param_l1_cache_line_size;
+ /* else leave it unset. */
+
+ if (param_construct_interfere_size)
+ {
+ if (param_construct_interfere_size < max_align)
+ error ("%<--param constructive-interference-size=%d%> is less than "
+ "%d", param_construct_interfere_size, max_align);
+ else if (param_construct_interfere_size > param_l1_cache_line_size)
+ warning (OPT_Winterference_size,
+ "%<--param constructive-interference-size=%d%> "
+ "is greater than %<--param l1-cache-line-size=%d%>",
+ param_construct_interfere_size, param_l1_cache_line_size);
+ }
+ else if (param_l1_cache_line_size >= max_align)
+ param_construct_interfere_size = param_l1_cache_line_size;
}
/* Enter an abi node in global-module context. returns a cookie to
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23cc68f92b5..78cfc100ac2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9018,6 +9018,43 @@ that has already been done in the current function. Therefore,
seemingly insignificant changes in the source program can cause the
warnings produced by @option{-Winline} to appear or disappear.
+@item -Winterference-size
+@opindex Winterference-size
+Warn about use of C++17 @code{std::hardware_destructive_interference_size}
+without specifying its value with @option{--param destructive-interference-size}.
+Also warn about questionable values for that option.
+
+This variable is intended to be used for controlling class layout, to
+avoid false sharing in concurrent code:
+
+@smallexample
+struct independent_fields @{
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> one;
+ alignas(std::hardware_destructive_interference_size) std::atomic<int> two;
+@};
+@end smallexample
+
+Here @samp{one} and @samp{two} are intended to be far enough apart
+that stores to one won't require accesses to the other to reload the
+cache line.
+
+By default, @option{--param destructive-interference-size} and
+@option{--param constructive-interference-size} are set based on the
+current @option{-mtune} option, typically to the L1 cache line size
+for the particular target CPU, sometimes to a range if tuning for a
+generic target. So all translation units that depend on ABI
+compatibility for the use of these variables must be compiled with
+the same @option{-mtune} (or @option{-mcpu}).
+
+If ABI stability is important, such as if the use is in a header for a
+library, you should probably not use the hardware interference size
+variables at all. Alternatively, you can force a particular value
+with @option{--param}.
+
+If you are confident that your use of the variable does not affect ABI
+outside a single build of your project, you can turn off the warning
+with @option{-Wno-interference-size}.
+
@item -Wint-in-bool-context
@opindex Wint-in-bool-context
@opindex Wno-int-in-bool-context
@@ -13938,6 +13975,34 @@ prefetch hints can be issued for any constant stride.
This setting is only useful for strides that are known and constant.
+@item destructive-interference-size
+@item constructive-interference-size
+The values for the C++17 variables
+@code{std::hardware_destructive_interference_size} and
+@code{std::hardware_constructive_interference_size}. The destructive
+interference size is the minimum recommended offset between two
+independent concurrently-accessed objects; the constructive
+interference size is the maximum recommended size of contiguous memory
+accessed together. Typically both will be the size of an L1 cache
+line for the target, in bytes. For a generic target covering a range of L1
+cache line sizes, typically the constructive interference size will be
+the small end of the range and the destructive size will be the large
+end.
+
+The destructive interference size is intended to be used for layout,
+and thus has ABI impact. The default value is not expected to be
+stable, and on some targets varies with @option{-mtune}, so use of
+this variable in a context where ABI stability is important, such as
+the public interface of a library, is strongly discouraged; if it is
+used in that context, users can stabilize the value using this
+option.
+
+The constructive interference size is less sensitive, as it is
+typically only used in a @samp{static_assert} to make sure that a type
+fits within a cache line.
+
+See also @option{-Winterference-size}.
+
@item loop-interchange-max-num-stmts
The maximum number of stmts in a loop to be interchanged.
diff --git a/gcc/params.opt b/gcc/params.opt
index 3a701e22c46..658ca028851 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -361,6 +361,22 @@ The maximum code size growth ratio when expanding into a jump table (in percent)
Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
The size of L1 cache line.
+-param=destructive-interference-size=
+Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
+The minimum recommended offset between two concurrently-accessed objects to
+avoid additional performance degradation due to contention introduced by the
+implementation. Typically the L1 cache line size, but can be larger to
+accommodate a variety of target processors with different cache line sizes.
+C++17 code might use this value in structure layout, but is strongly
+discouraged from doing so in public ABIs.
+
+-param=constructive-interference-size=
+Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
+The maximum recommended size of contiguous memory occupied by two objects
+accessed with temporal locality by concurrent threads. Typically the L1 cache
+line size, but can be smaller to accommodate a variety of target processors with
+different cache line sizes.
+
-param=l1-cache-size=
Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
The size of L1 cache.
diff --git a/gcc/testsuite/g++.dg/warn/Winterference-2.C b/gcc/testsuite/g++.dg/warn/Winterference-2.C
new file mode 100644
index 00000000000..2af75c63f83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference-2.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fmodules-ts }
+
+module ;
+
+#include <new>
+
+export module foo;
+
+export {
+ struct A {
+ alignas(std::hardware_destructive_interference_size) int x; // { dg-warning Winterference-size }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.C b/gcc/testsuite/g++.dg/warn/Winterference.C
new file mode 100644
index 00000000000..57c001bc032
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.C
@@ -0,0 +1,6 @@
+// Test that we warn about use of std::hardware_destructive_interference_size
+// in a header.
+// { dg-do compile { target c++17 } }
+
+// { dg-warning Winterference-size "" { target *-*-* } 0 }
+#include "Winterference.H"
diff --git a/gcc/testsuite/g++.dg/warn/Winterference.H b/gcc/testsuite/g++.dg/warn/Winterference.H
new file mode 100644
index 00000000000..36f0ad5f6d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winterference.H
@@ -0,0 +1,7 @@
+#include <new>
+
+struct A
+{
+ alignas(std::hardware_destructive_interference_size) int i;
+ alignas(std::hardware_destructive_interference_size) int j;
+};
diff --git a/gcc/testsuite/g++.target/aarch64/interference.C b/gcc/testsuite/g++.target/aarch64/interference.C
new file mode 100644
index 00000000000..0fc01655223
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Most AArch64 CPUs have an L1 cache line size of 64, but some recent ones use
+// 128 or even 256.
+static_assert(std::hardware_destructive_interference_size == 256);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/arm/interference.C b/gcc/testsuite/g++.target/arm/interference.C
new file mode 100644
index 00000000000..34fe8a52bff
--- /dev/null
+++ b/gcc/testsuite/g++.target/arm/interference.C
@@ -0,0 +1,9 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// Recent ARM CPUs have a cache line size of 64. Older ones have
+// a size of 32, but I guess they're old enough that we don't care?
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/gcc/testsuite/g++.target/i386/interference.C b/gcc/testsuite/g++.target/i386/interference.C
new file mode 100644
index 00000000000..c7b910e3ada
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/interference.C
@@ -0,0 +1,8 @@
+// Test C++17 hardware interference size constants
+// { dg-do compile { target c++17 } }
+
+#include <new>
+
+// It is generally agreed that these are the right values for all x86.
+static_assert(std::hardware_destructive_interference_size == 64);
+static_assert(std::hardware_constructive_interference_size == 64);
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index f950bf0f0db..f41004b5911 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -140,6 +140,9 @@
#define __cpp_lib_filesystem 201703
#define __cpp_lib_gcd 201606
#define __cpp_lib_gcd_lcm 201606
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+#endif
#define __cpp_lib_hypot 201603
#define __cpp_lib_invoke 201411L
#define __cpp_lib_lcm 201606
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 3349b13fd1b..7bc67a6cb02 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -183,9 +183,9 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
} // extern "C++"
#if __cplusplus >= 201703L
-#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
namespace std
{
+#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER
#define __cpp_lib_launder 201606
/// Pointer optimization barrier [ptr.launder]
template<typename _Tp>
@@ -205,8 +205,14 @@ namespace std
void launder(const void*) = delete;
void launder(volatile void*) = delete;
void launder(const volatile void*) = delete;
-}
#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
+
+#ifdef __GCC_DESTRUCTIVE_SIZE
+# define __cpp_lib_hardware_interference_size 201703L
+ inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE;
+ inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE;
+#endif // __GCC_DESTRUCTIVE_SIZE
+}
#endif // C++17
#if __cplusplus > 201703L
</cut>
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-master-aarch64-mainline-allmodconfig. So far, this commit has regressed CI configurations:
- tcwg_kernel/llvm-master-aarch64-mainline-allmodconfig
Culprit:
<cut>
commit c3496da580b0fc10fdeba8f6a5e6aef4c78b5598
Author: Slark Xiao <slark_xiao(a)163.com>
Date: Tue Aug 31 10:40:25 2021 +0800
net: Add depends on OF_NET for LiteX's LiteETH
Current settings may produce a build error when
CONFIG_OF_NET is disabled. The CONFIG_OF_NET controls
a headfile <linux/of.h> and some functions
in <linux/of_net.h>.
Signed-off-by: Slark Xiao <slark_xiao(a)163.com>
Signed-off-by: Jakub Kicinski <kuba(a)kernel.org>
</cut>
Results regressed to (for first_bad == c3496da580b0fc10fdeba8f6a5e6aef4c78b5598)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
29873
# linux build successful:
all
# First few build errors in logs:
from (for last_good == a9e7c3cedc2914f63cd135b75832b9bf850af782)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
29873
# linux build successful:
all
# linux boot successful:
boot
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Build top page/logs: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-linux-c3496da580b0fc10fdeba8f6a5e6aef4c78b5598
cd investigate-linux-c3496da580b0fc10fdeba8f6a5e6aef4c78b5598
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_kernel-llvm-bisect-llvm-master-aarch64-mainl… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl… --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 /linux/ ./ ./bisect/baseline/
cd linux
# Reproduce first_bad build
git checkout --detach c3496da580b0fc10fdeba8f6a5e6aef4c78b5598
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach a9e7c3cedc2914f63cd135b75832b9bf850af782
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Build log: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Full commit (up to 1000 lines):
<cut>
commit c3496da580b0fc10fdeba8f6a5e6aef4c78b5598
Author: Slark Xiao <slark_xiao(a)163.com>
Date: Tue Aug 31 10:40:25 2021 +0800
net: Add depends on OF_NET for LiteX's LiteETH
Current settings may produce a build error when
CONFIG_OF_NET is disabled. The CONFIG_OF_NET controls
a headfile <linux/of.h> and some functions
in <linux/of_net.h>.
Signed-off-by: Slark Xiao <slark_xiao(a)163.com>
Signed-off-by: Jakub Kicinski <kuba(a)kernel.org>
---
drivers/net/ethernet/litex/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/litex/Kconfig b/drivers/net/ethernet/litex/Kconfig
index 265dba414b41..63bf01d28f0c 100644
--- a/drivers/net/ethernet/litex/Kconfig
+++ b/drivers/net/ethernet/litex/Kconfig
@@ -17,6 +17,7 @@ if NET_VENDOR_LITEX
config LITEX_LITEETH
tristate "LiteX Ethernet support"
+ depends on OF_NET
help
If you wish to compile a kernel for hardware with a LiteX LiteEth
device then you should answer Y to this.
</cut>
Identified regression caused by *gcc:01b5038718056b024b370b74a874fbd92c5bbab3*:
commit 01b5038718056b024b370b74a874fbd92c5bbab3
Author: Aldy Hernandez <aldyh(a)redhat.com>
Disable threading through latches until after loop optimizations.
Results regressed to (for first_bad == 01b5038718056b024b370b74a874fbd92c5bbab3)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# true:
0
# benchmark -- -Os artifacts/build-01b5038718056b024b370b74a874fbd92c5bbab3/results_id:
1
# 459.GemsFDTD,GemsFDTD_base.default regressed by 102
# 464.h264ref,h264ref_base.default regressed by 102
from (for last_good == fb88bf9931f17d137eb50c001e1c924aa1e34e83)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# true:
0
# benchmark -- -Os artifacts/build-fb88bf9931f17d137eb50c001e1c924aa1e34e83/results_id:
1
This commit has regressed these CI configurations:
- tcwg_bmk_gnu_apm/gnu-master-aarch64-spec2k6-Os
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa…
Even more details: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa…
Reproduce builds:
<cut>
mkdir investigate-gcc-01b5038718056b024b370b74a874fbd92c5bbab3
cd investigate-gcc-01b5038718056b024b370b74a874fbd92c5bbab3
# 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_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_apm-gnu-master-aa… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 01b5038718056b024b370b74a874fbd92c5bbab3
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach fb88bf9931f17d137eb50c001e1c924aa1e34e83
../artifacts/test.sh
cd ..
</cut>
Full commit (up to 1000 lines):
<cut>
commit 01b5038718056b024b370b74a874fbd92c5bbab3
Author: Aldy Hernandez <aldyh(a)redhat.com>
Date: Thu Sep 9 20:30:28 2021 +0200
Disable threading through latches until after loop optimizations.
The motivation for this patch was enabling the use of global ranges in
the path solver, but this caused certain properties of loops being
destroyed which made subsequent loop optimizations to fail.
Consequently, this patch's mail goal is to disable jump threading
involving the latch until after loop optimizations have run.
As can be seen in the test adjustments, we mostly shift the threading
from the early threaders (ethread, thread[12] to the late threaders
thread[34]). I have nuked some of the early notes in the testcases
that came as part of the jump threader rewrite. They're mostly noise
now.
Note that we could probably relax some other restrictions in
profitable_path_p when loop optimizations have completed, but it would
require more testing, and I'm hesitant to touch more things than needed
at this point. I have added a reminder to the function to keep this
in mind.
Finally, perhaps as a follow-up, we should apply the same restrictions to
the forward threader. At some point I'd like to combine the cost models.
Tested on x86-64 Linux.
p.s. There is a thorough discussion involving the limitations of jump
threading involving loops here:
https://gcc.gnu.org/pipermail/gcc/2021-September/237247.html
gcc/ChangeLog:
* tree-pass.h (PROP_loop_opts_done): New.
* gimple-range-path.cc (path_range_query::internal_range_of_expr):
Intersect with global range.
* tree-ssa-loop.c (tree_ssa_loop_done): Set PROP_loop_opts_done.
* tree-ssa-threadbackward.c
(back_threader_profitability::profitable_path_p): Disable
threading through latches until after loop optimizations have run.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Adjust for disabling of
threading through latches.
* gcc.dg/tree-ssa/ssa-dom-thread-6.c: Same.
* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Same.
Co-authored-by: Michael Matz <matz(a)suse.de>
---
gcc/gimple-range-path.cc | 3 ++
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c | 4 +--
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c | 37 ++---------------------
gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c | 17 +----------
gcc/tree-pass.h | 2 ++
gcc/tree-ssa-loop.c | 2 +-
gcc/tree-ssa-threadbackward.c | 28 +++++++++++++++--
7 files changed, 37 insertions(+), 56 deletions(-)
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index a4fa3b296ff..c616b65756f 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -127,6 +127,9 @@ path_range_query::internal_range_of_expr (irange &r, tree name, gimple *stmt)
basic_block bb = stmt ? gimple_bb (stmt) : exit_bb ();
if (stmt && range_defined_in_block (r, name, bb))
{
+ if (TREE_CODE (name) == SSA_NAME)
+ r.intersect (gimple_range_global (name));
+
set_cache (r, name);
return true;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
index e1c33e86cd7..823ada982ff 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-dom2-stats -fdisable-tree-ethread" } */
+/* { dg-options "-O2 -fdump-tree-thread3-stats -fdump-tree-dom2-stats -fdisable-tree-ethread" } */
void foo();
void bla();
@@ -26,4 +26,4 @@ void thread_latch_through_header (void)
case. And we want to thread through the header as well. These
are both caught by threading in DOM. */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */
-/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "thread1"} } */
+/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "thread3"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
index c7bf867b084..ee46759bacc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c
@@ -1,41 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread2-details" } */
+/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread3-details" } */
-/* All the threads in the thread1 dump start on a X->BB12 edge, as can
- be seen in the dump:
-
- Registering FSM jump thread: (x, 12) incoming edge; ...
- etc
- etc
-
- Before the new evrp, we were threading paths that started at the
- following edges:
-
- Registering FSM jump thread: (10, 12) incoming edge
- Registering FSM jump thread: (6, 12) incoming edge
- Registering FSM jump thread: (9, 12) incoming edge
-
- This was because the PHI at BB12 had constant values coming in from
- BB10, BB6, and BB9:
-
- # state_10 = PHI <state_11(7), 0(10), state_11(5), 1(6), state_11(8), 2(9), state_11(11)>
-
- Now with the new evrp, we get:
-
- # state_10 = PHI <0(7), 0(10), state_11(5), 1(6), 0(8), 2(9), 1(11)>
-
- Thus, we have 3 more paths that are known to be constant and can be
- threaded. Which means that by the second threading pass, we can
- only find one profitable path.
-
- For the record, all these extra constants are better paths coming
- out of switches. For example:
-
- SWITCH_BB -> BBx -> BBy -> BBz -> PHI
-
- We now know the value of the switch index at PHI. */
/* { dg-final { scan-tree-dump-times "Registering FSM jump" 6 "thread1" } } */
-/* { dg-final { scan-tree-dump-times "Registering FSM jump" 1 "thread2" } } */
+/* { dg-final { scan-tree-dump-times "Registering FSM jump" 1 "thread3" } } */
int sum0, sum1, sum2, sum3;
int foo (char *s, char **ret)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
index 5fc2145a432..ba07942f9dd 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
@@ -1,23 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */
-/* Here we have the same issue as was commented in ssa-dom-thread-6.c.
- The PHI coming into the threader has a lot more constants, so the
- threader can thread more paths.
-
-$ diff clean/a.c.105t.mergephi2 a.c.105t.mergephi2
-252c252
-< # s_50 = PHI <s_49(10), 5(14), s_51(18), s_51(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), s_51(30)>
----
-> # s_50 = PHI <s_49(10), 5(14), 4(18), 5(22), 1(26), 1(29), 1(31), s_51(5), 4(12), 1(15), 5(17), 1(19), 3(21), 1(23), 6(25), 7(28), 7(30)>
-272a273
-
- I spot checked a few and they all have the same pattern. We are
- basically tracking the switch index better through multiple
- paths. */
-
/* { dg-final { scan-tree-dump "Jumps threaded: 18" "thread1" } } */
-/* { dg-final { scan-tree-dump "Jumps threaded: 8" "thread2" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 8" "thread3" } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */
/* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 83941bc0cee..eb75eb17951 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -225,6 +225,8 @@ protected:
been optimized. */
#define PROP_gimple_lomp_dev (1 << 16) /* done omp_device_lower */
#define PROP_rtl_split_insns (1 << 17) /* RTL has insns split. */
+#define PROP_loop_opts_done (1 << 18) /* SSA loop optimizations
+ have completed. */
#define PROP_gimple \
(PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 0cc4b3bbccf..1bbf2f1fb2c 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -540,7 +540,7 @@ const pass_data pass_data_tree_loop_done =
OPTGROUP_LOOP, /* optinfo_flags */
TV_NONE, /* tv_id */
PROP_cfg, /* properties_required */
- 0, /* properties_provided */
+ PROP_loop_opts_done, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_cleanup_cfg, /* todo_flags_finish */
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 449232c7715..e72992328de 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
#include "ssa.h"
#include "tree-cfgcleanup.h"
#include "tree-pretty-print.h"
+#include "cfghooks.h"
// Path registry for the backwards threader. After all paths have been
// registered with register_path(), thread_through_all_blocks() is called
@@ -564,7 +565,10 @@ back_threader_registry::thread_through_all_blocks (bool may_peel_loop_headers)
TAKEN_EDGE, otherwise it is NULL.
CREATES_IRREDUCIBLE_LOOP, if non-null is set to TRUE if threading this path
- would create an irreducible loop. */
+ would create an irreducible loop.
+
+ ?? It seems we should be able to loosen some of the restrictions in
+ this function after loop optimizations have run. */
bool
back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
@@ -725,7 +729,11 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
the last entry in the array when determining if we thread
through the loop latch. */
if (loop->latch == bb)
- threaded_through_latch = true;
+ {
+ threaded_through_latch = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " (latch)");
+ }
}
gimple *stmt = get_gimple_control_stmt (m_path[0]);
@@ -845,6 +853,22 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
"a multiway branch.\n");
return false;
}
+
+ /* Threading through an empty latch would cause code to be added to
+ the latch. This could alter the loop form sufficiently to cause
+ loop optimizations to fail. Disable these threads until after
+ loop optimizations have run. */
+ if ((threaded_through_latch
+ || (taken_edge && taken_edge->dest == loop->latch))
+ && !(cfun->curr_properties & PROP_loop_opts_done)
+ && empty_block_p (loop->latch))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " FAIL: FSM Thread through latch before loop opts would create non-empty latch\n");
+ return false;
+
+ }
return true;
}
</cut>
Progress
* UM-2 [QEMU upstream maintainership]
+ Respin of a linux-user cleanup patchset
+ Code review, as usual
* QEMU-406 [QEMU support for MVE (M-profile Vector Extension; Helium)]
+ Working on version 2 of the "optimized code gen for MVE" patchset;
this now covers all the insns that have an easy optimized version.
-- PMM
Successfully identified regression in *linux* in CI configuration tcwg_kernel/gnu-master-arm-mainline-allmodconfig. So far, this commit has regressed CI configurations:
- tcwg_kernel/gnu-master-arm-mainline-allmodconfig
Culprit:
<cut>
commit 3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151
Author: Linus Torvalds <torvalds(a)linux-foundation.org>
Date: Sun Sep 5 11:24:05 2021 -0700
Enable '-Werror' by default for all kernel builds
... but make it a config option so that broken environments can disable
it when required.
We really should always have a clean build, and will disable specific
over-eager warnings as required, if we can't fix them. But while I
fairly religiously enforce that in my own tree, it doesn't get enforced
by various build robots that don't necessarily report warnings.
So this just makes '-Werror' a default compiler flag, but allows people
to disable it for their configuration if they have some particular
issues.
Occasionally, new compiler versions end up enabling new warnings, and it
can take a while before we have them fixed (or the warnings disabled if
that is what it takes), so the config option allows for that situation.
Hopefully this will mean that I get fewer pull requests that have new
warnings that were not noticed by various automation we have in place.
Knock wood.
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
</cut>
Results regressed to (for first_bad == 3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
21769
# First few build errors in logs:
from (for last_good == fd47ff55c9c31101fcc06d20cb381da3d4089bd5)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1:
-5
# build_abe qemu:
-2
# linux_n_obj:
29880
# linux build successful:
all
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al…
Build top page/logs: https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-linux-3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151
cd investigate-linux-3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151
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_kernel-gnu-bisect-gnu-master-arm-mainline-al… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al… --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 /linux/ ./ ./bisect/baseline/
cd linux
# Reproduce first_bad build
git checkout --detach 3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach fd47ff55c9c31101fcc06d20cb381da3d4089bd5
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al…
Build log: https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-mainline-al…
Full commit (up to 1000 lines):
<cut>
commit 3fe617ccafd6f5bb33c2391d6f4eeb41c1fd0151
Author: Linus Torvalds <torvalds(a)linux-foundation.org>
Date: Sun Sep 5 11:24:05 2021 -0700
Enable '-Werror' by default for all kernel builds
... but make it a config option so that broken environments can disable
it when required.
We really should always have a clean build, and will disable specific
over-eager warnings as required, if we can't fix them. But while I
fairly religiously enforce that in my own tree, it doesn't get enforced
by various build robots that don't necessarily report warnings.
So this just makes '-Werror' a default compiler flag, but allows people
to disable it for their configuration if they have some particular
issues.
Occasionally, new compiler versions end up enabling new warnings, and it
can take a while before we have them fixed (or the warnings disabled if
that is what it takes), so the config option allows for that situation.
Hopefully this will mean that I get fewer pull requests that have new
warnings that were not noticed by various automation we have in place.
Knock wood.
Signed-off-by: Linus Torvalds <torvalds(a)linux-foundation.org>
---
Makefile | 3 +++
init/Kconfig | 14 ++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/Makefile b/Makefile
index 6bc1c5b17a62..d45fc2edf186 100644
--- a/Makefile
+++ b/Makefile
@@ -785,6 +785,9 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong
KBUILD_CFLAGS += $(stackp-flags-y)
+KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror
+KBUILD_CFLAGS += $(KBUILD_CFLAGS-y)
+
ifdef CONFIG_CC_IS_CLANG
KBUILD_CPPFLAGS += -Qunused-arguments
# The kernel builds with '-std=gnu89' so use of GNU extensions is acceptable.
diff --git a/init/Kconfig b/init/Kconfig
index e708180e9a59..8cb97f141b70 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -137,6 +137,20 @@ config COMPILE_TEST
here. If you are a user/distributor, say N here to exclude useless
drivers to be distributed.
+config WERROR
+ bool "Compile the kernel with warnings as errors"
+ default y
+ help
+ A kernel build should not cause any compiler warnings, and this
+ enables the '-Werror' flag to enforce that rule by default.
+
+ However, if you have a new (or very old) compiler with odd and
+ unusual warnings, or you have some architecture with problems,
+ you may need to disable this config option in order to
+ successfully build the kernel.
+
+ If in doubt, say Y.
+
config UAPI_HEADER_TEST
bool "Compile test UAPI headers"
depends on HEADERS_INSTALL && CC_CAN_LINK
</cut>
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3_LTO. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3_LTO
Culprit:
<cut>
commit 19dc02e99f802922a3af69e802465bee0723b57a
Author: Nikita Popov <nikita.ppv(a)gmail.com>
Date: Sun Aug 22 18:15:55 2021 +0200
[MergeICmps] Allow sinking past non-load/store
This is a followup to D106591. MergeICmps currently only allows
sinking the loads past either instructions that don't write to
memory at all, or simple loads/stores that don't modify the memory
the loads access.
The "simple loads/stores" part of this check doesn't seem necessary
to me -- AA isModRef() already accurately models any operation
that may clobber the memory. For example, in the adjusted test case
the transform is still fine if the call to @foo() isn't readonly,
but inaccessiblememonly -- in both cases, the call cannot modify
the loaded memory.
Differential Revision: https://reviews.llvm.org/D108517
</cut>
Results regressed to (for first_bad == 19dc02e99f802922a3af69e802465bee0723b57a)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O3_LTO artifacts/build-19dc02e99f802922a3af69e802465bee0723b57a/results_id:
1
# 464.h264ref,h264ref_base.default regressed by 105
from (for last_good == da12d88b1c5fc42b49b92fcf94917ca489dd677f)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O3_LTO artifacts/build-da12d88b1c5fc42b49b92fcf94917ca489dd677f/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of last_good: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3_LTO/4822
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of first_bad: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3_LTO/4807
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-llvm-19dc02e99f802922a3af69e802465bee0723b57a
cd investigate-llvm-19dc02e99f802922a3af69e802465bee0723b57a
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_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 /llvm/ ./ ./bisect/baseline/
cd llvm
# Reproduce first_bad build
git checkout --detach 19dc02e99f802922a3af69e802465bee0723b57a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach da12d88b1c5fc42b49b92fcf94917ca489dd677f
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Full commit (up to 1000 lines):
<cut>
commit 19dc02e99f802922a3af69e802465bee0723b57a
Author: Nikita Popov <nikita.ppv(a)gmail.com>
Date: Sun Aug 22 18:15:55 2021 +0200
[MergeICmps] Allow sinking past non-load/store
This is a followup to D106591. MergeICmps currently only allows
sinking the loads past either instructions that don't write to
memory at all, or simple loads/stores that don't modify the memory
the loads access.
The "simple loads/stores" part of this check doesn't seem necessary
to me -- AA isModRef() already accurately models any operation
that may clobber the memory. For example, in the adjusted test case
the transform is still fine if the call to @foo() isn't readonly,
but inaccessiblememonly -- in both cases, the call cannot modify
the loaded memory.
Differential Revision: https://reviews.llvm.org/D108517
---
llvm/lib/Transforms/Scalar/MergeICmps.cpp | 14 +-------------
.../Transforms/MergeICmps/X86/split-block-does-work.ll | 2 +-
2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
index f13f24ad2027..34465c76dd3d 100644
--- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp
+++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp
@@ -66,15 +66,6 @@ namespace {
#define DEBUG_TYPE "mergeicmps"
-// Returns true if the instruction is a simple load or a simple store
-static bool isSimpleLoadOrStore(const Instruction *I) {
- if (const LoadInst *LI = dyn_cast<LoadInst>(I))
- return LI->isSimple();
- if (const StoreInst *SI = dyn_cast<StoreInst>(I))
- return SI->isSimple();
- return false;
-}
-
// A BCE atom "Binary Compare Expression Atom" represents an integer load
// that is a constant offset from a base value, e.g. `a` or `o.c` in the example
// at the top.
@@ -244,10 +235,7 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst,
// If this instruction may clobber the loads and is in middle of the BCE cmp
// block instructions, then bail for now.
if (Inst->mayWriteToMemory()) {
- // Bail if this is not a simple load or store
- if (!isSimpleLoadOrStore(Inst))
- return false;
- // Disallow stores that might alias the BCE operands
+ // Disallow instructions that might modify the BCE operands
MemoryLocation LLoc = MemoryLocation::get(Cmp.Lhs.LoadI);
MemoryLocation RLoc = MemoryLocation::get(Cmp.Rhs.LoadI);
if (isModSet(AA.getModRefInfo(Inst, LLoc)) ||
diff --git a/llvm/test/Transforms/MergeICmps/X86/split-block-does-work.ll b/llvm/test/Transforms/MergeICmps/X86/split-block-does-work.ll
index 0b9663f44980..1e341b92918d 100644
--- a/llvm/test/Transforms/MergeICmps/X86/split-block-does-work.ll
+++ b/llvm/test/Transforms/MergeICmps/X86/split-block-does-work.ll
@@ -3,7 +3,7 @@
%S = type { i32, i32, i32, i32 }
-declare void @foo(...) readonly
+declare void @foo(...) inaccessiblememonly
; We can split %entry and create a memcmp(16 bytes).
define zeroext i1 @opeq1(
</cut>
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O2. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O2
Culprit:
<cut>
commit d39d3a327b1303012370e47d991459ffbfce45ef
Author: Peyton, Jonathan L <jonathan.l.peyton(a)intel.com>
Date: Fri Aug 20 16:06:13 2021 -0500
[OpenMP][test] fix omp_get_wtime.c test to be more accommodating
The omp_get_wtime.c test fails intermittently if the recorded times are
off by too much which can happen when many tests are run in parallel.
Instead of failing if one timing is a little off, take average of 100
timings minus the 10 worst.
Differential Revision: https://reviews.llvm.org/D108488
</cut>
Results regressed to (for first_bad == d39d3a327b1303012370e47d991459ffbfce45ef)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O2 artifacts/build-d39d3a327b1303012370e47d991459ffbfce45ef/results_id:
1
# 447.dealII,dealII_base.default regressed by 105
from (for last_good == f77174d4b8cfba3c0a53c78e53edbbaf57e37fc5)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O2 artifacts/build-f77174d4b8cfba3c0a53c78e53edbbaf57e37fc5/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of last_good: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O2/4734
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of first_bad: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O2/4757
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-llvm-d39d3a327b1303012370e47d991459ffbfce45ef
cd investigate-llvm-d39d3a327b1303012370e47d991459ffbfce45ef
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_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 /llvm/ ./ ./bisect/baseline/
cd llvm
# Reproduce first_bad build
git checkout --detach d39d3a327b1303012370e47d991459ffbfce45ef
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach f77174d4b8cfba3c0a53c78e53edbbaf57e37fc5
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Full commit (up to 1000 lines):
<cut>
commit d39d3a327b1303012370e47d991459ffbfce45ef
Author: Peyton, Jonathan L <jonathan.l.peyton(a)intel.com>
Date: Fri Aug 20 16:06:13 2021 -0500
[OpenMP][test] fix omp_get_wtime.c test to be more accommodating
The omp_get_wtime.c test fails intermittently if the recorded times are
off by too much which can happen when many tests are run in parallel.
Instead of failing if one timing is a little off, take average of 100
timings minus the 10 worst.
Differential Revision: https://reviews.llvm.org/D108488
---
openmp/runtime/test/api/omp_get_wtime.c | 75 ++++++++++++++++++++++++++-------
1 file changed, 59 insertions(+), 16 deletions(-)
diff --git a/openmp/runtime/test/api/omp_get_wtime.c b/openmp/runtime/test/api/omp_get_wtime.c
index e2bb211e0ce4..a862e07fc5a2 100644
--- a/openmp/runtime/test/api/omp_get_wtime.c
+++ b/openmp/runtime/test/api/omp_get_wtime.c
@@ -4,30 +4,73 @@
#include "omp_testsuite.h"
#include "omp_my_sleep.h"
-int test_omp_get_wtime()
-{
+#define NTIMES 100
+
+// This is the error % threshold. Be generous with the error threshold since
+// this test may be run in parallel with many other tests it may throw off the
+// sleep timing.
+#define THRESHOLD 33.0
+
+double test_omp_get_wtime(double desired_wait_time) {
double start;
double end;
- double measured_time;
- double wait_time = 0.2;
start = 0;
end = 0;
start = omp_get_wtime();
- my_sleep (wait_time);
+ my_sleep(desired_wait_time);
end = omp_get_wtime();
- measured_time = end-start;
- return ((measured_time > 0.97 * wait_time) && (measured_time < 1.03 * wait_time)) ;
+ return end - start;
}
-int main()
-{
- int i;
- int num_failed=0;
+int compare_times(const void *lhs, const void *rhs) {
+ const double *a = (const double *)lhs;
+ const double *b = (const double *)rhs;
+ return *a - *b;
+}
+
+int main() {
+ int i, final_count;
+ double percent_off;
+ double *begin, *end, *ptr;
+ double wait_time = 0.01;
+ double average = 0.0;
+ double n = 0.0;
+ double *times = (double *)malloc(sizeof(double) * NTIMES);
+
+ // Get each timing
+ for (i = 0; i < NTIMES; i++) {
+ times[i] = test_omp_get_wtime(wait_time);
+ }
+
+ // Remove approx the "worst" tenth of the timings
+ qsort(times, NTIMES, sizeof(double), compare_times);
+ begin = times;
+ end = times + NTIMES;
+ for (i = 0; i < NTIMES / 10; ++i) {
+ if (i % 2 == 0)
+ begin++;
+ else
+ end--;
+ }
+
+ // Get the average of the remaining timings
+ for (ptr = begin, final_count = 0; ptr != end; ++ptr, ++final_count)
+ average += times[i];
+ average /= (double)final_count;
+ free(times);
+
+ // Calculate the percent off of desired wait time
+ percent_off = (average - wait_time) / wait_time * 100.0;
+ // Should always be positive, but just in case
+ if (percent_off < 0)
+ percent_off = -percent_off;
- for(i = 0; i < REPETITIONS; i++) {
- if(!test_omp_get_wtime()) {
- num_failed++;
- }
+ if (percent_off > (double)THRESHOLD) {
+ fprintf(stderr, "error: average of %d runs (%lf) is of by %lf%%\n", NTIMES,
+ average, percent_off);
+ return EXIT_FAILURE;
}
- return num_failed;
+ printf("pass: average of %d runs (%lf) is only off by %lf%%\n", NTIMES,
+ average, percent_off);
+ return EXIT_SUCCESS;
}
</cut>
Successfully identified regression in *linux* in CI configuration tcwg_kernel/llvm-master-aarch64-mainline-allyesconfig. So far, this commit has regressed CI configurations:
- tcwg_kernel/llvm-master-aarch64-mainline-allyesconfig
Culprit:
<cut>
commit 342f43af70dbc74f8629381998f92c060e1763a2
Author: Maurizio Lombardi <mlombard(a)redhat.com>
Date: Thu Jul 29 15:52:50 2021 +0200
iscsi_ibft: fix crash due to KASLR physical memory remapping
Starting with commit a799c2bd29d1
("x86/setup: Consolidate early memory reservations")
memory reservations have been moved earlier during the boot process,
before the execution of the Kernel Address Space Layout Randomization code.
setup_arch() calls the iscsi_ibft's find_ibft_region() function
to find and reserve the memory dedicated to the iBFT and this function
also saves a virtual pointer to the iBFT table for later use.
The problem is that if KALSR is active, the physical memory gets
remapped somewhere else in the virtual address space and the pointer is
no longer valid, this will cause a kernel panic when the iscsi driver tries
to dereference it.
iBFT detected.
BUG: unable to handle page fault for address: ffff888000099fd8
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: 0000 [#1] SMP PTI
..snip..
Call Trace:
? ibft_create_kobject+0x1d2/0x1d2 [iscsi_ibft]
do_one_initcall+0x44/0x1d0
? kmem_cache_alloc_trace+0x119/0x220
do_init_module+0x5c/0x270
__do_sys_init_module+0x12e/0x1b0
do_syscall_64+0x40/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xae
Fix this bug by saving the address of the physical location
of the ibft; later the driver will use isa_bus_to_virt() to get
the correct virtual address.
N.B. On each reboot KASLR randomizes the virtual addresses so
assuming phys_to_virt before KASLR does its deed is incorrect.
Simplify the code by renaming find_ibft_region()
to reserve_ibft_region() and remove all the wrappers.
Signed-off-by: Maurizio Lombardi <mlombard(a)redhat.com>
Reviewed-by: Mike Rapoport <rppt(a)linux.ibm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad(a)kernel.org>
</cut>
Results regressed to (for first_bad == 342f43af70dbc74f8629381998f92c060e1763a2)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
19722
# First few build errors in logs:
from (for last_good == 62fb9874f5da54fdb243003b386128037319b219)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_llvm:
-5
# build_abe qemu:
-2
# linux_n_obj:
19795
# linux build successful:
all
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Build top page/logs: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-linux-342f43af70dbc74f8629381998f92c060e1763a2
cd investigate-linux-342f43af70dbc74f8629381998f92c060e1763a2
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_kernel-llvm-bisect-llvm-master-aarch64-mainl… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl… --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 /linux/ ./ ./bisect/baseline/
cd linux
# Reproduce first_bad build
git checkout --detach 342f43af70dbc74f8629381998f92c060e1763a2
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 62fb9874f5da54fdb243003b386128037319b219
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Build log: https://ci.linaro.org/job/tcwg_kernel-llvm-bisect-llvm-master-aarch64-mainl…
Full commit (up to 1000 lines):
<cut>
commit 342f43af70dbc74f8629381998f92c060e1763a2
Author: Maurizio Lombardi <mlombard(a)redhat.com>
Date: Thu Jul 29 15:52:50 2021 +0200
iscsi_ibft: fix crash due to KASLR physical memory remapping
Starting with commit a799c2bd29d1
("x86/setup: Consolidate early memory reservations")
memory reservations have been moved earlier during the boot process,
before the execution of the Kernel Address Space Layout Randomization code.
setup_arch() calls the iscsi_ibft's find_ibft_region() function
to find and reserve the memory dedicated to the iBFT and this function
also saves a virtual pointer to the iBFT table for later use.
The problem is that if KALSR is active, the physical memory gets
remapped somewhere else in the virtual address space and the pointer is
no longer valid, this will cause a kernel panic when the iscsi driver tries
to dereference it.
iBFT detected.
BUG: unable to handle page fault for address: ffff888000099fd8
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: 0000 [#1] SMP PTI
..snip..
Call Trace:
? ibft_create_kobject+0x1d2/0x1d2 [iscsi_ibft]
do_one_initcall+0x44/0x1d0
? kmem_cache_alloc_trace+0x119/0x220
do_init_module+0x5c/0x270
__do_sys_init_module+0x12e/0x1b0
do_syscall_64+0x40/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xae
Fix this bug by saving the address of the physical location
of the ibft; later the driver will use isa_bus_to_virt() to get
the correct virtual address.
N.B. On each reboot KASLR randomizes the virtual addresses so
assuming phys_to_virt before KASLR does its deed is incorrect.
Simplify the code by renaming find_ibft_region()
to reserve_ibft_region() and remove all the wrappers.
Signed-off-by: Maurizio Lombardi <mlombard(a)redhat.com>
Reviewed-by: Mike Rapoport <rppt(a)linux.ibm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad(a)kernel.org>
---
arch/x86/kernel/setup.c | 10 --------
drivers/firmware/iscsi_ibft.c | 10 +++++---
drivers/firmware/iscsi_ibft_find.c | 48 ++++++++++++++------------------------
include/linux/iscsi_ibft.h | 18 ++++++--------
4 files changed, 32 insertions(+), 54 deletions(-)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1e720626069a..b6a62af06a9f 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -571,16 +571,6 @@ void __init reserve_standard_io_resources(void)
}
-static __init void reserve_ibft_region(void)
-{
- unsigned long addr, size = 0;
-
- addr = find_ibft_region(&size);
-
- if (size)
- memblock_reserve(addr, size);
-}
-
static bool __init snb_gfx_workaround_needed(void)
{
#ifdef CONFIG_PCI
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index 7127a04bca19..612a59e213df 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -84,8 +84,10 @@ MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information");
MODULE_LICENSE("GPL");
MODULE_VERSION(IBFT_ISCSI_VERSION);
+static struct acpi_table_ibft *ibft_addr;
+
#ifndef CONFIG_ISCSI_IBFT_FIND
-struct acpi_table_ibft *ibft_addr;
+phys_addr_t ibft_phys_addr;
#endif
struct ibft_hdr {
@@ -858,11 +860,13 @@ static int __init ibft_init(void)
int rc = 0;
/*
- As on UEFI systems the setup_arch()/find_ibft_region()
+ As on UEFI systems the setup_arch()/reserve_ibft_region()
is called before ACPI tables are parsed and it only does
legacy finding.
*/
- if (!ibft_addr)
+ if (ibft_phys_addr)
+ ibft_addr = isa_bus_to_virt(ibft_phys_addr);
+ else
acpi_find_ibft_region();
if (ibft_addr) {
diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
index 64bb94523281..a0594590847d 100644
--- a/drivers/firmware/iscsi_ibft_find.c
+++ b/drivers/firmware/iscsi_ibft_find.c
@@ -31,8 +31,8 @@
/*
* Physical location of iSCSI Boot Format Table.
*/
-struct acpi_table_ibft *ibft_addr;
-EXPORT_SYMBOL_GPL(ibft_addr);
+phys_addr_t ibft_phys_addr;
+EXPORT_SYMBOL_GPL(ibft_phys_addr);
static const struct {
char *sign;
@@ -47,13 +47,24 @@ static const struct {
#define VGA_MEM 0xA0000 /* VGA buffer */
#define VGA_SIZE 0x20000 /* 128kB */
-static int __init find_ibft_in_mem(void)
+/*
+ * Routine used to find and reserve the iSCSI Boot Format Table
+ */
+void __init reserve_ibft_region(void)
{
unsigned long pos;
unsigned int len = 0;
void *virt;
int i;
+ ibft_phys_addr = 0;
+
+ /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
+ * only use ACPI for this
+ */
+ if (efi_enabled(EFI_BOOT))
+ return;
+
for (pos = IBFT_START; pos < IBFT_END; pos += 16) {
/* The table can't be inside the VGA BIOS reserved space,
* so skip that area */
@@ -70,35 +81,12 @@ static int __init find_ibft_in_mem(void)
/* if the length of the table extends past 1M,
* the table cannot be valid. */
if (pos + len <= (IBFT_END-1)) {
- ibft_addr = (struct acpi_table_ibft *)virt;
- pr_info("iBFT found at 0x%lx.\n", pos);
- goto done;
+ ibft_phys_addr = pos;
+ memblock_reserve(ibft_phys_addr, PAGE_ALIGN(len));
+ pr_info("iBFT found at 0x%lx.\n", ibft_phys_addr);
+ return;
}
}
}
}
-done:
- return len;
-}
-/*
- * Routine used to find the iSCSI Boot Format Table. The logical
- * kernel address is set in the ibft_addr global variable.
- */
-unsigned long __init find_ibft_region(unsigned long *sizep)
-{
- ibft_addr = NULL;
-
- /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
- * only use ACPI for this */
-
- if (!efi_enabled(EFI_BOOT))
- find_ibft_in_mem();
-
- if (ibft_addr) {
- *sizep = PAGE_ALIGN(ibft_addr->header.length);
- return (u64)virt_to_phys(ibft_addr);
- }
-
- *sizep = 0;
- return 0;
}
diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h
index b7b45ca82bea..790e7fcfc1a6 100644
--- a/include/linux/iscsi_ibft.h
+++ b/include/linux/iscsi_ibft.h
@@ -13,26 +13,22 @@
#ifndef ISCSI_IBFT_H
#define ISCSI_IBFT_H
-#include <linux/acpi.h>
+#include <linux/types.h>
/*
- * Logical location of iSCSI Boot Format Table.
- * If the value is NULL there is no iBFT on the machine.
+ * Physical location of iSCSI Boot Format Table.
+ * If the value is 0 there is no iBFT on the machine.
*/
-extern struct acpi_table_ibft *ibft_addr;
+extern phys_addr_t ibft_phys_addr;
/*
* Routine used to find and reserve the iSCSI Boot Format Table. The
- * mapped address is set in the ibft_addr variable.
+ * physical address is set in the ibft_phys_addr variable.
*/
#ifdef CONFIG_ISCSI_IBFT_FIND
-unsigned long find_ibft_region(unsigned long *sizep);
+void reserve_ibft_region(void);
#else
-static inline unsigned long find_ibft_region(unsigned long *sizep)
-{
- *sizep = 0;
- return 0;
-}
+static inline void reserve_ibft_region(void) {}
#endif
#endif /* ISCSI_IBFT_H */
</cut>
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O3
Culprit:
<cut>
commit 4cd8dd3fe05e099792e1494dedd074eb5ba289b6
Author: Amy Kwan <amy.kwan1(a)ibm.com>
Date: Sun Aug 22 13:46:52 2021 -0500
[scudo][standalone] Link tests against libatomic if libatomic exists
It is possible that libatomic does not exist on some systems. This patch updates
the scudo standalone tests to link against libatomic if the library exists.
This is an update to the original patch: https://reviews.llvm.org/D64134 and
aims to resolve https://bugs.llvm.org/show_bug.cgi?id=51431.
Differential Revision: https://reviews.llvm.org/D108503
</cut>
Results regressed to (for first_bad == 4cd8dd3fe05e099792e1494dedd074eb5ba289b6)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O3 artifacts/build-4cd8dd3fe05e099792e1494dedd074eb5ba289b6/results_id:
1
# 447.dealII,dealII_base.default regressed by 103
from (for last_good == d8d84c9df82fc114f2b22a533a8183065ca1a2e0)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -O3 artifacts/build-d8d84c9df82fc114f2b22a533a8183065ca1a2e0/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of last_good: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3/4515
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Results ID of first_bad: tx1_64/tcwg_bmk_llvm_tx1/bisect-llvm-master-aarch64-spec2k6-O3/4510
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-llvm-4cd8dd3fe05e099792e1494dedd074eb5ba289b6
cd investigate-llvm-4cd8dd3fe05e099792e1494dedd074eb5ba289b6
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_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 /llvm/ ./ ./bisect/baseline/
cd llvm
# Reproduce first_bad build
git checkout --detach 4cd8dd3fe05e099792e1494dedd074eb5ba289b6
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach d8d84c9df82fc114f2b22a533a8183065ca1a2e0
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tx1-llvm-master-…
Full commit (up to 1000 lines):
<cut>
commit 4cd8dd3fe05e099792e1494dedd074eb5ba289b6
Author: Amy Kwan <amy.kwan1(a)ibm.com>
Date: Sun Aug 22 13:46:52 2021 -0500
[scudo][standalone] Link tests against libatomic if libatomic exists
It is possible that libatomic does not exist on some systems. This patch updates
the scudo standalone tests to link against libatomic if the library exists.
This is an update to the original patch: https://reviews.llvm.org/D64134 and
aims to resolve https://bugs.llvm.org/show_bug.cgi?id=51431.
Differential Revision: https://reviews.llvm.org/D108503
---
compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
index f4186eba1688..eaa47a04a179 100644
--- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
@@ -39,7 +39,10 @@ foreach(lib ${SANITIZER_TEST_CXX_LIBRARIES})
endforeach()
list(APPEND LINK_FLAGS -pthread)
# Linking against libatomic is required with some compilers
-list(APPEND LINK_FLAGS -latomic)
+check_library_exists(atomic __atomic_load_8 "" COMPILER_RT_HAS_LIBATOMIC)
+if (COMPILER_RT_HAS_LIBATOMIC)
+ list(APPEND LINK_FLAGS -latomic)
+endif()
set(SCUDO_TEST_HEADERS
scudo_unit_test.h
</cut>
Progress (short week, 2 days)
* UM-2 [QEMU upstream maintainership]
+ Lots of code review and getting things upstream after trunk reopened
+ Wrote up a first draft of how to handle merging pullreqs, so that
other people can share this job with me
+ Sent a patchset that allows board models to mark some buses as
not suitable for plugging in user-created devices -- this avoids
problems with i2c devices appearing on buses that are supposed to
be for on-board devices only in the MPS2/MPS3 machines
* QEMU-406 [QEMU support for MVE (M-profile Vector Extension; Helium)]
+ MVE is now enabled upstream. (There are still some loose ends to
do under this JIRA task, though.)
+ Sent a patchset that makes some of the easier codegen optimizations
for the no-predication case. (Code review spotted an issue which
might be painful to sort out -- we'll see next week...)
-- PMM
Successfully identified regression in *binutils* in CI configuration tcwg_bmk_llvm_apm/llvm-master-arm-spec2k6-Oz. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_apm/llvm-master-arm-spec2k6-Oz
Culprit:
<cut>
commit 590d3faada8a12bf0937bbf68413956dc6a339a9
Author: Tom de Vries <tdevries(a)suse.de>
Date: Mon Aug 30 10:30:26 2021 +0200
[gdb/testsuite] Improve argument syntax of proc arange
The current syntax of proc arange is:
...
proc arange { arange_start arange_length {comment ""} {seg_sel ""} } {
...
and a typical call looks like:
...
arange $start $len
...
This style is somewhat annoying because if you want to specify the last
parameter, you need to give the default values of all the other optional ones
before as well:
...
arange $start $len "" $seg_sel
...
Update the syntax to:
...
proc arange { options arange_start arange_length } {
parse_options {
{ comment "" }
{ seg_sel "" }
}
...
such that a typical call looks like:
...
arange {} $start $len
...
and a call using seg_sel looks like:
...
arange {
seg_sel $seg_sel
} $start $len
...
Also update proc aranges, which already has an options argument, to use the
new proc parse_options.
Tested on x86_64-linux.
Co-Authored-By: Simon Marchi <simon.marchi(a)polymtl.ca>
</cut>
Results regressed to (for first_bad == 590d3faada8a12bf0937bbf68413956dc6a339a9)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -Oz_mthumb artifacts/build-590d3faada8a12bf0937bbf68413956dc6a339a9/results_id:
1
# 447.dealII,[.] contract<3> regressed by 200
from (for last_good == cb03dd22b36b7bd21a81137005ec42dab8355b62)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=thumb --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=thumb --set gcc_override_configure=--disable-libsanitizer:
-5
# build_llvm true:
-3
# true:
0
# benchmark -- -Oz_mthumb artifacts/build-cb03dd22b36b7bd21a81137005ec42dab8355b62/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-…
Results ID of last_good: apm_32/tcwg_bmk_llvm_apm/bisect-llvm-master-arm-spec2k6-Oz/4418
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-…
Results ID of first_bad: apm_32/tcwg_bmk_llvm_apm/bisect-llvm-master-arm-spec2k6-Oz/4431
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-binutils-590d3faada8a12bf0937bbf68413956dc6a339a9
cd investigate-binutils-590d3faada8a12bf0937bbf68413956dc6a339a9
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_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-… --fail
chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites)
./jenkins-scripts/tcwg_bmk-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 /binutils/ ./ ./bisect/baseline/
cd binutils
# Reproduce first_bad build
git checkout --detach 590d3faada8a12bf0937bbf68413956dc6a339a9
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach cb03dd22b36b7bd21a81137005ec42dab8355b62
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_apm-llvm-master-…
Full commit (up to 1000 lines):
<cut>
commit 590d3faada8a12bf0937bbf68413956dc6a339a9
Author: Tom de Vries <tdevries(a)suse.de>
Date: Mon Aug 30 10:30:26 2021 +0200
[gdb/testsuite] Improve argument syntax of proc arange
The current syntax of proc arange is:
...
proc arange { arange_start arange_length {comment ""} {seg_sel ""} } {
...
and a typical call looks like:
...
arange $start $len
...
This style is somewhat annoying because if you want to specify the last
parameter, you need to give the default values of all the other optional ones
before as well:
...
arange $start $len "" $seg_sel
...
Update the syntax to:
...
proc arange { options arange_start arange_length } {
parse_options {
{ comment "" }
{ seg_sel "" }
}
...
such that a typical call looks like:
...
arange {} $start $len
...
and a call using seg_sel looks like:
...
arange {
seg_sel $seg_sel
} $start $len
...
Also update proc aranges, which already has an options argument, to use the
new proc parse_options.
Tested on x86_64-linux.
Co-Authored-By: Simon Marchi <simon.marchi(a)polymtl.ca>
---
gdb/testsuite/gdb.dlang/watch-loc.exp | 2 +-
gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp | 6 +-
.../gdb.dwarf2/frame-inlined-in-outer-frame.exp | 2 +-
.../template-specification-full-name.exp | 2 +-
gdb/testsuite/gdb.testsuite/parse_options_args.exp | 59 ++++++++++++
gdb/testsuite/lib/dwarf.exp | 31 +++---
gdb/testsuite/lib/gdb.exp | 104 ++++++++++++++-------
7 files changed, 150 insertions(+), 56 deletions(-)
diff --git a/gdb/testsuite/gdb.dlang/watch-loc.exp b/gdb/testsuite/gdb.dlang/watch-loc.exp
index 6e8b26e3109..e13400ed479 100644
--- a/gdb/testsuite/gdb.dlang/watch-loc.exp
+++ b/gdb/testsuite/gdb.dlang/watch-loc.exp
@@ -68,7 +68,7 @@ Dwarf::assemble $asm_file {
}
aranges {} cu_start {
- arange $dmain_start $dmain_length
+ arange {} $dmain_start $dmain_length
}
}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
index e65b4c8610a..d55b7fd150e 100644
--- a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
@@ -125,9 +125,9 @@ Dwarf::assemble $asm_file {
}
aranges {} cu_label {
- arange [lindex $main_func 0] [lindex $main_func 1]
- arange [lindex $frame2_func 0] [lindex $frame2_func 1]
- arange [lindex $frame3_func 0] [lindex $frame3_func 1]
+ arange {} [lindex $main_func 0] [lindex $main_func 1]
+ arange {} [lindex $frame2_func 0] [lindex $frame2_func 1]
+ arange {} [lindex $frame3_func 0] [lindex $frame3_func 1]
}
}
diff --git a/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp b/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
index ff12cd79f19..f95558dffef 100644
--- a/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
+++ b/gdb/testsuite/gdb.dwarf2/frame-inlined-in-outer-frame.exp
@@ -95,7 +95,7 @@ Dwarf::assemble $dwarf_asm {
}
aranges {} cu_label {
- arange __cu_low_pc __cu_high_pc
+ arange {} __cu_low_pc __cu_high_pc
}
}
diff --git a/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp b/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp
index 5c59777e1b6..6e736f2c8ef 100644
--- a/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp
+++ b/gdb/testsuite/gdb.dwarf2/template-specification-full-name.exp
@@ -69,7 +69,7 @@ Dwarf::assemble $asm_file {
}
aranges {} cu_start {
- arange "$main_start" "$main_length"
+ arange {} "$main_start" "$main_length"
}
}
diff --git a/gdb/testsuite/gdb.testsuite/parse_options_args.exp b/gdb/testsuite/gdb.testsuite/parse_options_args.exp
new file mode 100644
index 00000000000..ce14fc3cd7c
--- /dev/null
+++ b/gdb/testsuite/gdb.testsuite/parse_options_args.exp
@@ -0,0 +1,59 @@
+# Copyright 2021 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Testsuite self-tests for parse_options and parse_args.
+
+with_test_prefix parse_options {
+ proc test1 { options a b } {
+ set v2 "defval2"
+ parse_options {
+ { opt1 defval1 }
+ { opt2 $v2 }
+ { opt3 }
+ { opt4 }
+ }
+
+ gdb_assert { [string equal $a "vala"] }
+ gdb_assert { [string equal $b "valb"] }
+ gdb_assert { [string equal $opt1 "val1"] }
+ gdb_assert { [string equal $opt2 "defval2"] }
+ gdb_assert { $opt3 == 1 }
+ gdb_assert { $opt4 == 0 }
+ }
+
+ set v1 "val1"
+ test1 { opt1 $v1 opt3 } "vala" "valb"
+}
+
+with_test_prefix parse_args {
+ proc test2 { args } {
+ parse_args {
+ { opt1 defval1 }
+ { opt2 defval2 }
+ { opt3 }
+ { opt4 }
+ }
+ gdb_assert { [llength $args] == 2 }
+ lassign $args a b
+ gdb_assert { [string equal $a "vala"] }
+ gdb_assert { [string equal $b "valb"] }
+ gdb_assert { [string equal $opt1 "val1"] }
+ gdb_assert { [string equal $opt2 "defval2"] }
+ gdb_assert { $opt3 == 1 }
+ gdb_assert { $opt4 == 0 }
+ }
+
+ set v1 "val1"
+ test2 -opt1 $v1 -opt3 "vala" "valb"
+}
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 120fa418201..7fb3561a443 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -2212,7 +2212,12 @@ namespace eval Dwarf {
# Emit a DWARF .debug_aranges entry.
- proc arange { arange_start arange_length {comment ""} {seg_sel ""} } {
+ proc arange { options arange_start arange_length } {
+ parse_options {
+ { comment "" }
+ { seg_sel "" }
+ }
+
if { $comment != "" } {
# Wrap
set comment " ($comment)"
@@ -2270,22 +2275,14 @@ namespace eval Dwarf {
variable _addr_size
variable _seg_size
- # Establish the defaults.
- set is_64 0
- set cu_is_64 0
- set section_version 2
- set _seg_size 0
-
# Handle options.
- foreach { name value } $options {
- switch -exact -- $name {
- is_64 { set is_64 $value }
- cu_is_64 { set cu_is_64 $value }
- section_version {set section_version $value }
- seg_size { set _seg_size $value }
- default { error "unknown option $name" }
- }
+ parse_options {
+ { is_64 0 }
+ { cu_is_64 0 }
+ { section_version 2 }
+ { seg_size 0 }
}
+ set _seg_size $seg_size
if { [is_64_target] } {
set _addr_size 8
@@ -2354,9 +2351,9 @@ namespace eval Dwarf {
# Terminator tuple.
set comment "Terminator"
if { $_seg_size == 0 } {
- arange 0 0 $comment
+ arange {comment $comment} 0 0
} else {
- arange 0 0 $comment 0
+ arange {comment $comment seg_sel 0} 0 0
}
# End label.
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 093392709b4..3aea7baaab0 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -7293,8 +7293,8 @@ proc using_fission { } {
return [regexp -- "-gsplit-dwarf" $debug_flags]
}
-# Search the caller's ARGS list and set variables according to the list of
-# valid options described by ARGSET.
+# Search LISTNAME in uplevel LEVEL caller and set variables according to the
+# list of valid options with prefix PREFIX described by ARGSET.
#
# The first member of each one- or two-element list in ARGSET defines the
# name of a variable that will be added to the caller's scope.
@@ -7305,13 +7305,15 @@ proc using_fission { } {
#
# If two elements are given, the second element is the default value of
# the variable. This is then overwritten if the option exists in ARGS.
+# If EVAL, then subst is called on the value, which allows variables
+# to be used.
#
# Any parse_args elements in (the caller's) ARGS will be removed, leaving
# any optional components.
-
+#
# Example:
# proc myproc {foo args} {
-# parse_args {{bar} {baz "abc"} {qux}}
+# parse_list args 1 {{bar} {baz "abc"} {qux}} "-" false
# # ...
# }
# myproc ABC -bar -baz DEF peanut butter
@@ -7319,43 +7321,79 @@ proc using_fission { } {
# foo (=ABC), bar (=1), baz (=DEF), and qux (=0)
# args will be the list {peanut butter}
-proc parse_args { argset } {
- upvar args args
+proc parse_list { level listname argset prefix eval } {
+ upvar $level $listname args
foreach argument $argset {
- if {[llength $argument] == 1} {
- # No default specified, so we assume that we should set
- # the value to 1 if the arg is present and 0 if it's not.
- # It is assumed that no value is given with the argument.
- set result [lsearch -exact $args "-$argument"]
- if {$result != -1} then {
- uplevel 1 [list set $argument 1]
- set args [lreplace $args $result $result]
- } else {
- uplevel 1 [list set $argument 0]
- }
- } elseif {[llength $argument] == 2} {
- # There are two items in the argument. The second is a
- # default value to use if the item is not present.
- # Otherwise, the variable is set to whatever is provided
- # after the item in the args.
- set arg [lindex $argument 0]
- set result [lsearch -exact $args "-[lindex $arg 0]"]
- if {$result != -1} then {
- uplevel 1 [list set $arg [lindex $args [expr $result+1]]]
- set args [lreplace $args $result [expr $result+1]]
- } else {
- uplevel 1 [list set $arg [lindex $argument 1]]
- }
- } else {
- error "Badly formatted argument \"$argument\" in argument set"
- }
+ if {[llength $argument] == 1} {
+ # Normalize argument, strip leading/trailing whitespace.
+ # Allows us to treat {foo} and { foo } the same.
+ set argument [string trim $argument]
+
+ # No default specified, so we assume that we should set
+ # the value to 1 if the arg is present and 0 if it's not.
+ # It is assumed that no value is given with the argument.
+ set pattern "$prefix$argument"
+ set result [lsearch -exact $args $pattern]
+
+ if {$result != -1} then {
+ set value 1
+ set args [lreplace $args $result $result]
+ } else {
+ set value 0
+ }
+ uplevel $level [list set $argument $value]
+ } elseif {[llength $argument] == 2} {
+ # There are two items in the argument. The second is a
+ # default value to use if the item is not present.
+ # Otherwise, the variable is set to whatever is provided
+ # after the item in the args.
+ set arg [lindex $argument 0]
+ set pattern "$prefix[lindex $arg 0]"
+ set result [lsearch -exact $args $pattern]
+
+ if {$result != -1} then {
+ set value [lindex $args [expr $result+1]]
+ if { $eval } {
+ set value [uplevel [expr $level + 1] [list subst $value]]
+ }
+ set args [lreplace $args $result [expr $result+1]]
+ } else {
+ set value [lindex $argument 1]
+ if { $eval } {
+ set value [uplevel $level [list subst $value]]
+ }
+ }
+ uplevel $level [list set $arg $value]
+ } else {
+ error "Badly formatted argument \"$argument\" in argument set"
+ }
}
+}
+
+# Search the caller's args variable and set variables according to the list of
+# valid options described by ARGSET.
+
+proc parse_args { argset } {
+ parse_list 2 args $argset "-" false
# The remaining args should be checked to see that they match the
# number of items expected to be passed into the procedure...
}
+# Process the caller's options variable and set variables according
+# to the list of valid options described by OPTIONSET.
+
+proc parse_options { optionset } {
+ parse_list 2 options $optionset "" true
+
+ # Require no remaining options.
+ upvar 1 options options
+ if { [llength $options] != 0 } {
+ error "Options left unparsed: $options"
+ }
+}
+
# Capture the output of COMMAND in a string ignoring PREFIX (a regexp);
# return that string.
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_gcc_bootstrap/master-arm-bootstrap_O3. So far, this commit has regressed CI configurations:
- tcwg_gcc_bootstrap/master-arm-bootstrap_O3
Culprit:
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
</cut>
Results regressed to (for first_bad == cad36f38576a6a781e3c62ab061c68f5b8dab13a)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
from (for last_good == 0960d937d9bee3c831d0b64a9c828c263a58ff89)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe bootstrap_O3:
2
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3…
Build top page/logs: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
cd investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
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_O3… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3… --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 cad36f38576a6a781e3c62ab061c68f5b8dab13a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 0960d937d9bee3c831d0b64a9c828c263a58ff89
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3…
Build log: https://ci.linaro.org/job/tcwg_gcc_bootstrap-bisect-master-arm-bootstrap_O3…
Full commit (up to 1000 lines):
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
---
gcc/expr.c | 19 ++++++++++++++++++-
gcc/simplify-rtx.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/gcc/expr.c b/gcc/expr.c
index 096c0315ecc..5dd98a9bccc 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -688,7 +688,24 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
&& (GET_MODE_PRECISION (subreg_promoted_mode (x))
>= GET_MODE_PRECISION (int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
- x = gen_lowpart (int_mode, SUBREG_REG (x));
+ {
+ scalar_int_mode int_orig_mode;
+ machine_mode orig_mode = GET_MODE (x);
+ x = gen_lowpart (int_mode, SUBREG_REG (x));
+
+ /* Preserve SUBREG_PROMOTED_VAR_P if the new mode is wider than
+ the original mode, but narrower than the inner mode. */
+ if (GET_CODE (x) == SUBREG
+ && GET_MODE_PRECISION (subreg_promoted_mode (x))
+ > GET_MODE_PRECISION (int_mode)
+ && is_a <scalar_int_mode> (orig_mode, &int_orig_mode)
+ && GET_MODE_PRECISION (int_mode)
+ > GET_MODE_PRECISION (int_orig_mode))
+ {
+ SUBREG_PROMOTED_VAR_P (x) = 1;
+ SUBREG_PROMOTED_SET (x, unsignedp);
+ }
+ }
if (GET_MODE (x) != VOIDmode)
oldmode = GET_MODE (x);
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e431e0c19d7..ebad5cb5a79 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1512,12 +1512,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_SIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_SIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 1);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Sign-extending a sign-extended subreg. */
+ return simplify_gen_unary (SIGN_EXTEND, mode,
+ subreg, subreg_mode);
}
/* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
@@ -1631,12 +1647,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_UNSIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_UNSIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 0);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Zero-extending a zero-extended subreg. */
+ return simplify_gen_unary (ZERO_EXTEND, mode,
+ subreg, subreg_mode);
}
/* Extending a widening multiplication should be canonicalized to
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_gnu_native_build/master-aarch64. So far, this commit has regressed CI configurations:
- tcwg_gnu_native_build/master-aarch64
Culprit:
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
</cut>
Results regressed to (for first_bad == cad36f38576a6a781e3c62ab061c68f5b8dab13a)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 /home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:05:59 make[2]: *** [/home/tcwg-buildslave/workspace/tcwg_gnu_6/abe/snapshots/gcc.git~master/libgcc/shared-object.mk:14: trunctfhf2.o] Error 1
from (for last_good == 0960d937d9bee3c831d0b64a9c828c263a58ff89)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe gcc:
2
# build_abe linux:
4
# build_abe glibc:
5
# build_abe gdb:
6
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/art…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/art…
Build top page/logs: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
cd investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
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_gnu_native_build-bisect-master-aarch64/1/art… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/art… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/art… --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 cad36f38576a6a781e3c62ab061c68f5b8dab13a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 0960d937d9bee3c831d0b64a9c828c263a58ff89
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/art…
Build log: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-aarch64/1/con…
Full commit (up to 1000 lines):
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
---
gcc/expr.c | 19 ++++++++++++++++++-
gcc/simplify-rtx.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/gcc/expr.c b/gcc/expr.c
index 096c0315ecc..5dd98a9bccc 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -688,7 +688,24 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
&& (GET_MODE_PRECISION (subreg_promoted_mode (x))
>= GET_MODE_PRECISION (int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
- x = gen_lowpart (int_mode, SUBREG_REG (x));
+ {
+ scalar_int_mode int_orig_mode;
+ machine_mode orig_mode = GET_MODE (x);
+ x = gen_lowpart (int_mode, SUBREG_REG (x));
+
+ /* Preserve SUBREG_PROMOTED_VAR_P if the new mode is wider than
+ the original mode, but narrower than the inner mode. */
+ if (GET_CODE (x) == SUBREG
+ && GET_MODE_PRECISION (subreg_promoted_mode (x))
+ > GET_MODE_PRECISION (int_mode)
+ && is_a <scalar_int_mode> (orig_mode, &int_orig_mode)
+ && GET_MODE_PRECISION (int_mode)
+ > GET_MODE_PRECISION (int_orig_mode))
+ {
+ SUBREG_PROMOTED_VAR_P (x) = 1;
+ SUBREG_PROMOTED_SET (x, unsignedp);
+ }
+ }
if (GET_MODE (x) != VOIDmode)
oldmode = GET_MODE (x);
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e431e0c19d7..ebad5cb5a79 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1512,12 +1512,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_SIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_SIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 1);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Sign-extending a sign-extended subreg. */
+ return simplify_gen_unary (SIGN_EXTEND, mode,
+ subreg, subreg_mode);
}
/* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
@@ -1631,12 +1647,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_UNSIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_UNSIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 0);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Zero-extending a zero-extended subreg. */
+ return simplify_gen_unary (ZERO_EXTEND, mode,
+ subreg, subreg_mode);
}
/* Extending a widening multiplication should be canonicalized to
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_gnu_cross_build/master-aarch64. So far, this commit has regressed CI configurations:
- tcwg_gnu_cross_build/master-aarch64
Culprit:
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
</cut>
Results regressed to (for first_bad == cad36f38576a6a781e3c62ab061c68f5b8dab13a)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
# 00:04:40 cc1: error: no include path in which to search for stdc-predef.h
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-1.h:127:36: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
# 00:04:48 make[2]: *** [/home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/static-object.mk:17: floatsitf.o] Error 1
# 00:04:48 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/soft-fp/op-2.h:249:37: internal compiler error: in subreg_promoted_mode, at rtl.h:3132
from (for last_good == 0960d937d9bee3c831d0b64a9c828c263a58ff89)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe stage1:
2
# build_abe linux:
3
# build_abe glibc:
4
# build_abe stage2:
5
# build_abe gdb:
6
# build_abe qemu:
7
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/arti…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/arti…
Build top page/logs: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
cd investigate-gcc-cad36f38576a6a781e3c62ab061c68f5b8dab13a
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_gnu_cross_build-bisect-master-aarch64/1/arti… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/arti… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/arti… --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 cad36f38576a6a781e3c62ab061c68f5b8dab13a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 0960d937d9bee3c831d0b64a9c828c263a58ff89
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/arti…
Build log: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-aarch64/1/cons…
Full commit (up to 1000 lines):
<cut>
commit cad36f38576a6a781e3c62ab061c68f5b8dab13a
Author: Roger Sayle <roger(a)nextmovesoftware.com>
Date: Tue Aug 31 11:45:07 2021 +0100
Preserve SUBREG_PROMOTED_VAR_P on (extend:HI (subreg/s:QI (reg:SI))).
SUBREG_PROMOTED_VAR_P is a mechanism for tracking that a partial subreg
is correctly zero-extended or sign-extended in the parent register. For
example, the RTL (subreg/s/v:QI (reg/v:SI 23 [ x ]) 0) indicates that the
byte x is zero extended in reg:SI 23, which is useful for optimization.
An example is that zero extending the above QImode value to HImode can
simply use a wider subreg, i.e. (subreg:HI (reg/v:SI 23 [ x ]) 0).
This patch addresses the oversight/missed optimization opportunity that
the new HImode subreg above should retain its SUBREG_PROMOTED_VAR_P
annotation as its value is guaranteed to be correctly extended in the
SImode parent. The code below to preserve SUBREG_PROMOTED_VAR_P is already
present in the middle-end (e.g. simplify-rtx.c:7232-7242) but missing
from one or two (precisely three) places that (accidentally) strip it.
Whilst there I also added another optimization. If we need to extend
the above QImode value beyond the SImode register holding it, say to
DImode, we can eliminate the SUBREG and simply extend from the SImode
register to DImode.
2021-08-31 Roger Sayle <roger(a)nextmovesoftware.com>
gcc/ChangeLog
* expr.c (convert_modes): Preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg.
* simplify-rtx.c (simplify_unary_operation_1) [SIGN_EXTEND]:
Likewise, preserve SUBREG_PROMOTED_VAR_P when creating a (wider)
partial subreg from a SUBREG_PROMOTED_VAR_P subreg. Generate
SIGN_EXTEND of the SUBREG_REG when a subreg would be paradoxical.
[ZERO_EXTEND]: Likewise, preserve SUBREG_PROMOTED_VAR_P when
creating a (wider) partial subreg from a SUBREG_PROMOTED_VAR_P
subreg. Generate ZERO_EXTEND of the SUBREG_REG when a subreg
would be paradoxical.
---
gcc/expr.c | 19 ++++++++++++++++++-
gcc/simplify-rtx.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 60 insertions(+), 11 deletions(-)
diff --git a/gcc/expr.c b/gcc/expr.c
index 096c0315ecc..5dd98a9bccc 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -688,7 +688,24 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
&& (GET_MODE_PRECISION (subreg_promoted_mode (x))
>= GET_MODE_PRECISION (int_mode))
&& SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp))
- x = gen_lowpart (int_mode, SUBREG_REG (x));
+ {
+ scalar_int_mode int_orig_mode;
+ machine_mode orig_mode = GET_MODE (x);
+ x = gen_lowpart (int_mode, SUBREG_REG (x));
+
+ /* Preserve SUBREG_PROMOTED_VAR_P if the new mode is wider than
+ the original mode, but narrower than the inner mode. */
+ if (GET_CODE (x) == SUBREG
+ && GET_MODE_PRECISION (subreg_promoted_mode (x))
+ > GET_MODE_PRECISION (int_mode)
+ && is_a <scalar_int_mode> (orig_mode, &int_orig_mode)
+ && GET_MODE_PRECISION (int_mode)
+ > GET_MODE_PRECISION (int_orig_mode))
+ {
+ SUBREG_PROMOTED_VAR_P (x) = 1;
+ SUBREG_PROMOTED_SET (x, unsignedp);
+ }
+ }
if (GET_MODE (x) != VOIDmode)
oldmode = GET_MODE (x);
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index e431e0c19d7..ebad5cb5a79 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1512,12 +1512,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_SIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_SIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 1);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Sign-extending a sign-extended subreg. */
+ return simplify_gen_unary (SIGN_EXTEND, mode,
+ subreg, subreg_mode);
}
/* (sign_extend:M (sign_extend:N <X>)) is (sign_extend:M <X>).
@@ -1631,12 +1647,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
target mode is the same as the variable's promotion. */
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
- && SUBREG_PROMOTED_UNSIGNED_P (op)
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
+ && SUBREG_PROMOTED_UNSIGNED_P (op))
{
- temp = rtl_hooks.gen_lowpart_no_emit (mode, SUBREG_REG (op));
- if (temp)
- return temp;
+ rtx subreg = SUBREG_REG (op);
+ machine_mode subreg_mode = GET_MODE (subreg);
+ if (!paradoxical_subreg_p (mode, subreg_mode))
+ {
+ temp = rtl_hooks.gen_lowpart_no_emit (mode, subreg);
+ if (temp)
+ {
+ /* Preserve SUBREG_PROMOTED_VAR_P. */
+ if (partial_subreg_p (temp))
+ {
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_SET (temp, 0);
+ }
+ return temp;
+ }
+ }
+ else
+ /* Zero-extending a zero-extended subreg. */
+ return simplify_gen_unary (ZERO_EXTEND, mode,
+ subreg, subreg_mode);
}
/* Extending a widening multiplication should be canonicalized to
</cut>
Successfully identified regression in *gdb* in CI configuration tcwg_gnu_native_build/master-arm. So far, this commit has regressed CI configurations:
- tcwg_gnu_native_build/master-arm
Culprit:
<cut>
commit 282aa4f7d292eb4bc213d028465a3b96f5af2f22
Author: Tom Tromey <tom(a)tromey.com>
Date: Sat Aug 28 13:16:50 2021 -0600
Add some parallel_for_each tests
Tom de Vries noticed that a patch in the DWARF scanner rewrite series
caused a regression in parallel_for_each -- it started crashing in the
case where the number of threads is 0 (there was an unchecked use of
"n-1" that was used to size an array).
He also pointed out that there were no tests of parallel_for_each.
This adds a few tests of parallel_for_each, primarily testing that
different settings for the number of threads will work. This test
catches the bug that he found in that series.
</cut>
Results regressed to (for first_bad == 282aa4f7d292eb4bc213d028465a3b96f5af2f22)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe gcc:
2
# build_abe linux:
4
# build_abe glibc:
5
# First few build errors in logs:
# 00:03:45 ../../../../../../gdb/gdb/unittests/parallel-for-selftests.c:53:30: error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’
# 00:03:45 make[1]: *** [unittests/parallel-for-selftests.o] Error 1
# 00:03:46 make: *** [all-gdb] Error 2
from (for last_good == ee8b88452c1cb1be97199942aee7a76bbca210ee)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe gcc:
2
# build_abe linux:
4
# build_abe glibc:
5
# build_abe gdb:
6
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/artifac…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/artifac…
Build top page/logs: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gdb-282aa4f7d292eb4bc213d028465a3b96f5af2f22
cd investigate-gdb-282aa4f7d292eb4bc213d028465a3b96f5af2f22
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_gnu_native_build-bisect-master-arm/1/artifac… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/artifac… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/artifac… --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 /gdb/ ./ ./bisect/baseline/
cd gdb
# Reproduce first_bad build
git checkout --detach 282aa4f7d292eb4bc213d028465a3b96f5af2f22
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach ee8b88452c1cb1be97199942aee7a76bbca210ee
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/artifac…
Build log: https://ci.linaro.org/job/tcwg_gnu_native_build-bisect-master-arm/1/console…
Full commit (up to 1000 lines):
<cut>
commit 282aa4f7d292eb4bc213d028465a3b96f5af2f22
Author: Tom Tromey <tom(a)tromey.com>
Date: Sat Aug 28 13:16:50 2021 -0600
Add some parallel_for_each tests
Tom de Vries noticed that a patch in the DWARF scanner rewrite series
caused a regression in parallel_for_each -- it started crashing in the
case where the number of threads is 0 (there was an unchecked use of
"n-1" that was used to size an array).
He also pointed out that there were no tests of parallel_for_each.
This adds a few tests of parallel_for_each, primarily testing that
different settings for the number of threads will work. This test
catches the bug that he found in that series.
---
gdb/Makefile.in | 1 +
gdb/unittests/parallel-for-selftests.c | 86 ++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 73a1bf83c85..320d3326a81 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -456,6 +456,7 @@ SELFTESTS_SRCS = \
unittests/offset-type-selftests.c \
unittests/observable-selftests.c \
unittests/optional-selftests.c \
+ unittests/parallel-for-selftests.c \
unittests/parse-connection-spec-selftests.c \
unittests/ptid-selftests.c \
unittests/main-thread-selftests.c \
diff --git a/gdb/unittests/parallel-for-selftests.c b/gdb/unittests/parallel-for-selftests.c
new file mode 100644
index 00000000000..7f61b709fa7
--- /dev/null
+++ b/gdb/unittests/parallel-for-selftests.c
@@ -0,0 +1,86 @@
+/* Self tests for parallel_for_each
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "gdbsupport/selftest.h"
+#include "gdbsupport/parallel-for.h"
+#include "gdbsupport/thread-pool.h"
+
+#if CXX_STD_THREAD
+
+namespace selftests {
+namespace parallel_for {
+
+struct save_restore_n_threads
+{
+ save_restore_n_threads ()
+ : n_threads (gdb::thread_pool::g_thread_pool->thread_count ())
+ {
+ }
+
+ ~save_restore_n_threads ()
+ {
+ gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
+ }
+
+ int n_threads;
+};
+
+static void
+test (int n_threads)
+{
+ save_restore_n_threads saver;
+ gdb::thread_pool::g_thread_pool->set_thread_count (n_threads);
+
+#define NUMBER 10000
+
+ std::atomic<int> counter = 0;
+ gdb::parallel_for_each (0, NUMBER,
+ [&] (int start, int end)
+ {
+ counter += end - start;
+ });
+
+ SELF_CHECK (counter == NUMBER);
+
+#undef NUMBER
+}
+
+static void
+test_n_threads ()
+{
+ test (0);
+ test (1);
+ test (3);
+}
+
+}
+}
+
+#endif /* CXX_STD_THREAD */
+
+void _initialize_parallel_for_selftests ();
+void
+_initialize_parallel_for_selftests ()
+{
+#ifdef CXX_STD_THREAD
+ selftests::register_test ("parallel_for",
+ selftests::parallel_for::test_n_threads);
+#endif /* CXX_STD_THREAD */
+}
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_gnu_cross_build/master-arm. So far, this commit has regressed CI configurations:
- tcwg_gnu_cross_build/master-arm
Culprit:
<cut>
commit caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1
Author: Sebastian Huber <sebastian.huber(a)embedded-brains.de>
Date: Tue Aug 17 09:53:43 2021 +0200
Use __builtin_trap() for abort() if inhibit_libc
abort() is used in gcc_assert() and gcc_unreachable() which is used by target
libraries such as libgcov.a. This patch changes the abort() definition under
certain conditions. If inhibit_libc is defined and abort is not already
defined, then abort() is defined to __builtin_trap().
The inhibit_libc define is usually defined if GCC is built for targets running
in embedded systems which may optionally use a C standard library. If
inhibit_libc is defined, then there may be still a full featured abort()
available. abort() is a heavy weight function which depends on signals and
file streams. For statically linked applications, this means that a dependency
on gcc_assert() pulls in the support for signals and file streams. This could
prevent using gcov to test low end targets for example. Using __builtin_trap()
avoids these dependencies if the target implements a "trap" instruction. The
application or operating system could use a trap handler to react to failed GCC
runtime checks which caused a trap.
gcc/
* tsystem.h (abort): Define abort() if inhibit_libc is defined and it
is not already defined.
</cut>
Results regressed to (for first_bad == caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# First few build errors in logs:
# 00:01:44 cc1: error: no include path in which to search for stdc-predef.h
# 00:02:05 /home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/unwind-arm-common.inc:55:24: error: macro passed 1 arguments, but takes just 0
# 00:02:05 make[2]: *** [/home/tcwg-buildslave/workspace/tcwg_gnu_1/abe/snapshots/gcc.git~master/libgcc/static-object.mk:17: unwind-arm.o] Error 1
# 00:02:06 make[1]: *** [Makefile:12484: all-target-libgcc] Error 2
# 00:02:06 make: *** [Makefile:953: all] Error 2
from (for last_good == d7e56b084d0b230ae5ee280f569d679fa0f09f4d)
# reset_artifacts:
-10
# true:
0
# build_abe binutils:
1
# build_abe stage1:
2
# build_abe linux:
3
# build_abe glibc:
4
# build_abe stage2:
5
# build_abe gdb:
6
# build_abe qemu:
7
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/artifact…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/artifact…
Build top page/logs: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1
cd investigate-gcc-caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1
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_gnu_cross_build-bisect-master-arm/1/artifact… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/artifact… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/artifact… --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 caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach d7e56b084d0b230ae5ee280f569d679fa0f09f4d
../artifacts/test.sh
cd ..
</cut>
History of pending regressions and results: https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/…
Artifacts: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/artifact…
Build log: https://ci.linaro.org/job/tcwg_gnu_cross_build-bisect-master-arm/1/consoleT…
Full commit (up to 1000 lines):
<cut>
commit caf81d3b57501b1f58dcd9b1ef9d7b4bc76f4ab1
Author: Sebastian Huber <sebastian.huber(a)embedded-brains.de>
Date: Tue Aug 17 09:53:43 2021 +0200
Use __builtin_trap() for abort() if inhibit_libc
abort() is used in gcc_assert() and gcc_unreachable() which is used by target
libraries such as libgcov.a. This patch changes the abort() definition under
certain conditions. If inhibit_libc is defined and abort is not already
defined, then abort() is defined to __builtin_trap().
The inhibit_libc define is usually defined if GCC is built for targets running
in embedded systems which may optionally use a C standard library. If
inhibit_libc is defined, then there may be still a full featured abort()
available. abort() is a heavy weight function which depends on signals and
file streams. For statically linked applications, this means that a dependency
on gcc_assert() pulls in the support for signals and file streams. This could
prevent using gcov to test low end targets for example. Using __builtin_trap()
avoids these dependencies if the target implements a "trap" instruction. The
application or operating system could use a trap handler to react to failed GCC
runtime checks which caused a trap.
gcc/
* tsystem.h (abort): Define abort() if inhibit_libc is defined and it
is not already defined.
---
gcc/tsystem.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gcc/tsystem.h b/gcc/tsystem.h
index e1e6a96a4f4..5c72c69ff3e 100644
--- a/gcc/tsystem.h
+++ b/gcc/tsystem.h
@@ -59,7 +59,7 @@ extern int atexit (void (*)(void));
#endif
#ifndef abort
-extern void abort (void) __attribute__ ((__noreturn__));
+#define abort() __builtin_trap ()
#endif
#ifndef strlen
</cut>
Progress (short week, 3 days):
* UM-2 [QEMU upstream maintainership]
+ QEMU 6.1.0 has now been released
+ Sent out the first arm pullreq for the 6.2 cycle, including
another slice of the MVE patches
+ tried to work through some of the codereview backlog
-- PMM