[llvm-dev] [Debug] Elide the unconditional branch instructions

David Blaikie via llvm-dev llvm-dev at lists.llvm.org
Tue Jul 25 07:32:42 PDT 2017


On Mon, Jul 24, 2017 at 8:17 PM Frozen via llvm-dev <llvm-dev at lists.llvm.org>
wrote:

>     This email is related with the code of commit:
> http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120409/140650.html.
> This commit will let our unconditional branch instruction not be deleted
> when its successor is the nature layout and its basic block's instruction
> only one instruction.
>
>   However, I have some concerns about it, especially in the debug mode.
> Let me show you some example:
>
> [1.cpp]
> 1.int main()
> 2.{
> 3.  int i;
> 4.
> 5.  for (i = 0; i < 256; i++)
> 6.  {
> 7.    continue;
> 8.  }
> 9.}
> [/1.cpp]
>
> When we use clang++ to compile it and use gdb to debug it.
>
> [Debug Part]
>
> (gdb) b main
> Breakpoint 1 at 0x100000f8b: file 1.cpp, line 5.
> (gdb) r
> Thread 2 hit Breakpoint 1, main () at 1.cpp:5
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    continue;
> (gdb) n
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    continue;
> (gdb) n
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    continue;
> [/Debug Part]
> This behavior is as expected.
> [LLVM Part]
> for.cond:                                         ; preds = %for.inc, %entry
>   %0 = load i32, i32* %i, align 4, !dbg !17
>   %cmp = icmp slt i32 %0, 256, !dbg !19
>   br i1 %cmp, label %for.body, label %for.end, !dbg !20
>
> for.body:                                         ; preds = %for.cond
> *  br label %for.inc, !dbg !21  ;  it will keep the debug information !21*
>
> for.inc:                                          ; preds = %for.body
>   %1 = load i32, i32* %i, align 4, !dbg !23
>   %inc = add nsw i32 %1, 1, !dbg !23
>   store i32 %inc, i32* %i, align 4, !dbg !23
>   br label %for.cond, !dbg !24, !llvm.loop !25
>
> for.end:                                          ; preds = %for.cond
>   %2 = load i32, i32* %retval, align 4, !dbg !27
>   ret i32 %2, !dbg !27
>
> !21 = !DILocation(line: 7, column: 5, scope: !22);
>
> However, let us see another source code example.
>
> [2.cpp]
> 1.int main()
> 2.{
> 3.  int i;
> 4.
> 5.  for (i = 0; i < 256; i++)
> 6.  {
> 7.    i++;
> 8.    continue;
> 9.  }
> 10.}
> [/2.cpp]
>
> If we debug it, we can see that:
> [Debug Part]
>
> (gdb) b main
> Breakpoint 1 at 0x100000f7b: file 2.cpp, line 5.
> (gdb) r
> Thread 2 hit Breakpoint 1, main () at 2.cpp:5
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    i++;
> (gdb) n
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    i++;
> (gdb) n
> 5	  for (i = 0; i < 256; i++)
> (gdb) n
> 7	    i++;
> (gdb) n
> 5	  for (i = 0; i < 256; i++)
> [/Debug Part]
>
> *We can not stop at continue statement of line 8! *
> Let us see the llvm ir:
> [LLVM]
> for.cond:                                         ; preds = %for.inc, %entry
>   %0 = load i32, i32* %i, align 4, !dbg !17
>   %cmp = icmp slt i32 %0, 256, !dbg !19
>   br i1 %cmp, label %for.body, label %for.end, !dbg !20
>
> for.body:                                         ; preds = %for.cond
>   %1 = load i32, i32* %i, align 4, !dbg !21
>   %inc = add nsw i32 %1, 1, !dbg !21
>   store i32 %inc, i32* %i, align 4, !dbg !21*  br label %for.inc, !dbg !23;  ; // Here is continue statement, but its basic block instructions size > 1 and its successor is nature layout, which will be deleted*
>
> for.inc:                                          ; preds = %for.body
>   %2 = load i32, i32* %i, align 4, !dbg !24
>   %inc1 = add nsw i32 %2, 1, !dbg !24
>   store i32 %inc1, i32* %i, align 4, !dbg !24
>   br label %for.cond, !dbg !25, !llvm.loop !26
>
> for.end:                                          ; preds = %for.cond
>   %3 = load i32, i32* %retval, align 4, !dbg !28
>   ret i32 %3, !dbg !28
>
> !23 = !DILocation(line: 8, column: 5, scope: !22)
>
> As comment, *br label %for.inc, !dbg !23;* will be deleted and we can not
> get right debug behavior.
>
> So I propose one changeset, if we have debug information, we don't
> eliminate the unconditional branch instruction, otherwise we eliminate it.
>

It is a fairly strong goal of LLVM that the presence or absence of debug
information should not affect the optimization decisions/code of the final
binary, unfortunately.


>
>  /// (fall-through) successor, and update the CFG.
>  void FastISel::fastEmitBranch(MachineBasicBlock *MSucc,
>                                const DebugLoc &DbgLoc) {
> -  if (FuncInfo.MBB->getBasicBlock()->size() > 1 &&
> -      FuncInfo.MBB->isLayoutSuccessor(MSucc)) {
> -    // For more accurate line information if this is the only instruction
> -    // in the block then emit it, otherwise we have the unconditional
> +  if (FuncInfo.MBB->isLayoutSuccessor(MSucc) && !DbgLoc) {
> +    // For more accurate line information if this is in debug mode
> +    // then emit it, otherwise we have the unconditional
>      // fall-through case, which needs no instructions.
>    } else {
>      // The unconditional branch case.
>
> Wish to hear more comments and feedbacks.
>
>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170725/0b7638db/attachment.html>


More information about the llvm-dev mailing list