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.
This commit is contained in:
parent
dbffeadf7f
commit
d5d7dfab81
4 changed files with 53 additions and 3 deletions
30
gcc/testsuite/gnat.dg/opt105.adb
Normal file
30
gcc/testsuite/gnat.dg/opt105.adb
Normal file
|
@ -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;
|
6
gcc/testsuite/gnat.dg/opt105_pkg.adb
Normal file
6
gcc/testsuite/gnat.dg/opt105_pkg.adb
Normal file
|
@ -0,0 +1,6 @@
|
|||
package body Opt105_Pkg is
|
||||
|
||||
function Cond1 return Boolean is (False);
|
||||
function Cond2 return Boolean is (False);
|
||||
|
||||
end Opt105_Pkg;
|
11
gcc/testsuite/gnat.dg/opt105_pkg.ads
Normal file
11
gcc/testsuite/gnat.dg/opt105_pkg.ads
Normal file
|
@ -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;
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue