virtual subregister liveness?

Hi,

After dead-mi-elimination I'm experiencing a machine verifier failure
at this virtual subregister write:

  %5.sub1 = COPY undef %11

The machine verifier essentially complains that the rest of the
register is undefined (a subregister write implies a "read" of the
other parts).

So the problem is that dead-mi-elimination has removed the previously
existing defines of %5.sub0. Yet I'm unsure where the actual fault lies
and I can't seem to find any documentation or list email that explains
the modeling in detail. A few ideas:

Are there some restrictions on where dead-mi-elimination can be run?
(I'm working with an out-of-tree target and we've put this failing
dead-mi-elimination pass pretty soon after register coalescing.)

Or is the use-list for %5 in MRI incorrectly constructed as it doesn't
contain the remaining instruction? (These use-lists are what dead-mi-
elimination is using to decide if an instruction is dead or not.)

Or is the fault that there is no MO spelling out an implicit use
%5.sub0?

The actual verifier error is:

*** Bad machine code: Virtual register defs don't dominate all uses.

Hi,

After dead-mi-elimination I'm experiencing a machine verifier failure
at this virtual subregister write:

%5.sub1 = COPY undef %11

The machine verifier essentially complains that the rest of the
register is undefined (a subregister write implies a "read" of the
other parts).

So the problem is that dead-mi-elimination has removed the previously
existing defines of %5.sub0. Yet I'm unsure where the actual fault lies
and I can't seem to find any documentation or list email that explains
the modeling in detail. A few ideas:

If %5 is used in full, %5.sub0 is supposed to be defined before that use.
If %5.sub0 was defined with an implicit_def that means, IIRC, that we just miss an undef flag on %5.sub1 (undef in that case means that we don’t care about the contain of the other lane.)

Could you provide the MIR before and after dead-mi-elimination? Just the part where %5 is involved should suffice.

>
> Hi,
>
> After dead-mi-elimination I'm experiencing a machine verifier
> failure
> at this virtual subregister write:
>
> %5.sub1 = COPY undef %11
>
> The machine verifier essentially complains that the rest of the
> register is undefined (a subregister write implies a "read" of the
> other parts).
>
> So the problem is that dead-mi-elimination has removed the
> previously
> existing defines of %5.sub0. Yet I'm unsure where the actual fault
> lies
> and I can't seem to find any documentation or list email that
> explains
> the modeling in detail. A few ideas:

If %5 is used in full, %5.sub0 is supposed to be defined before that
use.
If %5.sub0 was defined with an implicit_def that means, IIRC, that we
just miss an undef flag on %5.sub1 (undef in that case means that we
don’t care about the contain of the other lane.)

Could you provide the MIR before and after dead-mi-elimination? Just
the part where %5 is involved should suffice.

Thanks. So this is what it looks like before register coalescing (bb.3
dominates bb.1):

  bb.1:
    ...
    %22:an32_0_7 = COPY killed %5.hiPair_then_loAcc
    ...

  bb.3:
    ...
    %5:an32quads = COPY killed %13
    %5.hiPair_then_hiAcc:an32quads = COPY undef %11
    ...

After register coalescing and until dead-mi-elimination, it looks like
this:

  bb.0:
    ...
    undef %5.hiPair_then_loAcc:an32quads = COPY %12
    ...

  bb.1:
    ...
    %5.hiPair_then_loAcc:an32quads = or_a40_a40_a40_aN32
%5.hiPair_then_loAcc, %21, 0, $noreg, 0, implicit-def dead $ccreg
    ...

  bb.3:
    ...
    %5.hiPair_then_hiAcc:an32quads = COPY undef %11
    ...

Then after dead-mi-elimination, all that remains is:

  bb.3:
    ...
    %5.hiPair_then_hiAcc:an32quads = COPY undef %11
    ...

This is what's directly involving %5, so I hope it is the right amount
of info. I included MIR from before simple-register-coalescing because
one possibility is that there is something fishy happening in there.
The code is originally csmith-generated, btw. Thanks again.

Hi Jesper,

Hi,

After dead-mi-elimination I’m experiencing a machine verifier
failure
at this virtual subregister write:

%5.sub1 = COPY undef %11

The machine verifier essentially complains that the rest of the
register is undefined (a subregister write implies a “read” of the
other parts).

So the problem is that dead-mi-elimination has removed the
previously
existing defines of %5.sub0. Yet I’m unsure where the actual fault
lies
and I can’t seem to find any documentation or list email that
explains
the modeling in detail. A few ideas:

