Bug 40135 - using alias-set zero for union accesses necessary because of RTL alias oracle
Summary: using alias-set zero for union accesses necessary because of RTL alias oracle
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.5.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: alias, missed-optimization
Depends on:
Blocks: 71002
  Show dependency treegraph
 
Reported: 2009-05-13 20:30 UTC by Richard Biener
Modified: 2019-10-23 12:35 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-01-07 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2009-05-13 20:30:43 UTC
The RTL alias oracle does defer to TBAA even for the case of disambiguating
two accesses based on decls.  This makes

  /* Permit type-punning when accessing a union, provided the access
     is directly through the union.  For example, this code does not
     permit taking the address of a union member and then storing
     through it.  Even the type-punning allowed here is a GCC
     extension, albeit a common and useful one; the C standard says
     that such accesses have implementation-defined behavior.  */
  for (u = t;
       TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
       u = TREE_OPERAND (u, 0))
    if (TREE_CODE (u) == COMPONENT_REF
        && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
      return 0;

in c-common.c necessary which needlessly pessimizes TBAA in the face
of union accesses.
Comment 1 Richard Biener 2009-05-13 20:31:29 UTC
The tree alias oracle gets this right.
Comment 2 Andrew Pinski 2012-01-07 21:41:20 UTC
Confirmed.
Comment 3 Richard Biener 2014-09-08 14:11:30 UTC
At least improved (but maybe not fixed) by

2010-02-16  Richard Guenther  <rguenther@suse.de>

        * alias.c (memrefs_conflict_p): Distinguish must-alias from don't know.
        (true_dependence): If memrefs_conflict_p computes must-alias
        trust it.  Move TBAA check after offset-based disambiguation.
        (canon_true_dependence): Likewise.
Comment 4 Richard Biener 2014-09-08 14:12:50 UTC
Ok it still has in the function comment

   ???  Contrary to the tree alias oracle this does not return
   one for X + non-constant and Y + non-constant when X and Y are equal.
   If that is fixed the TBAA hack for union type-punning can be removed.  */

which explains what is remaining to do.
Comment 5 Richard Biener 2014-09-08 14:20:53 UTC
Eventually just removing the call to mems_in_disjoint_alias_sets_p fixes the
rest (rtx_refs_may_alias_p will apply TBAA as well, _after_ positively
bailing out on the union punning).
Comment 6 Richard Biener 2014-09-09 09:00:29 UTC
For reference I see for example

FAIL: gcc.target/i386/avx2-vpblendd128-2.c execution test
FAIL: gcc.target/i386/avx2-vpblendd256-2.c execution test
FAIL: gcc.target/i386/avx2-vpblendw-2.c execution test
FAIL: gcc.target/i386/avx2-vpbroadcastd128-2.c execution test
FAIL: gcc.target/i386/avx2-vpbroadcastd256-2.c execution test
FAIL: gcc.target/i386/avx2-vpbroadcastw128-2.c execution test
FAIL: gcc.target/i386/avx2-vpbroadcastw256-2.c execution test
FAIL: gcc.target/i386/avx2-vpermd-2.c execution test
FAIL: gcc.target/i386/avx2-vpermps-2.c execution test
FAIL: gcc.target/i386/avx2-vpmaxsd-2.c execution test
FAIL: gcc.target/i386/avx2-vpmaxsw-2.c execution test
FAIL: gcc.target/i386/avx2-vpmaxud-2.c execution test
FAIL: gcc.target/i386/avx2-vpmaxuw-2.c execution test
FAIL: gcc.target/i386/avx2-vpminsd-2.c execution test
FAIL: gcc.target/i386/avx2-vpminsw-2.c execution test
FAIL: gcc.target/i386/avx2-vpminud-2.c execution test
FAIL: gcc.target/i386/avx2-vpminuw-2.c execution test
FAIL: gcc.target/i386/avx2-vpmuldq-2.c execution test
FAIL: gcc.target/i386/avx2-vpmulhrsw-2.c execution test
FAIL: gcc.target/i386/avx2-vpmulhuw-2.c execution test
FAIL: gcc.target/i386/avx2-vpmulhw-2.c execution test
FAIL: gcc.target/i386/avx2-vpmulld-2.c execution test
...
FAIL: gcc.target/i386/avx2-vpunpckhdq-2.c execution test
FAIL: gcc.target/i386/avx2-vpunpckhwd-2.c execution test
FAIL: gcc.target/i386/avx2-vpunpckldq-2.c execution test
FAIL: gcc.target/i386/avx2-vpunpcklwd-2.c execution test

but for example gcc.target/i386/avx2-vpblendd128-2.c contains "invalid"
type-punning through unions:

static void
init_pblendd128 (int *src1, int *src2, int seed)
{
  int i, sign = 1;

  for (i = 0; i < 4; i++)
    {
      src1[i] = (i + seed) * (i + seed) * sign;
      src2[i] = (i + seed + 20) * sign;
      sign = -sign;
    }
}
...
static void
avx2_test (void)
{
  union128i_d src1, src2, dst;
  int dst_ref[4];
  int i;

  for (i = 0; i < NUM; i++)
    {
      init_pblendd128 (src1.a, src2.a, i);

      dst.x = _mm_blend_epi32 (src1.x, src2.x, MASK);

which stores into src1/src2 via a pointer access and only reads via a direct
access to the union.

That's not how the GCC extension specifies union type-punning. I've filed
PR63211 for that.

Here the stores do not end up in alias-set zero and with removing the
c-common.c hack the loads also end up not using alias-set zero.  Without
the fix the loads use alias-set zero and thus keep the int-stores live.

There is also no easy must-alias to identify here as the stores happen
in a loop.
Comment 7 Richard Biener 2019-10-23 12:35:31 UTC
Fixed by

2016-06-29  Richard Biener  <rguenther@suse.de>

        PR middle-end/71002
        * c-common.c (c_common_get_alias_set): Remove union type punning case.

        * alias.c (component_uses_parent_alias_set_from): Handle
        type punning through union accesses by using the union alias set.
        * gimple.c (gimple_get_alias_set): Remove union type punning case.