From 29fc9edc64e0e00a0ade3065238365a4aa46ec59 Mon Sep 17 00:00:00 2001 From: Sam James Date: Thu, 8 Feb 2024 10:48:38 +0000 Subject: 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 --- ...fix-ICE-when-moving-statements-to-empty-B.patch | 129 +++++++++++ ...fix-ICE-when-destination-BB-for-stores-st.patch | 250 +++++++++++++++++++++ ...-don-t-cache-restart_loop-in-vectorizable.patch | 93 ++++++++ .../78_all_PR113776-c-boolean-conversion.patch | 117 ++++++++++ 14.0.0/gentoo/README.history | 7 + 5 files changed, 596 insertions(+) create mode 100644 14.0.0/gentoo/75_all_PR113731_fix-ICE-when-moving-statements-to-empty-B.patch create mode 100644 14.0.0/gentoo/76_all_PR113750_fix-ICE-when-destination-BB-for-stores-st.patch create mode 100644 14.0.0/gentoo/77_all_PR113808-middle-end-don-t-cache-restart_loop-in-vectorizable.patch create mode 100644 14.0.0/gentoo/78_all_PR113776-c-boolean-conversion.patch 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 +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 +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 +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 +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 -- cgit v1.2.3-65-gdbad