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;