mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[MC] Don't recreate a label if it's already used
Summary: This patch keeps track of MCSymbols created for blocks that were referenced in inline asm. It prevents creating a new symbol which doesn't refer to the block. Inline asm may have a reference to a label. The asm parser however doesn't recognize it as a label and tries to create a new symbol. The result being that instead of the original symbol (e.g. ".Ltmp0") the parser replaces it in the inline asm with the new one (e.g. ".Ltmp00") without updating it in the symbol table. So the machine basic block retains the "old" symbol (".Ltmp0"), but the inline asm uses the new one (".Ltmp00"). Reviewers: nickdesaulniers, craig.topper Subscribers: nathanchance, javed.absar, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65304 llvm-svn: 368477
This commit is contained in:
parent
d6ddff770e
commit
5c86e999b1
@ -113,6 +113,9 @@ namespace llvm {
|
|||||||
/// number of section symbols with the same name).
|
/// number of section symbols with the same name).
|
||||||
StringMap<bool, BumpPtrAllocator &> UsedNames;
|
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
|
/// The next ID to dole out to an unnamed assembler temporary symbol with
|
||||||
/// a given prefix.
|
/// a given prefix.
|
||||||
StringMap<unsigned> NextID;
|
StringMap<unsigned> NextID;
|
||||||
@ -382,6 +385,16 @@ namespace llvm {
|
|||||||
/// APIs.
|
/// APIs.
|
||||||
const SymbolTable &getSymbols() const { return Symbols; }
|
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
|
/// \name Section Management
|
||||||
|
@ -432,6 +432,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
|
|||||||
const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
|
const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
|
||||||
MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
|
MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
|
||||||
Sym->print(OS, AP->MAI);
|
Sym->print(OS, AP->MAI);
|
||||||
|
MMI->getContext().registerInlineAsmLabel(Sym);
|
||||||
} else if (MI->getOperand(OpNo).isMBB()) {
|
} else if (MI->getOperand(OpNo).isMBB()) {
|
||||||
const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
|
const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
|
||||||
Sym->print(OS, AP->MAI);
|
Sym->print(OS, AP->MAI);
|
||||||
|
@ -61,6 +61,7 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
|
|||||||
MCTargetOptions const *TargetOpts, bool DoAutoReset)
|
MCTargetOptions const *TargetOpts, bool DoAutoReset)
|
||||||
: SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
|
: SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi),
|
||||||
Symbols(Allocator), UsedNames(Allocator),
|
Symbols(Allocator), UsedNames(Allocator),
|
||||||
|
InlineAsmUsedLabelNames(Allocator),
|
||||||
CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
|
CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0),
|
||||||
AutoReset(DoAutoReset), TargetOptions(TargetOpts) {
|
AutoReset(DoAutoReset), TargetOptions(TargetOpts) {
|
||||||
SecureLogFile = AsSecureLogFileName;
|
SecureLogFile = AsSecureLogFileName;
|
||||||
@ -90,6 +91,7 @@ void MCContext::reset() {
|
|||||||
XCOFFAllocator.DestroyAll();
|
XCOFFAllocator.DestroyAll();
|
||||||
|
|
||||||
MCSubtargetAllocator.DestroyAll();
|
MCSubtargetAllocator.DestroyAll();
|
||||||
|
InlineAsmUsedLabelNames.clear();
|
||||||
UsedNames.clear();
|
UsedNames.clear();
|
||||||
Symbols.clear();
|
Symbols.clear();
|
||||||
Allocator.Reset();
|
Allocator.Reset();
|
||||||
@ -272,6 +274,10 @@ void MCContext::setSymbolValue(MCStreamer &Streamer,
|
|||||||
Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
|
Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MCContext::registerInlineAsmLabel(MCSymbol *Sym) {
|
||||||
|
InlineAsmUsedLabelNames[Sym->getName()] = Sym;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Section Management
|
// Section Management
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -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
|
// If this is an absolute variable reference, substitute it now to preserve
|
||||||
// semantics in the face of reassignment.
|
// semantics in the face of reassignment.
|
||||||
|
63
test/CodeGen/AArch64/callbr-asm-label.ll
Normal file
63
test/CodeGen/AArch64/callbr-asm-label.ll
Normal file
@ -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(...)
|
30
test/CodeGen/X86/callbr-asm-label-addr.ll
Normal file
30
test/CodeGen/X86/callbr-asm-label-addr.ll
Normal file
@ -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)
|
@ -12,7 +12,7 @@ define i32 @test1(i32 %a) {
|
|||||||
; CHECK-NEXT: addl $4, %eax
|
; CHECK-NEXT: addl $4, %eax
|
||||||
; CHECK-NEXT: #APP
|
; CHECK-NEXT: #APP
|
||||||
; CHECK-NEXT: xorl %eax, %eax
|
; CHECK-NEXT: xorl %eax, %eax
|
||||||
; CHECK-NEXT: jmp .Ltmp00
|
; CHECK-NEXT: jmp .Ltmp0
|
||||||
; CHECK-NEXT: #NO_APP
|
; CHECK-NEXT: #NO_APP
|
||||||
; CHECK-NEXT: .LBB0_1: # %normal
|
; CHECK-NEXT: .LBB0_1: # %normal
|
||||||
; CHECK-NEXT: xorl %eax, %eax
|
; 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: # Parent Loop BB2_3 Depth=3
|
||||||
; CHECK-NEXT: # => This Inner Loop Header: Depth=4
|
; CHECK-NEXT: # => This Inner Loop Header: Depth=4
|
||||||
; CHECK-NEXT: #APP
|
; CHECK-NEXT: #APP
|
||||||
; CHECK-NEXT: jmp .Ltmp10
|
; CHECK-NEXT: jmp .Ltmp1
|
||||||
; CHECK-NEXT: jmp .Ltmp20
|
; CHECK-NEXT: jmp .Ltmp2
|
||||||
; CHECK-NEXT: jmp .Ltmp30
|
; CHECK-NEXT: jmp .Ltmp3
|
||||||
; CHECK-NEXT: #NO_APP
|
; CHECK-NEXT: #NO_APP
|
||||||
; CHECK-NEXT: .LBB2_5: # %normal0
|
; CHECK-NEXT: .LBB2_5: # %normal0
|
||||||
; CHECK-NEXT: # in Loop: Header=BB2_4 Depth=4
|
; CHECK-NEXT: # in Loop: Header=BB2_4 Depth=4
|
||||||
; CHECK-NEXT: #APP
|
; CHECK-NEXT: #APP
|
||||||
; CHECK-NEXT: jmp .Ltmp10
|
; CHECK-NEXT: jmp .Ltmp1
|
||||||
; CHECK-NEXT: jmp .Ltmp20
|
; CHECK-NEXT: jmp .Ltmp2
|
||||||
; CHECK-NEXT: jmp .Ltmp30
|
; CHECK-NEXT: jmp .Ltmp3
|
||||||
; CHECK-NEXT: jmp .Ltmp40
|
; CHECK-NEXT: jmp .Ltmp4
|
||||||
; CHECK-NEXT: #NO_APP
|
; CHECK-NEXT: #NO_APP
|
||||||
; CHECK-NEXT: .LBB2_6: # %normal1
|
; CHECK-NEXT: .LBB2_6: # %normal1
|
||||||
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
|
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||||||
|
Loading…
Reference in New Issue
Block a user