From 12030494fce2aefa338f5bc33c19611e015003f2 Mon Sep 17 00:00:00 2001 From: Konstantin Schwarz Date: Wed, 8 Apr 2020 14:40:43 +0200 Subject: [PATCH] [GlobalISel] Introduce InlineAsmLowering class Summary: Similar to the CallLowering class used for lowering LLVM IR calls to MIR calls, we introduce a separate class for lowering LLVM IR inline asm to MIR INLINEASM. There is no functional change yet, all existing tests should pass. Reviewers: arsenm, dsanders, aemerson, volkan, t.p.northover, paquette Reviewed By: aemerson Subscribers: gargaroff, wdng, mgorny, rovka, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78316 --- .../include/llvm/CodeGen/GlobalISel/IRTranslator.h | 2 +- .../llvm/CodeGen/GlobalISel/InlineAsmLowering.h | 46 ++++++++++++++++ llvm/include/llvm/CodeGen/TargetSubtargetInfo.h | 5 ++ llvm/lib/CodeGen/GlobalISel/CMakeLists.txt | 1 + llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 36 +++--------- llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp | 64 ++++++++++++++++++++++ llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 5 ++ llvm/lib/Target/AArch64/AArch64Subtarget.h | 3 + 8 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 llvm/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h create mode 100644 llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 4b11628..43ad83b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -235,7 +235,7 @@ private: bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder); - bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); + bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder); /// Returns true if the value should be split into multiple LLTs. /// If \p Offsets is given then the split type's offsets will be stored in it. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h new file mode 100644 index 0000000..21553df --- /dev/null +++ b/llvm/include/llvm/CodeGen/GlobalISel/InlineAsmLowering.h @@ -0,0 +1,46 @@ +//===- llvm/CodeGen/GlobalISel/InlineAsmLowering.h --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file describes how to lower LLVM inline asm to machine code INLINEASM. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H +#define LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H + +namespace llvm { +class CallBase; +class MachineIRBuilder; +class TargetLowering; + +class InlineAsmLowering { + const TargetLowering *TLI; + + virtual void anchor(); + +public: + bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB) const; + +protected: + /// Getter for generic TargetLowering class. + const TargetLowering *getTLI() const { return TLI; } + + /// Getter for target specific TargetLowering class. + template const XXXTargetLowering *getTLI() const { + return static_cast(TLI); + } + +public: + InlineAsmLowering(const TargetLowering *TLI) : TLI(TLI) {} + virtual ~InlineAsmLowering() = default; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h index 395c9e1..169652e 100644 --- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -29,6 +29,7 @@ namespace llvm { class CallLowering; +class InlineAsmLowering; class InstrItineraryData; struct InstrStage; class InstructionSelector; @@ -102,6 +103,10 @@ public: } virtual const CallLowering *getCallLowering() const { return nullptr; } + virtual const InlineAsmLowering *getInlineAsmLowering() const { + return nullptr; + } + // FIXME: This lets targets specialize the selector by subtarget (which lets // us do things like a dedicated avx512 selector). However, we might want // to also specialize selectors by MachineFunction, which would let us be diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index c04cf36..b2b0f54 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_component_library(LLVMGlobalISel CombinerHelper.cpp GISelChangeObserver.cpp IRTranslator.cpp + InlineAsmLowering.cpp InstructionSelect.cpp InstructionSelector.cpp LegalityPredicates.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 74f6a2f..72d4dbe 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -1565,37 +1566,18 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, return false; } -bool IRTranslator::translateInlineAsm(const CallInst &CI, +bool IRTranslator::translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder) { - const InlineAsm &IA = cast(*CI.getCalledValue()); - StringRef ConstraintStr = IA.getConstraintString(); - - bool HasOnlyMemoryClobber = false; - if (!ConstraintStr.empty()) { - // Until we have full inline assembly support, we just try to handle the - // very simple case of just "~{memory}" to avoid falling back so often. - if (ConstraintStr != "~{memory}") - return false; - HasOnlyMemoryClobber = true; - } - - unsigned ExtraInfo = 0; - if (IA.hasSideEffects()) - ExtraInfo |= InlineAsm::Extra_HasSideEffects; - if (IA.getDialect() == InlineAsm::AD_Intel) - ExtraInfo |= InlineAsm::Extra_AsmDialect; - // HACK: special casing for ~memory. - if (HasOnlyMemoryClobber) - ExtraInfo |= (InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore); + const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering(); - auto Inst = MIRBuilder.buildInstr(TargetOpcode::INLINEASM) - .addExternalSymbol(IA.getAsmString().c_str()) - .addImm(ExtraInfo); - if (const MDNode *SrcLoc = CI.getMetadata("srcloc")) - Inst.addMetadata(SrcLoc); + if (!ALI) { + LLVM_DEBUG( + dbgs() << "Inline asm lowering is not supported for this target yet\n"); + return false; + } - return true; + return ALI->lowerInlineAsm(MIRBuilder, CB); } bool IRTranslator::translateCallBase(const CallBase &CB, diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp new file mode 100644 index 0000000..e425910 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp @@ -0,0 +1,64 @@ +//===-- lib/CodeGen/GlobalISel/InlineAsmLowering.cpp ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements the lowering from LLVM IR inline asm to MIR INLINEASM +/// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" + +#define DEBUG_TYPE "inline-asm-lowering" + +using namespace llvm; + +void InlineAsmLowering::anchor() {} + +bool InlineAsmLowering::lowerInlineAsm(MachineIRBuilder &MIRBuilder, + const CallBase &Call) const { + + const InlineAsm *IA = cast(Call.getCalledValue()); + StringRef ConstraintStr = IA->getConstraintString(); + + bool HasOnlyMemoryClobber = false; + if (!ConstraintStr.empty()) { + // Until we have full inline assembly support, we just try to handle the + // very simple case of just "~{memory}" to avoid falling back so often. + if (ConstraintStr != "~{memory}") + return false; + HasOnlyMemoryClobber = true; + } + + unsigned ExtraInfo = 0; + if (IA->hasSideEffects()) + ExtraInfo |= InlineAsm::Extra_HasSideEffects; + if (IA->getDialect() == InlineAsm::AD_Intel) + ExtraInfo |= InlineAsm::Extra_AsmDialect; + + // HACK: special casing for ~memory. + if (HasOnlyMemoryClobber) + ExtraInfo |= (InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore); + + auto Inst = MIRBuilder.buildInstr(TargetOpcode::INLINEASM) + .addExternalSymbol(IA->getAsmString().c_str()) + .addImm(ExtraInfo); + if (const MDNode *SrcLoc = Call.getMetadata("srcloc")) + Inst.addMetadata(SrcLoc); + + return true; +} diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index dc744f5..2353229 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -182,6 +182,7 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU, ReserveXRegister.set(18); CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering())); + InlineAsmLoweringInfo.reset(new InlineAsmLowering(getTargetLowering())); Legalizer.reset(new AArch64LegalizerInfo(*this)); auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo()); @@ -199,6 +200,10 @@ const CallLowering *AArch64Subtarget::getCallLowering() const { return CallLoweringInfo.get(); } +const InlineAsmLowering *AArch64Subtarget::getInlineAsmLowering() const { + return InlineAsmLoweringInfo.get(); +} + InstructionSelector *AArch64Subtarget::getInstructionSelector() const { return InstSelector.get(); } diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index 3b19907..c18afcc 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -19,6 +19,7 @@ #include "AArch64RegisterInfo.h" #include "AArch64SelectionDAGInfo.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" @@ -233,6 +234,7 @@ protected: /// GlobalISel related APIs. std::unique_ptr CallLoweringInfo; + std::unique_ptr InlineAsmLoweringInfo; std::unique_ptr InstSelector; std::unique_ptr Legalizer; std::unique_ptr RegBankInfo; @@ -268,6 +270,7 @@ public: return &getInstrInfo()->getRegisterInfo(); } const CallLowering *getCallLowering() const override; + const InlineAsmLowering *getInlineAsmLowering() const override; InstructionSelector *getInstructionSelector() const override; const LegalizerInfo *getLegalizerInfo() const override; const RegisterBankInfo *getRegBankInfo() const override; -- 2.7.4