Hi,
this is a regression present on the mainline and 8 branch in the form of wrong
code generated for an Ada program manipulating bit-packed boolean array types.
The problem is in the new range optimization code of the reassoc pass: from
_64 = _63 | 4;
_73 = _64 & 191;
_76 = _64 >> 6;
_77 = (boolean) _76;
_78 = (boolean) _64;
_79 = _77 | _78;
it deduces:
Optimizing range tests _76 +[0, 0] and _64 +[0, 0]
|...]
_64 = _63 | 4;
_73 = _64 & 191;
_76 = _64 >> 6;
_90 = _76 | _64;
_19 = _90 != 0;
_77 = (boolean) _76;
_78 = (boolean) _64;
_79 = _19;
which is not equivalent. The proposed fix is to avoid bypassing a conversion
to a boolean type from a type with greater precision in init_range_entry.
Tested on x86_64-suse-linux, OK for the mainline?
2018-07-16 Eric Botcazou <ebotca...@adacore.com>
PR tree-optimization/86514
* tree-ssa-reassoc.c (init_range_entry) <CASE_CONVERT>: Return for a
conversion to a boolean type from a type with greater precision.
2018-07-16 Eric Botcazou <ebotca...@adacore.com>
* gnat.dg/opt73.adb: New test.
--
Eric Botcazou
Index: tree-ssa-reassoc.c
===================================================================
--- tree-ssa-reassoc.c (revision 262658)
+++ tree-ssa-reassoc.c (working copy)
@@ -2168,8 +2168,13 @@ init_range_entry (struct range_entry *r,
continue;
CASE_CONVERT:
if (is_bool)
- goto do_default;
- if (TYPE_PRECISION (TREE_TYPE (arg0)) == 1)
+ {
+ if ((TYPE_PRECISION (exp_type) == 1
+ || TREE_CODE (exp_type) == BOOLEAN_TYPE)
+ && TYPE_PRECISION (TREE_TYPE (arg0)) > 1)
+ return;
+ }
+ else if (TYPE_PRECISION (TREE_TYPE (arg0)) == 1)
{
if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
is_bool = true;
-- { dg-do run }
-- { dg-options "-O" }
procedure Opt73 is
type Terminal_Set_Indexed_By_Non_Terminal is
array (Natural range <>, Natural range <>) of Boolean with Pack;
type Terminal_Set_Per_Non_Terminal
(Last_Terminal : Natural;
Last_Non_Terminal : Natural) is
record
Map : Terminal_Set_Indexed_By_Non_Terminal
(1 .. Last_Non_Terminal, 0 .. Last_Terminal);
end record;
Follow : Terminal_Set_Per_Non_Terminal (5, 4);
Expect : Terminal_Set_Per_Non_Terminal :=
(5, 4, (1 => (2 => True, others => False),
others => (others => False)));
procedure Get_Follow (Value : out Terminal_Set_Per_Non_Terminal) is
begin
Value.Map := (others => (others => False));
Value.Map (1, 2) := True;
Value.Map (2, 0) := Value.Map (2, 0) or Value.Map (1, 0);
end;
begin
Get_Follow (Follow);
if Follow /= Expect then
raise Program_Error;
end if;
end;