If %5 is used in full, %5.sub0 is supposed to be defined before that
use.
If %5.sub0 was defined with an implicit_def that means, IIRC, that we
just miss an undef flag on %5.sub1 (undef in that case means that we
don’t care about the contain of the other lane.)

Could you provide the MIR before and after dead-mi-elimination? Just
the part where %5 is involved should suffice.

Thanks. So this is what it looks like before register coalescing (bb.3
dominates bb.1):

bb.1:

%22:an32_0_7 = COPY killed %5.hiPair_then_loAcc

bb.3:

%5:an32quads = COPY killed %13
%5.hiPair_then_hiAcc:an32quads = COPY undef %11

After register coalescing and until dead-mi-elimination, it looks like
this:

bb.0:

undef %5.hiPair_then_loAcc:an32quads = COPY %12

bb.1:

%5.hiPair_then_loAcc:an32quads = or_a40_a40_a40_aN32
%5.hiPair_then_loAcc, %21, 0, $noreg, 0, implicit-def dead $ccreg

bb.3:

%5.hiPair_then_hiAcc:an32quads = COPY undef %11

Then after dead-mi-elimination, all that remains is:

bb.3:

%5.hiPair_then_hiAcc:an32quads = COPY undef %11

Sounds like that when dead-mi-elimination removes the %5’s def in bb.1, it should have set an undef flag on the bb.3’s definition. Otherwise, dead-mi-elimination should have considered %5.hiPair_then_loAcc alive at bb.3’s def and shouldn’t have removed the instruction.

Without seeing more of %5’s uses I don’t know which one it is (missing undef or instruction shouldn’t have been removed), but hopefully that gives you things to look at.

Cheers,
-Quentin

Hi Quentin,

Hi Jesper,

>
> > >
> > > Hi,
> > >
> > > After dead-mi-elimination I'm experiencing a machine verifier
> > > failure
> > > at this virtual subregister write:
> > >
> > > %5.sub1 = COPY undef %11
> > >
> > > The machine verifier essentially complains that the rest of the
> > > register is undefined (a subregister write implies a "read" of
> > > the
> > > other parts).
> > >
> > > So the problem is that dead-mi-elimination has removed the
> > > previously
> > > existing defines of %5.sub0. Yet I'm unsure where the actual
> > > fault
> > > lies
> > > and I can't seem to find any documentation or list email that
> > > explains
> > > the modeling in detail. A few ideas:
> >
> > If %5 is used in full, %5.sub0 is supposed to be defined before
> > that
> > use.
> > If %5.sub0 was defined with an implicit_def that means, IIRC,
> > that we
> > just miss an undef flag on %5.sub1 (undef in that case means that
> > we
> > don’t care about the contain of the other lane.)
> >
> > Could you provide the MIR before and after dead-mi-elimination?
> > Just
> > the part where %5 is involved should suffice.
>
> Thanks. So this is what it looks like before register coalescing
> (bb.3
> dominates bb.1):
> bb.1:
> ...
> %22:an32_0_7 = COPY killed %5.hiPair_then_loAcc
> ...
>
> bb.3:
> ...
> %5:an32quads = COPY killed %13
> %5.hiPair_then_hiAcc:an32quads = COPY undef %11
> ...
>
>
> After register coalescing and until dead-mi-elimination, it looks
> like
> this:
>
> bb.0:
> ...
> undef %5.hiPair_then_loAcc:an32quads = COPY %12
> ...
>
> bb.1:
> ...
> %5.hiPair_then_loAcc:an32quads = or_a40_a40_a40_aN32
> %5.hiPair_then_loAcc, %21, 0, $noreg, 0, implicit-def dead $ccreg
> ...
>
> bb.3:
> ...
> %5.hiPair_then_hiAcc:an32quads = COPY undef %11
> ...
>
>
> Then after dead-mi-elimination, all that remains is:
>
> bb.3:
> ...
> %5.hiPair_then_hiAcc:an32quads = COPY undef %11
> …

Sounds like that when dead-mi-elimination removes the %5’s def in
bb.1, it should have set an undef flag on the bb.3’s definition.
Otherwise, dead-mi-elimination should have considered
%5.hiPair_then_loAcc alive at bb.3’s def and shouldn’t have removed
the instruction.

Without seeing more of %5’s uses I don’t know which one it is
(missing undef or instruction shouldn’t have been removed), but
hopefully that gives you things to look at.

Cheers,
-Quentin

Thanks, I now found the time to look at it a bit more, created a tiny
ARM reproducer and filed a bug report:
https://bugs.llvm.org/show_bug.cgi?id=43433

I think both your suggestions may point to valid solutions if the core
problem is that that dead-mi-elimination doesn't understand subregs
well enough.

Best Regards,
Jesper