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

Frozen via llvm-dev llvm-dev at lists.llvm.org
Mon Jul 24 20:17:13 PDT 2017


    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.

 /// (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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170725/127970d2/attachment.html>


More information about the llvm-dev mailing list