Fix a lot of confusion around inserting nops on empty functions.
authorRafael Espindola <rafael.espindola@gmail.com>
Mon, 15 Sep 2014 18:32:58 +0000 (18:32 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Mon, 15 Sep 2014 18:32:58 +0000 (18:32 +0000)
On MachO, and MachO only, we cannot have a truly empty function since that
breaks the linker logic for atomizing the section.

When we are emitting a frame pointer, the presence of an unreachable will
create a cfi instruction pointing past the last instruction. This is perfectly
fine. The FDE information encodes the pc range it applies to. If some tool
cannot handle this, we should explicitly say which bug we are working around
and only work around it when it is actually relevant (not for ELF for example).

Given the unreachable we could omit the .cfi_def_cfa_register, but then
again, we could also omit the entire function prologue if we wanted to.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217801 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetInstrInfo.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/TargetInstrInfo.cpp
lib/Target/Sparc/SparcInstrInfo.cpp
lib/Target/Sparc/SparcInstrInfo.h
test/CodeGen/PowerPC/empty-functions.ll [deleted file]
test/CodeGen/SPARC/empty-functions.ll [deleted file]
test/CodeGen/X86/empty-functions.ll

index 930199509c5fba9a20a04e26cecf7a01d021be91..2910b2024ab0b0067a5cd21556f76590f4eed7fb 100644 (file)
@@ -847,10 +847,8 @@ public:
                           MachineBasicBlock::iterator MI) const;
 
 
-  /// getNoopForMachoTarget - Return the noop instruction to use for a noop.
-  virtual void getNoopForMachoTarget(MCInst &NopInst) const {
-    // Default to just using 'nop' string.
-  }
+  /// Return the noop instruction to use for a noop.
+  virtual void getNoopForMachoTarget(MCInst &NopInst) const;
 
 
   /// isPredicated - Returns true if the instruction is already predicated.
index b1fc46b41128696d2bc2ba00590c71b299bba3f3..b26d8d6f101220b8b358b51ac22cefbfd66d38cf 100644 (file)
@@ -731,12 +731,10 @@ void AsmPrinter::EmitFunctionBody() {
 
   // Print out code for the function.
   bool HasAnyRealCode = false;
-  const MachineInstr *LastMI = nullptr;
   for (auto &MBB : *MF) {
     // Print a label for the basic block.
     EmitBasicBlockStart(MBB);
     for (auto &MI : MBB) {
-      LastMI = &MI;
 
       // Print the assembly for the instruction.
       if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
@@ -797,24 +795,14 @@ void AsmPrinter::EmitFunctionBody() {
     EmitBasicBlockEnd(MBB);
   }
 
-  // If the last instruction was a prolog label, then we have a situation where
-  // we emitted a prolog but no function body. This results in the ending prolog
-  // label equaling the end of function label and an invalid "row" in the
-  // FDE. We need to emit a noop in this situation so that the FDE's rows are
-  // valid.
-  bool RequiresNoop = LastMI && LastMI->isCFIInstruction();
-
   // If the function is empty and the object file uses .subsections_via_symbols,
   // then we need to emit *something* to the function body to prevent the
   // labels from collapsing together.  Just emit a noop.
-  if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) || RequiresNoop) {
+  if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)) {
     MCInst Noop;
     TM.getSubtargetImpl()->getInstrInfo()->getNoopForMachoTarget(Noop);
-    if (Noop.getOpcode()) {
-      OutStreamer.AddComment("avoids zero-length function");
-      OutStreamer.EmitInstruction(Noop, getSubtargetInfo());
-    } else  // Target not mc-ized yet.
-      OutStreamer.EmitRawText(StringRef("\tnop\n"));
+    OutStreamer.AddComment("avoids zero-length function");
+    OutStreamer.EmitInstruction(Noop, getSubtargetInfo());
   }
 
   const Function *F = MF->getFunction();
index 277073f0c8affd10c89c45f76b088cdf64a8b5d5..ab45f89a628e232e32190d37d4589334e30b9c83 100644 (file)
@@ -372,6 +372,10 @@ static const TargetRegisterClass *canFoldCopy(const MachineInstr *MI,
   return nullptr;
 }
 
