public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "jakub at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug rtl-optimization/23324] [4.1 Regression] unsigned bitfield in struct not accessed correctly at -O2 and above
Date: Thu, 08 Sep 2005 14:04:00 -0000	[thread overview]
Message-ID: <20050908140347.12651.qmail@sourceware.org> (raw)
In-Reply-To: <20050811080838.23324.lindig@cs.uni-sb.de>


------- Additional Comments From jakub at gcc dot gnu dot org  2005-09-08 14:03 -------
This seems to be a serious problem introduced by PR middle-end/9997 fix,
at least if I understand it right.

The testcase I'm looking at is, on ppc64-linux -m32 -O2:
extern void abort (void);
#define A(x) if (!(x)) abort ()

static union at6 {} vv6 = {};
static struct et6
{
  struct bt6
  {
    signed av6:6;
    signed bv6:7;
    signed cv6:6;
    signed dv6:5;
    unsigned char ev6;
    unsigned int fv6;
    long int gv6;
  } mv6;
  unsigned long int nv6;
  signed ov6:12;
  signed pv6:3;
  signed qv6:2;
  signed rv6:10;
  union ct6 { long int hv6; float iv6; float jv6; } sv6;
  int *tv6;
  union dt6 { double kv6; float lv6; } uv6;
} wv6 = {
  { 8, 9, 2, 4, '\x10', 67426805U, 1047191860L },
  1366022414UL, 858, 1, 1, 305,
  { 1069379046L }, (int *) 358273621U,
  { 3318.041978 }
};
static double xv6 = 19239.101269;
static long long int yv6 = 1207859169L;
static int zv6 = 660195606;

static union at6
callee_af6 (struct et6 ap6, double bp6, long long int cp6, int dp6)
{
  A (wv6.mv6.av6 == ap6.mv6.av6);
  A (wv6.mv6.bv6 == ap6.mv6.bv6);
  A (wv6.mv6.cv6 == ap6.mv6.cv6);
  A (wv6.mv6.dv6 == ap6.mv6.dv6);
  A (wv6.mv6.ev6 == ap6.mv6.ev6);
  A (wv6.mv6.fv6 == ap6.mv6.fv6);
  A (wv6.mv6.gv6 == ap6.mv6.gv6);
  A (wv6.nv6 == ap6.nv6);
  A (wv6.ov6 == ap6.ov6);
  A (wv6.pv6 == ap6.pv6);
  A (wv6.qv6 == ap6.qv6);
  A (wv6.rv6 == ap6.rv6);
  A (wv6.sv6.hv6 == ap6.sv6.hv6);
  A (wv6.tv6 == ap6.tv6);
  A (wv6.uv6.kv6 == ap6.uv6.kv6);
  A (xv6 == bp6);
  A (yv6 == cp6);
  A (zv6 == dp6);
  return vv6;
}

static void
caller_bf6 (void)
{
  union at6 bav6;
  bav6 = callee_af6 (wv6, xv6, yv6, zv6);
}

static unsigned char uv7 = '\x46';
static float vv7 = 96636.982442;
static double wv7 = 28450.711801;
static union ct7 {} xv7 = {};
static struct et7
{
  struct dt7
  {
    float iv7;
    unsigned short int jv7;
  } kv7;
  float lv7[0];
  signed mv7:9;
  short int nv7;
  double ov7;
  float pv7;
} yv7 = {
  { 30135.996213, 42435 },
  {}, 170, 22116, 26479.628148, 4082.960685
};
static union ft7
{
  float qv7;
  float *rv7;
  unsigned int *sv7;
} zv7 = { 5042.227886 };
static int bav7 = 1345451862;
static struct gt7 { double tv7; } bbv7 = { 47875.491954 };
static long int bcv7[1] = { 1732133482L };
static long long int bdv7 = 381678602L;

