https://gcc.gnu.org/g:62151c32e3dc06322dec5543dc231e310140d3a3

commit r14-11645-g62151c32e3dc06322dec5543dc231e310140d3a3
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               | 11 ++++++++---
 4 files changed, 55 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 b8c5cc0e0d30..89236637a591 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -319,11 +319,16 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
       /* arg0_def_stmt should be conditional.  */
       if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb 
(arg0_def_stmt)))
        return NULL;
-      /* If arg1 is an INTEGER_CST, fold it to new type.  */
+
+      /* 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))))
        {
          if (gimple_assign_cast_p (arg0_def_stmt))
            {
@@ -340,7 +345,7 @@ factor_out_conditional_operation (edge e0, edge e1, gphi 
*phi,
                 it will not generate any zero/sign extend in that case.  */
              if ((TYPE_PRECISION (TREE_TYPE (new_arg0))
                    != TYPE_PRECISION (TREE_TYPE (arg1)))
-                 && new_arg0 != gimple_cond_lhs (cond_stmt)
+                 && new_arg0 != gimple_cond_lhs (cond_stmt)
                  && new_arg0 != gimple_cond_rhs (cond_stmt)
                  && gimple_bb (arg0_def_stmt) == e0->src)
                {

Reply via email to