Bug 90450 - [9 Regression] Hash function in gather_mem_refs_stmt does not match with mem_ref_hasher::equal
Summary: [9 Regression] Hash function in gather_mem_refs_stmt does not match with mem_...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 10.0
: P2 normal
Target Milestone: 9.2
Assignee: Richard Biener
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-05-13 07:35 UTC by Martin Liška
Modified: 2019-06-06 11:08 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 10.0, 9.1.1
Known to fail: 9.1.0
Last reconfirmed: 2019-05-13 00:00:00


Attachments
patch (1.06 KB, patch)
2019-05-21 12:02 UTC, Richard Biener
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Liška 2019-05-13 07:35:32 UTC
As mentioned in following sub-thread: https://gcc.gnu.org/ml/gcc-patches/2018-10/msg01885.html

Using the sanitization patch I see:

$ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.dg/torture/pr63941.c -O2 -c
hash table checking failed: equal operator returns true for a pair of values with a different hash value
during GIMPLE pass: lim
/home/marxin/Programming/gcc/gcc/testsuite/gcc.dg/torture/pr63941.c: In function ‘fn1’:
/home/marxin/Programming/gcc/gcc/testsuite/gcc.dg/torture/pr63941.c:6:1: internal compiler error: in hashtab_chk_error, at hash-table.h:1015
    6 | fn1 ()
      | ^~~
0x1372cfd hashtab_chk_error
	/home/marxin/Programming/gcc/gcc/hash-table.h:1015
0x137e501 hash_table<mem_ref_hasher, false, xcallocator>::verify(ao_ref* const&, unsigned int)
	/home/marxin/Programming/gcc/gcc/hash-table.h:1036
0x137d5d5 hash_table<mem_ref_hasher, false, xcallocator>::find_slot_with_hash(ao_ref* const&, unsigned int, insert_option)
	/home/marxin/Programming/gcc/gcc/hash-table.h:953
0x137874a gather_mem_refs_stmt
	/home/marxin/Programming/gcc/gcc/tree-ssa-loop-im.c:1501
0x1378e4d analyze_memory_references
	/home/marxin/Programming/gcc/gcc/tree-ssa-loop-im.c:1625
0x137b334 tree_ssa_lim
	/home/marxin/Programming/gcc/gcc/tree-ssa-loop-im.c:2646
0x137b460 execute
	/home/marxin/Programming/gcc/gcc/tree-ssa-loop-im.c:2708
Comment 1 Richard Biener 2019-05-13 09:58:30 UTC
Not exactly sure what happens, need to investigate.  The testcase looks
innocous enough at least ...
Comment 2 Martin Liška 2019-05-13 10:12:48 UTC
(In reply to Richard Biener from comment #1)
> Not exactly sure what happens, need to investigate.  The testcase looks
> innocous enough at least ...

It's about 'd[f]' and 'd[0]' references. The former one is hashed in else branch and the later
in true branch. These are then equal in mem_ref_hasher::equal as operand_equal_p can return true
for these 2 array references.

  1479        if (aor.max_size_known_p ()
  1480            && aor.offset.is_constant (&offset)
  1481            && aor.size.is_constant (&size)
  1482            && aor.max_size.is_constant (&max_size)
  1483            && size == max_size
  1484            && (size % BITS_PER_UNIT) == 0
  1485            /* We're canonicalizing to a MEM where TYPE_SIZE specifies the
  1486               size.  Make sure this is consistent with the extraction.  */
  1487            && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (*mem)))
  1488            && known_eq (wi::to_poly_offset (TYPE_SIZE (TREE_TYPE (*mem))),
  1489                         aor.size)
  1490            && (mem_base = get_addr_base_and_unit_offset (aor.ref, &mem_off)))
  1491          {
  1492            hash = iterative_hash_expr (ao_ref_base (&aor), 0);
  1493            hash = iterative_hash_host_wide_int (offset, hash);
  1494            hash = iterative_hash_host_wide_int (size, hash);
  1495          }
  1496        else
  1497          {
  1498            hash = iterative_hash_expr (aor.ref, 0);
  1499            aor.max_size = -1;
  1500          }
Comment 3 rguenther@suse.de 2019-05-13 10:32:57 UTC
On Mon, 13 May 2019, marxin at gcc dot gnu.org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90450
> 
> --- Comment #2 from Martin Liška <marxin at gcc dot gnu.org> ---
> (In reply to Richard Biener from comment #1)
> > Not exactly sure what happens, need to investigate.  The testcase looks
> > innocous enough at least ...
> 
> It's about 'd[f]' and 'd[0]' references. The former one is hashed in else
> branch and the later
> in true branch. These are then equal in mem_ref_hasher::equal as
> operand_equal_p can return true
> for these 2 array references.

Huh?  Would have to debug this.  The equality function probably
should start with


 if (mem1->mem.max_size_known_p ()
     != obj2->max_size_known_p ())
   return false;

which may fix the issue.  As said, need to reproduce locally.
Comment 4 Richard Biener 2019-05-13 10:52:41 UTC
OK, so it's not operand_equal_p of d[f.1_1] and d[0] returning true but
the comparison involving the ao_ref pieces.  And indeed the variable-offset
one is fenced off by

          && (mem_base = get_addr_base_and_unit_offset (aor.ref, &mem_off)))

