[LLVMdev] Questions about live-ins, live-outs

Kevin Modzelewski kmod at dropbox.com
Fri Mar 21 03:39:30 PDT 2014


Did some more digging, and it seems like the issue isn't with the tail
merging or the register scavenger; it seems to be because the "%R14<def> =
COPY %RDI" instruction is missing a kill flag on rdi.  Tracing through, it
gets removed in LiveRangeCalc::extendToUses, which has a comment "Clear all
kill flags. They will be reinserted after register allocation by
LiveIntervalAnalysis::addKillFlags()."

It looks like, though, that since this is a physical register, it doesn't
get added back during addKillFlags because that only looks at virtual
registers.  I tried changing the logic so that extendToUses() only removes
the kill flags from virtual registers, which fixes my particular case, but
it causes some test failures so I guess is probably not the right way to
go.  Does anyone have advice on how to proceed?  Otherwise I guess I'll
just file a bug and move on.

Kevin


On Wed, Mar 19, 2014 at 7:59 PM, Kevin Modzelewski <kmod at dropbox.com> wrote:

> Hi all,
>
> I'm trying to start using the LiveOuts-exporting feature of the new
> stackmap/patchpoint intrinsics, and I'm running into some issues where I
> seem to be getting the wrong set of registers.  This is my first foray into
> CodeGen, so my understanding of everything I'm about to say is pretty hazy,
> but I believe that the stackmap/patchpoint functionality simply tacks on
> the existing LiveOuts that are already being calculated, which makes me
> think the issues I'm about to describe are about the LiveOuts calculation
> rather than being stackmap/patchpoint-specific.
>
> I'm running into an issue where I get some registers in the LiveOuts set
> that are clearly not live after the call; specifically, I'm sometimes get
> that %rdi or %rsi are live after a function call which uses a normal
> C-calling convention.  Or maybe I'm misunderstanding the meaning of
> LiveOuts; I'm assuming that they refer to registers that contain values
> that will be used later.
>
> Here's a boiled-down version of the IR:
> define void @f(i64) {
>   %2 = load %0** @n, align 8
>   %3 = getelementptr inbounds %0* %2, i64 0, i32 0
>   %4 = call i1 @foo()
>   br i1 %4, label %9, label %5
>
> ; <label>:5                                       ; preds = %5, %1
>   %6 = phi i64* [ %3, %5 ], [ %3, %1 ]
>   %7 = tail call i64 (i64, i32, i8*, i32, ...)*
> @llvm.experimental.patchpoint.i64(i64 116, i32 13, i8* inttoptr (i64 12346
> to i8*), i32 3, i64 %0, i64 1, i64* %6)
>   %8 = call i1 @foo()
>   br i1 %8, label %9, label %5
>
> ; <label>:9                                       ; preds = %5, %1
>   ret void
> }
>
> And here's the generated assembly listing:
> f:
>         pushq   %r14
>         pushq   %rbx
>         pushq   %rax
>         movq    %rdi, %r14
>         movq    n(%rip), %rbx
>         jmp     .LBB0_2
>         .align  16, 0x90
> .LBB0_1:
>         movl    $1, %esi
>         movq    %r14, %rdi
>         movq    %rbx, %rdx
>         movabsq $12346, %r11
>         callq   *%r11
> .LBB0_2:
>         callq   foo
>         testb   $1, %al
>         je      .LBB0_1
> .LBB0_3:
>         addq    $8, %rsp
>         popq    %rbx
>         popq    %r14
>         retq
>
> It's claiming that %rdi is live after the "callq %r11" at the end of
> LBB0_1, which based on my understanding of what the live outs are supposed
> to represent shouldn't be true.  Looking into it, it seems to be because it
> considers the live outs of LBB0_1 to include RDI; it seems to determine
> that because RDI is included in the live-ins of LBB0_2.  Again, assuming my
> understanding of what live-ins are supposed to be is correct, that seems
> wrong.
>
> Tracing through when RDI gets added to that set, it's during block
> tail-merging.  Specifically, it's in the BranchFolder::MaintainLiveIns(),
> which does a forward propagation of the BB that I haven't completely dug
> into; it's working on this basic block:
> BB#0: derived from LLVM BB %1
>     Live Ins: %RDI %R14 %RBX
>         PUSH64r %R14<kill>, %RSP<imp-def>, %RSP<imp-use>; flags: FrameSetup
>         PROLOG_LABEL <MCSym=.Ltmp0>
>         PUSH64r %RBX<kill>, %RSP<imp-def>, %RSP<imp-use>; flags: FrameSetup
>         PROLOG_LABEL <MCSym=.Ltmp1>
>         PUSH64r %RAX<undef>, %RSP<imp-def>, %RSP<imp-use>; flags:
> FrameSetup
>         PROLOG_LABEL <MCSym=.Ltmp2>
>         %R14<def> = COPY %RDI
>         %RBX<def> = MOV64rm %RIP, 1, %noreg, <ga:@n>, %noreg; mem:LD8[@n]
>         CALL64pcrel32 <ga:@foo>, <regmask>, %RSP<imp-use>, %RSP<imp-def>,
> %AL<imp-def>
>         TEST8ri %AL<kill>, 1, %EFLAGS<imp-def>
>         JE_4 <BB#2>, %EFLAGS<imp-use>
>     Successors according to CFG: BB#3(16) BB#2(16)
>
> The register scavanger determines that rdi is a live out of this block
> [that doesn't seem to be the case?] so the tail-merger adds it as a live-in
> of what will become LBB0_2 (seems weird as well, since they're at exit of
> BB#0 doesn't correspond to the entry of LBB0_2).  At this point I'm pretty
> confused -- am I misunderstanding what LiveOuts are supposed to be?  Or
> does BranchFolder::MaintainLiveIns do the wrong thing?  Or is the register
> scavanger calculating the liveness differently?  I'm not that clear on how
> the liveness information is used at different points in the pipeline, and
> clearly something isn't adding up for me, so if anyway could shed some
> light on this I'd much appreciate it...
>
>
> Kevin
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140321/f79553e6/attachment.html>


More information about the llvm-dev mailing list