]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix crash with constant initializer caused by IPA
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 5 Jun 2025 11:20:26 +0000 (13:20 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Thu, 5 Jun 2025 13:27:12 +0000 (15:27 +0200)
The testcase compiled with -O2 -gnatn makes the compiler crash in
vect_can_force_dr_alignment_p during SLP vectorization:

  if (decl_in_symtab_p (decl)
      && !symtab_node::get (decl)->can_increase_alignment_p ())
    return false;

because symtab_node::get (decl) returns a null node.  The phenomenon occurs
for a pair of twin symbols listed like so in .cgraph:

Opt7_Pkg.T12b/17 (Opt7_Pkg.T12b)
  Type: variable definition analyzed
  Visibility: semantic_interposition external public artificial
  Aux: @0x44d45e0
  References:
  Referring: opt7_pkg__enum_name_table/13 (addr) opt7_pkg__enum_name_table/13
(addr)
  Availability: not-ready
  Varpool flags: initialized read-only const-value-known

Opt7_Pkg.T8b/16 (Opt7_Pkg.T8b)
  Type: variable definition analyzed
  Visibility: semantic_interposition external public artificial
  Aux: @0x7f9fda3fff00
  References:
  Referring: opt7_pkg__enum_name_table/13 (addr) opt7_pkg__enum_name_table/13
(addr)
  Availability: not-ready
  Varpool flags: initialized read-only const-value-known

with:

opt7_pkg__enum_name_table/13 (Opt7_Pkg.Enum_Name_Table)
  Type: variable definition analyzed
  Visibility: semantic_interposition external public
  Aux: @0x44d45e0
  References: Opt7_Pkg.T8b/16 (addr) Opt7_Pkg.T8b/16 (addr) Opt7_Pkg.T12b/17
(addr) Opt7_Pkg.T12b/17 (addr)
  Referring: opt7_pkg__image/2 (read) opt7_pkg__image/2 (read)
opt7_pkg__image/2 (read) opt7_pkg__image/2 (read) opt7_pkg__image/2 (read)
opt7_pkg__image/2 (read) opt7_pkg__image/2 (read) opt7_pkg__image/2 (read)
  Availability: not-ready
  Varpool flags: initialized read-only const-value-known

being the crux of the matter.

What happens is that symtab_remove_unreachable_nodes leaves the last symbol
in kind of a limbo state: in .remove_symbols, we have:

opt7_pkg__enum_name_table/13 (Opt7_Pkg.Enum_Name_Table)
  Type: variable
  Body removed by symtab_remove_unreachable_nodes
  Visibility: externally_visible semantic_interposition external public
  References:
  Referring: opt7_pkg__image/2 (read) opt7_pkg__image/2 (read)
  Availability: not_available
  Varpool flags: initialized read-only const-value-known

This means that the "body" (DECL_INITIAL) of the symbol has been disregarded
during reachability analysis, causing the first two symbols to be discarded:

Reclaiming variables: Opt7_Pkg.T12b/17 Opt7_Pkg.T8b/16

but the DECL_INITIAL is explicitly preserved for later constant folding,
which makes it possible to retrofit the DECLs corresponding to the first
two symbols in the GIMPLE IR and ultimately leads to the crash.

gcc/
* tree-vect-data-refs.cc (vect_can_force_dr_alignment_p): Return
false if the variable has no symtab node.

gcc/testsuite/
* gnat.dg/specs/opt7.ads: New test.
* gnat.dg/specs/opt7_pkg.ads: New helper.
* gnat.dg/specs/opt7_pkg.adb: Likewise.

gcc/testsuite/gnat.dg/specs/opt7.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/opt7_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/opt7_pkg.ads [new file with mode: 0644]
gcc/tree-vect-data-refs.cc

diff --git a/gcc/testsuite/gnat.dg/specs/opt7.ads b/gcc/testsuite/gnat.dg/specs/opt7.ads
new file mode 100644 (file)
index 0000000..ee151f0
--- /dev/null
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatn" }
+
+with Opt7_Pkg; use Opt7_Pkg;
+
+package Opt7 is
+
+  type Rec is record
+    E : Enum;
+  end record;
+
+  function Image (R : Rec) return String is
+    (if R.E = A then Image (R.E) else "");
+
+end Opt7;
diff --git a/gcc/testsuite/gnat.dg/specs/opt7_pkg.adb b/gcc/testsuite/gnat.dg/specs/opt7_pkg.adb
new file mode 100644 (file)
index 0000000..1c9d79b
--- /dev/null
@@ -0,0 +1,15 @@
+package body Opt7_Pkg is
+
+  type Constant_String_Access is access constant String;
+
+  type Enum_Name is array (Enum) of Constant_String_Access;
+
+  Enum_Name_Table : constant Enum_Name :=
+    (A => new String'("A"), B => new String'("B"));
+
+  function Image (E : Enum) return String is
+  begin
+    return Enum_Name_Table (E).all;
+  end Image;
+
+end Opt7_Pkg;
diff --git a/gcc/testsuite/gnat.dg/specs/opt7_pkg.ads b/gcc/testsuite/gnat.dg/specs/opt7_pkg.ads
new file mode 100644 (file)
index 0000000..2dd271b
--- /dev/null
@@ -0,0 +1,9 @@
+-- { dg-excess-errors "no code generated" }
+
+package Opt7_Pkg is
+
+  type Enum is (A, B);
+
+  function Image (E : Enum) return String with Inline;
+
+end Opt7_Pkg;
index 3ba271b9e69273dbc7817a8e0b09e60af319c308..4ca9ab73d690001e165e8e866993a0656f96b7bd 100644 (file)
@@ -7151,7 +7151,8 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment)
     return false;
 
   if (decl_in_symtab_p (decl)
-      && !symtab_node::get (decl)->can_increase_alignment_p ())
+      && (!symtab_node::get (decl)
+         || !symtab_node::get (decl)->can_increase_alignment_p ()))
     return false;
 
   if (TREE_STATIC (decl))