LLVM 24.0.0git
WebAssemblyInstructionSelector.cpp
Go to the documentation of this file.
1//===- WebAssemblyInstructionSelector.cpp ------------------------*- 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/// \file
9/// This file implements the targeting of the InstructionSelector class for
10/// WebAssembly.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
25#include "llvm/IR/IntrinsicsWebAssembly.h"
26
27#define DEBUG_TYPE "wasm-isel"
28
29using namespace llvm;
30
31namespace {
32
33#define GET_GLOBALISEL_PREDICATE_BITSET
34#include "WebAssemblyGenGlobalISel.inc"
35#undef GET_GLOBALISEL_PREDICATE_BITSET
36
37class WebAssemblyInstructionSelector : public InstructionSelector {
38public:
39 WebAssemblyInstructionSelector(const WebAssemblyTargetMachine &TM,
40 const WebAssemblySubtarget &STI,
42
43 bool select(MachineInstr &I) override;
44
46 selectAddrOperands32(MachineOperand &Root) const;
48 selectAddrOperands64(MachineOperand &Root) const;
49
50 static const char *getName() { return DEBUG_TYPE; }
51
52private:
53 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
55
57 selectAddrOperands(LLT AddrType, unsigned int ConstOpc,
58 MachineOperand &Root) const;
59
61 const WebAssemblySubtarget &STI;
65
66#define GET_GLOBALISEL_PREDICATES_DECL
67#include "WebAssemblyGenGlobalISel.inc"
68#undef GET_GLOBALISEL_PREDICATES_DECL
69
70#define GET_GLOBALISEL_TEMPORARIES_DECL
71#include "WebAssemblyGenGlobalISel.inc"
72#undef GET_GLOBALISEL_TEMPORARIES_DECL
73};
74
75} // end anonymous namespace
76
77#define GET_GLOBALISEL_IMPL
78#include "WebAssemblyGenGlobalISel.inc"
79#undef GET_GLOBALISEL_IMPL
80
81WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
84 : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
85 RBI(RBI),
86
88#include "WebAssemblyGenGlobalISel.inc"
91#include "WebAssemblyGenGlobalISel.inc"
93{
94}
95
97WebAssemblyInstructionSelector::selectAddrOperands(LLT AddrType,
98 unsigned int ConstOpc,
99 MachineOperand &Root) const {
100 return {{
101 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
102 [=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
103 }};
104}
105
106InstructionSelector::ComplexRendererFns
107WebAssemblyInstructionSelector::selectAddrOperands32(
108 MachineOperand &Root) const {
109 return selectAddrOperands(LLT::integer(32), WebAssembly::CONST_I32, Root);
110}
111
112InstructionSelector::ComplexRendererFns
113WebAssemblyInstructionSelector::selectAddrOperands64(
114 MachineOperand &Root) const {
115 return selectAddrOperands(LLT::integer(64), WebAssembly::CONST_I64, Root);
116}
117
118bool WebAssemblyInstructionSelector::selectCopy(
119 MachineInstr &I, MachineRegisterInfo &MRI) const {
120 Register DstReg = I.getOperand(0).getReg();
121 Register SrcReg = I.getOperand(1).getReg();
122
123 const TargetRegisterClass *DstRC =
124 TRI.getConstrainedRegClassForReg(DstReg, MRI);
125 if (!DstRC)
126 return false;
127
128 const TargetRegisterClass *SrcRC =
129 TRI.getConstrainedRegClassForReg(SrcReg, MRI);
130 if (!SrcRC)
131 return false;
132
133 if (DstReg.isVirtual())
134 RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
135 if (SrcReg.isVirtual())
136 RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI);
137
138 if (DstRC != SrcRC) {
139 if (DstReg.isPhysical() || SrcReg.isPhysical())
140 llvm_unreachable("COPY to/from SP[32/64] or FP[32/64] with mismatching "
141 "classes not currently supported");
142
143 if (DstRC == &WebAssembly::I32RegClass &&
144 SrcRC == &WebAssembly::F32RegClass) {
145 I.setDesc(TII.get(WebAssembly::I32_REINTERPRET_F32));
146 return true;
147 }
148 if (DstRC == &WebAssembly::F32RegClass &&
149 SrcRC == &WebAssembly::I32RegClass) {
150 I.setDesc(TII.get(WebAssembly::F32_REINTERPRET_I32));
151 return true;
152 }
153 if (DstRC == &WebAssembly::I64RegClass &&
154 SrcRC == &WebAssembly::F64RegClass) {
155 I.setDesc(TII.get(WebAssembly::I64_REINTERPRET_F64));
156 return true;
157 }
158 if (DstRC == &WebAssembly::F64RegClass &&
159 SrcRC == &WebAssembly::I64RegClass) {
160 I.setDesc(TII.get(WebAssembly::F64_REINTERPRET_I64));
161 return true;
162 }
163
164 llvm_unreachable("COPY between unsupported reg classes.");
165 }
166
167 return true;
168}
169
170bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
171 MachineBasicBlock &MBB = *I.getParent();
173 MachineRegisterInfo &MRI = MF.getRegInfo();
174 const TargetLowering &TLI = *STI.getTargetLowering();
175
176 if (!I.isPreISelOpcode()) {
177 if (I.isCopy())
178 return selectCopy(I, MRI);
179 return true;
180 }
181
182 if (selectImpl(I, *CoverageInfo))
183 return true;
184
185 using namespace TargetOpcode;
186
187 switch (I.getOpcode()) {
188 case G_IMPLICIT_DEF: {
189 const Register DefReg = I.getOperand(0).getReg();
190
191 const TargetRegisterClass *DefRC =
192 TRI.getConstrainedRegClassForReg(DefReg, MRI);
193
194 if (!DefRC)
195 return false;
196
197 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
198 return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
199 }
200 case G_PTRTOINT: {
201 bool PtrIsI64 = MRI.getType(I.getOperand(1).getReg()).getSizeInBits() == 64;
202
203 I.setDesc(
204 TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
206 return true;
207 }
208 case G_INTTOPTR: {
209 bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
210
211 I.setDesc(
212 TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
214 return true;
215 }
216 case G_PTRMASK: {
217 bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
218
219 I.setDesc(TII.get(PtrIsI64 ? WebAssembly::AND_I64 : WebAssembly::AND_I32));
221 return true;
222 }
223 case G_GLOBAL_VALUE: {
224 assert(I.getOperand(1).getTargetFlags() == 0 &&
225 "Unexpected target flags on generic G_GLOBAL_VALUE instruction");
226
227 unsigned OperandFlags = 0;
228 const llvm::GlobalValue *GV = I.getOperand(1).getGlobal();
229 LLT PtrTy = MRI.getType(I.getOperand(0).getReg());
230 bool PtrIsI64 = PtrTy.getSizeInBits() == 64;
231
232 if (TLI.isPositionIndependent()) {
233 if (TM.shouldAssumeDSOLocal(GV)) {
234 const char *BaseName;
235 if (GV->getValueType()->isFunctionTy()) {
236 BaseName = MF.createExternalSymbolName("__table_base");
238 } else {
239 BaseName = MF.createExternalSymbolName("__memory_base");
241 }
242 MachineIRBuilder B(I);
243
245 PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
246
248 PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
249
250 B.buildInstr(PtrIsI64 ? WebAssembly::GLOBAL_GET_I64
251 : WebAssembly::GLOBAL_GET_I32)
252 .addDef(MemBase)
253 .addExternalSymbol(BaseName);
254
255 B.buildInstr(PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32)
256 .addDef(Offset)
257 .addGlobalAddress(GV, I.getOperand(1).getOffset(), OperandFlags);
258
259 auto MIB =
260 B.buildInstr(PtrIsI64 ? WebAssembly::ADD_I64 : WebAssembly::ADD_I32)
261 .addDef(I.getOperand(0).getReg())
262 .addReg(MemBase)
263 .addReg(Offset);
265
266 I.eraseFromParent();
267 return true;
268 }
270 }
271
272 unsigned NewOpc =
273 PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
274
275 if (OperandFlags & WebAssemblyII::MO_GOT) {
276 NewOpc =
277 PtrIsI64 ? WebAssembly::GLOBAL_GET_I64 : WebAssembly::GLOBAL_GET_I32;
278 }
279
280 I.setDesc(TII.get(NewOpc));
281 I.getOperand(1).setTargetFlags(OperandFlags);
283
284 return true;
285 }
286 default:
287 break;
288 }
289
290 return false;
291}
292
293namespace llvm {
294InstructionSelector *
296 const WebAssemblySubtarget &Subtarget,
297 const WebAssemblyRegisterBankInfo &RBI) {
298 return new WebAssemblyInstructionSelector(TM, Subtarget, RBI);
299}
300} // namespace llvm
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static StringRef getName(Value *V)
This file describes how to lower LLVM code to machine code.
This file provides WebAssembly-specific target descriptions.
This file declares the targeting of the RegisterBankInfo class for WebAssembly.
This file contains the WebAssembly implementation of the WebAssemblyRegisterInfo class.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
Type * getValueType() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const char * createExternalSymbolName(StringRef Name)
Allocate a string and populate it with the given external symbol name.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
bool isPositionIndependent() const
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition Type.h:273
This class provides the information for the target register banks.
const WebAssemblyTargetLowering * getTargetLowering() const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
OperandFlags
These are flags set on operands, but should be considered private, all access should go through the M...
Definition MCInstrDesc.h:51
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:159
InstructionSelector * createWebAssemblyInstructionSelector(const WebAssemblyTargetMachine &TM, const WebAssemblySubtarget &Subtarget, const WebAssemblyRegisterBankInfo &RBI)
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58