summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2014-09-15 18:32:58 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2014-09-15 18:32:58 +0000
commit6865d6f08a52ad4280009196f41cf35cc1400e8b (patch)
tree75735f620ef26becd87d8b8d3ae3ff689d8921cd
parent9dcb724d311456e1db023dde9aead5968e87f160 (diff)
downloadbcm5719-llvm-6865d6f08a52ad4280009196f41cf35cc1400e8b.tar.gz
bcm5719-llvm-6865d6f08a52ad4280009196f41cf35cc1400e8b.zip
Fix a lot of confusion around inserting nops on empty functions.
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. llvm-svn: 217801
-rw-r--r--llvm/include/llvm/Target/TargetInstrInfo.h6
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp18
-rw-r--r--llvm/lib/CodeGen/TargetInstrInfo.cpp4
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp5
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.h2
-rw-r--r--llvm/test/CodeGen/PowerPC/empty-functions.ll13
-rw-r--r--llvm/test/CodeGen/SPARC/empty-functions.ll8
-rw-r--r--llvm/test/CodeGen/X86/empty-functions.ll31
8 files changed, 39 insertions, 48 deletions
diff --git a/llvm/include/llvm/Target/TargetInstrInfo.h b/llvm/include/llvm/Target/TargetInstrInfo.h
index 930199509c5..2910b2024ab 100644
--- a/llvm/include/llvm/Target/TargetInstrInfo.h
+++ b/llvm/include/llvm/Target/TargetInstrInfo.h
@@ -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.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index b1fc46b4112..b26d8d6f101 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -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();
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 277073f0c8a..ab45f89a628 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -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 {
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index 6836d8d6f68..8b2e6bc5f32 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -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
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.h b/llvm/lib/Target/Sparc/SparcInstrInfo.h
index 2c39bbc3000..fe93ed7b57c 100644
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.h
+++ b/llvm/lib/Target/Sparc/SparcInstrInfo.h
@@ -93,8 +93,6 @@ public:
const TargetRegisterInfo *TRI) const override;
unsigned getGlobalBaseReg(MachineFunction *MF) const;
-
- void getNoopForMachoTarget(MCInst &NopInst) const override;
};
}
diff --git a/llvm/test/CodeGen/PowerPC/empty-functions.ll b/llvm/test/CodeGen/PowerPC/empty-functions.ll
deleted file mode 100644
index bed16cfe82a..00000000000
--- a/llvm/test/CodeGen/PowerPC/empty-functions.ll
+++ /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/llvm/test/CodeGen/SPARC/empty-functions.ll b/llvm/test/CodeGen/SPARC/empty-functions.ll
deleted file mode 100644
index 92522994cc7..00000000000
--- a/llvm/test/CodeGen/SPARC/empty-functions.ll
+++ /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
diff --git a/llvm/test/CodeGen/X86/empty-functions.ll b/llvm/test/CodeGen/X86/empty-functions.ll
index ac5174db5fc..42349688a71 100644
--- a/llvm/test/CodeGen/X86/empty-functions.ll
+++ b/llvm/test/CodeGen/X86/empty-functions.ll
@@ -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
OpenPOWER on IntegriCloud