summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/MC/MCContext.h13
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp1
-rw-r--r--llvm/lib/MC/MCContext.cpp6
-rw-r--r--llvm/lib/MC/MCParser/AsmParser.cpp4
-rw-r--r--llvm/test/CodeGen/AArch64/callbr-asm-label.ll63
-rw-r--r--llvm/test/CodeGen/X86/callbr-asm-label-addr.ll30
-rw-r--r--llvm/test/CodeGen/X86/callbr-asm.ll16
7 files changed, 124 insertions, 9 deletions
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index d5bbff5834d..69e3128e194 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -113,6 +113,9 @@ namespace llvm {
/// number of section symbols with the same name).
StringMap<bool, BumpPtrAllocator &> UsedNames;
+ /// Keeps track of labels that are used in inline assembly.
+ SymbolTable InlineAsmUsedLabelNames;
+
/// The next ID to dole out to an unnamed assembler temporary symbol with
/// a given prefix.
StringMap<unsigned> NextID;
@@ -382,6 +385,16 @@ namespace llvm {
/// APIs.
const SymbolTable &getSymbols() const { return Symbols; }
+ /// isInlineAsmLabel - Return true if the name is a label referenced in
+ /// inline assembly.
+ MCSymbol *getInlineAsmLabel(StringRef Name) const {
+ return InlineAsmUsedLabelNames.lookup(Name);
+ }
+
+ /// registerInlineAsmLabel - Records that the name is a label referenced in
+ /// inline assembly.
+ void registerInlineAsmLabel(MCSymbol *Sym);
+
/// @}
/// \name Section Management
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 7721e996aca..5e49fec9c05 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -432,6 +432,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
Sym->print(OS, AP->MAI);
+ MMI->getContext().registerInlineAsmLabel(Sym);
} else if (MI->getOperand(OpNo).isMBB()) {
const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
Sym->print(OS, AP->MAI);
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index a030f5e4eb0..6975ab3af53 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -61,6 +61,7 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
MCTargetOptions const *TargetOpts, bool DoAutoReset)
: SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
Symbols(Allocator), UsedNames(Allocator),
+ InlineAsmUsedLabelNames(Allocator),
CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
AutoReset(DoAutoReset), TargetOptions(TargetOpts) {
SecureLogFile = AsSecureLogFileName;
@@ -90,6 +91,7 @@ void MCContext::reset() {
XCOFFAllocator.DestroyAll();
MCSubtargetAllocator.DestroyAll();
+ InlineAsmUsedLabelNames.clear();
UsedNames.clear();
Symbols.clear();
Allocator.Reset();
@@ -272,6 +274,10 @@ void MCContext::setSymbolValue(MCStreamer &Streamer,
Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
}
+void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
+ InlineAsmUsedLabelNames[Sym->getName()] = Sym;
+}
+
//===----------------------------------------------------------------------===//
// Section Management
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 27def715ca0..381bf964161 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1158,7 +1158,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
}
- MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
+ MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName);
+ if (!Sym)
+ Sym = getContext().getOrCreateSymbol(SymbolName);
// If this is an absolute variable reference, substitute it now to preserve
// semantics in the face of reassignment.
diff --git a/llvm/test/CodeGen/AArch64/callbr-asm-label.ll b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll
new file mode 100644
index 00000000000..583587da71a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll
@@ -0,0 +1,63 @@
+; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s
+
+@X = common local_unnamed_addr global i32 0, align 4
+
+define i32 @test1() {
+; CHECK-LABEL: test1:
+; CHECK: .word b
+; CHECK-NEXT: .word .Ltmp0
+; CHECK-LABEL: .Ltmp0:
+; CHECK-LABEL: .LBB0_1: // %l_yes
+; CHECK-LABEL: .LBB0_2: // %cleanup
+entry:
+ callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "X"(i8* blockaddress(@test1, %l_yes))
+ to label %cleanup [label %l_yes]
+
+l_yes:
+ br label %cleanup
+
+cleanup:
+ %retval.0 = phi i32 [ 1, %l_yes ], [ 0, %entry ]
+ ret i32 %retval.0
+}
+
+define void @test2() {
+; CHECK-LABEL: test2:
+entry:
+ %0 = load i32, i32* @X, align 4
+ %and = and i32 %0, 1
+ %tobool = icmp eq i32 %and, 0
+ br i1 %tobool, label %if.end10, label %if.then
+
+if.then:
+; CHECK: .word b
+; CHECK-NEXT: .word .Ltmp2
+; CHECK-LABEL: .Ltmp2:
+; CHECK-NEXT: .LBB1_3: // %if.end6
+ callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "X"(i8* blockaddress(@test2, %if.end6))
+ to label %if.then4 [label %if.end6]
+
+if.then4:
+ %call5 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)()
+ br label %if.end6
+
+if.end6:
+ %.pre = load i32, i32* @X, align 4
+ %.pre13 = and i32 %.pre, 1
+ %phitmp = icmp eq i32 %.pre13, 0
+ br i1 %phitmp, label %if.end10, label %if.then9
+
+if.then9:
+; CHECK-LABEL: .Ltmp4:
+; CHECK-NEXT: .LBB1_5: // %l_yes
+ callbr void asm sideeffect "", "X"(i8* blockaddress(@test2, %l_yes))
+ to label %if.end10 [label %l_yes]
+
+if.end10:
+ br label %l_yes
+
+l_yes:
+ ret void
+}
+
+declare i32 @g(...)
diff --git a/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
new file mode 100644
index 00000000000..dc0e8363465
--- /dev/null
+++ b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll
@@ -0,0 +1,30 @@
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i32 @test1(i32 %x) {
+; CHECK-LABEL: test1:
+; CHECK: .quad .Ltmp0
+; CHECK-NEXT: .quad .Ltmp1
+; CHECK-LABEL: .Ltmp1:
+; CHECK-LABEL: .LBB0_1: # %bar
+; CHECK-NEXT: callq foo
+; CHECK-LABEL: .Ltmp0:
+; CHECK-NEXT: # %bb.2: # %baz
+entry:
+ callbr void asm sideeffect ".quad ${0:l}\0A\09.quad ${1:l}", "i,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %baz), i8* blockaddress(@test1, %bar))
+ to label %asm.fallthrough [label %bar]
+
+asm.fallthrough:
+ br label %bar
+
+bar:
+ %call = tail call i32 @foo(i32 %x)
+ br label %baz
+
+baz:
+ %call1 = tail call i32 @mux(i32 %call)
+ ret i32 %call1
+}
+
+declare i32 @foo(i32)
+
+declare i32 @mux(i32)
diff --git a/llvm/test/CodeGen/X86/callbr-asm.ll b/llvm/test/CodeGen/X86/callbr-asm.ll
index 48a80ae167b..ed3c314ed42 100644
--- a/llvm/test/CodeGen/X86/callbr-asm.ll
+++ b/llvm/test/CodeGen/X86/callbr-asm.ll
@@ -12,7 +12,7 @@ define i32 @test1(i32 %a) {
; CHECK-NEXT: addl $4, %eax
; CHECK-NEXT: #APP
; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: jmp .Ltmp00
+; CHECK-NEXT: jmp .Ltmp0
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: .LBB0_1: # %normal
; CHECK-NEXT: xorl %eax, %eax
@@ -87,17 +87,17 @@ define dso_local i32 @test3(i32 %a) {
; CHECK-NEXT: # Parent Loop BB2_3 Depth=3
; CHECK-NEXT: # => This Inner Loop Header: Depth=4
; CHECK-NEXT: #APP
-; CHECK-NEXT: jmp .Ltmp10
-; CHECK-NEXT: jmp .Ltmp20
-; CHECK-NEXT: jmp .Ltmp30
+; CHECK-NEXT: jmp .Ltmp1
+; CHECK-NEXT: jmp .Ltmp2
+; CHECK-NEXT: jmp .Ltmp3
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: .LBB2_5: # %normal0
; CHECK-NEXT: # in Loop: Header=BB2_4 Depth=4
; CHECK-NEXT: #APP
-; CHECK-NEXT: jmp .Ltmp10
-; CHECK-NEXT: jmp .Ltmp20
-; CHECK-NEXT: jmp .Ltmp30
-; CHECK-NEXT: jmp .Ltmp40
+; CHECK-NEXT: jmp .Ltmp1
+; CHECK-NEXT: jmp .Ltmp2
+; CHECK-NEXT: jmp .Ltmp3
+; CHECK-NEXT: jmp .Ltmp4
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: .LBB2_6: # %normal1
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
OpenPOWER on IntegriCloud