https://gcc.gnu.org/g:d5d7dfab811de74cff88759785d0d5068b3b1121
commit r15-9535-gd5d7dfab811de74cff88759785d0d5068b3b1121 Author: Eric Botcazou <ebotca...@gcc.gnu.org> Date: Wed Apr 16 22:01:31 2025 +0200 Fix wrong optimization of conditional expression with enumeration type This is a regression introduced on the mainline and 14 branch by: https://gcc.gnu.org/pipermail/gcc-cvs/2023-October/391658.html The change bypasses int_fits_type_p (essentially) to work around the signedness constraints, but in doing so disregards the peculiarities of boolean types whose precision is not 1 dealt with by the predicate, leading to the creation of a problematic conversion here. Fixed by special-casing boolean types whose precision is not 1, as done in several other places. gcc/ * tree-ssa-phiopt.cc (factor_out_conditional_operation): Do not bypass the int_fits_type_p test for boolean types whose precision is not 1. gcc/testsuite/ * gnat.dg/opt105.adb: New test. * gnat.dg/opt105_pkg.ads, gnat.dg/opt105_pkg.adb: New helper. Diff: --- gcc/testsuite/gnat.dg/opt105.adb | 30 ++++++++++++++++++++++++++++++ gcc/testsuite/gnat.dg/opt105_pkg.adb | 6 ++++++ gcc/testsuite/gnat.dg/opt105_pkg.ads | 11 +++++++++++ gcc/tree-ssa-phiopt.cc | 9 ++++++--- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/gcc/testsuite/gnat.dg/opt105.adb b/gcc/testsuite/gnat.dg/opt105.adb new file mode 100644 index 000000000000..eb2c19733a40 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105.adb @@ -0,0 +1,30 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Opt105_Pkg; use Opt105_Pkg; + +procedure Opt105 is + + Val : constant Enum := + (if Enabled then (if Disabled then Two else One) else Three); + +begin + if Cond1 then + return; + end if; + + if Cond2 then + return; + end if; + + case Val is + when One => + raise Program_Error; + + when Two => + raise Constraint_Error; + + when Three => + null; + end case; +end; diff --git a/gcc/testsuite/gnat.dg/opt105_pkg.adb b/gcc/testsuite/gnat.dg/opt105_pkg.adb new file mode 100644 index 000000000000..e00de943dbff --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105_pkg.adb @@ -0,0 +1,6 @@ +package body Opt105_Pkg is + + function Cond1 return Boolean is (False); + function Cond2 return Boolean is (False); + +end Opt105_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt105_pkg.ads b/gcc/testsuite/gnat.dg/opt105_pkg.ads new file mode 100644 index 000000000000..2b373b720c5b --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105_pkg.ads @@ -0,0 +1,11 @@ +package Opt105_Pkg is + + type Enum is (One, Two, Three); + + Enabled : Boolean := False; + Disabled : Boolean := False; + + function Cond1 return Boolean; + function Cond2 return Boolean; + +end Opt105_Pkg; diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 7d2d1696ee70..a194bf675e4e 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -403,12 +403,15 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt))) return false; - /* Only handle if arg1 is a INTEGER_CST and one that fits - into the new type or if it is the same precision. */ + /* If arg1 is an INTEGER_CST, fold it to new type if it fits, or else + if the bits will not be modified during the conversion, except for + boolean types whose precision is not 1 (see int_fits_type_p). */ if (!INTEGRAL_TYPE_P (TREE_TYPE (new_arg0)) || !(int_fits_type_p (arg1, TREE_TYPE (new_arg0)) || (TYPE_PRECISION (TREE_TYPE (new_arg0)) - == TYPE_PRECISION (TREE_TYPE (arg1))))) + == TYPE_PRECISION (TREE_TYPE (arg1)) + && (TREE_CODE (TREE_TYPE (new_arg0)) != BOOLEAN_TYPE + || TYPE_PRECISION (TREE_TYPE (new_arg0)) == 1)))) return false; /* For the INTEGER_CST case, we are just moving the