public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
From: Jim Wilson <wilson@cygnus.com>
To: linux-ia64@vger.kernel.org
Subject: Re: [Linux-ia64] gcc bug
Date: Sat, 27 Jan 2001 04:20:31 +0000	[thread overview]
Message-ID: <marc-linux-ia64-105590693005107@msgid-missing> (raw)
In-Reply-To: <marc-linux-ia64-105590693005105@msgid-missing>

There was a comment about non-int bitfields.  This isn't allowed by the ISO C
standard, but it is a very common extension.  Most C compilers support it.
Gcc will give a warning about this construct if you use -pedantic.  This
isn't related to the problem though.

The problem with the code is that it uses invalid casts.  ISO C says that
if you access an object using a type other than what the object was declared
with, then the result is undefined.  There are a few exceptions, signedness
doesn't matter, qualifiers don't matter, aggregate types containing the type
are OK, and char is OK.  (In the 1989 ANSI C standard, this is in section 3.3
Expressions.)  This rule exists so that C compilers can do type-based alias
analysis.  Gcc tries to do aliasing based on addresses first, but if it gets
confused by address arithmetic, then it will try type-based alias analysis.
So in this case, it decides that the read of the unsigned int w and the
store to struct f w can't alias because the types are different, and then it
emits an instruction schedule that causes the code to perform differently than
what you expected.  This code would probably work on other targets.  The
lack of addressing modes in IA-64 makes it harder for the alias analysis pass
to figure out whether two addresses are the same, and hence we fall back on
type-based aliasing more often than we would on say an IA-32 machine.

Gcc does support type punning via unions, though the ISO C standard technically
does not allow this.  If you write the code like this it should work
union g {
  struct f f;
  unsigned long l;
};

  ((union g*)&w)->f.lo = ((union g*)&value1)->f.lo;
  ((union g*)&w)->f.hi = ((union g*)&value2)->f.hi;

However, this is a bit cryptic.  It would be clearer, and you will get much
more efficient code, if you write it something like this.  Using & usually
forces values onto the stack.  If we do it this way, we do everything in
registers until the write to r.

union g {
  struct f f;
  unsigned long l;
};

doit (unsigned long value1, unsigned long value2)
{
  union g w, t, u;

  t.l = value1;
  w.f.lo = t.f.lo;
  u.l = value2;
  w.f.hi = u.f.hi;
  r = w.l;
}

int
main (int argc, char **argv)
{
  doit(0xbeef, 0xfeed00000000);
  printf ("%lx\n", r);
}

Jim


  parent reply	other threads:[~2001-01-27  4:20 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-01-26  8:09 [Linux-ia64] gcc bug David Mosberger
2001-01-26  9:40 ` Keith Owens
2001-01-27  4:20 ` Jim Wilson [this message]
2001-01-27  5:21 ` David Mosberger

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=marc-linux-ia64-105590693005107@msgid-missing \
    --to=wilson@cygnus.com \
    --cc=linux-ia64@vger.kernel.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