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

Reply via email to