Bug 90303 - [9 Regression] ICE in hash_odr_name with fastcall attribute starting with r267359
Summary: [9 Regression] ICE in hash_odr_name with fastcall attribute starting with r26...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 9.0
: P2 normal
Target Milestone: 9.2
Assignee: Jakub Jelinek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-05-01 18:01 UTC by Jakub Jelinek
Modified: 2019-05-17 20:08 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-05-02 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2019-05-01 18:01:03 UTC
struct A { virtual void foo (); };
template <class> class B : A {};
typedef void (__attribute__((fastcall)) F) ();
B<F> e;

ICEs with -m32 on x86_64-linux (and on i686-linux), starting with r267359.
Comment 1 Jakub Jelinek 2019-05-01 18:23:54 UTC
Seems TYPE_CANONICAL is NULL on the RECORD_TYPE B as well as its TYPE_MAIN_VARIANT.
Comment 2 Jakub Jelinek 2019-05-02 08:50:04 UTC
This comes from build_type_attribute_qual_variant:
1159	      if (ntype != dtype)
1160		/* This variant was already in the hash table, don't mess with
1161		   TYPE_CANONICAL.  */;
1162	      else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
1163		       || !comp_type_attributes (ntype, ttype))
1164		/* If the target-dependent attributes make NTYPE different from
1165		   its canonical type, we will need to use structural equality
1166		   checks for this type.
1167	
1168		   We shouldn't get here for stripping attributes from a type;
1169		   the no-attribute type might not need structural comparison.  But
1170		   we can if was discarded from type_hash_table.  */
1171		SET_TYPE_STRUCTURAL_EQUALITY (ntype);
1172	      else if (TYPE_CANONICAL (ntype) == ntype)
1173		TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
for the FUNCTION_TYPE, so the fntype has NULL TYPE_CANONICAL and then:
9558		  if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
9559		    /* This instantiation is another name for the primary
9560		       template type. Set the TYPE_CANONICAL field
9561		       appropriately. */
9562		    TYPE_CANONICAL (t) = template_type;
9563		  else if (any_template_arguments_need_structural_equality_p (arglist))
9564		    /* Some of the template arguments require structural
9565		       equality testing, so this template class requires
9566		       structural equality testing. */
9567		    SET_TYPE_STRUCTURAL_EQUALITY (t);
because any_template_arguments_need_structural_equality_p is true, we keep TYPE_CANONICAL cleared.

The following patch fixes the ICE for me, but am not sure if it is 100% correct.  I don't see other parts in the middle-end that would not accept types with NULL TYPE_CANONICAL, they sometimes punt, or do more careful comparison, but don't just ICE.

--- gcc/ipa-devirt.c.jj	2019-04-15 19:45:28.796340266 +0200
+++ gcc/ipa-devirt.c	2019-05-02 10:46:03.077896176 +0200
@@ -2020,7 +2020,7 @@ obj_type_ref_class (const_tree ref)
   ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
   gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
   tree ret = TREE_TYPE (ref);
-  if (!in_lto_p)
+  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))
     ret = TYPE_CANONICAL (ret);
   else
     ret = get_odr_type (ret)->type;
@@ -2042,7 +2042,7 @@ get_odr_type (tree type, bool insert)
   int base_id = -1;
 
   type = TYPE_MAIN_VARIANT (type);
-  if (!in_lto_p)
+  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
     type = TYPE_CANONICAL (type);
 
   gcc_checking_assert (can_be_name_hashed_p (type)
Comment 3 Jan Hubicka 2019-05-02 08:57:29 UTC
> This comes from build_type_attribute_qual_variant:
> 1159          if (ntype != dtype)
> 1160            /* This variant was already in the hash table, don't mess with
> 1161               TYPE_CANONICAL.  */;
> 1162          else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
> 1163                   || !comp_type_attributes (ntype, ttype))
> 1164            /* If the target-dependent attributes make NTYPE different from
> 1165               its canonical type, we will need to use structural equality
> 1166               checks for this type.
> 1167    
> 1168               We shouldn't get here for stripping attributes from a type;
> 1169               the no-attribute type might not need structural comparison. 
> But
> 1170               we can if was discarded from type_hash_table.  */
> 1171            SET_TYPE_STRUCTURAL_EQUALITY (ntype);

