[llvm] r301219 - Don't emit CFI instructions at the end of a function

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 11:46:00 PDT 2017


Author: adrian
Date: Mon Apr 24 13:45:59 2017
New Revision: 301219

URL: http://llvm.org/viewvc/llvm-project?rev=301219&view=rev
Log:
Don't emit CFI instructions at the end of a function

When functions are terminated by unreachable instructions, the last
instruction might trigger a CFI instruction to be generated. However,
emitting it would be be illegal since the function (and thus the FDE
the CFI is in) has already ended with the previous instruction.

Darwin's dwarfdump --verify --eh-frame complains about this and the
specification supports this.
Relevant bits from the DWARF 5 standard (6.4 Call Frame Information):

"[The] address_range [field in an FDE]: The number of bytes of
 program instructions described by this entry."

"Row creation instructions: [...]
 The new location value is always greater than the current one."
The first quotation implies that a CFI cannot describe a target
address outside of the enclosing FDE's range.

rdar://problem/26244988

Differential Revision: https://reviews.llvm.org/D32246

Added:
    llvm/trunk/test/CodeGen/X86/eh-frame-unreachable.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/test/CodeGen/PowerPC/empty-functions.ll
    llvm/trunk/test/CodeGen/SPARC/empty-functions.ll
    llvm/trunk/test/CodeGen/X86/empty-functions.ll

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=301219&r1=301218&r2=301219&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Mon Apr 24 13:45:59 2017
@@ -938,6 +938,16 @@ void AsmPrinter::emitCFIInstruction(cons
   if (needsCFIMoves() == CFI_M_None)
     return;
 
+  // If there is no "real" instruction following this CFI instruction, skip
+  // emitting it; it would be beyond the end of the function's FDE range.
+  auto *MBB = MI.getParent();
+  auto I = std::next(MI.getIterator());
+  while (I != MBB->end() && I->isTransient())
+    ++I;
+  if (I == MBB->instr_end() &&
+      MBB->getReverseIterator() == MBB->getParent()->rbegin())
+    return;
+
   const std::vector<MCCFIInstruction> &Instrs = MF->getFrameInstructions();
   unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
   const MCCFIInstruction &CFI = Instrs[CFIIndex];

Modified: llvm/trunk/test/CodeGen/PowerPC/empty-functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/empty-functions.ll?rev=301219&r1=301218&r2=301219&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/empty-functions.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/empty-functions.ll Mon Apr 24 13:45:59 2017
@@ -24,9 +24,7 @@ entry:
 ; LINUX-NO-FP-NEXT: .size   func, .L[[END]]-.L[[BEGIN]]
 ; LINUX-NO-FP-NEXT: .cfi_endproc
 
-; A cfi directive can point to the end of a function. It (and in fact the
-; entire body) could be optimized out because of the unreachable, but we
-; don't do it right now.
+; A cfi directive cannot point to the end of a function.
 ; LINUX-FP: func:
 ; LINUX-FP-NEXT: {{^}}.L[[BEGIN:.*]]:{{$}}
 ; LINUX-FP-NEXT: .cfi_startproc
@@ -38,8 +36,6 @@ entry:
 ; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
 ; LINUX-FP-NEXT: .cfi_offset r31, -4
 ; LINUX-FP-NEXT: mr 31, 1
-; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
-; LINUX-FP-NEXT: .cfi_def_cfa_register r31
 ; LINUX-FP-NEXT: {{^}}.L[[END:.*]]:{{$}}
 ; LINUX-FP-NEXT: .size   func, .L[[END]]-.L[[BEGIN]]
 ; LINUX-FP-NEXT: .cfi_endproc

Modified: llvm/trunk/test/CodeGen/SPARC/empty-functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/empty-functions.ll?rev=301219&r1=301218&r2=301219&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/empty-functions.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/empty-functions.ll Mon Apr 24 13:45:59 2017
@@ -14,19 +14,11 @@ entry:
 ; LINUX-NO-FP-NEXT: .size   func, .L{{.*}}-func
 ; LINUX-NO-FP-NEXT: .cfi_endproc
 
-; A cfi directive can point to the end of a function. It (and in fact the
-; entire body) could be optimized out because of the unreachable, but we
-; don't do it right now.
+; A cfi directive cannot point to the end of a function.
 ; LINUX-FP: func:
 ; LINUX-FP-NEXT: .cfi_startproc
 ; LINUX-FP-NEXT: {{^}}!
 ; LINUX-FP-NEXT: save %sp, -96, %sp
 ; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
-; LINUX-FP-NEXT: .cfi_def_cfa_register %fp
-; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
-; LINUX-FP-NEXT: .cfi_window_save
-; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
-; LINUX-FP-NEXT: .cfi_register 15, 31
-; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
 ; LINUX-FP-NEXT: .size   func, .Lfunc_end0-func
 ; LINUX-FP-NEXT: .cfi_endproc

Added: llvm/trunk/test/CodeGen/X86/eh-frame-unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/eh-frame-unreachable.ll?rev=301219&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/eh-frame-unreachable.ll (added)
+++ llvm/trunk/test/CodeGen/X86/eh-frame-unreachable.ll Mon Apr 24 13:45:59 2017
@@ -0,0 +1,11 @@
+; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
+; Test that we don't emit a row that extends beyond the FDE's range_size.
+;
+; CHECK: movq	%rsp, %rbp
+; CHECK-NEXT:	.cfi_endproc
+; CHECK-NOT: .cfi
+
+define void @f() #0 {
+  unreachable
+}
+attributes #0 = { "no-frame-pointer-elim"="true" }

Modified: llvm/trunk/test/CodeGen/X86/empty-functions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/empty-functions.ll?rev=301219&r1=301218&r2=301219&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/empty-functions.ll (original)
+++ llvm/trunk/test/CodeGen/X86/empty-functions.ll Mon Apr 24 13:45:59 2017
@@ -23,8 +23,6 @@ entry:
 ; CHECK-FP-NEXT: :
 ; CHECK-FP-NEXT: .cfi_offset %rbp, -16
 ; CHECK-FP-NEXT: movq %rsp, %rbp
-; CHECK-FP-NEXT: :
-; CHECK-FP-NEXT: .cfi_def_cfa_register %rbp
 ; CHECK-FP-NEXT: .cfi_endproc
 
 ; An empty function is perfectly fine on ELF.
@@ -35,9 +33,7 @@ entry:
 ; LINUX-NO-FP-NEXT: .size   func, .L{{.*}}-func
 ; LINUX-NO-FP-NEXT: .cfi_endproc
 
-; A cfi directive can point to the end of a function. It (and in fact the
-; entire body) could be optimized out because of the unreachable, but we
-; don't do it right now.
+; A cfi directive cannot point to the end of a function.
 ; LINUX-FP: func:
 ; LINUX-FP-NEXT: .cfi_startproc
 ; LINUX-FP-NEXT: {{^}}#
@@ -48,7 +44,5 @@ entry:
 ; LINUX-FP-NEXT: .cfi_offset %rbp, -16
 ; LINUX-FP-NEXT: movq        %rsp, %rbp
 ; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
-; LINUX-FP-NEXT: .cfi_def_cfa_register %rbp
-; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
 ; LINUX-FP-NEXT: .size   func, .Lfunc_end0-func
 ; LINUX-FP-NEXT: .cfi_endproc




More information about the llvm-commits mailing list