Successfully identified regression in *gcc* in CI configuration tcwg_bmk_gnu_tk1/gnu-release-arm-spec2k6-O3_LTO. So far, this commit has regressed CI configurations:
- tcwg_bmk_gnu_tk1/gnu-release-arm-spec2k6-O3_LTO
Culprit:
<cut>
commit 9b0365879b3c4917f5a2485a1fca8bb678484bfe
Author: Richard Sandiford <richard.sandiford(a)arm.com>
Date: Mon Oct 7 08:39:12 2019 +0000
[IRA] Handle fully-tied destinations in a similar way to earlyclobbers
IRA's make_early_clobber_and_input_conflicts checks for cases in
which an output operand is likely to be an earlyclobber and an input
operand is unlikely to be tieable with it. If so, the allocno for
the output conflicts with the allocno for the input. This seems
to work well.
However, a similar situation arises if an output operand is likely
to be tied to one of a set of input operands X and if another input
operand has a different value from all of the operands in X.
E.g. if we have:
0: "=r, r"
1: "0, r"
2: "r, 0"
3: "r, r"
operand 0 will always be tied to operand 1 or operand 2, so if operand 3
is different from them both, operand 0 acts like an earlyclobber as far
as operand 3 (only) is concerned. The same is true for operand 2 in:
0: "=r"
1: "0"
2: "r"
In the second example, we'd normally have a copy between operand 1 and
operand 0 if operand 1 dies in the instruction, and so there's rarely
a problem. But if operand 1 doesn't die in the instruction, operand 0
still acts as an earlyclobber for operand 2 (if different from operand 1),
since in that case LRA must copy operand 1 to operand 0 before the
instruction.
As the existing comment says:
Avoid introducing unnecessary conflicts by checking classes of the
constraints and pseudos because otherwise significant code
degradation is possible for some targets.
I think that's doubly true here. E.g. it's perfectly reasonable to have
constraints like:
0: "=r, r"
1: "0, r"
2: "r, r"
on targets like s390 that have shorter instructions for tied operands,
but that don't want the size difference to influence RA too much.
We shouldn't treat operand 0 as earlyclobber wrt operand 2 in that case.
This patch therefore treats a normal tied non-earlyclobber output as
being effectively earlyclobber wrt to an input if it is so for *all*
preferred alternatives.
2019-10-07 Richard Sandiford <richard.sandiford(a)arm.com>
gcc/
* ira-lives.c (check_and_make_def_conflict): Handle cases in which
DEF is not a true earlyclobber but is tied to a specific input
operand, and so is effectively earlyclobber wrt inputs that have
different values.
(make_early_clobber_and_input_conflicts): Pass this case to the above.
From-SVN: r276650
</cut>
Results regressed to (for first_bad == 9b0365879b3c4917f5a2485a1fca8bb678484bfe)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer:
-5
# true:
0
# benchmark -O3_LTO_marm -- artifacts/build-9b0365879b3c4917f5a2485a1fca8bb678484bfe/results_id:
1
# 470.lbm,lbm_base.default regressed by 122
# 454.calculix,calculix_base.default regressed by 105
from (for last_good == ad00d6c1746fdcbfd86b2d50f2500d7ccb0d1691)
# reset_artifacts:
-10
# build_abe binutils:
-9
# build_abe stage1 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer:
-8
# build_abe linux:
-7
# build_abe glibc:
-6
# build_abe stage2 -- --set gcc_override_configure=--with-mode=arm --set gcc_override_configure=--disable-libsanitizer:
-5
# true:
0
# benchmark -O3_LTO_marm -- artifacts/build-ad00d6c1746fdcbfd86b2d50f2500d7ccb0d1691/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-a…
Results ID of last_good: tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-release-arm-spec2k6-O3_LTO/1079
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-a…
Results ID of first_bad: tk1_32/tcwg_bmk_gnu_tk1/bisect-gnu-release-arm-spec2k6-O3_LTO/1049
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-a…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-9b0365879b3c4917f5a2485a1fca8bb678484bfe
cd investigate-gcc-9b0365879b3c4917f5a2485a1fca8bb678484bfe
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_gnu-bisect-tcwg_bmk_tk1-gnu-release-a… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-a… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-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
cd gcc
# Reproduce first_bad build
git checkout --detach 9b0365879b3c4917f5a2485a1fca8bb678484bfe
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach ad00d6c1746fdcbfd86b2d50f2500d7ccb0d1691
../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_gnu-bisect-tcwg_bmk_tk1-gnu-release-a…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tk1-gnu-release-a…
Full commit (up to 1000 lines):
<cut>
commit 9b0365879b3c4917f5a2485a1fca8bb678484bfe
Author: Richard Sandiford <richard.sandiford(a)arm.com>
Date: Mon Oct 7 08:39:12 2019 +0000
[IRA] Handle fully-tied destinations in a similar way to earlyclobbers
IRA's make_early_clobber_and_input_conflicts checks for cases in
which an output operand is likely to be an earlyclobber and an input
operand is unlikely to be tieable with it. If so, the allocno for
the output conflicts with the allocno for the input. This seems
to work well.
However, a similar situation arises if an output operand is likely
to be tied to one of a set of input operands X and if another input
operand has a different value from all of the operands in X.
E.g. if we have:
0: "=r, r"
1: "0, r"
2: "r, 0"
3: "r, r"
operand 0 will always be tied to operand 1 or operand 2, so if operand 3
is different from them both, operand 0 acts like an earlyclobber as far
as operand 3 (only) is concerned. The same is true for operand 2 in:
0: "=r"
1: "0"
2: "r"
In the second example, we'd normally have a copy between operand 1 and
operand 0 if operand 1 dies in the instruction, and so there's rarely
a problem. But if operand 1 doesn't die in the instruction, operand 0
still acts as an earlyclobber for operand 2 (if different from operand 1),
since in that case LRA must copy operand 1 to operand 0 before the
instruction.
As the existing comment says:
Avoid introducing unnecessary conflicts by checking classes of the
constraints and pseudos because otherwise significant code
degradation is possible for some targets.
I think that's doubly true here. E.g. it's perfectly reasonable to have
constraints like:
0: "=r, r"
1: "0, r"
2: "r, r"
on targets like s390 that have shorter instructions for tied operands,
but that don't want the size difference to influence RA too much.
We shouldn't treat operand 0 as earlyclobber wrt operand 2 in that case.
This patch therefore treats a normal tied non-earlyclobber output as
being effectively earlyclobber wrt to an input if it is so for *all*
preferred alternatives.
2019-10-07 Richard Sandiford <richard.sandiford(a)arm.com>
gcc/
* ira-lives.c (check_and_make_def_conflict): Handle cases in which
DEF is not a true earlyclobber but is tied to a specific input
operand, and so is effectively earlyclobber wrt inputs that have
different values.
(make_early_clobber_and_input_conflicts): Pass this case to the above.
From-SVN: r276650
---
gcc/ChangeLog | 8 ++++++
gcc/ira-lives.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 80 insertions(+), 14 deletions(-)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ce915859592..798d16cf0c6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2019-10-07 Richard Sandiford <richard.sandiford(a)arm.com>
+
+ * ira-lives.c (check_and_make_def_conflict): Handle cases in which
+ DEF is not a true earlyclobber but is tied to a specific input
+ operand, and so is effectively earlyclobber wrt inputs that have
+ different values.
+ (make_early_clobber_and_input_conflicts): Pass this case to the above.
+
2019-10-07 Richard Sandiford <richard.sandiford(a)arm.com>
* machmode.h (opt_mode): Mark constructors with CONSTEXPR.
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index cce73a1c3d4..098b0e73953 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -633,9 +633,28 @@ check_and_make_def_use_conflict (rtx dreg, rtx orig_dreg,
/* Check and make if necessary conflicts for definition DEF of class
DEF_CL of the current insn with input operands. Process only
- constraints of alternative ALT. */
+ constraints of alternative ALT.
+
+ One of three things is true when this function is called:
+
+ (1) DEF is an earlyclobber for alternative ALT. Input operands then
+ conflict with DEF in ALT unless they explicitly match DEF via 0-9
+ constraints.
+
+ (2) DEF matches (via 0-9 constraints) an operand that is an
+ earlyclobber for alternative ALT. Other input operands then
+ conflict with DEF in ALT.
+
+ (3) [FOR_TIE_P] Some input operand X matches DEF for alternative ALT.
+ Input operands with a different value from X then conflict with
+ DEF in ALT.
+
+ However, there's still a judgement call to make when deciding
+ whether a conflict in ALT is important enough to be reflected
+ in the pan-alternative allocno conflict set. */
static void
-check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
+check_and_make_def_conflict (int alt, int def, enum reg_class def_cl,
+ bool for_tie_p)
{
int use, use_match;
ira_allocno_t a;
@@ -669,14 +688,40 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
if (use == def || recog_data.operand_type[use] == OP_OUT)
continue;
+ /* An earlyclobber on DEF doesn't apply to an input operand X if X
+ explicitly matches DEF, but it applies to other input operands
+ even if they happen to be the same value as X.
+
+ In contrast, if an input operand X is tied to a non-earlyclobber
+ DEF, there's no conflict with other input operands that have the
+ same value as X. */
+ if (op_alt[use].matches == def
+ || (for_tie_p
+ && rtx_equal_p (recog_data.operand[use],
+ recog_data.operand[op_alt[def].matched])))
+ continue;
+
if (op_alt[use].anything_ok)
use_cl = ALL_REGS;
else
use_cl = op_alt[use].cl;
+ if (use_cl == NO_REGS)
+ continue;
+
+ /* If DEF is simply a tied operand, ignore cases in which this
+ alternative requires USE to have a likely-spilled class.
+ Adding a conflict would just constrain USE further if DEF
+ happens to be allocated first. */
+ if (for_tie_p && targetm.class_likely_spilled_p (use_cl))
+ continue;
/* If there's any alternative that allows USE to match DEF, do not
record a conflict. If that causes us to create an invalid
- instruction due to the earlyclobber, reload must fix it up. */
+ instruction due to the earlyclobber, reload must fix it up.
+
+ Likewise, if we're treating a tied DEF like a partial earlyclobber,
+ do not record a conflict if there's another alternative in which
+ DEF is neither tied nor earlyclobber. */
for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++)
{
if (!TEST_BIT (preferred_alternatives, alt1))
@@ -691,6 +736,12 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
&& recog_data.constraints[use - 1][0] == '%'
&& op_alt1[use - 1].matches == def))
break;
+ if (for_tie_p
+ && !op_alt1[def].earlyclobber
+ && op_alt1[def].matched < 0
+ && alternative_class (op_alt1, def) != NO_REGS
+ && alternative_class (op_alt1, use) != NO_REGS)
+ break;
}
if (alt1 < recog_data.n_alternatives)
@@ -701,8 +752,7 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
if ((use_match = op_alt[use].matches) >= 0)
{
- if (use_match == def)
- continue;
+ gcc_checking_assert (use_match != def);
if (op_alt[use_match].anything_ok)
use_cl = ALL_REGS;
@@ -717,7 +767,11 @@ check_and_make_def_conflict (int alt, int def, enum reg_class def_cl)
/* Make conflicts of early clobber pseudo registers of the current
insn with its inputs. Avoid introducing unnecessary conflicts by
checking classes of the constraints and pseudos because otherwise
- significant code degradation is possible for some targets. */
+ significant code degradation is possible for some targets.
+
+ For these purposes, tying an input to an output makes that output act
+ like an earlyclobber for inputs with a different value, since the output
+ register then has a predetermined purpose on input to the instruction. */
static void
make_early_clobber_and_input_conflicts (void)
{
@@ -732,15 +786,19 @@ make_early_clobber_and_input_conflicts (void)
if (TEST_BIT (preferred_alternatives, alt))
for (def = 0; def < n_operands; def++)
{
- def_cl = NO_REGS;
- if (op_alt[def].earlyclobber)
+ if (op_alt[def].anything_ok)
+ def_cl = ALL_REGS;
+ else
+ def_cl = op_alt[def].cl;
+ if (def_cl != NO_REGS)
{
- if (op_alt[def].anything_ok)
- def_cl = ALL_REGS;
- else
- def_cl = op_alt[def].cl;
- check_and_make_def_conflict (alt, def, def_cl);
+ if (op_alt[def].earlyclobber)
+ check_and_make_def_conflict (alt, def, def_cl, false);
+ else if (op_alt[def].matched >= 0
+ && !targetm.class_likely_spilled_p (def_cl))
+ check_and_make_def_conflict (alt, def, def_cl, true);
}
+
if ((def_match = op_alt[def].matches) >= 0
&& (op_alt[def_match].earlyclobber
|| op_alt[def].earlyclobber))
@@ -749,7 +807,7 @@ make_early_clobber_and_input_conflicts (void)
def_cl = ALL_REGS;
else
def_cl = op_alt[def_match].cl;
- check_and_make_def_conflict (alt, def, def_cl);
+ check_and_make_def_conflict (alt, def, def_cl, false);
}
}
}
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_gnu/gnu-master-arm-check_bootstrap. So far, this commit has regressed CI configurations:
- tcwg_gnu/gnu-master-arm-check_bootstrap
Culprit:
<cut>
commit 8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
Author: Ian Lance Taylor <iant(a)golang.org>
Date: Mon Jun 28 16:47:55 2021 -0700
compiler: in composite literals use temps only for interfaces
For a composite literal we only need to introduce a temporary variable
if we may be converting to an interface type, so only do it then.
This saves over 80% of compilation time when using gccgo to compile
cmd/internal/obj/x86, as the GCC middle-end spends a lot of time
pointlessly computing interactions between temporary variables.
For PR debug/101064
For golang/go#46600
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/331513
</cut>
Results regressed to (for first_bad == 8a8a7d332d5d01db5aea7336a36d9fd71a679fb1)
# reset_artifacts:
-10
# build_abe bootstrap:
0
# build_abe check_bootstrap:
1
# # Comparing directories
# # REFERENCE: base-artifacts/sumfiles
# # CURRENT: /home/tcwg-buildslave/workspace/tcwg_gnu_2/artifacts/build-8a8a7d332d5d01db5aea7336a36d9fd71a679fb1/sumfiles
#
# # Comparing 12 common sum files:
# g++.sum
# gcc.sum
# gfortran.sum
# go.sum
# gotools.sum
# libatomic.sum
# libffi.sum
# libgo.sum
# libgomp.sum
# libitm.sum
# libstdc++.sum
# objc.sum
# Comparing:
# REFERENCE:/tmp/gxx-sum1.1601595
# CURRENT: /tmp/gxx-sum2.1601595
#
# ` +---------+---------+
# o RUN STATUS: | REF | RES |
# +------------------------------------------+---------+---------+
# | Passes [PASS] | 460522 | 460519 |
# | Unexpected fails [FAIL] | 194 | 197 |
# | Errors [ERROR] | 0 | 0 |
# | Unexpected passes [XPASS] | 15 | 15 |
# | Expected fails [XFAIL] | 2737 | 2737 |
# | Unresolved [UNRESOLVED] | 104 | 104 |
# | Unsupported [UNSUPPORTED] | 22896 | 22896 |
# | Untested [UNTESTED] | 10 | 10 |
# +------------------------------------------+---------+---------+
#
# REF PASS ratio: 0.952271
# RES PASS ratio: 0.952265
#
# o REGRESSIONS:
# +------------------------------------------+---------+
# | PASS now FAIL [PASS => FAIL] | 3 |
# +------------------------------------------+---------+
# | TOTAL_REGRESSIONS | 3 |
# +------------------------------------------+---------+
#
# - PASS now FAIL [PASS => FAIL]:
#
# Executed from: go.test/go-test.exp
# go:go.test/test/fixedbugs/issue19182.go execution, -O2 -g
# Executed from: /home/tcwg-buildslave/workspace/tcwg_gnu_2/abe/snapshots/gcc.git~master/libgo/libgo.exp
# libgo:os/signal
# libgo:sync/atomic
#
#
#
# o IMPROVEMENTS TO BE CHECKED:
# +------------------------------------------+---------+
# +------------------------------------------+---------+
# | TOTAL_IMPROVEMENTS_TO_BE_CHECKED | 0 |
# +------------------------------------------+---------+
#
#
# # Regressions found
# # Regressions in 12 common sum files found
from (for last_good == c60d9160b4d966dbea5b1bbea4f817c64d0bee2d)
# reset_artifacts:
-10
# build_abe bootstrap:
0
# build_abe check_bootstrap:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72…
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72…
Build top page/logs: https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72/
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
cd investigate-gcc-8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
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-bisect-gnu-master-arm-check_bootstrap/72… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72… --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
cd gcc
# Reproduce first_bad build
git checkout --detach 8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach c60d9160b4d966dbea5b1bbea4f817c64d0bee2d
../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-bisect-gnu-master-arm-check_bootstrap/72…
Build log: https://ci.linaro.org/job/tcwg_gcc-bisect-gnu-master-arm-check_bootstrap/72…
Full commit (up to 1000 lines):
<cut>
commit 8a8a7d332d5d01db5aea7336a36d9fd71a679fb1
Author: Ian Lance Taylor <iant(a)golang.org>
Date: Mon Jun 28 16:47:55 2021 -0700
compiler: in composite literals use temps only for interfaces
For a composite literal we only need to introduce a temporary variable
if we may be converting to an interface type, so only do it then.
This saves over 80% of compilation time when using gccgo to compile
cmd/internal/obj/x86, as the GCC middle-end spends a lot of time
pointlessly computing interactions between temporary variables.
For PR debug/101064
For golang/go#46600
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/331513
---
gcc/go/gofrontend/MERGE | 2 +-
gcc/go/gofrontend/expressions.cc | 17 +++++++++++++----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index f16fb9facc3..f7bcc8c484a 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-bcafcb3c39530bb325514d6377747eb3127d1a03
+cad187fe3aceb2a7d964b64c70dfa8c8ad24ce65
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 5d45e4baab4..94342b2f9b8 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -15148,7 +15148,7 @@ Struct_construction_expression::do_copy()
}
// Flatten a struct construction expression. Store the values into
-// temporaries in case they need interface conversion.
+// temporaries if they may need interface conversion.
Expression*
Struct_construction_expression::do_flatten(Gogo*, Named_object*,
@@ -15162,10 +15162,13 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
return this;
Location loc = this->location();
+ const Struct_field_list* fields = this->type_->struct_type()->fields();
+ Struct_field_list::const_iterator pf = fields->begin();
for (Expression_list::iterator pv = this->vals()->begin();
pv != this->vals()->end();
- ++pv)
+ ++pv, ++pf)
{
+ go_assert(pf != fields->end());
if (*pv != NULL)
{
if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type())
@@ -15173,7 +15176,8 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
go_assert(saw_errors());
return Expression::make_error(loc);
}
- if (!(*pv)->is_multi_eval_safe())
+ if (pf->type()->interface_type() != NULL
+ && !(*pv)->is_multi_eval_safe())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, *pv, loc);
@@ -15448,7 +15452,7 @@ Array_construction_expression::do_check_types(Gogo*)
}
// Flatten an array construction expression. Store the values into
-// temporaries in case they need interface conversion.
+// temporaries if they may need interface conversion.
Expression*
Array_construction_expression::do_flatten(Gogo*, Named_object*,
@@ -15467,6 +15471,11 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
if (this->is_constant_array() || this->is_static_initializer())
return this;
+ // If the array element type is not an interface type, we don't need
+ // temporaries.
+ if (this->type_->array_type()->element_type()->interface_type() == NULL)
+ return this;
+
Location loc = this->location();
for (Expression_list::iterator pv = this->vals()->begin();
pv != this->vals()->end();
</cut>
Successfully identified regression in *llvm* in CI configuration tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O2_LTO. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_tx1/llvm-master-aarch64-spec2k6-O2_LTO
Culprit:
<cut>
commit 6998f8ae2d14e096aff33968f226587b5c1a193a
Author: David Sherwood <david.sherwood(a)arm.com>
Date: Wed Mar 10 08:34:19 2021 +0000
[LoopVectorize] Simplify scalar cost calculation in getInstructionCost
This patch simplifies the calculation of certain costs in
getInstructionCost when isScalarAfterVectorization() returns a true value.
There are a few places where we multiply a cost by a number N, i.e.
unsigned N = isScalarAfterVectorization(I, VF) ? VF.getKnownMinValue() : 1;
return N * TTI.getArithmeticInstrCost(...
After some investigation it seems that there are only these cases that occur
in practice:
1. VF is a scalar, in which case N = 1.
2. VF is a vector. We can only get here if: a) the instruction is a
GEP/bitcast/PHI with scalar uses, or b) this is an update to an induction
variable that remains scalar.
I have changed the code so that N is assumed to always be 1. For GEPs
the cost is always 0, since this is calculated later on as part of the
load/store cost. PHI nodes are costed separately and were never previously
multiplied by VF. For all other cases I have added an assert that none of
the users needs scalarising, which didn't fire in any unit tests.
Only one test required fixing and I believe the original cost for the scalar
add instruction to have been wrong, since only one copy remains after
vectorisation.
I have also added a new test for the case when a pointer PHI feeds directly
into a store that will be scalarised as we were previously never testing it.
Differential Revision: https://reviews.llvm.org/D99718
</cut>
Results regressed to (for first_bad == 6998f8ae2d14e096aff33968f226587b5c1a193a)
# 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_LTO -- artifacts/build-6998f8ae2d14e096aff33968f226587b5c1a193a/results_id:
1
# 462.libquantum,libquantum_base.default regressed by 113
from (for last_good == c835630c25a4f9925517949579f66a43b113fbc9)
# 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_LTO -- artifacts/build-c835630c25a4f9925517949579f66a43b113fbc9/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_LTO/1050
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_LTO/1048
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-6998f8ae2d14e096aff33968f226587b5c1a193a
cd investigate-llvm-6998f8ae2d14e096aff33968f226587b5c1a193a
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
cd llvm
# Reproduce first_bad build
git checkout --detach 6998f8ae2d14e096aff33968f226587b5c1a193a
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach c835630c25a4f9925517949579f66a43b113fbc9
../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 6998f8ae2d14e096aff33968f226587b5c1a193a
Author: David Sherwood <david.sherwood(a)arm.com>
Date: Wed Mar 10 08:34:19 2021 +0000
[LoopVectorize] Simplify scalar cost calculation in getInstructionCost
This patch simplifies the calculation of certain costs in
getInstructionCost when isScalarAfterVectorization() returns a true value.
There are a few places where we multiply a cost by a number N, i.e.
unsigned N = isScalarAfterVectorization(I, VF) ? VF.getKnownMinValue() : 1;
return N * TTI.getArithmeticInstrCost(...
After some investigation it seems that there are only these cases that occur
in practice:
1. VF is a scalar, in which case N = 1.
2. VF is a vector. We can only get here if: a) the instruction is a
GEP/bitcast/PHI with scalar uses, or b) this is an update to an induction
variable that remains scalar.
I have changed the code so that N is assumed to always be 1. For GEPs
the cost is always 0, since this is calculated later on as part of the
load/store cost. PHI nodes are costed separately and were never previously
multiplied by VF. For all other cases I have added an assert that none of
the users needs scalarising, which didn't fire in any unit tests.
Only one test required fixing and I believe the original cost for the scalar
add instruction to have been wrong, since only one copy remains after
vectorisation.
I have also added a new test for the case when a pointer PHI feeds directly
into a store that will be scalarised as we were previously never testing it.
Differential Revision: https://reviews.llvm.org/D99718
---
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 73 +++++++++++++---------
.../AArch64/no_vector_instructions.ll | 2 +-
.../LoopVectorize/AArch64/predication_costs.ll | 35 +++++++++++
.../Transforms/LoopVectorize/scalarized-bitcast.ll | 40 ++++++++++++
4 files changed, 121 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 2b413fc49505..f25af23c86c2 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -7383,10 +7383,39 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
Type *RetTy = I->getType();
if (canTruncateToMinimalBitwidth(I, VF))
RetTy = IntegerType::get(RetTy->getContext(), MinBWs[I]);
- VectorTy = isScalarAfterVectorization(I, VF) ? RetTy : ToVectorTy(RetTy, VF);
auto SE = PSE.getSE();
TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
+ auto hasSingleCopyAfterVectorization = [this](Instruction *I,
+ ElementCount VF) -> bool {
+ if (VF.isScalar())
+ return true;
+
+ auto Scalarized = InstsToScalarize.find(VF);
+ assert(Scalarized != InstsToScalarize.end() &&
+ "VF not yet analyzed for scalarization profitability");
+ return !Scalarized->second.count(I) &&
+ llvm::all_of(I->users(), [&](User *U) {
+ auto *UI = cast<Instruction>(U);
+ return !Scalarized->second.count(UI);
+ });
+ };
+
+ if (isScalarAfterVectorization(I, VF)) {
+ // With the exception of GEPs and PHIs, after scalarization there should
+ // only be one copy of the instruction generated in the loop. This is
+ // because the VF is either 1, or any instructions that need scalarizing
+ // have already been dealt with by the the time we get here. As a result,
+ // it means we don't have to multiply the instruction cost by VF.
+ assert(I->getOpcode() == Instruction::GetElementPtr ||
+ I->getOpcode() == Instruction::PHI ||
+ (I->getOpcode() == Instruction::BitCast &&
+ I->getType()->isPointerTy()) ||
+ hasSingleCopyAfterVectorization(I, VF));
+ VectorTy = RetTy;
+ } else
+ VectorTy = ToVectorTy(RetTy, VF);
+
// TODO: We need to estimate the cost of intrinsic calls.
switch (I->getOpcode()) {
case Instruction::GetElementPtr:
@@ -7514,21 +7543,16 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
Op2VK = TargetTransformInfo::OK_UniformValue;
SmallVector<const Value *, 4> Operands(I->operand_values());
- unsigned N = isScalarAfterVectorization(I, VF) ? VF.getKnownMinValue() : 1;
- return N * TTI.getArithmeticInstrCost(
- I->getOpcode(), VectorTy, CostKind,
- TargetTransformInfo::OK_AnyValue,
- Op2VK, TargetTransformInfo::OP_None, Op2VP, Operands, I);
+ return TTI.getArithmeticInstrCost(
+ I->getOpcode(), VectorTy, CostKind, TargetTransformInfo::OK_AnyValue,
+ Op2VK, TargetTransformInfo::OP_None, Op2VP, Operands, I);
}
case Instruction::FNeg: {
assert(!VF.isScalable() && "VF is assumed to be non scalable.");
- unsigned N = isScalarAfterVectorization(I, VF) ? VF.getKnownMinValue() : 1;
- return N * TTI.getArithmeticInstrCost(
- I->getOpcode(), VectorTy, CostKind,
- TargetTransformInfo::OK_AnyValue,
- TargetTransformInfo::OK_AnyValue,
- TargetTransformInfo::OP_None, TargetTransformInfo::OP_None,
- I->getOperand(0), I);
+ return TTI.getArithmeticInstrCost(
+ I->getOpcode(), VectorTy, CostKind, TargetTransformInfo::OK_AnyValue,
+ TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None,
+ TargetTransformInfo::OP_None, I->getOperand(0), I);
}
case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(I);
@@ -7583,6 +7607,10 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
VectorTy = ToVectorTy(getMemInstValueType(I), Width);
return getMemoryInstructionCost(I, VF);
}
+ case Instruction::BitCast:
+ if (I->getType()->isPointerTy())
+ return 0;
+ LLVM_FALLTHROUGH;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPToUI:
@@ -7593,8 +7621,7 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
case Instruction::SIToFP:
case Instruction::UIToFP:
case Instruction::Trunc:
- case Instruction::FPTrunc:
- case Instruction::BitCast: {
+ case Instruction::FPTrunc: {
// Computes the CastContextHint from a Load/Store instruction.
auto ComputeCCH = [&](Instruction *I) -> TTI::CastContextHint {
assert((isa<LoadInst>(I) || isa<StoreInst>(I)) &&
@@ -7672,14 +7699,7 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
}
}
- unsigned N;
- if (isScalarAfterVectorization(I, VF)) {
- assert(!VF.isScalable() && "VF is assumed to be non scalable");
- N = VF.getKnownMinValue();
- } else
- N = 1;
- return N *
- TTI.getCastInstrCost(Opcode, VectorTy, SrcVecTy, CCH, CostKind, I);
+ return TTI.getCastInstrCost(Opcode, VectorTy, SrcVecTy, CCH, CostKind, I);
}
case Instruction::Call: {
bool NeedToScalarize;
@@ -7694,11 +7714,8 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF,
case Instruction::ExtractValue:
return TTI.getInstructionCost(I, TTI::TCK_RecipThroughput);
default:
- // The cost of executing VF copies of the scalar instruction. This opcode
- // is unknown. Assume that it is the same as 'mul'.
- return VF.getKnownMinValue() * TTI.getArithmeticInstrCost(
- Instruction::Mul, VectorTy, CostKind) +
- getScalarizationOverhead(I, VF);
+ // This opcode is unknown. Assume that it is the same as 'mul'.
+ return TTI.getArithmeticInstrCost(Instruction::Mul, VectorTy, CostKind);
} // end of switch.
}
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll b/llvm/test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll
index 247ea35ff5d0..3061998518ad 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll
@@ -6,7 +6,7 @@ target triple = "aarch64--linux-gnu"
; CHECK-LABEL: all_scalar
; CHECK: LV: Found scalar instruction: %i.next = add nuw nsw i64 %i, 2
-; CHECK: LV: Found an estimated cost of 2 for VF 2 For instruction: %i.next = add nuw nsw i64 %i, 2
+; CHECK: LV: Found an estimated cost of 1 for VF 2 For instruction: %i.next = add nuw nsw i64 %i, 2
; CHECK: LV: Not considering vector loop of width 2 because it will not generate any vector instructions
;
define void @all_scalar(i64* %a, i64 %n) {
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/predication_costs.ll b/llvm/test/Transforms/LoopVectorize/AArch64/predication_costs.ll
index b0ebb4edf2ad..858b28ddd321 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/predication_costs.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/predication_costs.ll
@@ -86,6 +86,41 @@ for.end:
ret void
}
+; CHECK-LABEL: predicated_store_phi
+;
+; Same as predicate_store except we use a pointer PHI to maintain the address
+;
+; CHECK: Found new scalar instruction: %addr = phi i32* [ %a, %entry ], [ %addr.next, %for.inc ]
+; CHECK: Found new scalar instruction: %addr.next = getelementptr inbounds i32, i32* %addr, i64 1
+; CHECK: Scalarizing and predicating: store i32 %tmp2, i32* %addr, align 4
+; CHECK: Found an estimated cost of 0 for VF 2 For instruction: %addr = phi i32* [ %a, %entry ], [ %addr.next, %for.inc ]
+; CHECK: Found an estimated cost of 3 for VF 2 For instruction: store i32 %tmp2, i32* %addr, align 4
+;
+define void @predicated_store_phi(i32* %a, i1 %c, i32 %x, i64 %n) {
+entry:
+ br label %for.body
+
+for.body:
+ %i = phi i64 [ 0, %entry ], [ %i.next, %for.inc ]
+ %addr = phi i32 * [ %a, %entry ], [ %addr.next, %for.inc ]
+ %tmp1 = load i32, i32* %addr, align 4
+ %tmp2 = add nsw i32 %tmp1, %x
+ br i1 %c, label %if.then, label %for.inc
+
+if.then:
+ store i32 %tmp2, i32* %addr, align 4
+ br label %for.inc
+
+for.inc:
+ %i.next = add nuw nsw i64 %i, 1
+ %cond = icmp slt i64 %i.next, %n
+ %addr.next = getelementptr inbounds i32, i32* %addr, i64 1
+ br i1 %cond, label %for.body, label %for.end
+
+for.end:
+ ret void
+}
+
; CHECK-LABEL: predicated_udiv_scalarized_operand
;
; This test checks that we correctly compute the cost of the predicated udiv
diff --git a/llvm/test/Transforms/LoopVectorize/scalarized-bitcast.ll b/llvm/test/Transforms/LoopVectorize/scalarized-bitcast.ll
new file mode 100644
index 000000000000..0c97e6ac475e
--- /dev/null
+++ b/llvm/test/Transforms/LoopVectorize/scalarized-bitcast.ll
@@ -0,0 +1,40 @@
+; REQUIRES: asserts
+; RUN: opt -loop-vectorize -force-vector-width=2 -debug-only=loop-vectorize -S -o - < %s 2>&1 | FileCheck %s
+
+%struct.foo = type { i32, i64 }
+
+; CHECK: LV: Found an estimated cost of 0 for VF 2 For instruction: %0 = bitcast i64* %b to i32*
+
+; The bitcast below will be scalarized due to the predication in the loop. Bitcasts
+; between pointer types should be treated as free, despite the scalarization.
+define void @foo(%struct.foo* noalias nocapture %in, i32* noalias nocapture readnone %out, i64 %n) {
+entry:
+ br label %for.body
+
+for.body: ; preds = %entry, %if.end
+ %i.012 = phi i64 [ %inc, %if.end ], [ 0, %entry ]
+ %b = getelementptr inbounds %struct.foo, %struct.foo* %in, i64 %i.012, i32 1
+ %0 = bitcast i64* %b to i32*
+ %a = getelementptr inbounds %struct.foo, %struct.foo* %in, i64 %i.012, i32 0
+ %1 = load i32, i32* %a, align 8
+ %tobool.not = icmp eq i32 %1, 0
+ br i1 %tobool.not, label %if.end, label %land.lhs.true
+
+land.lhs.true: ; preds = %for.body
+ %2 = load i32, i32* %0, align 4
+ %cmp2 = icmp sgt i32 %2, 0
+ br i1 %cmp2, label %if.then, label %if.end
+
+if.then: ; preds = %land.lhs.true
+ %sub = add nsw i32 %2, -1
+ store i32 %sub, i32* %0, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %land.lhs.true, %for.body
+ %inc = add nuw nsw i64 %i.012, 1
+ %exitcond.not = icmp eq i64 %inc, %n
+ br i1 %exitcond.not, label %for.end, label %for.body
+
+for.end: ; preds = %if.end
+ ret void
+}
</cut>
Successfully identified regression in *glibc* in CI configuration tcwg_bmk_gnu_tx1/gnu-master-aarch64-spec2k6-O2_LTO. So far, this commit has regressed CI configurations:
- tcwg_bmk_gnu_tx1/gnu-master-aarch64-spec2k6-O2_LTO
Culprit:
<cut>
commit 8208be389bce84be0e1c35a3daa0c3467418f921
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Mon Jun 28 08:33:57 2021 +0200
Install shared objects under their ABI names
Previously, the installed objects were named like libc-2.33.so,
and the ABI soname libc.so.6 was just a symbolic link.
The Makefile targets to install these symbolic links are no longer
needed after this, so they are removed with this commit. The more
general $(make-link) command (which invokes scripts/rellns-sh) is
retained because other symbolic links are still needed.
Reviewed-by: Carlos O'Donell <carlos(a)redhat.com>
Tested-by: Carlos O'Donell <carlos(a)rehdat.com>
</cut>
Results regressed to (for first_bad == 8208be389bce84be0e1c35a3daa0c3467418f921)
# 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 -O2_LTO -- artifacts/build-8208be389bce84be0e1c35a3daa0c3467418f921/results_id:
1
# 434.zeusmp,zeusmp_base.default regressed by 7549591
# 435.gromacs,gromacs_base.default regressed by 10863956
# 447.dealII,dealII_base.default regressed by 12999253
# 454.calculix,calculix_base.default regressed by 3929138
# 465.tonto,tonto_base.default regressed by 12056000
# 459.GemsFDTD,GemsFDTD_base.default regressed by 7978538
# 410.bwaves,bwaves_base.default regressed by 8373106
# 416.gamess,gamess_base.default regressed by 4372732
# 481.wrf,wrf_base.default regressed by 8973237
# 436.cactusADM,cactusADM_base.default regressed by 4181826
# 437.leslie3d,leslie3d_base.default regressed by 7255644
from (for last_good == 6bf789d69e6be48419094ca98f064e00297a27d5)
# 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 -O2_LTO -- artifacts/build-6bf789d69e6be48419094ca98f064e00297a27d5/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa…
Results ID of last_good: tx1_64/tcwg_bmk_gnu_tx1/bisect-gnu-master-aarch64-spec2k6-O2_LTO/976
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa…
Results ID of first_bad: tx1_64/tcwg_bmk_gnu_tx1/bisect-gnu-master-aarch64-spec2k6-O2_LTO/988
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-glibc-8208be389bce84be0e1c35a3daa0c3467418f921
cd investigate-glibc-8208be389bce84be0e1c35a3daa0c3467418f921
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_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-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
cd glibc
# Reproduce first_bad build
git checkout --detach 8208be389bce84be0e1c35a3daa0c3467418f921
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 6bf789d69e6be48419094ca98f064e00297a27d5
../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_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-master-aa…
Full commit (up to 1000 lines):
<cut>
commit 8208be389bce84be0e1c35a3daa0c3467418f921
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Mon Jun 28 08:33:57 2021 +0200
Install shared objects under their ABI names
Previously, the installed objects were named like libc-2.33.so,
and the ABI soname libc.so.6 was just a symbolic link.
The Makefile targets to install these symbolic links are no longer
needed after this, so they are removed with this commit. The more
general $(make-link) command (which invokes scripts/rellns-sh) is
retained because other symbolic links are still needed.
Reviewed-by: Carlos O'Donell <carlos(a)redhat.com>
Tested-by: Carlos O'Donell <carlos(a)rehdat.com>
---
Makefile | 6 ------
Makerules | 45 +++++----------------------------------------
NEWS | 8 ++++++++
elf/Makefile | 10 ++--------
4 files changed, 15 insertions(+), 54 deletions(-)
diff --git a/Makefile b/Makefile
index 0157b53cb8..f98d5a9e67 100644
--- a/Makefile
+++ b/Makefile
@@ -109,12 +109,6 @@ elf/ldso_install:
# Ignore the error if we cannot update /etc/ld.so.cache.
ifeq (no,$(cross-compiling))
ifeq (yes,$(build-shared))
-install: install-symbolic-link
-.PHONY: install-symbolic-link
-install-symbolic-link: subdir_install
- $(symbolic-link-prog) $(symbolic-link-list)
- rm -f $(symbolic-link-list)
-
install:
-test ! -x $(elf-objpfx)ldconfig || LC_ALL=C \
$(elf-objpfx)ldconfig $(addprefix -r ,$(install_root)) \
diff --git a/Makerules b/Makerules
index f2587907fb..596fa68376 100644
--- a/Makerules
+++ b/Makerules
@@ -990,14 +990,12 @@ versioned := $(strip $(foreach so,$(install-lib.so),\
install-lib.so-versioned := $(filter $(versioned), $(install-lib.so))
install-lib.so-unversioned := $(filter-out $(versioned), $(install-lib.so))
-# For libraries whose soname have version numbers, we install three files:
+# For libraries whose soname have version numbers, we install two files:
# $(inst_libdir)/libfoo.so -- for linking, symlink or ld script
-# $(inst_slibdir)/libfoo.so.NN -- for loading by SONAME, symlink
-# $(inst_slibdir)/libfoo-X.Y.Z.so -- the real shared object file
+# $(inst_slibdir)/libfoo.so.NN -- for loading by SONAME
install-lib-nosubdir: $(install-lib.so-unversioned:%=$(inst_slibdir)/%) \
$(foreach L,$(install-lib.so-versioned),\
$(inst_libdir)/$L \
- $(inst_slibdir)/$(L:.so=)-$(version).so \
$(inst_slibdir)/$L$($L-version))
# Install all the unversioned shared libraries.
@@ -1030,35 +1028,10 @@ ln -f $(objpfx)/$(@F) $@
endef
endif
-ifeq (yes,$(build-shared))
-ifeq (no,$(cross-compiling))
-symbolic-link-prog := $(elf-objpfx)sln
-symbolic-link-list := $(elf-objpfx)symlink.list
-define make-shlib-link
-echo `$(..)scripts/rellns-sh -p $< $@` $@ >> $(symbolic-link-list)
-endef
-else # cross-compiling
-# We need a definition that can be used by elf/Makefile's install rules.
-symbolic-link-prog = $(LN_S)
-endif
-endif
-ifndef make-shlib-link
-define make-shlib-link
-rm -f $@
-$(LN_S) `$(..)scripts/rellns-sh -p $< $@` $@
-endef
-endif
-
ifdef libc.so-version
-# For a library specified to be version N, install three files:
-# libc.so -> libc.so.N (e.g. libc.so.6)
-# libc.so.6 -> libc-VERSION.so (e.g. libc-1.10.so)
-
-$(inst_slibdir)/libc.so$(libc.so-version): $(inst_slibdir)/libc-$(version).so \
- $(+force)
- $(make-shlib-link)
-$(inst_slibdir)/libc-$(version).so: $(common-objpfx)libc.so $(+force)
+$(inst_slibdir)/libc.so$(libc.so-version): $(common-objpfx)libc.so $(+force)
$(do-install-program)
+
install: $(inst_slibdir)/libc.so$(libc.so-version)
# This fragment of linker script gives the OUTPUT_FORMAT statement
@@ -1126,15 +1099,7 @@ include $(o-iterator)
generated += $(foreach o,$(versioned),$o$($o-version))
define o-iterator-doit
-$(inst_slibdir)/$o$($o-version): $(inst_slibdir)/$(o:.so=)-$(version).so \
- $(+force);
- $$(make-shlib-link)
-endef
-object-suffixes-left := $(versioned)
-include $(o-iterator)
-
-define o-iterator-doit
-$(inst_slibdir)/$(o:.so=)-$(version).so: $(objpfx)$o $(+force);
+$(inst_slibdir)/$o$($o-version): $(objpfx)$o $(+force);
$$(do-install-program)
endef
object-suffixes-left := $(versioned)
diff --git a/NEWS b/NEWS
index b24ebf9898..37ba4334c6 100644
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,14 @@ Deprecated and removed features, and other changes affecting compatibility:
buggy kernel interfaces (for instance some CIFS version) that could still
see spurious EINTR error when cancellation interrupts a blocking syscall.
+* Previously, glibc installed its various shared objects under versioned
+ file names such as libc-2.33.so. The ABI sonames (e.g., libc.so.6)
+ were provided as symbolic links. Starting with glibc 2.34, the shared
+ objects are installed under their ABI sonames directly, without
+ symbolic links. This increases compatibility with distribution
+ package managers that delete removed files late during the package
+ upgrade or downgrade process.
+
Changes to build and runtime requirements:
* On Linux, the shm_open, sem_open, and related functions now expect the
diff --git a/elf/Makefile b/elf/Makefile
index 62f7e8a225..cdbcc14087 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -630,20 +630,14 @@ $(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig
CPPFLAGS-dl-load.c += -I$(objpfx). -I$(csu-objpfx).
ifeq (yes,$(build-shared))
-$(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force)
+$(inst_rtlddir)/$(rtld-installed-name): $(objpfx)ld.so $(+force)
$(make-target-directory)
$(do-install-program)
-$(inst_rtlddir)/$(rtld-installed-name): \
- $(inst_slibdir)/$(rtld-version-installed-name) \
- $(inst_slibdir)/libc-$(version).so
- $(make-target-directory)
- $(make-shlib-link)
-
# Special target called by parent to install just the dynamic linker.
.PHONY: ldso_install
ldso_install: $(inst_rtlddir)/$(rtld-installed-name)
-endif
+endif # $(build-shared)
# Workarounds for ${exec_prefix} expansion in configure variables.
</cut>
Successfully identified regression in *gcc* in CI configuration tcwg_bmk_llvm_tk1/llvm-release-arm-spec2k6-Os. So far, this commit has regressed CI configurations:
- tcwg_bmk_llvm_tk1/llvm-release-arm-spec2k6-Os
Culprit:
<cut>
commit b6bf4d8a773cde07e751542f2911307d78b717fd
Author: Andreas Tobler <andreast(a)gcc.gnu.org>
Date: Thu Apr 25 22:03:35 2019 +0200
freebsd64.h: Add bits for 32-bit multilib support.
2019-04-25 Andreas Tobler <andreast(a)gcc.gnu.org>
* config/i386/freebsd64.h: Add bits for 32-bit multilib support.
* config/i386/t-freebsd64: New file.
* config.gcc: Add the t-freebsd64 for multilib support.
From-SVN: r270586
</cut>
Results regressed to (for first_bad == b6bf4d8a773cde07e751542f2911307d78b717fd)
# 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 -Os_mthumb -- artifacts/build-b6bf4d8a773cde07e751542f2911307d78b717fd/results_id:
1
# 429.mcf,mcf_base.default regressed by 104
# 470.lbm,lbm_base.default regressed by 103
from (for last_good == 8a55f9c57a1ffd900262aa2fc2015822dc059331)
# 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 -Os_mthumb -- artifacts/build-baseline/results_id:
1
Artifacts of last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-llvm-release…
Results ID of last_good: tk1_32/tcwg_bmk_llvm_tk1/baseline-llvm-release-arm-spec2k6-Os/824
Artifacts of first_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-llvm-release…
Results ID of first_bad: tk1_32/tcwg_bmk_llvm_tk1/bisect-llvm-release-arm-spec2k6-Os/929
Build top page/logs: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-llvm-release…
Configuration details:
Reproduce builds:
<cut>
mkdir investigate-gcc-b6bf4d8a773cde07e751542f2911307d78b717fd
cd investigate-gcc-b6bf4d8a773cde07e751542f2911307d78b717fd
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_tk1-llvm-release… --fail
curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-llvm-release… --fail
curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-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
cd gcc
# Reproduce first_bad build
git checkout --detach b6bf4d8a773cde07e751542f2911307d78b717fd
../artifacts/test.sh
# Reproduce last_good build
git checkout --detach 8a55f9c57a1ffd900262aa2fc2015822dc059331
../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_tk1-llvm-release…
Build log: https://ci.linaro.org/job/tcwg_bmk_ci_llvm-bisect-tcwg_bmk_tk1-llvm-release…
Full commit (up to 1000 lines):
<cut>
commit b6bf4d8a773cde07e751542f2911307d78b717fd
Author: Andreas Tobler <andreast(a)gcc.gnu.org>
Date: Thu Apr 25 22:03:35 2019 +0200
freebsd64.h: Add bits for 32-bit multilib support.
2019-04-25 Andreas Tobler <andreast(a)gcc.gnu.org>
* config/i386/freebsd64.h: Add bits for 32-bit multilib support.
* config/i386/t-freebsd64: New file.
* config.gcc: Add the t-freebsd64 for multilib support.
From-SVN: r270586
---
gcc/ChangeLog | 6 ++++++
gcc/config.gcc | 5 ++++-
gcc/config/i386/freebsd64.h | 5 ++++-
gcc/config/i386/t-freebsd64 | 30 ++++++++++++++++++++++++++++++
4 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7cd02c850d3..3a927ed00d3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2019-04-25 Andreas Tobler <andreast(a)gcc.gnu.org>
+
+ * config/i386/freebsd64.h: Add bits for 32-bit multilib support.
+ * config/i386/t-freebsd64: New file.
+ * config.gcc: Add the t-freebsd64 for multilib support.
+
2019-04-25 Uroš Bizjak <ubizjak(a)gmail.com>
* doc/extend.texi (vector_size): Add missing comma after @xref.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 09fb9ecd2cd..c7a464c89d0 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4927,7 +4927,10 @@ case ${target} in
;;
i[34567]86-*-dragonfly* | x86_64-*-dragonfly*)
;;
- i[34567]86-*-freebsd* | x86_64-*-freebsd*)
+ i[34567]86-*-freebsd*)
+ ;;
+ x86_64-*-freebsd*)
+ tmake_file="${tmake_file} i386/t-freebsd64"
;;
ia64*-*-linux*)
;;
diff --git a/gcc/config/i386/freebsd64.h b/gcc/config/i386/freebsd64.h
index 1f99e812f01..bffe19c14ff 100644
--- a/gcc/config/i386/freebsd64.h
+++ b/gcc/config/i386/freebsd64.h
@@ -31,7 +31,7 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#define LINK_SPEC "\
- %{m32:-m elf_i386_fbsd} \
+ %{m32:-m elf_i386_fbsd}%{!m32:-m elf_x86_64_fbsd} \
%{p:%nconsider using '-pg' instead of '-p' with gprof(1)} \
%{v:-V} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
@@ -42,3 +42,6 @@ along with GCC; see the file COPYING3. If not see
-dynamic-linker %(fbsd_dynamic_linker) } \
%{static:-Bstatic}} \
%{symbolic:-Bsymbolic}"
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "m64" }
diff --git a/gcc/config/i386/t-freebsd64 b/gcc/config/i386/t-freebsd64
new file mode 100644
index 00000000000..0dd05d479ac
--- /dev/null
+++ b/gcc/config/i386/t-freebsd64
@@ -0,0 +1,30 @@
+# Copyright (C) 2019 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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, or (at your option)
+# any later version.
+#
+# GCC 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 GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# The 32-bit libraries are found in /usr/lib32
+
+# To support i386 and x86-64, the directory structrue
+# should be:
+#
+# /lib has x86-64 libraries.
+# /lib32 has i386 libraries.
+#
+
+MULTILIB_OPTIONS = m32
+MULTILIB_DIRNAMES = 32
+MULTILIB_OSDIRNAMES = ../lib32
</cut>
Hey, Maxim,
You recently mentioned we have such a setup working, yes? Is there an easy
way to point the qemu portion to a custom branch?
I'm currently working on adding vdso support to qemu, and want to make sure
that the unwind info that I've written works correctly with libgcc and
llvm's libunwind.
Also, what arm CPU models are being used? My edge cases are v4, v4t, m0
(which is not really linux-user, but I think Christophe Lyon had made work).
r~