Hmm, bit odd code.
> 
> --- gcc/ipa-devirt.c.jj 2019-04-15 19:45:28.796340266 +0200
> +++ gcc/ipa-devirt.c    2019-05-02 10:46:03.077896176 +0200
> @@ -2020,7 +2020,7 @@ obj_type_ref_class (const_tree ref)
>    ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
>    gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
>    tree ret = TREE_TYPE (ref);
> -  if (!in_lto_p)
> +  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))

This code is here to go from incomplete type to complete type after
free_lang_data was run.  By punting here we will lose optimization.
Perhaps it is safe to go to main variant first and then to type
canonical since the main variant will not have type_canonical cleared by
hunk above?

Honza
>      ret = TYPE_CANONICAL (ret);
>    else
>      ret = get_odr_type (ret)->type;
> @@ -2042,7 +2042,7 @@ get_odr_type (tree type, bool insert)
>    int base_id = -1;
> 
>    type = TYPE_MAIN_VARIANT (type);
> -  if (!in_lto_p)
> +  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
>      type = TYPE_CANONICAL (type);
> 
>    gcc_checking_assert (can_be_name_hashed_p (type)
> 
> -- 
> You are receiving this mail because:
> You are on the CC list for the bug.
Comment 4 Jakub Jelinek 2019-05-02 09:01:40 UTC
No, TYPE_CANONICAL (TYPE_MAIN_VARIANT (type)) is also NULL, for the same reasons.
It is a template instantiation with a template parameter that needs structural equality.
Comment 5 Jan Hubicka 2019-05-02 09:19:57 UTC
I see, i suppose we may lose some optimizations in early opts because of
this but your patch is safe and I don't think the missed optimizations
are very important (if they are we should avoid having structural
equality on such types)

Honza
Comment 6 Jakub Jelinek 2019-05-03 07:32:37 UTC
Author: jakub
Date: Fri May  3 07:32:06 2019
New Revision: 270835

URL: https://gcc.gnu.org/viewcvs?rev=270835&root=gcc&view=rev
Log:
	PR tree-optimization/90303
	* ipa-devirt.c (obj_type_ref_class, get_odr_type): Don't use
	TYPE_CANONICAL for TYPE_STRUCTURAL_EQUALITY_P types in !in_lto_p mode.

	* g++.target/i386/pr90303.C: New test.

Added:
    trunk/gcc/testsuite/g++.target/i386/pr90303.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ipa-devirt.c
    trunk/gcc/testsuite/ChangeLog
Comment 7 Jakub Jelinek 2019-05-03 12:40:55 UTC
Fixed for 10.1+ so far.
Comment 8 Jakub Jelinek 2019-05-17 19:48:56 UTC
Author: jakub
Date: Fri May 17 19:48:25 2019
New Revision: 271349

URL: https://gcc.gnu.org/viewcvs?rev=271349&root=gcc&view=rev
Log:
	Backported from mainline
	2019-05-03  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/90303
	* ipa-devirt.c (obj_type_ref_class, get_odr_type): Don't use
	TYPE_CANONICAL for TYPE_STRUCTURAL_EQUALITY_P types in !in_lto_p mode.

	* g++.target/i386/pr90303.C: New test.

Added:
    branches/gcc-9-branch/gcc/testsuite/g++.target/i386/pr90303.C
Modified:
    branches/gcc-9-branch/gcc/ChangeLog
    branches/gcc-9-branch/gcc/ipa-devirt.c
    branches/gcc-9-branch/gcc/testsuite/ChangeLog
Comment 9 Jakub Jelinek 2019-05-17 20:08:53 UTC
Fixed.