diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -327,6 +327,9 @@ /// True if the function includes any inline assembly. bool HasInlineAsm = false; + /// True if the function includes any inline assembly br. + bool HasInlineAsmBr = false; + /// True if any WinCFI instruction have been emitted in this function. bool HasWinCFI = false; @@ -730,11 +733,17 @@ return HasInlineAsm; } + /// Returns true if the function contains any inline assembly br. + bool hasInlineAsmBr() const { return HasInlineAsmBr; } + /// Set a flag that indicates that the function contains inline assembly. void setHasInlineAsm(bool B) { HasInlineAsm = B; } + /// Set a flag that indicates that the function contains inline assembly br. + void setHasInlineAsmBr(bool B) { HasInlineAsmBr = B; } + bool hasWinCFI() const { return HasWinCFI; } diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -1264,6 +1264,10 @@ getOpcode() == TargetOpcode::INLINEASM_BR; } + bool isInlineAsmBr() const { + return getOpcode() == TargetOpcode::INLINEASM_BR; + } + /// FIXME: Seems like a layering violation that the AsmDialect, which is X86 /// specific, be attached to a generic MachineInstr. bool isMSInlineAsm() const { diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -290,7 +290,7 @@ // SelectionDAG. MachineFrameInfo &MFI = MF.getFrameInfo(); for (const auto &MBB : MF) { - if (MFI.hasCalls() && MF.hasInlineAsm()) + if (MFI.hasCalls() && MF.hasInlineAsm() && MF.hasInlineAsmBr()) break; for (const auto &MI : MBB) { @@ -298,6 +298,8 @@ MFI.setHasCalls(true); if (MI.isInlineAsm()) MF.setHasInlineAsm(true); + if (MI.isInlineAsmBr()) + MF.setHasInlineAsmBr(true); } } diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -348,6 +348,7 @@ bool HasPHI = false; bool HasInlineAsm = false; + bool HasInlineAsmBr = false; bool AllTiedOpsRewritten = true, HasTiedOps = false; for (const MachineBasicBlock &MBB : MF) { for (const MachineInstr &MI : MBB) { @@ -355,6 +356,8 @@ HasPHI = true; if (MI.isInlineAsm()) HasInlineAsm = true; + if (MI.isInlineAsmBr()) + HasInlineAsmBr = true; for (unsigned I = 0; I < MI.getNumOperands(); ++I) { const MachineOperand &MO = MI.getOperand(I); if (!MO.isReg() || !MO.getReg()) @@ -371,6 +374,7 @@ if (!HasPHI) Properties.set(MachineFunctionProperties::Property::NoPHIs); MF.setHasInlineAsm(HasInlineAsm); + MF.setHasInlineAsmBr(HasInlineAsmBr); if (HasTiedOps && AllTiedOpsRewritten) Properties.set(MachineFunctionProperties::Property::TiedOpsRewritten); diff --git a/llvm/lib/CodeGen/MachineFunctionSplitter.cpp b/llvm/lib/CodeGen/MachineFunctionSplitter.cpp --- a/llvm/lib/CodeGen/MachineFunctionSplitter.cpp +++ b/llvm/lib/CodeGen/MachineFunctionSplitter.cpp @@ -95,6 +95,10 @@ if (!MF.getFunction().hasProfileData()) return false; + // The terminator in the inline assembly may not be able to be rewritten. + if (MF.hasInlineAsmBr()) + return false; + // TODO: We don't split functions where a section attribute has been set // since the split part may not be placed in a contiguous region. It may also // be more beneficial to augment the linker to ensure contiguous layout of diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -433,6 +433,7 @@ SDB->init(GFI, AA, LibInfo); MF->setHasInlineAsm(false); + MF->setHasInlineAsmBr(false); FuncInfo->SplitCSR = false; @@ -614,7 +615,7 @@ // Determine if there are any calls in this machine function. MachineFrameInfo &MFI = MF->getFrameInfo(); for (const auto &MBB : *MF) { - if (MFI.hasCalls() && MF->hasInlineAsm()) + if (MFI.hasCalls() && MF->hasInlineAsm() && MF->hasInlineAsmBr()) break; for (const auto &MI : MBB) { @@ -626,6 +627,9 @@ if (MI.isInlineAsm()) { MF->setHasInlineAsm(true); } + if (MI.isInlineAsmBr()) { + MF->setHasInlineAsmBr(true); + } } } diff --git a/llvm/test/CodeGen/X86/machine-function-splitter.ll b/llvm/test/CodeGen/X86/machine-function-splitter.ll --- a/llvm/test/CodeGen/X86/machine-function-splitter.ll +++ b/llvm/test/CodeGen/X86/machine-function-splitter.ll @@ -243,6 +243,29 @@ } +; InlineAsmBr prevents machine function splitting on the function. +define void @inlineasmbr(i1 zeroext %0) nounwind !prof !14 !section_prefix !15 { +;; Check that no text.split is generated for this function. +; MFS-DEFAULTS-LABEL: inlineasmbr +; MFS-DEFAULTS-NOT: .section .text.split.inlineasmbr + callbr void asm sideeffect "# jump to $0", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@inlineasmbr, %5)) + to label %7 [label %5] + br i1 %0, label %3, label %5, !prof !17 + +3: ; preds = %1 + %4= call i32 @bar() + br label %7 + +5: ; preds = %1 + %6 = call i32 @baz() + br label %7 + +7: ; preds = %5, %3 + %8 = tail call i32 @qux() + ret void +} + + declare i32 @bar() declare i32 @baz() declare i32 @bam()