diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2025-04-16 22:01:31 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2025-04-16 22:05:00 +0200 |
commit | d5d7dfab811de74cff88759785d0d5068b3b1121 (patch) | |
tree | 4def80d1caecea3c3ae23d2e7234b2b5351d2aa7 | |
parent | dbffeadf7f682625c7ac8c251ee62c02c90f32df (diff) | |
download | gcc-d5d7dfab811de74cff88759785d0d5068b3b1121.zip gcc-d5d7dfab811de74cff88759785d0d5068b3b1121.tar.gz gcc-d5d7dfab811de74cff88759785d0d5068b3b1121.tar.bz2 |
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.
-rw-r--r-- | gcc/testsuite/gnat.dg/opt105.adb | 30 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt105_pkg.adb | 6 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt105_pkg.ads | 11 | ||||
-rw-r--r-- | 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 0000000..eb2c197 --- /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 0000000..e00de94 --- /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 0000000..2b373b7 --- /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 7d2d169..a194bf6 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 |