aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2025-04-16 22:01:31 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2025-04-16 22:05:00 +0200
commitd5d7dfab811de74cff88759785d0d5068b3b1121 (patch)
tree4def80d1caecea3c3ae23d2e7234b2b5351d2aa7
parentdbffeadf7f682625c7ac8c251ee62c02c90f32df (diff)
downloadgcc-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.adb30
-rw-r--r--gcc/testsuite/gnat.dg/opt105_pkg.adb6
-rw-r--r--gcc/testsuite/gnat.dg/opt105_pkg.ads11
-rw-r--r--gcc/tree-ssa-phiopt.cc9
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