Skip to content

Commit 1203049

Browse files
[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
1 parent 61bccda commit 1203049

File tree

8 files changed

+134
-28
lines changed

8 files changed

+134
-28
lines changed

llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ class IRTranslator : public MachineFunctionPass {
235235
bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
236236
MachineIRBuilder &MIRBuilder);
237237

238-
bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder);
238+
bool translateInlineAsm(const CallBase &CB, MachineIRBuilder &MIRBuilder);
239239

240240
/// Returns true if the value should be split into multiple LLTs.
241241
/// If \p Offsets is given then the split type's offsets will be stored in it.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===- llvm/CodeGen/GlobalISel/InlineAsmLowering.h --------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file describes how to lower LLVM inline asm to machine code INLINEASM.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H
15+
#define LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H
16+
17+
namespace llvm {
18+
class CallBase;
19+
class MachineIRBuilder;
20+
class TargetLowering;
21+
22+
class InlineAsmLowering {
23+
const TargetLowering *TLI;
24+
25+
virtual void anchor();
26+
27+
public:
28+
bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB) const;
29+
30+
protected:
31+
/// Getter for generic TargetLowering class.
32+
const TargetLowering *getTLI() const { return TLI; }
33+
34+
/// Getter for target specific TargetLowering class.
35+
template <class XXXTargetLowering> const XXXTargetLowering *getTLI() const {
36+
return static_cast<const XXXTargetLowering *>(TLI);
37+
}
38+
39+
public:
40+
InlineAsmLowering(const TargetLowering *TLI) : TLI(TLI) {}
41+
virtual ~InlineAsmLowering() = default;
42+
};
43+
44+
} // end namespace llvm
45+
46+
#endif // LLVM_CODEGEN_GLOBALISEL_INLINEASMLOWERING_H

llvm/include/llvm/CodeGen/TargetSubtargetInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
namespace llvm {
3030

3131
class CallLowering;
32+
class InlineAsmLowering;
3233
class InstrItineraryData;
3334
struct InstrStage;
3435
class InstructionSelector;
@@ -102,6 +103,10 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
102103
}
103104
virtual const CallLowering *getCallLowering() const { return nullptr; }
104105

106+
virtual const InlineAsmLowering *getInlineAsmLowering() const {
107+
return nullptr;
108+
}
109+
105110
// FIXME: This lets targets specialize the selector by subtarget (which lets
106111
// us do things like a dedicated avx512 selector). However, we might want
107112
// to also specialize selectors by MachineFunction, which would let us be

llvm/lib/CodeGen/GlobalISel/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_llvm_component_library(LLVMGlobalISel
88
CombinerHelper.cpp
99
GISelChangeObserver.cpp
1010
IRTranslator.cpp
11+
InlineAsmLowering.cpp
1112
InstructionSelect.cpp
1213
InstructionSelector.cpp
1314
LegalityPredicates.cpp

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/CodeGen/FunctionLoweringInfo.h"
2424
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
2525
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
26+
#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
2627
#include "llvm/CodeGen/LowLevelType.h"
2728
#include "llvm/CodeGen/MachineBasicBlock.h"
2829
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -1565,37 +1566,18 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
15651566
return false;
15661567
}
15671568

