[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
This commit is contained in:
Konstantin Schwarz 2020-04-08 14:40:43 +02:00
parent 61bccda9d9
commit 12030494fc
8 changed files with 134 additions and 28 deletions

View File

@ -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.

View File

@ -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 <class XXXTargetLowering> const XXXTargetLowering *getTLI() const {
return static_cast<const XXXTargetLowering *>(TLI);
}
public:
InlineAsmLowering(const TargetLowering *TLI) : TLI(TLI) {}
virtual ~InlineAsmLowering() = default;
};
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H

View File

@ -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

View File

@ -8,6 +8,7 @@ add_llvm_component_library(LLVMGlobalISel
CombinerHelper.cpp
GISelChangeObserver.cpp
IRTranslator.cpp
InlineAsmLowering.cpp
InstructionSelect.cpp
InstructionSelector.cpp
LegalityPredicates.cpp

View File

@ -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<InlineAsm>(*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;
const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering();
if (!ALI) {
LLVM_DEBUG(
dbgs() << "Inline asm lowering is not supported for this target yet\n");
return false;
}
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 = CI.getMetadata("srcloc"))
Inst.addMetadata(SrcLoc);
return true;
return ALI->lowerInlineAsm(MIRBuilder, CB);
}
bool IRTranslator::translateCallBase(const CallBase &CB,

View File

@ -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<InlineAsm>(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;
}

View File

@ -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();
}

View File

@ -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<CallLowering> CallLoweringInfo;
std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo;
std::unique_ptr<InstructionSelector> InstSelector;
std::unique_ptr<LegalizerInfo> Legalizer;
std::unique_ptr<RegisterBankInfo> 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;