[LLVMdev] MC Register mapping question (MCRegUnitIterator )
Arnold Schwaighofer
arnolds at codeaurora.org
Thu Aug 30 12:43:11 PDT 2012
Hi Sergei,
Register units != sub registers.
Register units are an abstraction to describe overlapping of registers
effectively.
You probably wanted to use MCSubRegIterator.
On Thu, Aug 30, 2012 at 2:30 PM, Sergei Larin <slarin at codeaurora.org> wrote:
> Hello Jakob and everyone,
>
> I am observing an issue with MCRegUnitIterator in my back end, and trying
> to reverse engineer some of the table gen magic around it, but if you or
> someone readily knows the answer, I would highly appreciate it.
>
> Here is the problem.
>
> In my back end we have a rather simple int register file structure:
>
> // Integer registers.
> def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>;
> def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>;
> def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>;
> def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>;
> ...
>
> ...which could be accessed as double regs in pairs:
>
> // Aliases of the R* registers used to hold 64-bit int values (doubles).
> let SubRegIndices = [subreg_loreg, subreg_hireg] in {
> def D0 : Rd< 0, "r1:0", [R0, R1]>, DwarfRegNum<[32]>;
> def D1 : Rd< 2, "r3:2", [R2, R3]>, DwarfRegNum<[34]>;
> def D2 : Rd< 4, "r5:4", [R4, R5]>, DwarfRegNum<[36]>;
>
> So R2:R3 are subregs of D1.
>
> These definitions are mapped to HexagonGenRegisterInfo.inc in something like
> this:
> enum {
> NoRegister,
> D0 = 1,
> D1 = 2,
> D2 = 3,
> D3 = 4,
> D4 = 5,
> ...
> R0 = 27,
> R1 = 28,
> R2 = 29,
> R3 = 30,
> R4 = 31,
> ...
> NUM_TARGET_REGS // 62
> };
>
> On the other end of the problem, I use the following to iterate over
> sub-regs of (in this case) D1:
>
> for (MCRegUnitIterator Units(Reg, &TRI); Units.isValid(); ++Units) {
> DEBUG(dbgs() << "\tUnit (" << *Units << ")\n");
> ...
> }
>
> For Reg==2==D1 I expect to see *Units to be 29==R2 and 30==R3 (its subregs).
> Instead I see it to take values of 2==D1 and 3==D2!
>
> Moreover, if I iterate over units of an ordinary register, let's say
> Reg==29==R2, *Units above iterates once with value of 2==D1!
>
> Either I do not understand how MCRegUnitIterator should work, or (more
> likely) I have a problem in lib/Target/Hexagon/HexagonRegisterInfo.td,
> because it seems that in HexagonGenRegisterInfo.inc I got something that
> confuses tables to iterate over for subregs...
>
> So, if you know what it might be, please let me know. Thanks a lot.
>
> Sergei Larin
>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by
> The Linux Foundation
>
>
>> -----Original Message-----
>> From: llvmdev-bounces at cs.uiuc.edu [mailto:llvmdev-bounces at cs.uiuc.edu]
>> On Behalf Of Sergei Larin
>> Sent: Tuesday, August 28, 2012 4:34 PM
>> To: 'Andrew Trick'
>> Cc: 'LLVM Developers Mailing List'
>> Subject: Re: [LLVMdev] Assert in LiveInterval update
>>
>> Andy, Lang,
>>
>> Thanks for the suggestion.
>>
>>
>> I have spent more time with it today, and I do see some strange
>> things in liveness update. I am not at the actual cause yet, but here
>> is what I got so
>> far:
>>
>> I have the following live ranges when I start scheduling a region:
>>
>> R2 = [0B,48r:0)[352r,416r:5)...
>> R3 = [0B,48r:0)[368r,416r:5)...
>> R4 = [0B,32r:0)[384r,416r:4)...
>> R5 = [0B,32r:0)[400r,416r:4)...
>>
>> I schedule the following instruction (48B):
>>
>> 0B BB#0: derived from LLVM BB %entry
>> Live Ins: %R0 %R1 %D1 %D2
>> 8B %vreg27<def> = COPY %R1<kill>; IntRegs:%vreg27
>> 12B %vreg30<def> = LDriw <fi#-1>, 0;
>> mem:LD4[FixedStack-1](align=8) IntRegs:%vreg30
>> 20B %vreg31<def> = LDriw <fi#-2>, 0; mem:LD4[FixedStack-2]
>> IntRegs:%vreg31
>> 24B %vreg26<def> = COPY %R0<kill>; IntRegs:%vreg26
>> 28B %vreg106<def> = TFRI 16777216;
>> IntRegs:%vreg106<<<<<<<<<<<<<<<<<<<<<<<<<<< CurrentTop
>> 32B %vreg29<def> = COPY %D2<kill>; DoubleRegs:%vreg29
>> 48B %vreg28<def> = COPY %D1<kill>; DoubleRegs:%vreg28
>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Needs to move above 28B
>> 96B %vreg37<def> = LDriw <fi#-8>, 0; mem:LD4[FixedStack-8]
>> IntRegs:%vreg37
>>
>> In Hexagon %D1==%R0:R1 (double reg), %D2==%R2:R3 etc.
>> The MI move triggers liveness update, which first triggers SlotIndex
>> renumbering:
>>
>> *** Renumbered SlotIndexes 24-56 ***
>>
>> So my 48B becomes 56B, so after the update new live ranges look like
>> this:
>>
>> R2 = [0B,56r:0)[352r,416r:5)...
>> R3 = [0B,56r:0)[368r,416r:5)...
>> R4 = [0B,48r:0)[384r,416r:4)...
>> R5 = [0B,48r:0)[400r,416r:4)...
>>
>> Then in LiveIntervals::handleMove OldIndex 56B and NewIndex is 32B
>> (also new after renumbering. But happens to match another old one).
>> collectRanges for MI figures that it is moving a paired register, and
>> correctly(?) selects these two ranges to update for %R2:R3
>>
>> [0B,56r:0)[368r,416r:5)...
>> [0B,56r:0)[352r,416r:5)...
>>
>> ___BUT____ after the update, my new ranges look like this:
>>
>> R2 = [0B,32r:0)[352r,416r:5)...
>> R3 = [0B,48r:0)[368r,416r:5)...<<<<< Bogus range, 56r should have
>> become 48r
>> R4 = [0B,48r:0)[384r,416r:4)...
>> R5 = [0B,48r:0)[400r,416r:4)...
>> ....
>> 0B BB#0: derived from LLVM BB %entry
>> Live Ins: %R0 %R1 %D1 %D2
>> 8B %vreg27<def> = COPY %R1<kill>; IntRegs:%vreg27
>> 12B %vreg30<def> = LDriw <fi#-1>, 0;
>> mem:LD4[FixedStack-1](align=8) IntRegs:%vreg30
>> 20B %vreg31<def> = LDriw <fi#-2>, 0; mem:LD4[FixedStack-2]
>> IntRegs:%vreg31
>> 24B %vreg26<def> = COPY %R0<kill>; IntRegs:%vreg26
>> 32B %vreg28<def> = COPY %D1<kill>; DoubleRegs:%vreg28
>> <<<<<<<<<<<<<<<< Moved instruction
>> 40B %vreg106<def> = TFRI 16777216; IntRegs:%vreg106
>> 48B %vreg29<def> = COPY %D2<kill>; DoubleRegs:%vreg29
>> 96B %vreg37<def> = LDriw <fi#-8>, 0; mem:LD4[FixedStack-8]
>> IntRegs:%vreg37
>>
>> This is not caught at this time, and only much later, when another
>> instruction is scheduled to __the same slot___ the old one "occupied"
>> (48B), the discrepancy is caught by one of unrelated asserts... I think
>> at that time there are simply some stale aliases in liveness table.
>>
>> I'm going to continue with this tomorrow, but if this helps to identify
>> a lurking bug today, my day was worth it :) :) :)
>>
>> Sergei
>>
>> --
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum.
>>
>>
>> > -----Original Message-----
>> > From: Andrew Trick [mailto:atrick at apple.com]
>> > Sent: Tuesday, August 28, 2012 3:47 PM
>> > To: Sergei Larin
>> > Cc: LLVM Developers Mailing List; Lang Hames
>> > Subject: Re: [LLVMdev] Assert in LiveInterval update
>> >
>> > On Aug 28, 2012, at 8:18 AM, Sergei Larin <slarin at codeaurora.org>
>> > wrote:
>> > >
>> > > I've described that issue (see below) when you were out of town...
>> > > I think I am getting more context on it. Please take a look...
>> > >
>> > > So, in short, when the new MI scheduler performs move of an
>> > > instruction, it does something like this:
>> > >
>> > > // Move the instruction to its new location in the instruction
>> > stream.
>> > > MachineInstr *MI = SU->getInstr();
>> > >
>> > > if (IsTopNode) {
>> > > assert(SU->isTopReady() && "node still has unscheduled
>> > dependencies");
>> > > if (&*CurrentTop == MI) <<<<<<<<<<<<<<<<<< Here
>> we
>> > make
>> > > sure that CurrentTop != MI.
>> > > CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
>> > > else {
>> > > moveInstruction(MI, CurrentTop);
>> > > TopRPTracker.setPos(MI);
>> > > }
>> > > ...
>> > >
>> > > But in moveInstruction we use
>> > >
>> > > // Update the instruction stream.
>> > > BB->splice(InsertPos, BB, MI);
>> > >
>> > > And splice as far as I understand moves MI to the location right
>> > > __before__ InsertPos. Our previous check made sure that InsertPos
>> !=
>> > > MI, But I do hit a case, when MI == InsertPos--, and effectively
>> > tries
>> > > to swap instruction with itself... which make live update mechanism
>> > very unhappy.
>> > >
>> > > If I am missing something in intended logic, please explain,
>> > otherwise
>> > > it looks like we need to adjust that check to make sure we never
>> > > even considering this situation (swapping with self).
>> > >
>> > > I also wonder if we want explicit check in live update with more
>> > > meaningful assert :)
>> >
>> > Thanks for debugging this! The code above assumes that you're moving
>> > an unscheduled instruction, which should never be above InsertPos for
>> > top- down scheduling. If the instruction was in multiple ready Q's,
>> > then you may attempt to schedule it multiple times. You can avoid
>> this
>> > by checking Su->isScheduled in your Strategy's pickNode. See
>> > InstructionShuffler::pickNode for an example. I don't see an
>> > equivalent check in ConvergingScheduler, but there probably should
>> be.
>> >
>> > Another possibility to consider is something strange with
>> DebugValues,
>> > which I haven't tested much.
>> >
>> > I reproduced the same assert on arm and filed PR13719. I'm not sure
>> > yet if it's exactly the same issue, but we can move the discussion
>> there.
>> >
>> > We need a better assert in live update and probably the scheduler
>> too.
>> > Lang mentioned he may look at the issue today. Meanwhile, I hope my
>> > suggestion above helps.
>> >
>> > -Andy
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list