+void TargetInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
+  llvm_unreachable("Not a MachO target");
+}
+
 bool TargetInstrInfo::
 canFoldMemoryOperand(const MachineInstr *MI,
                      const SmallVectorImpl<unsigned> &Ops) const {
index 6836d8d6f6870f22028012ba00fb9bd9d2e910f8..8b2e6bc5f32fbc177cf84e273e9b50df0bf1f8f8 100644 (file)
@@ -37,11 +37,6 @@ SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST)
     RI(ST), Subtarget(ST) {
 }
 
-/// getNoopForMachoTarget - Return the noop instruction to use for a noop.
-void SparcInstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
-  NopInst.setOpcode(SP::NOP);
-}
-
 /// isLoadFromStackSlot - If the specified machine instruction is a direct
 /// load from a stack slot, return the virtual or physical register number of
 /// the destination along with the FrameIndex of the loaded stack slot.  If
index 2c39bbc3000012669d101d94e9d329c8e9ad355d..fe93ed7b57c76ea553d9ddf63ec4de6715b20838 100644 (file)
@@ -93,8 +93,6 @@ public:
                             const TargetRegisterInfo *TRI) const override;
 
   unsigned getGlobalBaseReg(MachineFunction *MF) const;
-
-  void getNoopForMachoTarget(MCInst &NopInst) const override;
 };
 
 }
diff --git a/test/CodeGen/PowerPC/empty-functions.ll b/test/CodeGen/PowerPC/empty-functions.ll
deleted file mode 100644 (file)
index bed16cf..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-; RUN: llc < %s -mtriple=powerpc-apple-darwin | FileCheck -check-prefix=CHECK-NO-FP %s
-; RUN: llc < %s -mtriple=powerpc-apple-darwin -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s
-; RUN: llc < %s -mtriple=powerpc-netbsd -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s
-
-define void @func() {
-entry:
-  unreachable
-}
-; CHECK-NO-FP:     _func:
-; CHECK-NO-FP:     nop
-
-; CHECK-FP:      {{_?}}func:
-; CHECK-FP: nop {{[;#]}} avoids zero-length function
diff --git a/test/CodeGen/SPARC/empty-functions.ll b/test/CodeGen/SPARC/empty-functions.ll
deleted file mode 100644 (file)
index 9252299..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: llc < %s -mtriple=sparc-unknown-openbsd -disable-fp-elim | FileCheck -check-prefix=CHECK-FP-LABEL %s
-
-define void @func() {
-entry:
-  unreachable
-}
-; CHECK-FP-LABEL:      {{_?}}func:
-; CHECK-FP-LABEL: nop {{[;!]}} avoids zero-length function
index ac5174db5fc590872b2b579cc1a5da6ea58a41d1..42349688a710747e46a77e24a57d034716122691 100644 (file)
@@ -1,10 +1,14 @@
 ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck -check-prefix=CHECK-NO-FP %s
 ; RUN: llc < %s -mtriple=x86_64-apple-darwin -disable-fp-elim | FileCheck -check-prefix=CHECK-FP %s
+; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=LINUX-NO-FP %s
+; RUN: llc < %s -mtriple=x86_64-linux-gnu -disable-fp-elim | FileCheck -check-prefix=LINUX-FP %s
 
 define void @func() {
 entry:
   unreachable
 }
+
+; MachO cannot handle an empty function.
 ; CHECK-NO-FP:     _func:
 ; CHECK-NO-FP-NEXT: .cfi_startproc
 ; CHECK-NO-FP:     nop
@@ -21,5 +25,30 @@ entry:
 ; CHECK-FP-NEXT: movq %rsp, %rbp
 ; CHECK-FP-NEXT: :
 ; CHECK-FP-NEXT: .cfi_def_cfa_register %rbp
-; CHECK-FP-NEXT: nop
 ; CHECK-FP-NEXT: .cfi_endproc
+
+; An empty function is perfectly fine on ELF.
+; LINUX-NO-FP: func:
+; LINUX-NO-FP-NEXT: .cfi_startproc
+; LINUX-NO-FP-NEXT: {{^}}#
+; LINUX-NO-FP-NEXT: {{^}}.L{{.*}}:{{$}}
+; 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.
+; LINUX-FP: func:
+; LINUX-FP-NEXT: .cfi_startproc
+; LINUX-FP-NEXT: {{^}}#
+; LINUX-FP-NEXT: pushq %rbp
+; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
+; LINUX-FP-NEXT:  .cfi_def_cfa_offset 16
+; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
+; 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, .Ltmp3-func
+; LINUX-FP-NEXT: .cfi_endproc