Fix recent thinko in operand_equal_p
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 4 Nov 2022 10:23:12 +0000 (11:23 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Fri, 4 Nov 2022 14:14:50 +0000 (15:14 +0100)
There is a thinko in a recent improvement made to operand_equal_p where
the code just looks at operand 2 of COMPONENT_REF, if it is present, to
compare addresses.  That's wrong because operand 2 contains the number of
DECL_OFFSET_ALIGN-bit-sized words so, when DECL_OFFSET_ALIGN > 8, not all
the  bytes are included and some of them are in DECL_FIELD_BIT_OFFSET, see
get_inner_reference for the model computation.

In other words, you would need to compare operand 2 and DECL_OFFSET_ALIGN
and DECL_FIELD_BIT_OFFSET in this situation, but I'm not sure this is worth
the hassle in practice so the fix just removes this alternate handling.

gcc/
* fold-const.cc (operand_compare::operand_equal_p) <COMPONENT_REF>:
Do not take into account operand 2.
(operand_compare::hash_operand) <COMPONENT_REF>: Likewise.

gcc/testsuite/
* gnat.dg/opt99.adb: New test.
* gnat.dg/opt99_pkg1.ads, gnat.dg/opt99_pkg1.adb: New helper.
* gnat.dg/opt99_pkg2.ads: Likewise.

gcc/fold-const.cc
gcc/testsuite/gnat.dg/opt99.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt99_pkg1.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt99_pkg1.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt99_pkg2.ads [new file with mode: 0644]

index 7e1ea58..b89cac9 100644 (file)
@@ -3377,9 +3377,6 @@ operand_compare::operand_equal_p (const_tree arg0, const_tree arg1,
                if (compare_address
                    && (flags & OEP_ADDRESS_OF_SAME_FIELD) == 0)
                  {
-                   if (TREE_OPERAND (arg0, 2)
-                       || TREE_OPERAND (arg1, 2))
-                     return OP_SAME_WITH_NULL (2);
                    tree field0 = TREE_OPERAND (arg0, 1);
                    tree field1 = TREE_OPERAND (arg1, 1);
 
@@ -3890,17 +3887,10 @@ operand_compare::hash_operand (const_tree t, inchash::hash &hstate,
              if (sflags & OEP_ADDRESS_OF)
                {
                  hash_operand (TREE_OPERAND (t, 0), hstate, flags);
-                 if (TREE_OPERAND (t, 2))
-                   hash_operand (TREE_OPERAND (t, 2), hstate,
-                                 flags & ~OEP_ADDRESS_OF);
-                 else
-                   {
-                     tree field = TREE_OPERAND (t, 1);
-                     hash_operand (DECL_FIELD_OFFSET (field),
-                                   hstate, flags & ~OEP_ADDRESS_OF);
-                     hash_operand (DECL_FIELD_BIT_OFFSET (field),
-                                   hstate, flags & ~OEP_ADDRESS_OF);
-                   }
+                 hash_operand (DECL_FIELD_OFFSET (TREE_OPERAND (t, 1)),
+                               hstate, flags & ~OEP_ADDRESS_OF);
+                 hash_operand (DECL_FIELD_BIT_OFFSET (TREE_OPERAND (t, 1)),
+                               hstate, flags & ~OEP_ADDRESS_OF);
                  return;
                }
              break;
diff --git a/gcc/testsuite/gnat.dg/opt99.adb b/gcc/testsuite/gnat.dg/opt99.adb
new file mode 100644 (file)
index 0000000..8805d47
--- /dev/null
@@ -0,0 +1,15 @@
+-- { dg-do run }
+-- { dg-options "-O" }
+
+with Opt99_Pkg1; use Opt99_Pkg1;
+
+procedure Opt99 is
+  C : constant My_Character := (D => True, C => ' ');
+  D : Derived;
+
+begin
+  Set (D, C, C);
+  if not D.C2.D then
+    raise Program_Error;
+  end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/opt99_pkg1.adb b/gcc/testsuite/gnat.dg/opt99_pkg1.adb
new file mode 100644 (file)
index 0000000..476b09c
--- /dev/null
@@ -0,0 +1,10 @@
+package body Opt99_Pkg1 is
+
+  procedure Set (D: in out Derived; C1, C2 : My_Character) is
+  begin
+    D.I  := 0;
+    D.C1 := C1;
+    D.C2 := C2;
+  end;
+
+end Opt99_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/opt99_pkg1.ads b/gcc/testsuite/gnat.dg/opt99_pkg1.ads
new file mode 100644 (file)
index 0000000..3e26561
--- /dev/null
@@ -0,0 +1,19 @@
+with Opt99_Pkg2;
+
+package Opt99_Pkg1 is
+
+  type My_Character (D : Boolean := False) is record
+    case D is
+      when False => null;
+      when True  => C : Character;
+    end case;
+  end record;
+
+  type Derived is new Opt99_Pkg2.Root with record
+    I : Integer;
+    C1, C2 : My_Character;
+  end record;
+
+  procedure Set (D: in out Derived; C1, C2 : My_Character);
+
+end Opt99_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/opt99_pkg2.ads b/gcc/testsuite/gnat.dg/opt99_pkg2.ads
new file mode 100644 (file)
index 0000000..09aaff1
--- /dev/null
@@ -0,0 +1,13 @@
+package Opt99_Pkg2 is
+
+  function Get_Max return Positive is (4);
+
+  C : constant Positive := Get_Max;
+
+  type Arr is array (1 .. C) of Integer;
+
+  type Root is tagged record
+    Data : Arr;
+  end record;
+
+end Opt99_Pkg2;