Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -112,6 +112,9 @@ /// number of section symbols with the same name). StringMap 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 NextID; @@ -377,6 +380,18 @@ /// 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(StringRef Name, MCSymbol *Sym) { + InlineAsmUsedLabelNames[Name] = Sym; + } + /// @} /// \name Section Management Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -432,6 +432,7 @@ const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); Sym->print(OS, AP->MAI); + MMI->getContext().registerInlineAsmLabel(Sym->getName(), Sym); } else if (MI->getOperand(OpNo).isMBB()) { const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); Sym->print(OS, AP->MAI); Index: lib/CodeGen/MachineModuleInfo.cpp =================================================================== --- lib/CodeGen/MachineModuleInfo.cpp +++ lib/CodeGen/MachineModuleInfo.cpp @@ -121,7 +121,11 @@ BBCallbacks.back().setMap(this); Entry.Index = BBCallbacks.size() - 1; Entry.Fn = BB->getParent(); - Entry.Symbols.push_back(Context.createTempSymbol()); + Entry.Symbols.push_back( + Context.createTempSymbol( + !any_of(BB->uses(), [](const Value *V) { + return isa(V); + }))); return Entry.Symbols; } Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -61,6 +61,7 @@ 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) { SecureLogFile = AsSecureLogFileName; @@ -90,6 +91,7 @@ XCOFFAllocator.DestroyAll(); MCSubtargetAllocator.DestroyAll(); + InlineAsmUsedLabelNames.clear(); UsedNames.clear(); Symbols.clear(); Allocator.Reset(); Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -1158,7 +1158,9 @@ } } - 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. Index: test/CodeGen/AArch64/callbr-asm-label.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/callbr-asm-label.ll @@ -0,0 +1,63 @@ +; RUN: llc < %s -mtriple=armv4t-unknown-linux-gnueabi | FileCheck %s + +@X = common local_unnamed_addr global i32 0, align 4 + +define i32 @test1() { +; CHECK-LABEL: test1: +; CHECK: .long b +; CHECK-NEXT: .long .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: .long b +; CHECK-NEXT: .long .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(...) Index: test/CodeGen/AArch64/callbr-asm-obj-file.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/callbr-asm-obj-file.ll @@ -0,0 +1,102 @@ +; RUN: llc < %s -mtriple=aarch64-unknown-linux-gnu -filetype=obj -o - \ +; RUN: | llvm-objdump -triple aarch64-unknown-linux-gnu -d - \ +; RUN: | FileCheck %s + +%struct.c = type { i1 (...)* } + +@l = common hidden local_unnamed_addr global i32 0, align 4 + +; CHECK-LABEL: 0000000000000000 test1: +; CHECK-LABEL: 0000000000000018 $d.1: +; CHECK-LABEL: 0000000000000020 $x.2: +; CHECK-NEXT: b #16 <$x.4+0x4> +; CHECK-LABEL: 000000000000002c $x.4: +; CHECK-NEXT: b #4 <$x.4+0x4> +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret +define hidden i32 @test1() { + %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %2 = icmp eq i32 %1, 0 + br i1 %2, label %3, label %5 + +3: ; preds = %0 + callbr void asm sideeffect "1: nop\0A\09.quad a\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test1, %7)) + to label %4 [label %7] + +4: ; preds = %3 + br label %7 + +5: ; preds = %0 + %6 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + br label %7 + +7: ; preds = %3, %4, %5 + %8 = phi i32 [ %6, %5 ], [ 0, %4 ], [ 0, %3 ] + ret i32 %8 +} + +declare dso_local i32 @g(...) local_unnamed_addr + +declare dso_local i32 @i(...) local_unnamed_addr + +; CHECK-LABEL: 000000000000003c test2: +; CHECK: bl #0 +; CHECK-LABEL: 0000000000000064 $d.5: +; CHECK-LABEL: 000000000000006c $x.6: +; CHECK-NEXT: b #-24 +define hidden i32 @test2() local_unnamed_addr { + %1 = load i32, i32* @l, align 4 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %10, label %3 + +3: ; preds = %0 + %4 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %5 = icmp eq i32 %4, 0 + br i1 %5, label %6, label %7 + +6: ; preds = %3 + callbr void asm sideeffect "1: nop\0A\09.quad b\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test2, %7)) + to label %10 [label %9] + +7: ; preds = %3 + %8 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + br label %10 + +9: ; preds = %6 + br label %10 + +10: ; preds = %7, %0, %6, %9 + ret i32 undef +} + +; CHECK-LABEL: 0000000000000084 test3: +; CHECK-LABEL: 00000000000000a8 $d.9: +; CHECK-LABEL: 00000000000000b0 $x.10: +; CHECK-NEXT: b #20 <$x.12+0x8> +; CHECK-LABEL: 00000000000000bc $x.12: +; CHECK-NEXT: b #4 <$x.12+0x4> +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret +define internal i1 @test3() { + %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %2 = icmp eq i32 %1, 0 + br i1 %2, label %3, label %5 + +3: ; preds = %0 + callbr void asm sideeffect "1: nop\0A\09.quad c\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test3, %8)) + to label %4 [label %8] + +4: ; preds = %3 + br label %8 + +5: ; preds = %0 + %6 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + %7 = icmp ne i32 %6, 0 + br label %8 + +8: ; preds = %3, %4, %5 + %9 = phi i1 [ %7, %5 ], [ false, %4 ], [ false, %3 ] + ret i1 %9 +} Index: test/CodeGen/X86/callbr-asm-label-addr.ll =================================================================== --- /dev/null +++ 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) Index: test/CodeGen/X86/callbr-asm-obj-file.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/callbr-asm-obj-file.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu -filetype=obj -o - \ +; RUN: | llvm-objdump -triple x86_64-linux-gnu -d - \ +; RUN: | FileCheck %s + +; CHECK: 0000000000000000 test1: +; CHECK-NEXT: 0: 74 00 je 0 +; CHECK-NEXT: 2: c3 retq + +define void @test1() { +entry: + callbr void asm sideeffect "je ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %a.b.normal.jump)) + to label %asm.fallthrough [label %a.b.normal.jump] + +asm.fallthrough: + ret void + +a.b.normal.jump: + ret void +} Index: test/CodeGen/X86/callbr-asm.ll =================================================================== --- test/CodeGen/X86/callbr-asm.ll +++ test/CodeGen/X86/callbr-asm.ll @@ -12,7 +12,7 @@ ; 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 @@ ; 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