subregisters, def-kill

Hi,

I am combining 16-bit registers to a 32 bit register in order to make a wide store, as per below:

732 %reg16506:hi16<def,dead> = COPY %reg16445;
740 %reg16506:lo16 = COPY %reg16468;
748 %r3<def,dead> = store %reg16506, %r3,

As you can see, LiveVariables has marked the high part dead, even though the super-register is used at SlotIndex 748. Why is this? Should I add anything special to the basic BuildMI calls?

The LiveIntervalsAnalysis, then adds ranges to 16506 for the whole block - even prior to 732 which is the first subreg-def. This is a loop body, but 16506 is marked as killed at 748, so I don’t see why there is a live range from earlier than 732. The coalescer will then report “Interference”, and not coalesce the COPY to the subreg due to overlapping live intervals.

Any good tips and explanation would be appreciated,

Jonas

That code is not in SSA form as LiveVariables requires, there can only be one def per virtual register. You need to use INSERT_SUBREG or REG_SEQUENCE to do this.

/jakob

I see, thanks.

I used to work with GCC, which has an SSA-property verification run after each pass. It is surprising to find that LLVM does not check this!

Jonas

It should. Here is how you can fix it:

  • Add a flag to MachineRegisterInfo: isSSA(). It should be true initially and cleared by the 2-addr and phi-elim passes.

  • Add code to MachineVerifier.cpp that checks for multiple virtual register defs when MRI->isSSA() is true.

Then send your patches to llvm-commits!

Thanks,

/jakob

If I write

%reg16506 = INSERT_SUBREG %reg16506, %reg16445, hi16; #1
%reg16506 = INSERT_SUBREG %reg16506, %reg16468, lo16; #2
store %reg16506 #3

it will not coalesce, as

LiveVariables:

on
#2: %16506 gets #2 as a kill
#3: %16506 gets #3 as an additional kill

LiveIntervalAnalysis:
The common case of a def/kill in same MBB, is missed, as there are two kills, one for the store-MI, and one for the last COPY. Thus, two false live-ranges are later added, to the end of the block, and from the beginning - as it is believed it is not a local live-range.

SimpleRegisterCoalescing:
This ends up as overlapping live-ranges, where the value numbers did not become one, and Interference is reported.

This must then be considered bad code in LLVM.

But if I write

%reg16507 = COPY %reg16445;
%reg16508 = COPY %reg16468;
%reg16506 = REG_SEQUENCE %reg16507, hi16, %reg16508, lo16;
%reg16509 = st_2_1_postMod %reg16506, %reg16441, %reg16454, pred:20, pred:%CCReg;

then, there is not an erroneous live-range that interferes, so it coalesces.

I suppose this means that the first version with INSERT_SUBREG’s is breaking the SSA-form? Or am I doing it wrong?

In a similar case, the coalescer will not join the %reg16478 into %reg16511, although it makes perfect sense [after SimpleRegisterCoalescer]:

836L %reg16511:hi16 = COPY %reg16473:lo16, %reg16511;
844L %reg16511:lo16 = COPY %reg16478:lo16;
852L %r4<def,dead> = st_postMod %reg16511, %r4

844L %reg16511:lo16 = COPY %reg16478:lo16; Accum:%reg16511,16478
Considering merging %reg16478 with reg%16511 to Accum
RHS = %reg16478,0.000000e+00 = [804d,844d:0) 0@804d
LHS = %reg16511,0.000000e+00 = [836d,844d:1)[844d,852d:0) 0@844d 1@836d
Interference!

It seems that there is a Live range from the first COPY to the store, which interferes with the second COPY, which should have been coalesced. I find it worrisome that LLVM is not recognizing sub-registers apart from the super register. I would like to work with subregisters so as to define subregister liveness, but I find that LLVM is only keeping live information for the super-register, regardless of which subreg was defined. How could I overcome this?

However, if I simply change the order of the COPY’s, then I have no problem:

%reg16511:lo16 = COPY %reg16482, %reg16511;
%reg16511:hi16 = COPY %reg16479;
%r4<def,dead> = st_2_1_postMod %reg16511, %r4

836L %reg16511:lo16 = COPY %reg16478:lo16, %reg16511;
Considering merging %reg16478 with reg%16511 to Accum
RHS = %reg16478,0.000000e+00 = [804d,836d:0) 0@804d
LHS = %reg16511,0.000000e+00 = [836d,844d:1)[844d,852d:0) 0@844d 1@836d
updated: 804L %reg16511 = exz_2_22_right %reg16471, 15, pred:20, pred:%reg0; Accum:%reg16511 A0_3:%reg16471
Joined. Result = %reg16511,0.000000e+00 = [804d,844d:1)[844d,852d:0) 0@844d 1@804d

So what is the story, then? Should the COPY’s always be placed in order of coalescing probability in the cases of placing COPYs to a REG_SEQUENCE? One would have hoped for the coalescer to handle this no matter what the order, I guess. I could even omit the COPY after checking that the register classes match, but in general it would have been preferred with a strong coalescer, so as to not always have to worry about introducing COPY’s.

I tried without any COPY’s, and this went all the way through, only to find that the register-classes are not used as constraints as in GCC, so the register allocator had no problem with allocating to the wrong register class. Disappointing, after all, this is defined in the .td files and available in the OperandInfo’s.

Jonas

If I write

%reg16506 = INSERT_SUBREG %reg16506, %reg16445, hi16; #1
%reg16506 = INSERT_SUBREG %reg16506, %reg16468, lo16; #2
store %reg16506 #3

This is still not SSA, you need something like:

a = IMPLICIT_DEF
b = INSERT_SUBREG a, foo, hi16
c = INSERT_SUBREG c, bar, lo16

But as you correctly observe:

it will not coalesce, as

Which is why we added REG_SEQUENCE:

But if I write

%reg16507 = COPY %reg16445;
%reg16508 = COPY %reg16468;
%reg16506 = REG_SEQUENCE %reg16507, hi16, %reg16508, lo16;
%reg16509 = st_2_1_postMod %reg16506, %reg16441, %reg16454, pred:20, pred:%CCReg;

then, there is not an erroneous live-range that interferes, so it coalesces.

Yes, this is correct.

I suppose this means that the first version with INSERT_SUBREG’s is breaking the SSA-form? Or am I doing it wrong?

You were doing it wrong, but even when done correctly, chained INSERT_SUBREGs don’t coalesce. That is really a coalescer bug.

In a similar case, the coalescer will not join the %reg16478 into %reg16511, although it makes perfect sense [after SimpleRegisterCoalescer]:

836L %reg16511:hi16 = COPY %reg16473:lo16, %reg16511;
844L %reg16511:lo16 = COPY %reg16478:lo16;
852L %r4<def,dead> = st_postMod %reg16511, %r4

844L %reg16511:lo16 = COPY %reg16478:lo16; Accum:%reg16511,16478
Considering merging %reg16478 with reg%16511 to Accum
RHS = %reg16478,0.000000e+00 = [804d,844d:0) 0@804d
LHS = %reg16511,0.000000e+00 = [836d,844d:1)[844d,852d:0) 0@844d 1@836d
Interference!

It seems that there is a Live range from the first COPY to the store, which interferes with the second COPY, which should have been coalesced. I find it worrisome that LLVM is not recognizing sub-registers apart from the super register. I would like to work with subregisters so as to define subregister liveness, but I find that LLVM is only keeping live information for the super-register, regardless of which subreg was defined. How could I overcome this?

I am planning to fix this, but it is not an easy problem. The REG_SEQUENCE instruction provides a workaround.

/jakob