[LLVMdev] Assert in live update from MI scheduler.

Andrew Trick atrick at apple.com
Thu Jun 14 10:57:35 PDT 2012


Sergei,

Absolutely right, the copy/ldriw should not be reordered. I was attempting to explain that I consider it a phi-elimination bug, not a DAG builder bug. Liveness will also have problems with this code in the long run.

To avoid confusion, I filed PR13112: Phi elimination generates uninitialized vreg uses, and disabled the SSA check until its fixes in r158461. 

However, your C code is also fishy. I'm not sure what xx_stack is. In the machine code, if you only execute the loop body once, never taking the backedge, then you load from a garbage pointer after exiting the loop. I think you're saying that's intended behavior, which is fine. Just thought I would point it out.

-Andy

On Jun 13, 2012, at 3:25 PM, Sergei Larin <slarin at codeaurora.org> wrote:

> Ok, after a long detour I am back to where I have started. I think there is a problem at dep DAG construction. Let me try to convince you…
>  
> Here is the C code we are dealing with:
>  
> push ()
> {
>   struct xx_stack *stack, *top;
>   for (stack = xx_stack; stack; stack = stack->next)
>     top = stack;
>   yy_instr = top->first;
> }
>  
> If the loop never iterates, “top” will have garbage in it. If it iterates even once, it will presumably have valid pointer. Bad, but perfectly valid code.
>  
> In SSA it looked like this:
> BB#0: derived from LLVM BB %entry
>     %vreg5<def> = IMPLICIT_DEF; IntRegs:%vreg5 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Dummy def.
>     %vreg4<def> = TFRI_V4 <ga:@xx_stack>; IntRegs:%vreg4
>     Successors according to CFG: BB#1
>  
> BB#1: derived from LLVM BB %for.cond
>     Predecessors according to CFG: BB#0 BB#1
>     %vreg0<def> = PHI %vreg4, <BB#0>, %vreg3, <BB#1>; IntRegs:%vreg0,%vreg4,%vreg3
>     %vreg1<def> = PHI %vreg5, <BB#0>, %vreg2, <BB#1>; IntRegs:%vreg1,%vreg5,%vreg2 <<<<<<<<<<< Use of that dummy value.
>     %vreg2<def> = LDriw %vreg0<kill>, 0; mem:LD4[%stack.0.in] IntRegs:%vreg2,%vreg0
>  
>  
> By the time it has gotten to the scheduler, it became this:
>  
> BB#0: derived from LLVM BB %entry
>     %vreg9<def> = TFRI_V4 <ga:@xx_stack>; IntRegs:%vreg9
>     Successors according to CFG: BB#1
>  
> BB#1: derived from LLVM BB %for.cond
>     Predecessors according to CFG: BB#0 BB#1
>     %vreg1<def> = COPY %vreg10<kill>; IntRegs:%vreg1,%vreg10 <<<<<<<<<<<<< First use uninitialized vreg10
>     %vreg10<def> = LDriw %vreg9<kill>, 0; mem:LD4[%stack.0.in] IntRegs:%vreg10,%vreg9
>     %vreg9<def> = ADD_ri %vreg10, 8; IntRegs:%vreg9,%vreg10
>     %vreg6<def> = CMPEQri %vreg10, 0; PredRegs:%vreg6 IntRegs:%vreg10
>     JMP_cNot %vreg6<kill>, <BB#1>, %PC<imp-def>; PredRegs:%vreg6
>     JMP <BB#2>
>     Successors according to CFG: BB#2 BB#1
>  
> BB#2: derived from LLVM BB %for.end
>     Predecessors according to CFG: BB#1
>     %vreg7<def> = LDriw %vreg1<kill>, 0; mem:LD4[%first1](tbaa=!"any pointer") IntRegs:%vreg7,%vreg1
>     STriw_GP <ga:@yy_instr>, 0, %vreg7<kill>; mem:ST4[@yy_instr](tbaa=!"any pointer") IntRegs:%vreg7
>     JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,undef>
>  
> If loop never iterates, vreg10 and vreg1 will hold garbage (as they should!). If it iterates even once, vreg1 use in BB2 will be fine.
> This exactly matches original C code behavior.
>  
> If it is a legitimate code sequence, we need to handle it in DAG dep construction, and introduce anti dep between
>     %vreg1<def> = COPY %vreg10<kill>; IntRegs:%vreg1,%vreg10
>     %vreg10<def> = LDriw %vreg9<kill>, 0; mem:LD4[%stack.0.in] IntRegs:%vreg10,%vreg9
>  
> …because reordering them is wrong.  The rest of this thread discusses my logic about how to do it.
> By the way, it is exactly same code on trunk…
>  
> I am testing your suggested workaround, and will update with results.
>  
> Thanks for your patience.
>  
> Sergei
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum.
>  
> From: Andrew Trick [mailto:atrick at apple.com] 
> Sent: Wednesday, June 13, 2012 3:29 PM
> To: Sergei Larin
> Cc: 'Jakob Olesen'; llvmdev at cs.uiuc.edu
> Subject: Re: [LLVMdev] Assert in live update from MI scheduler.
>  
>  
> On Jun 13, 2012, at 1:15 PM, Sergei Larin <slarin at codeaurora.org> wrote:
> 
> 
> Andy,
>  
>   You are probably right here – look at this – before phi elimination this code looks much more sane:
>  
> # *** IR Dump After Live Variable Analysis ***:
> # Machine code for function push: SSA
> Function Live Outs: %R0
>  
> BB#0: derived from LLVM BB %entry
>     %vreg5<def> = IMPLICIT_DEF; IntRegs:%vreg5
>     %vreg4<def> = TFRI_V4 <ga:@xx_stack>; IntRegs:%vreg4
>     Successors according to CFG: BB#1
>  
> BB#1: derived from LLVM BB %for.cond
>     Predecessors according to CFG: BB#0 BB#1
>     %vreg0<def> = PHI %vreg4, <BB#0>, %vreg3, <BB#1>; IntRegs:%vreg0,%vreg4,%vreg3
>     %vreg1<def> = PHI %vreg5, <BB#0>, %vreg2, <BB#1>; IntRegs:%vreg1,%vreg5,%vreg2
>     %vreg2<def> = LDriw %vreg0<kill>, 0; mem:LD4[%stack.0.in] IntRegs:%vreg2,%vreg0
>     %vreg3<def> = ADD_ri %vreg2, 8; IntRegs:%vreg3,%vreg2
>     %vreg6<def> = CMPEQri %vreg2, 0; PredRegs:%vreg6 IntRegs:%vreg2
>     JMP_cNot %vreg6<kill>, <BB#1>, %PC<imp-def>; PredRegs:%vreg6
>     JMP <BB#2>
>     Successors according to CFG: BB#2 BB#1
>  
> BB#2: derived from LLVM BB %for.end
>     Predecessors according to CFG: BB#1
>     %vreg7<def> = LDriw %vreg1<kill>, 0; mem:LD4[%first1](tbaa=!"any pointer") IntRegs:%vreg7,%vreg1
>     STriw_GP <ga:@yy_instr>, 0, %vreg7<kill>; mem:ST4[@yy_instr](tbaa=!"any pointer") IntRegs:%vreg7
>     %vreg8<def> = IMPLICIT_DEF; IntRegs:%vreg8
>     %R0<def> = COPY %vreg8<kill>; IntRegs:%vreg8
>     JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,kill>
>  
> Right after the dead vreg is introduced:
>  
> # *** IR Dump After Eliminate PHI nodes for register allocation ***:
> # Machine code for function push: Post SSA
> Function Live Outs: %R0
>  
> BB#0: derived from LLVM BB %entry
>     %vreg4<def> = TFRI_V4 <ga:@xx_stack>; IntRegs:%vreg4
>     %vreg9<def> = COPY %vreg4<kill>; IntRegs:%vreg9,%vreg4
>     Successors according to CFG: BB#1
>  
> BB#1: derived from LLVM BB %for.cond
>     Predecessors according to CFG: BB#0 BB#1
>     %vreg0<def> = COPY %vreg9<kill>; IntRegs:%vreg0,%vreg9
>     %vreg1<def> = COPY %vreg10<kill>; IntRegs:%vreg1,%vreg10 <<<<<<<<<<<<<<<<<<<<<<<<<<< Not defined on first iteration….
>     %vreg2<def> = LDriw %vreg0<kill>, 0; mem:LD4[%stack.0.in] IntRegs:%vreg2,%vreg0
>     %vreg3<def> = ADD_ri %vreg2, 8; IntRegs:%vreg3,%vreg2
>     %vreg6<def> = CMPEQri %vreg2, 0; PredRegs:%vreg6 IntRegs:%vreg2
>     %vreg9<def> = COPY %vreg3<kill>; IntRegs:%vreg9,%vreg3
>     %vreg10<def> = COPY %vreg2<kill>; IntRegs:%vreg10,%vreg2
>     JMP_cNot %vreg6<kill>, <BB#1>, %PC<imp-def>; PredRegs:%vreg6
>     JMP <BB#2>
>     Successors according to CFG: BB#2 BB#1
>  
> BB#2: derived from LLVM BB %for.end
>     Predecessors according to CFG: BB#1
>     %vreg7<def> = LDriw %vreg1<kill>, 0; mem:LD4[%first1](tbaa=!"any pointer") IntRegs:%vreg7,%vreg1
>     STriw_GP <ga:@yy_instr>, 0, %vreg7<kill>; mem:ST4[@yy_instr](tbaa=!"any pointer") IntRegs:%vreg7
>     %vreg8<def> = IMPLICIT_DEF; IntRegs:%vreg8
>     %R0<def> = COPY %vreg8<kill>; IntRegs:%vreg8
>     JMPR %PC<imp-def>, %R31<imp-use>, %R0<imp-use,kill>
>  
> # End machine code for function push.
>  
> So the problem is elsewhere after all…
>  
> Sergei,
>  
> If you don't want an undefined variable here, that's something you should look into. Otherwise, the machine code before phi elimination looks ok. Phi elimination is not doing everything I would like it to do in this case. I'll have to try constructing a test case by hand. Until I figure out the right fix, you may want to work around by disabling the SSA check in the scheduler.
>  
> Thanks
> -Andy
>  

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120614/276050f5/attachment.html>


More information about the llvm-dev mailing list