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
27#include "llvm/IR/IntrinsicsWebAssembly.h"
28
29#define DEBUG_TYPE "wasm-isel"
30
31using namespace llvm;
32
33namespace {
34
35#define GET_GLOBALISEL_PREDICATE_BITSET
36#include "WebAssemblyGenGlobalISel.inc"
37#undef GET_GLOBALISEL_PREDICATE_BITSET
38
39class WebAssemblyInstructionSelector : public InstructionSelector {
40public:
41 WebAssemblyInstructionSelector(const WebAssemblyTargetMachine &TM,
42 const WebAssemblySubtarget &STI,
44
45 bool select(MachineInstr &I) override;
46
48 selectAddrOperands32(MachineOperand &Root) const;
50 selectAddrOperands64(MachineOperand &Root) const;
51
52 static const char *getName() { return DEBUG_TYPE; }
53
54private:
55 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
57
59 selectAddrOperands(LLT AddrType, unsigned int ConstOpc,
60 MachineOperand &Root) const;
61
63 const WebAssemblySubtarget &STI;
67
68#define GET_GLOBALISEL_PREDICATES_DECL
69#include "WebAssemblyGenGlobalISel.inc"
70#undef GET_GLOBALISEL_PREDICATES_DECL
71
72#define GET_GLOBALISEL_TEMPORARIES_DECL
73#include "WebAssemblyGenGlobalISel.inc"
74#undef GET_GLOBALISEL_TEMPORARIES_DECL
75};
76
77} // end anonymous namespace
78
79#define GET_GLOBALISEL_IMPL
80#include "WebAssemblyGenGlobalISel.inc"
81#undef GET_GLOBALISEL_IMPL
82
83WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
86 : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
87 RBI(RBI),
88
90#include "WebAssemblyGenGlobalISel.inc"
93#include "WebAssemblyGenGlobalISel.inc"
95{
96}
97
99WebAssemblyInstructionSelector::selectAddrOperands(LLT AddrType,
100 unsigned int ConstOpc,
101 MachineOperand &Root) const {
102 return {{
103 [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
104 [=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
105 }};
106}
107
108InstructionSelector::ComplexRendererFns
109WebAssemblyInstructionSelector::selectAddrOperands32(
110 MachineOperand &Root) const {
111 return selectAddrOperands(LLT::integer(32), WebAssembly::CONST_I32, Root);
112}
113
114InstructionSelector::ComplexRendererFns
115WebAssemblyInstructionSelector::selectAddrOperands64(
116 MachineOperand &Root) const {
117 return selectAddrOperands(LLT::integer(64), WebAssembly::CONST_I64, Root);
118}
119
120bool WebAssemblyInstructionSelector::selectCopy(
121 MachineInstr &I, MachineRegisterInfo &MRI) const {
122 Register DstReg = I.getOperand(0).getReg();
123 Register SrcReg = I.getOperand(1).getReg();
124
125 const TargetRegisterClass *DstRC =
126 TRI.getConstrainedRegClassForReg(DstReg, MRI);
127 if (!DstRC)
128 return false;
129
130 const TargetRegisterClass *SrcRC =
131 TRI.getConstrainedRegClassForReg(SrcReg, MRI);
132 if (!SrcRC)
133 return false;
134
135 if (DstReg.isVirtual())
136 RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
137 if (SrcReg.isVirtual())
138 RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI);
139
140 if (DstRC != SrcRC) {
141 if (DstReg.isPhysical() || SrcReg.isPhysical())
142 llvm_unreachable("COPY to/from SP[32/64] or FP[32/64] with mismatching "
143 "classes not currently supported");
144
145 if (DstRC == &WebAssembly::I32RegClass &&
146 SrcRC == &WebAssembly::F32RegClass) {
147 I.setDesc(TII.get(WebAssembly::I32_REINTERPRET_F32));
148 return true;
149 }
150 if (DstRC == &WebAssembly::F32RegClass &&
151 SrcRC == &WebAssembly::I32RegClass) {
152 I.setDesc(TII.get(WebAssembly::F32_REINTERPRET_I32));
153 return true;
154 }
155 if (DstRC == &WebAssembly::I64RegClass &&
156 SrcRC == &WebAssembly::F64RegClass) {
157 I.setDesc(TII.get(WebAssembly::I64_REINTERPRET_F64));
158 return true;
159 }
160 if (DstRC == &WebAssembly::F64RegClass &&
161 SrcRC == &WebAssembly::I64RegClass) {
162 I.setDesc(TII.get(WebAssembly::F64_REINTERPRET_I64));
163 return true;
164 }
165
166 llvm_unreachable("COPY between unsupported reg classes.");
167 }
168
169 return true;
170}
171
172bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
173 MachineBasicBlock &MBB = *I.getParent();
175 MachineRegisterInfo &MRI = MF.getRegInfo();
176 const TargetLowering &TLI = *STI.getTargetLowering();
177
178 if (!I.isPreISelOpcode()) {
179 if (I.isCopy())
180 return selectCopy(I, MRI);
181 return true;
182 }
183
184 if (selectImpl(I, *CoverageInfo))
185 return true;
186
187 using namespace TargetOpcode;
188
189 switch (I.getOpcode()) {
190 case G_IMPLICIT_DEF: {
191 const Register DefReg = I.getOperand(0).getReg();
192
193 const TargetRegisterClass *DefRC =
194 TRI.getConstrainedRegClassForReg(DefReg, MRI);
195
196 if (!DefRC)
197 return false;
198
199 I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
200 return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
201 }
202 case G_PTRTOINT: {
203 bool PtrIsI64 = MRI.getType(I.getOperand(1).getReg()).getSizeInBits() == 64;
204
205 I.setDesc(
206 TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
208 return true;
209 }
210 case G_INTTOPTR: {
211 bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
212
213 I.setDesc(
214 TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
216 return true;
217 }
218 case G_PTRMASK: {
219 bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
220
221 I.setDesc(TII.get(PtrIsI64 ? WebAssembly::AND_I64 : WebAssembly::AND_I32));
223 return true;
224 }
225 case G_GLOBAL_VALUE: {
226 assert(I.getOperand(1).getTargetFlags() == 0 &&
227 "Unexpected target flags on generic G_GLOBAL_VALUE instruction");
228
229 unsigned OperandFlags = 0;
230 const llvm::GlobalValue *GV = I.getOperand(1).getGlobal();
231 LLT PtrTy = MRI.getType(I.getOperand(0).getReg());
232 bool PtrIsI64 = PtrTy.getSizeInBits() == 64;
233
234 if (TLI.isPositionIndependent()) {
235 if (TM.shouldAssumeDSOLocal(GV)) {
236 const char *BaseName;
237 if (GV->getValueType()->isFunctionTy()) {
238 BaseName = MF.createExternalSymbolName("__table_base");
240 } else {
241 BaseName = MF.createExternalSymbolName("__memory_base");
243 }
244 MachineIRBuilder B(I);
245
247 PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
248
250 PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
251
252 B.buildInstr(PtrIsI64 ? WebAssembly::GLOBAL_GET_I64
253 : WebAssembly::GLOBAL_GET_I32)
254 .addDef(MemBase)
255 .addExternalSymbol(BaseName);
256
257 B.buildInstr(PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32)
258 .addDef(Offset)
259 .addGlobalAddress(GV, I.getOperand(1).getOffset(), OperandFlags);
260
261 auto MIB =
262 B.buildInstr(PtrIsI64 ? WebAssembly::ADD_I64 : WebAssembly::ADD_I32)
263 .addDef(I.getOperand(0).getReg())
264 .addReg(MemBase)
265 .addReg(Offset);
267
268 I.eraseFromParent();
269 return true;
270 }
272 }
273
274 unsigned NewOpc =
275 PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
276
277 if (OperandFlags & WebAssemblyII::MO_GOT) {
278 NewOpc =
279 PtrIsI64 ? WebAssembly::GLOBAL_GET_I64 : WebAssembly::GLOBAL_GET_I32;
280 }
281
282 I.setDesc(TII.get(NewOpc));
283 I.getOperand(1).setTargetFlags(OperandFlags);
285
286 return true;
287 }
288 default:
289 break;
290 }
291
292 return false;
293}
294
295namespace llvm {
296InstructionSelector *
298 const WebAssemblySubtarget &Subtarget,
299 const WebAssemblyRegisterBankInfo &RBI) {
300 return new WebAssemblyInstructionSelector(TM, Subtarget, RBI);
301}
302} // 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.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
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:578
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