aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam James <sam@gentoo.org>2024-02-08 10:48:38 +0000
committerSam James <sam@gentoo.org>2024-02-08 10:53:06 +0000
commit29fc9edc64e0e00a0ade3065238365a4aa46ec59 (patch)
tree9c5334519610e1224b3883d0702ce521e83c515a
parent14.0.0: drop upstream 76_all_PR113731-vect-crash.patch (diff)
downloadgcc-patches-29fc9edc64e0e00a0ade3065238365a4aa46ec59.tar.gz
gcc-patches-29fc9edc64e0e00a0ade3065238365a4aa46ec59.tar.bz2
gcc-patches-29fc9edc64e0e00a0ade3065238365a4aa46ec59.zip
14.0.0: backport more vectorisation fixes & postgres const expression fix
Bug: https://gcc.gnu.org/PR113808 Bug: https://gcc.gnu.org/PR113750 Bug: https://gcc.gnu.org/PR113731 Bug: https://gcc.gnu.org/PR113734 (should be same as PR113808) Bug: https://gcc.gnu.org/PR113776 Bug: https://bugs.gentoo.org/923804 Bug: https://bugs.gentoo.org/923936 Signed-off-by: Sam James <sam@gentoo.org>
-rw-r--r--14.0.0/gentoo/75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch129
-rw-r--r--14.0.0/gentoo/76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch250
-rw-r--r--14.0.0/gentoo/77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch93
-rw-r--r--14.0.0/gentoo/78_all_PR113776-c-boolean-conversion.patch117
-rw-r--r--14.0.0/gentoo/README.history7
5 files changed, 596 insertions, 0 deletions
diff --git a/14.0.0/gentoo/75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch b/14.0.0/gentoo/75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch
new file mode 100644
index 0000000..1146246
--- /dev/null
+++ b/14.0.0/gentoo/75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch
@@ -0,0 +1,129 @@
+From c22a0c0ca1a5c31d107f90efd2221eb8bc198205 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+Date: Wed, 7 Feb 2024 10:58:25 +0000
+Subject: [PATCH 1/3] middle-end: fix ICE when moving statements to empty BB
+ [PR113731]
+
+We use gsi_move_before (&stmt_gsi, &dest_gsi); to request that the new statement
+be placed before any other statement. Typically this then moves the current
+pointer to be after the statement we just inserted.
+
+However it looks like when the BB is empty, this does not happen and the CUR
+pointer stays NULL. There's a comment in the source of gsi_insert_before that
+explains:
+
+/* If CUR is NULL, we link at the end of the sequence (this case happens
+
+This adds a default parameter to gsi_move_before to allow us to control where
+the insertion happens.
+
+gcc/ChangeLog:
+
+ PR tree-optimization/113731
+ * gimple-iterator.cc (gsi_move_before): Take new parameter for update
+ method.
+ * gimple-iterator.h (gsi_move_before): Default new param to
+ GSI_SAME_STMT.
+ * tree-vect-loop.cc (move_early_exit_stmts): Call gsi_move_before with
+ GSI_NEW_STMT.
+
+gcc/testsuite/ChangeLog:
+
+ PR tree-optimization/113731
+ * gcc.dg/vect/vect-early-break_111-pr113731.c: New test.
+
+(cherry picked from commit 8f6ed71d8fff3c3c6249651a72aee084e31ffb9e)
+---
+ gcc/gimple-iterator.cc | 7 +++---
+ gcc/gimple-iterator.h | 3 ++-
+ .../vect/vect-early-break_111-pr113731.c | 22 +++++++++++++++++++
+ gcc/tree-vect-loop.cc | 3 +--
+ 4 files changed, 29 insertions(+), 6 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_111-pr113731.c
+
+diff --git a/gcc/gimple-iterator.cc b/gcc/gimple-iterator.cc
+index 517c53376f05..55ef3198c52b 100644
+--- a/gcc/gimple-iterator.cc
++++ b/gcc/gimple-iterator.cc
+@@ -666,10 +666,11 @@ gsi_move_after (gimple_stmt_iterator *from, gimple_stmt_iterator *to)
+
+
+ /* Move the statement at FROM so it comes right before the statement
+- at TO. */
++ at TO using method M. M defaults to GSI_SAME_STMT. */
+
+ void
+-gsi_move_before (gimple_stmt_iterator *from, gimple_stmt_iterator *to)
++gsi_move_before (gimple_stmt_iterator *from, gimple_stmt_iterator *to,
++ gsi_iterator_update m)
+ {
+ gimple *stmt = gsi_stmt (*from);
+ gsi_remove (from, false);
+@@ -677,7 +678,7 @@ gsi_move_before (gimple_stmt_iterator *from, gimple_stmt_iterator *to)
+ /* For consistency with gsi_move_after, it might be better to have
+ GSI_NEW_STMT here; however, that breaks several places that expect
+ that TO does not change. */
+- gsi_insert_before (to, stmt, GSI_SAME_STMT);
++ gsi_insert_before (to, stmt, m);
+ }
+
+
+diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
+index 2e83a9660efc..78014a43cb93 100644
+--- a/gcc/gimple-iterator.h
++++ b/gcc/gimple-iterator.h
+@@ -86,7 +86,8 @@ extern gimple_stmt_iterator gsi_for_stmt (gimple *);
+ extern gimple_stmt_iterator gsi_for_stmt (gimple *, gimple_seq *);
+ extern gphi_iterator gsi_for_phi (gphi *);
+ extern void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *);
+-extern void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *);
++extern void gsi_move_before (gimple_stmt_iterator *, gimple_stmt_iterator *,
++ gsi_iterator_update = GSI_SAME_STMT);
+ extern void gsi_move_to_bb_end (gimple_stmt_iterator *, basic_block);
+ extern void gsi_insert_on_edge (edge, gimple *);
+ extern void gsi_insert_seq_on_edge (edge, gimple_seq);
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_111-pr113731.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_111-pr113731.c
+new file mode 100644
+index 000000000000..b205f470660a
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_111-pr113731.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_long } */
++/* { dg-additional-options "-msse4.2" { target i?86-*-* x86_64-*-* } } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++char* inet_net_pton_ipv4_bits;
++char inet_net_pton_ipv4_odst;
++void __errno_location();
++void inet_net_pton_ipv4();
++void inet_net_pton() { inet_net_pton_ipv4(); }
++void inet_net_pton_ipv4(char *dst, int size) {
++ while ((inet_net_pton_ipv4_bits > dst) & inet_net_pton_ipv4_odst) {
++ if (size-- <= 0)
++ goto emsgsize;
++ *dst++ = '\0';
++ }
++emsgsize:
++ __errno_location();
++}
+diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
+index 30b90d99925b..9aba94bd6ca2 100644
+--- a/gcc/tree-vect-loop.cc
++++ b/gcc/tree-vect-loop.cc
+@@ -11800,8 +11800,7 @@ move_early_exit_stmts (loop_vec_info loop_vinfo)
+ dump_printf_loc (MSG_NOTE, vect_location, "moving stmt %G", stmt);
+
+ gimple_stmt_iterator stmt_gsi = gsi_for_stmt (stmt);
+- gsi_move_before (&stmt_gsi, &dest_gsi);
+- gsi_prev (&dest_gsi);
++ gsi_move_before (&stmt_gsi, &dest_gsi, GSI_NEW_STMT);
+ }
+
+ /* Update all the stmts with their new reaching VUSES. */
+--
+2.43.0
+
diff --git a/14.0.0/gentoo/76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch b/14.0.0/gentoo/76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch
new file mode 100644
index 0000000..e502439
--- /dev/null
+++ b/14.0.0/gentoo/76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch
@@ -0,0 +1,250 @@
+From 7140d52db24a930955fca57f3e8b6147d0a7fa97 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+Date: Wed, 7 Feb 2024 10:59:32 +0000
+Subject: [PATCH 2/3] middle-end: fix ICE when destination BB for stores starts
+ with a label [PR113750]
+
+The report shows that if the FE leaves a label as the first thing in the dest
+BB then we ICE because we move the stores before the label.
+
+This is easy to fix if we know that there's still only one way into the BB.
+We would have already rejected the loop if there was multiple paths into the BB
+however I added an additional check just for early break in case the other
+constraints are relaxed later with an explanation.
+
+After that we fix the issue just by getting the GSI after the labels and I add
+a bunch of testcases for different positions the label can be added. Only the
+vect-early-break_112-pr113750.c one results in the label being kept.
+
+gcc/ChangeLog:
+
+ PR tree-optimization/113750
+ * tree-vect-data-refs.cc (vect_analyze_early_break_dependences): Check
+ for single predecessor when doing early break vect.
+ * tree-vect-loop.cc (move_early_exit_stmts): Get gsi at the start but
+ after labels.
+
+gcc/testsuite/ChangeLog:
+
+ PR tree-optimization/113750
+ * gcc.dg/vect/vect-early-break_112-pr113750.c: New test.
+ * gcc.dg/vect/vect-early-break_113-pr113750.c: New test.
+ * gcc.dg/vect/vect-early-break_114-pr113750.c: New test.
+ * gcc.dg/vect/vect-early-break_115-pr113750.c: New test.
+ * gcc.dg/vect/vect-early-break_116-pr113750.c: New test.
+
+(cherry picked from commit 5c3ba60024fedc6b3d374ebb071bcf5b3e27cd62)
+---
+ .../vect/vect-early-break_112-pr113750.c | 26 +++++++++++++++++++
+ .../vect/vect-early-break_113-pr113750.c | 26 +++++++++++++++++++
+ .../vect/vect-early-break_114-pr113750.c | 26 +++++++++++++++++++
+ .../vect/vect-early-break_115-pr113750.c | 26 +++++++++++++++++++
+ .../vect/vect-early-break_116-pr113750.c | 26 +++++++++++++++++++
+ gcc/tree-vect-data-refs.cc | 12 +++++++++
+ gcc/tree-vect-loop.cc | 2 +-
+ 7 files changed, 143 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c
+ create mode 100644 gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c
+
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c
+new file mode 100644
+index 000000000000..559ebd84d5c3
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_112-pr113750.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_int } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++#ifndef N
++#define N 800
++#endif
++unsigned vect_a[N];
++unsigned vect_b[N];
++
++unsigned test4(unsigned x)
++{
++ unsigned ret = 0;
++ for (int i = 0; i < N; i++)
++ {
++ vect_b[i] = x + i;
++ if (vect_a[i] != x)
++ break;
++foo:
++ vect_a[i] = x;
++ }
++ return ret;
++}
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c
+new file mode 100644
+index 000000000000..ba85780a46b1
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_113-pr113750.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_int } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++#ifndef N
++#define N 800
++#endif
++unsigned vect_a[N];
++unsigned vect_b[N];
++
++unsigned test4(unsigned x)
++{
++ unsigned ret = 0;
++ for (int i = 0; i < N; i++)
++ {
++ vect_b[i] = x + i;
++ if (vect_a[i] != x)
++ break;
++ vect_a[i] = x;
++foo:
++ }
++ return ret;
++}
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c
+new file mode 100644
+index 000000000000..37af2998688f
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_114-pr113750.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_int } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++#ifndef N
++#define N 800
++#endif
++unsigned vect_a[N];
++unsigned vect_b[N];
++
++unsigned test4(unsigned x)
++{
++ unsigned ret = 0;
++ for (int i = 0; i < N; i++)
++ {
++ vect_b[i] = x + i;
++foo:
++ if (vect_a[i] != x)
++ break;
++ vect_a[i] = x;
++ }
++ return ret;
++}
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c
+new file mode 100644
+index 000000000000..502686d308e2
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_115-pr113750.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_int } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++#ifndef N
++#define N 800
++#endif
++unsigned vect_a[N];
++unsigned vect_b[N];
++
++unsigned test4(unsigned x)
++{
++ unsigned ret = 0;
++ for (int i = 0; i < N; i++)
++ {
++foo:
++ vect_b[i] = x + i;
++ if (vect_a[i] != x)
++ break;
++ vect_a[i] = x;
++ }
++ return ret;
++}
+diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c
+new file mode 100644
+index 000000000000..4e02158aa351
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_116-pr113750.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-add-options vect_early_break } */
++/* { dg-require-effective-target vect_early_break } */
++/* { dg-require-effective-target vect_int } */
++
++/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */
++
++#ifndef N
++#define N 800
++#endif
++unsigned vect_a[N];
++unsigned vect_b[N];
++
++unsigned test4(unsigned x)
++{
++ unsigned ret = 0;
++ for (int i = 0; i < N; i++)
++ {
++ vect_b[i] = x + i;
++ if (vect_a[i] != x)
++foo:
++ break;
++ vect_a[i] = x;
++ }
++ return ret;
++}
+diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
+index 2ca5a1b131bf..2d3691a14564 100644
+--- a/gcc/tree-vect-data-refs.cc
++++ b/gcc/tree-vect-data-refs.cc
+@@ -819,6 +819,18 @@ vect_analyze_early_break_dependences (loop_vec_info loop_vinfo)
+ trapped already during loop form analysis. */
+ gcc_assert (dest_bb->loop_father == loop);
+
++ /* Check that the destination block we picked has only one pred. To relax this we
++ have to take special care when moving the statements. We don't currently support
++ such control flow however this check is there to simplify how we handle
++ labels that may be present anywhere in the IL. This check is to ensure that the
++ labels aren't significant for the CFG. */
++ if (!single_pred (dest_bb))
++ return opt_result::failure_at (vect_location,
++ "chosen loop exit block (BB %d) does not have a "
++ "single predecessor which is currently not "
++ "supported for early break vectorization.\n",
++ dest_bb->index);
++
+ LOOP_VINFO_EARLY_BRK_DEST_BB (loop_vinfo) = dest_bb;
+
+ if (!LOOP_VINFO_EARLY_BRK_VUSES (loop_vinfo).is_empty ())
+diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
+index 9aba94bd6ca2..190df9ec7741 100644
+--- a/gcc/tree-vect-loop.cc
++++ b/gcc/tree-vect-loop.cc
+@@ -11786,7 +11786,7 @@ move_early_exit_stmts (loop_vec_info loop_vinfo)
+
+ /* Move all stmts that need moving. */
+ basic_block dest_bb = LOOP_VINFO_EARLY_BRK_DEST_BB (loop_vinfo);
+- gimple_stmt_iterator dest_gsi = gsi_start_bb (dest_bb);
++ gimple_stmt_iterator dest_gsi = gsi_after_labels (dest_bb);
+
+ for (gimple *stmt : LOOP_VINFO_EARLY_BRK_STORES (loop_vinfo))
+ {
+--
+2.43.0
+
diff --git a/14.0.0/gentoo/77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch b/14.0.0/gentoo/77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch
new file mode 100644
index 0000000..1983aa7
--- /dev/null
+++ b/14.0.0/gentoo/77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch
@@ -0,0 +1,93 @@
+From ce2e742d5439c3f70f6ff641164541e506c808d1 Mon Sep 17 00:00:00 2001
+From: Tamar Christina <tamar.christina@arm.com>
+Date: Thu, 8 Feb 2024 10:43:13 +0000
+Subject: [PATCH 3/3] middle-end: don't cache restart_loop in
+ vectorizable_live_operations [PR113808]
+
+There's a bug in vectorizable_live_operation that restart_loop is defined
+outside the loop.
+
+This variable is supposed to indicate whether we are doing a first or last
+index reduction. The problem is that by defining it outside the loop it becomes
+dependent on the order we visit the USE/DEFs.
+
+In the given example, the loop isn't PEELED, but we visit the early exit uses
+first. This then sets the boolean to true and it can't get to false again.
+
+So when we visit the main exit we still treat it as an early exit for that
+SSA name.
+
+This cleans it up and renames the variables to something that's hopefully
+clearer to their intention.
+
+gcc/ChangeLog:
+
+ PR tree-optimization/113808
+ * tree-vect-loop.cc (vectorizable_live_operation): Don't cache the
+ value cross iterations.
+
+gcc/testsuite/ChangeLog:
+
+ PR tree-optimization/113808
+ * gfortran.dg/vect/vect-early-break_1-PR113808.f90: New test.
+
+(cherry picked from commit 3f69db1812106cb5bab203e17a60300ac51cdc68)
+---
+ .../vect/vect-early-break_1-PR113808.f90 | 21 +++++++++++++++++++
+ gcc/tree-vect-loop.cc | 5 ++---
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+ create mode 100644 gcc/testsuite/gfortran.dg/vect/vect-early-break_1-PR113808.f90
+
+diff --git a/gcc/testsuite/gfortran.dg/vect/vect-early-break_1-PR113808.f90 b/gcc/testsuite/gfortran.dg/vect/vect-early-break_1-PR113808.f90
+new file mode 100644
+index 000000000000..5c339fa7a348
+--- /dev/null
++++ b/gcc/testsuite/gfortran.dg/vect/vect-early-break_1-PR113808.f90
+@@ -0,0 +1,21 @@
++! { dg-add-options vect_early_break }
++! { dg-require-effective-target vect_early_break }
++! { dg-require-effective-target vect_long_long }
++! { dg-additional-options "-fopenmp-simd" }
++
++! { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } }
++
++program main
++ integer :: n, i,k
++ n = 11
++ do i = 1, n,2
++ !$omp simd lastprivate(k)
++ do k = 1, i + 41
++ if (k > 11 + 41 .or. k < 1) error stop
++ end do
++ end do
++ if (k /= 53) then
++ print *, k, 53
++ error stop
++ endif
++end
+diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
+index 190df9ec7741..eed2268e9bae 100644
+--- a/gcc/tree-vect-loop.cc
++++ b/gcc/tree-vect-loop.cc
+@@ -10950,7 +10950,7 @@ vectorizable_live_operation (vec_info *vinfo, stmt_vec_info stmt_info,
+ did. For the live values we want the value at the start of the iteration
+ rather than at the end. */
+ edge main_e = LOOP_VINFO_IV_EXIT (loop_vinfo);
+- bool restart_loop = LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo);
++ bool all_exits_as_early_p = LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo);
+ FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, lhs)
+ if (!is_gimple_debug (use_stmt)
+ && !flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
+@@ -10966,8 +10966,7 @@ vectorizable_live_operation (vec_info *vinfo, stmt_vec_info stmt_info,
+ /* For early exit where the exit is not in the BB that leads
+ to the latch then we're restarting the iteration in the
+ scalar loop. So get the first live value. */
+- restart_loop = restart_loop || !main_exit_edge;
+- if (restart_loop
++ if ((all_exits_as_early_p || !main_exit_edge)
+ && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def)
+ {
+ tmp_vec_lhs = vec_lhs0;
+--
+2.43.0
+
diff --git a/14.0.0/gentoo/78_all_PR113776-c-boolean-conversion.patch b/14.0.0/gentoo/78_all_PR113776-c-boolean-conversion.patch
new file mode 100644
index 0000000..52d731f
--- /dev/null
+++ b/14.0.0/gentoo/78_all_PR113776-c-boolean-conversion.patch
@@ -0,0 +1,117 @@
+From bfcee89a63538b80b966b2fa7ad21d4d38fd8b3c Mon Sep 17 00:00:00 2001
+From: Joseph Myers <josmyers@redhat.com>
+Date: Thu, 8 Feb 2024 01:34:09 +0000
+Subject: [PATCH] c: Fix boolean conversion of floating constant as integer
+ constant expression [PR113776]
+
+My fix for bug 111059 and bug 111911 caused a conversion of a floating
+constant to boolean to wrongly no longer be considered an integer
+constant expression, because logic to insert a NOP_EXPR in
+c_objc_common_truthvalue_conversion for an argument not an integer
+constant expression itself now took place after rather than before the
+conversion to bool. In the specific case of casting a floating
+constant to bool, the result is an integer constant expression even
+though the argument isn't (build_c_cast deals with ensuring that casts
+to integer type of anything of floating type more complicated than a
+single floating constant don't get wrongly treated as integer constant
+expressions even if they fold to constants), so fix the logic in
+c_objc_common_truthvalue_conversion to handle that special case.
+
+Bootstrapped with no regressions for x86_64-pc-linux-gnu.
+
+ PR c/113776
+
+gcc/c
+ * c-typeck.cc (c_objc_common_truthvalue_conversion): Return an
+ integer constant expression for boolean conversion of floating
+ constant.
+
+gcc/testsuite/
+ * gcc.dg/pr113776-1.c, gcc.dg/pr113776-2.c, gcc.dg/pr113776-3.c,
+ gcc.dg/pr113776-4.c: New tests.
+
+(cherry picked from commit bfd72bb44eca83b0db2b0bab895f27a8a44247a2)
+---
+ gcc/c/c-typeck.cc | 12 +++++++++++-
+ gcc/testsuite/gcc.dg/pr113776-1.c | 5 +++++
+ gcc/testsuite/gcc.dg/pr113776-2.c | 4 ++++
+ gcc/testsuite/gcc.dg/pr113776-3.c | 7 +++++++
+ gcc/testsuite/gcc.dg/pr113776-4.c | 6 ++++++
+ 5 files changed, 33 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.dg/pr113776-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr113776-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr113776-3.c
+ create mode 100644 gcc/testsuite/gcc.dg/pr113776-4.c
+
+diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
+index 3b519c48ae0a..ddeab1e2a8a1 100644
+--- a/gcc/c/c-typeck.cc
++++ b/gcc/c/c-typeck.cc
+@@ -13572,7 +13572,17 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr, tree type)
+ break;
+ }
+
+- int_const = (TREE_CODE (expr) == INTEGER_CST && !TREE_OVERFLOW (expr));
++ /* Conversion of a floating constant to boolean goes through here
++ and yields an integer constant expression. Otherwise, the result
++ is only an integer constant expression if the argument is. */
++ int_const = ((TREE_CODE (expr) == INTEGER_CST && !TREE_OVERFLOW (expr))
++ || ((TREE_CODE (expr) == REAL_CST
++ || TREE_CODE (expr) == COMPLEX_CST)
++ && (TREE_CODE (type) == BOOLEAN_TYPE
++ || (TREE_CODE (type) == ENUMERAL_TYPE
++ && ENUM_UNDERLYING_TYPE (type) != NULL_TREE
++ && (TREE_CODE (ENUM_UNDERLYING_TYPE (type))
++ == BOOLEAN_TYPE)))));
+ int_operands = EXPR_INT_CONST_OPERANDS (expr);
+ if (int_operands && TREE_CODE (expr) != INTEGER_CST)
+ {
+diff --git a/gcc/testsuite/gcc.dg/pr113776-1.c b/gcc/testsuite/gcc.dg/pr113776-1.c
+new file mode 100644
+index 000000000000..36190fbc3fec
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr113776-1.c
+@@ -0,0 +1,5 @@
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -pedantic" } */
++
++char d[(_Bool)0.5 == 1 ? 1 : -1];
++char f[(_Bool)0.0 == 0 ? 1 : -1];
+diff --git a/gcc/testsuite/gcc.dg/pr113776-2.c b/gcc/testsuite/gcc.dg/pr113776-2.c
+new file mode 100644
+index 000000000000..9e88210892a4
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr113776-2.c
+@@ -0,0 +1,4 @@
++/* { dg-do compile } */
++/* { dg-options "-std=c11 -pedantic" } */
++
++enum e { A = (_Bool) 0.0, B = (_Bool) 0.5, C = (_Bool) 1.0 };
+diff --git a/gcc/testsuite/gcc.dg/pr113776-3.c b/gcc/testsuite/gcc.dg/pr113776-3.c
+new file mode 100644
+index 000000000000..c615994a89f6
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr113776-3.c
+@@ -0,0 +1,7 @@
++/* { dg-do compile } */
++/* { dg-options "-std=c23 -pedantic" } */
++
++enum ebool : bool { BF, BT };
++
++char d[(enum ebool)0.5 == 1 ? 1 : -1];
++char f[(enum ebool)0.0 == 0 ? 1 : -1];
+diff --git a/gcc/testsuite/gcc.dg/pr113776-4.c b/gcc/testsuite/gcc.dg/pr113776-4.c
+new file mode 100644
+index 000000000000..1b57557746e1
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/pr113776-4.c
+@@ -0,0 +1,6 @@
++/* { dg-do compile } */
++/* { dg-options "-std=c23 -pedantic" } */
++
++enum ebool : bool { BF, BT };
++
++enum e { A = (enum ebool) 0.0, B = (enum ebool) 0.5, C = (enum ebool) 1.0 };
+--
+2.43.0
+
diff --git a/14.0.0/gentoo/README.history b/14.0.0/gentoo/README.history
index afaa988..dd2e0a0 100644
--- a/14.0.0/gentoo/README.history
+++ b/14.0.0/gentoo/README.history
@@ -1,3 +1,10 @@
+20 8 Feb 2024
+
+ + 75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch
+ + 76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch
+ + 77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch
+ + 78_all_PR113776-c-boolean-conversion.patch
+
19 5 Feb 2024
- 76_all_PR113467-vect-miscompile.patch