[llvm-commits] [PATCH] Fix Bug 4657: register scavenger asserts with subreg lowering

Jakob Stoklund Olesen stoklund at 2pi.dk
Sun Aug 2 16:01:21 PDT 2009


On 02/08/2009, at 21.47, Evan Cheng wrote:

>
> On Aug 2, 2009, at 6:01 AM, Jakob Stoklund Olesen wrote:
>> * Don't eliminate an identity copy when the source register is
>> <undef>. Instead, replace INSERT_SUBREG with an IMPLICIT_DEF
>> instruction.
>
> Can we change this to <undef> of the subsequent use(s)? Or is it too
> much work?

That would be preferable, but to be honest, I don't know how to find  
all the uses. Are we even sure they are in the same MBB? Would I have  
to modify live-in lists on successor blocks as well?

LowerExtract() just scans the MBB:

     // Find the kill of the destination register's live range, and  
insert
     // a kill of the source register at that point.
     if (MI->getOperand(1).isKill() && !MI->getOperand(0).isDead())
       for (MachineBasicBlock::iterator MII =
              next(MachineBasicBlock::iterator(MI));
            MII != MBB->end(); ++MII)
         if (MII->killsRegister(DstReg, &TRI)) {
           MII->addRegisterKilled(SuperReg, &TRI, /*AddIfNotFound=*/ 
true);
           break;
         }

Is that correct? DstReg may not be killed in the MBB - it could be  
live-out. If that happens, Superreg won't be killed either. I don't  
think that is actually a problem.

>
>> * When replacing %Q1<def, dead> = INSERT_SUBREG ..., add an <imp-
>> kill> of the super register.
>
> I am not sure if I understand this? Can you show me an example?

The test case CodeGen/Blackfin/printf2.ll produces:

	%R1<def,dead> = INSERT_SUBREG %R1<undef>, %R0L<kill,undef>, 1
	ADJCALLSTACKDOWN 12, %SP<imp-def>, %SP<imp-use>
	CALLa <ga:printf>, %R0<imp-def,dead>, %R1<imp-def,dead>, %R2<imp- 
def,dead>, ...
	ADJCALLSTACKUP 12, 0, %SP<imp-def>, %SP<imp-use>
	%R0<def> = LOADimm7 0
	RTS %R0<imp-use,kill>, %RETS<imp-use>

Undef everywhere. Then we run LowerSubregs:

subreg: CONVERTING: %R1<def,dead> = INSERT_SUBREG %R1<undef>,  
%R0L<kill,undef>, 1
subreg: %R1L<def,dead> = SLL16i %R0L, 0, %AZ<imp-def>, %AN<imp-def>,  
%V<imp-def>, %VS<imp-def>

Notice that if %R1 were live, it would be killed by the INSERT_SUBREG  
but not by the replacement SLL16i. This is a bad example because %R1  
is marked <undef>. Pretend that it isn't. LowerInsert already  
transfers the <dead> flag:

     // Transfer the kill/dead flags, if needed.
     if (MI->getOperand(0).isDead())
       TransferDeadFlag(MI, DstSubReg, TRI);

It just forgets to kill the super-register. I would add %R1<imp- 
use,kill> to the end of SLL16i to make sure the super-register is dead.

This example actually raises another issue:

%R1<def,dead> = INSERT_SUBREG undef, undef

can be eliminated, and

%R1<def> = INSERT_SUBREG undef, undef

can be replaced with IMPLICIT_DEF. Even when you would normally insert  
a sub-register copy.

>
>> * Fix a bug in transferring the kill flag from InsReg: InsReg is
>> operand #2, not #1.
>>
>> In the regscavenger:
>>
>> * Allow imp-use of a dead register.
>
> I don't get this part. Is this using an implicit_def?

It would allow SLL16i ..., %R1<imp-use,kill> even when %R1 is dead. It  
mirrors the "double define with imp-def is legal" rule.

>
>> * Allow redefining a sub-register of a live super register.
>
> To be precise, it should be modeled as a use and def. See
> LiveVariables.cpp
>
>         // The larger register is previously defined. Now a smaller
> part is
>         // being re-defined. Treat it as read/mod/write if there are
> uses
>         // below.
>         // EAX =
>         // AX  =        EAX<imp-use,kill>, EAX<imp-def>

I see. I will have to update the machine code verifier as well.

The exact meaning of the kill/def/undef/imp flags is quite hard to get  
right. Particularly the subreg stuff is difficult. It may be a good  
idea to document it in great detail, and the make sure the machine  
code verifier and scavenger agree.

[...]

>> %Q1<def> = INSERT_SUBREG %Q1<undef>, %D2<kill>, 5

> Are you saying in this case there isn't a matching q1 = insert_subreg
> %q1, x, 6? I think using implicit_def is perfectly ok then. Part of Q1
> is implicitly defined.

Sometimes there is, sometimes there isn't. Blackfin implements anyext  
like this:

def : Pat<(i32 (anyext D16L:$src)),
           (INSERT_SUBREG (i32 (IMPLICIT_DEF)),
                          (COPY_TO_REGCLASS D16L:$src, D16L),
                          bfin_subreg_lo16)>;

The high part of the register is left undefined for a true "anyext".  
When INSERT_SUBREG is lowered, it still must define the full register.

Example: (i32 (anyext (ONES D:$src))) becomes:

%R1.L<def> = ONES %R0<kill>
%R1<def> = INSERT_SUBREG %R1<undef>, %R1.L<kill>

This is perfectly fine until LowerSubregs removes INSERT_SUBREG  
because it is an identity copy. Then %R1 is no longer live. Actually,  
it seems a bit dodgy to propagate %R1<undef> to all uses just because  
it is the result of an "anyext".


>
> The patch looks good except for this part:
>
>
> -    assert(isUsed(Reg) && "Using an undefined register!");
> +    assert((MO.isImplicit() || isUsed(Reg)) && "Using an undefined
> register!");
>
> Do you mean MO.isUndef()?

No, this is the "Allow imp-use of a dead register" rule discussed  
above. Perhaps the rule should be "Allow imp-kill of a dead register"?

assert(((MO.isImplicit() && MO.isKill()) || isUsed(Reg)) && .... ?

I think we need a way to say "make sure this register is killed, dead  
or alive". I have been using <imp-kill> for that purpose.

/jakob




More information about the llvm-commits mailing list