This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PING: [PATCH] Fix PR 20972

On Fri, 2005-04-29 at 04:05, Bernd Schmidt wrote:
> Can you think of a way of doing that which wouldn't effectively disable 
> what Vlad was trying to do with his patch?

My day job interfered with my attempt to look at this.  I am not very
familiar with Vlad's patch, but from what I understand of what it does,
my suggestion won't effect Vlad's patch except to make it unnecessary in
some cases.

E.g. currently we get RTL like this
  function start:
  bitfield insert into r100 (r100 used uninitialized)
  function end
since r100 is used uninitialized, it is considered live from the program
start.  Vlad's patch changes the lifetime to start at the point where it
is first initialized.

My suggestion is to change this to
  function start:
  r100 = 0
  bitfield insert into r100 (r100 used uninitialized)
  function end
Now, Vlad's patch is no longer necessary, because the register is
initialized, and it is obvious where its lifetime starts.  This change
has two benefits
1) Combine can optimize away the bitfield insert, giving shorter and
faster code.
2) We can avoid uninitialized register reads, which on IA-64 can lead to
an illegal instruction fault if the NaT bit is set.

We still need Vlad's patch for the case explained in the comment before
make_accurate_live_analysis, where we have a variable defined inside a
loop and used after the loop.  We would not be inserting extra code in
this case.

The bit-field insert case is effectively the same as the case in PR
20972, in both cases, we have a value that is both used and set in the
same expression, and this expression is performing an uninitialized
read.  It should be possible to detect this and fix it without
interfering with other cases, such as the loop case that Vlad was trying
to fix.

The bit-field problem can be seen with simple testcases if you look at
the assembly output.  Consider this testcase

struct baz { int : 24; int bar : 8; };
void sub2 (struct baz);
sub (int i)
  struct baz foo; = i;
  sub2 (foo);

if I compile this for x86 with -O, I get
        movzbl  8(%ebp), %eax
        sall    $24, %eax
        andl    $16777215, %edx
        orl     %eax, %edx
        movl    %edx, (%esp)
Note that %edx is being used uninitialized.  Also notice that we could
do this 3 instructions trivially.

If we emit a
	movl	0, %edx
during global immediately before the andl, then combine will optimize
away the zero init, the andl, and the orl, giving a 3 instruction
sequence with no uninitialized register reads.

We could actually do this with one instruction if we don't mind the risk
of some uninitialized memory reads, but that might be more trouble than
it is worth.  I'd be happy with the 3 instruction sequence.
Jim Wilson, GNU Tools Support,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]