summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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