1568-
bool IRTranslator::translateInlineAsm(const CallInst &CI,
1569+
bool IRTranslator::translateInlineAsm(const CallBase &CB,
15691570
MachineIRBuilder &MIRBuilder) {
1570-
const InlineAsm &IA = cast<InlineAsm>(*CI.getCalledValue());
1571-
StringRef ConstraintStr = IA.getConstraintString();
1572-
1573-
bool HasOnlyMemoryClobber = false;
1574-
if (!ConstraintStr.empty()) {
1575-
// Until we have full inline assembly support, we just try to handle the
1576-
// very simple case of just "~{memory}" to avoid falling back so often.
1577-
if (ConstraintStr != "~{memory}")
1578-
return false;
1579-
HasOnlyMemoryClobber = true;
1580-
}
1581-
1582-
unsigned ExtraInfo = 0;
1583-
if (IA.hasSideEffects())
1584-
ExtraInfo |= InlineAsm::Extra_HasSideEffects;
1585-
if (IA.getDialect() == InlineAsm::AD_Intel)
1586-
ExtraInfo |= InlineAsm::Extra_AsmDialect;
15871571

1588-
// HACK: special casing for ~memory.
1589-
if (HasOnlyMemoryClobber)
1590-
ExtraInfo |= (InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore);
1572+
const InlineAsmLowering *ALI = MF->getSubtarget().getInlineAsmLowering();
15911573

1592-
auto Inst = MIRBuilder.buildInstr(TargetOpcode::INLINEASM)
1593-
.addExternalSymbol(IA.getAsmString().c_str())
1594-
.addImm(ExtraInfo);
1595-
if (const MDNode *SrcLoc = CI.getMetadata("srcloc"))
1596-
Inst.addMetadata(SrcLoc);
1574+
if (!ALI) {
1575+
LLVM_DEBUG(
1576+
dbgs() << "Inline asm lowering is not supported for this target yet\n");
1577+
return false;
1578+
}
15971579

1598-
return true;
1580+
return ALI->lowerInlineAsm(MIRBuilder, CB);
15991581
}
16001582

16011583
bool IRTranslator::translateCallBase(const CallBase &CB,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===-- lib/CodeGen/GlobalISel/InlineAsmLowering.cpp ----------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file implements the lowering from LLVM IR inline asm to MIR INLINEASM
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
15+
#include "llvm/CodeGen/Analysis.h"
16+
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17+
#include "llvm/CodeGen/GlobalISel/Utils.h"
18+
#include "llvm/CodeGen/MachineOperand.h"
19+
#include "llvm/CodeGen/MachineRegisterInfo.h"
20+
#include "llvm/CodeGen/TargetLowering.h"
21+
#include "llvm/IR/DataLayout.h"
22+
#include "llvm/IR/Instructions.h"
23+
#include "llvm/IR/LLVMContext.h"
24+
#include "llvm/IR/Module.h"
25+
26+
#define DEBUG_TYPE "inline-asm-lowering"
27+
28+
using namespace llvm;
29+
30+
void InlineAsmLowering::anchor() {}
31+
32+
bool InlineAsmLowering::lowerInlineAsm(MachineIRBuilder &MIRBuilder,
33+
const CallBase &Call) const {
34+
35+
const InlineAsm *IA = cast<InlineAsm>(Call.getCalledValue());
36+
StringRef ConstraintStr = IA->getConstraintString();
37+
38+
bool HasOnlyMemoryClobber = false;
39+
if (!ConstraintStr.empty()) {
40+
// Until we have full inline assembly support, we just try to handle the
41+
// very simple case of just "~{memory}" to avoid falling back so often.
42+
if (ConstraintStr != "~{memory}")
43+
return false;
44+
HasOnlyMemoryClobber = true;
45+
}
46+
47+
unsigned ExtraInfo = 0;
48+
if (IA->hasSideEffects())
49+
ExtraInfo |= InlineAsm::Extra_HasSideEffects;
50+
if (IA->getDialect() == InlineAsm::AD_Intel)
51+
ExtraInfo |= InlineAsm::Extra_AsmDialect;
52+
53+
// HACK: special casing for ~memory.
54+
if (HasOnlyMemoryClobber)
55+
ExtraInfo |= (InlineAsm::Extra_MayLoad | InlineAsm::Extra_MayStore);
56+
57+
auto Inst = MIRBuilder.buildInstr(TargetOpcode::INLINEASM)
58+
.addExternalSymbol(IA->getAsmString().c_str())
59+
.addImm(ExtraInfo);
60+
if (const MDNode *SrcLoc = Call.getMetadata("srcloc"))
61+
Inst.addMetadata(SrcLoc);
62+
63+
return true;
64+
}

llvm/lib/Target/AArch64/AArch64Subtarget.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
182182
ReserveXRegister.set(18);
183183

184184
CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
185+
InlineAsmLoweringInfo.reset(new InlineAsmLowering(getTargetLowering()));
185186
Legalizer.reset(new AArch64LegalizerInfo(*this));
186187

187188
auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo());
@@ -199,6 +200,10 @@ const CallLowering *AArch64Subtarget::getCallLowering() const {
199200
return CallLoweringInfo.get();
200201
}
201202

203+
const InlineAsmLowering *AArch64Subtarget::getInlineAsmLowering() const {
204+
return InlineAsmLoweringInfo.get();
205+
}
206+
202207
InstructionSelector *AArch64Subtarget::getInstructionSelector() const {
203208
return InstSelector.get();
204209
}

llvm/lib/Target/AArch64/AArch64Subtarget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "AArch64RegisterInfo.h"
2020
#include "AArch64SelectionDAGInfo.h"
2121
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
22+
#include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
2223
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
2324
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
2425
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
@@ -233,6 +234,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
233234

234235
/// GlobalISel related APIs.
235236
std::unique_ptr<CallLowering> CallLoweringInfo;
237+
std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo;
236238
std::unique_ptr<InstructionSelector> InstSelector;
237239
std::unique_ptr<LegalizerInfo> Legalizer;
238240
std::unique_ptr<RegisterBankInfo> RegBankInfo;
@@ -268,6 +270,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
268270
return &getInstrInfo()->getRegisterInfo();
269271
}
270272
const CallLowering *getCallLowering() const override;
273+
const InlineAsmLowering *getInlineAsmLowering() const override;
271274
InstructionSelector *getInstructionSelector() const override;
272275
const LegalizerInfo *getLegalizerInfo() const override;
273276
const RegisterBankInfo *getRegBankInfo() const override;

0 commit comments

Comments
 (0)