Hi,

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 that are 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.

Tested on x86-64/Linux, OK for the mainline and 14 branch?


2025-04-15  Eric Botcazou  <ebotca...@adacore.com>

        * 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.


2025-04-15  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt105.adb: New test.
        * gnat.dg/opt105_pkg.ads, gnat.dg/opt105_pkg.adb: New helper.

-- 
Eric Botcazou
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 7d2d1696ee7..a194bf675e4 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
-- { 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;
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;
package body Opt105_Pkg is

  function Cond1 return Boolean is (False);
  function Cond2 return Boolean is (False);

end Opt105_Pkg;

Reply via email to