but using max_size == -1 as tie-breaker doesn't work for the entities in
the hash-table (we never compare!) because we only use max_size == -1
on the on-stack ref we use for the find_slot_with_hash call but actually
insert the original value:

...
      else
        {
          hash = iterative_hash_expr (aor.ref, 0);
          aor.max_size = -1;
        }
      slot = memory_accesses.refs->find_slot_with_hash (&aor, hash, INSERT);
      aor.max_size = saved_maxsize;

so the checking code is "flawed"...  (I thought we didn't want to lose
the extra disambiguation opportunity from having known max_size).

So - not really a bug.

Could be worked around by extra runtime overhead checking everything
we check before the decision on the hashing scheme also in the equality
routine.  Or finding some spare bit in the non-loop-IM private ao_ref
stucture.   Or constructing a full im_mem_ref on the stack even if
hash lookup only really needs the ao_ref and put this extra bit there.

Bah :/

Guard the checking on entry type == comparable type?
Comment 5 Richard Biener 2019-05-21 12:02:27 UTC
Created attachment 46389 [details]
patch

The attached should fix the issue.  Martin?
Comment 6 Richard Biener 2019-05-22 07:44:59 UTC
Author: rguenth
Date: Wed May 22 07:44:24 2019
New Revision: 271503

URL: https://gcc.gnu.org/viewcvs?rev=271503&root=gcc&view=rev
Log:
2019-05-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90450
	* tree-ssa-loop-im.c (struct im_mem_ref): Add ref_decomposed.
	(mem_ref_hasher::equal): Check it.
	(mem_ref_alloc): Initialize it.
	(gather_mem_refs_stmt): Set it.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/tree-ssa-loop-im.c
Comment 7 Richard Biener 2019-05-22 07:46:10 UTC
Fixed on trunk sofar.
Comment 8 Richard Biener 2019-06-06 11:07:17 UTC
Author: rguenth
Date: Thu Jun  6 11:06:45 2019
New Revision: 271995

URL: https://gcc.gnu.org/viewcvs?rev=271995&root=gcc&view=rev
Log:
2019-06-06  Richard Biener  <rguenther@suse.de>

	Backport from mainline
	2019-05-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90450
	* tree-ssa-loop-im.c (struct im_mem_ref): Add ref_decomposed.
	(mem_ref_hasher::equal): Check it.
	(mem_ref_alloc): Initialize it.
	(gather_mem_refs_stmt): Set it.

	2019-05-15  Richard Biener  <rguenther@suse.de>

	PR c/90474
	* c-common.c (c_common_mark_addressable_vec): Also mark
	a COMPOUND_LITERAL_EXPR_DECL addressable similar to
	c_mark_addressable.

	2019-05-13  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90402
	* tree-if-conv.c (tree_if_conversion): Value number only
	the loop body by making the latch an exit of the region
	as well.
	* tree-ssa-sccvn.c (process_bb): Add flag whether to skip
	processing PHIs.
	(do_rpo_vn): Deal with multiple edges into the entry block
	that are not backedges inside the region by skipping PHIs
	of the entry block.

	* gcc.dg/torture/pr90402-1.c: New testcase.

	2019-05-06  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/90328
	* tree-data-ref.h (dr_may_alias_p): Pass in the actual loop nest.
	* tree-data-ref.c (dr_may_alias_p): Check whether the clique
	is valid in the loop nest before using it.
	(initialize_data_dependence_relation): Adjust.
	* graphite-scop-detection.c (build_alias_set): Pass the SCOP enclosing
	loop as loop-nest to dr_may_alias_p.

	* gcc.dg/torture/pr90328.c: New testcase.

Added:
    branches/gcc-9-branch/gcc/testsuite/gcc.dg/torture/pr90328.c
    branches/gcc-9-branch/gcc/testsuite/gcc.dg/torture/pr90402-1.c
Modified:
    branches/gcc-9-branch/gcc/ChangeLog
    branches/gcc-9-branch/gcc/c-family/ChangeLog
    branches/gcc-9-branch/gcc/c-family/c-common.c
    branches/gcc-9-branch/gcc/graphite-scop-detection.c
    branches/gcc-9-branch/gcc/testsuite/ChangeLog
    branches/gcc-9-branch/gcc/tree-data-ref.c
    branches/gcc-9-branch/gcc/tree-data-ref.h
    branches/gcc-9-branch/gcc/tree-if-conv.c
    branches/gcc-9-branch/gcc/tree-ssa-loop-im.c
    branches/gcc-9-branch/gcc/tree-ssa-sccvn.c
Comment 9 Richard Biener 2019-06-06 11:08:01 UTC
Fixed.