static unsigned char
callee_af7 (float ap7, double bp7, union ct7 cp7, struct et7 dp7,
            union ft7 ep7, int fp7, struct gt7 gp7, long int hp7[1],
            long long int ip7)
{
  A (vv7 == ap7);
  A (wv7 == bp7);
  A (yv7.kv7.iv7 == dp7.kv7.iv7);
  A (yv7.kv7.jv7 == dp7.kv7.jv7);
  A (yv7.mv7 == dp7.mv7);
  A (yv7.nv7 == dp7.nv7);
  A (yv7.ov7 == dp7.ov7);
  A (yv7.pv7 == dp7.pv7);
  A (zv7.qv7 == ep7.qv7);
  A (bav7 == fp7);
  A (bbv7.tv7 == gp7.tv7);
  A (bcv7[0] == hp7[0]);
  A (bdv7 == ip7);
  return uv7;
}

static void
caller_bf7 (void)
{
  unsigned char bev7;

  bev7 = callee_af7 (vv7, wv7, xv7, yv7, zv7, bav7, bbv7, bcv7, bdv7);
  A (uv7 == bev7);
}

int
main ()
{
  caller_bf6 ();
  caller_bf7 ();
  return 0;
}

expand_used_vars is assigning stack slots just to 2 variables, ap6 and dp7.
ap6's alias set (5) has has_zero_child set to 1, as it contains an unsigned char
field (ap6.mv6.ev6), dp7's alias set (13) does not.
But one has_zero_child is enough for alias_sets_conflict_p (5, 13) == 1.
The problem is that add_alias_set_conflicts uses just !alias_sets_conflict_p
and not something stronger to find which variables can't overlap.
ap6 and dp7 MAY conflict (which is correct), but that is not enough to
guarantee the two variables can overlap (they IMHO can't).

When CSE uses later the alias info, it sees a read from ap6.mv6.gv6 field
(long int type, alias set 4) and write, part of initializing whole dp7,
using alias set 13 (dp7's alias set).  But there are no long int fields in
dp7, so alias_sets_conflict_p (4, 13) == 0 and thus CSE decides the write
couldn't possibly invalidate av6.mv6.gv6 value at that location.

Now the question is what add_alias_set_conflicts should check if both vars are
aggregates instead of alias_sets_conflict_p (or better yet in addition to, if
!alias_sets_conflict_p, we know the variables can't overlap quickly).
Certainly for all fields (recursively) of one aggregate it needs to ensure they
may conflict with the other aggregate's alias set and vice versa.
That will handle the case of a MEM reading/writing a field and another MEM
reading/writing the other variable as whole (well, at least using whole
variable's alias set).  Plus if there are fields which themselves are aggregates,
we would I think need to ensure that aggregate subfield may conflict with all
fields in the other variable that might overlap it (i.e. look at field offsets
etc.).



-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rth at gcc dot gnu dot org
         AssignedTo|jakub at gcc dot gnu dot org|unassigned at gcc dot gnu
                   |                            |dot org
           Severity|normal                      |critical
             Status|ASSIGNED                    |NEW
   Target Milestone|4.1.0                       |4.0.2


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23324


  parent reply	other threads:[~2005-09-08 14:04 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-11  8:08 [Bug c/23324] New: unsigned bitfield in struct not passed correctly as argument lindig at cs dot uni-sb dot de
2005-08-11  8:11 ` [Bug c/23324] " lindig at cs dot uni-sb dot de
2005-08-11  8:15 ` lindig at cs dot uni-sb dot de
2005-08-11 12:13 ` [Bug rtl-optimization/23324] " pinskia at gcc dot gnu dot org
2005-08-11 12:23 ` [Bug rtl-optimization/23324] [4.1 Regression] " pinskia at gcc dot gnu dot org
2005-08-11 12:24 ` [Bug rtl-optimization/23324] [4.1 Regression] unsigned bitfield in struct not accessed correctly pinskia at gcc dot gnu dot org
2005-08-11 12:34 ` pinskia at gcc dot gnu dot org
2005-09-01  3:48 ` [Bug rtl-optimization/23324] [4.1 Regression] unsigned bitfield in struct not accessed correctly at -O2 and above amodra at bigpond dot net dot au
2005-09-07 18:58 ` jakub at gcc dot gnu dot org
2005-09-08 14:04 ` jakub at gcc dot gnu dot org [this message]
2005-09-27 16:08 ` [Bug rtl-optimization/23324] [4.0/4.1 " mmitchel at gcc dot gnu dot org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050908140347.12651.qmail@sourceware.org \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).