LLVM 24.0.0git
WebAssemblyExplicitLocals.cpp
Go to the documentation of this file.
1//===-- WebAssemblyExplicitLocals.cpp - Make Locals Explicit --------------===//
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 converts any remaining registers into WebAssembly locals.
11///
12/// After register stackification and register coloring, convert non-stackified
13/// registers into locals, inserting explicit local.get and local.set
14/// instructions.
15///
16//===----------------------------------------------------------------------===//
17
19#include "WebAssembly.h"
29#include "llvm/CodeGen/Passes.h"
30#include "llvm/IR/Analysis.h"
31#include "llvm/Support/Debug.h"
33using namespace llvm;
34
35#define DEBUG_TYPE "wasm-explicit-locals"
36
37namespace {
38class WebAssemblyExplicitLocalsLegacy final : public MachineFunctionPass {
39 StringRef getPassName() const override {
40 return "WebAssembly Explicit Locals";
41 }
42
43 void getAnalysisUsage(AnalysisUsage &AU) const override {
44 AU.setPreservesCFG();
46 }
47
48 bool runOnMachineFunction(MachineFunction &MF) override;
49
50public:
51 static char ID; // Pass identification, replacement for typeid
52 WebAssemblyExplicitLocalsLegacy() : MachineFunctionPass(ID) {}
53};
54} // end anonymous namespace
55
56char WebAssemblyExplicitLocalsLegacy::ID = 0;
57INITIALIZE_PASS(WebAssemblyExplicitLocalsLegacy, DEBUG_TYPE,
58 "Convert registers to WebAssembly locals", false, false)
59
61 return new WebAssemblyExplicitLocalsLegacy();
62}
63
64static void checkFrameBase(WebAssemblyFunctionInfo &MFI, unsigned Local,
65 unsigned Reg) {
66 // Mark a local for the frame base vreg.
67 if (MFI.isFrameBaseVirtual() && Reg == MFI.getFrameBaseVreg()) {
69 dbgs() << "Allocating local " << Local << "for VReg "
70 << Register(Reg).virtRegIndex() << '\n';
71 });
73 }
74}
75
76/// Return a local id number for the given register, assigning it a new one
77/// if it doesn't yet have one.
78static unsigned getLocalId(DenseMap<unsigned, unsigned> &Reg2Local,
79 WebAssemblyFunctionInfo &MFI, unsigned &CurLocal,
80 unsigned Reg) {
81 auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal));
82 if (P.second) {
83 checkFrameBase(MFI, CurLocal, Reg);
84 ++CurLocal;
85 }
86 return P.first->second;
87}
88
89/// Get the appropriate drop opcode for the given register class.
90static unsigned getDropOpcode(const TargetRegisterClass *RC) {
91 if (RC == &WebAssembly::I32RegClass)
92 return WebAssembly::DROP_I32;
93 if (RC == &WebAssembly::I64RegClass)
94 return WebAssembly::DROP_I64;
95 if (RC == &WebAssembly::F32RegClass)
96 return WebAssembly::DROP_F32;
97 if (RC == &WebAssembly::F64RegClass)
98 return WebAssembly::DROP_F64;
99 if (RC == &WebAssembly::V128RegClass)
100 return WebAssembly::DROP_V128;
101 if (RC == &WebAssembly::FUNCREFRegClass)
102 return WebAssembly::DROP_FUNCREF;
103 if (RC == &WebAssembly::EXTERNREFRegClass)
104 return WebAssembly::DROP_EXTERNREF;
105 if (RC == &WebAssembly::EXNREFRegClass)
106 return WebAssembly::DROP_EXNREF;
107 llvm_unreachable("Unexpected register class");
108}
109
110/// Get the appropriate local.get opcode for the given register class.
111static unsigned getLocalGetOpcode(const TargetRegisterClass *RC) {
112 if (RC == &WebAssembly::I32RegClass)
113 return WebAssembly::LOCAL_GET_I32;
114 if (RC == &WebAssembly::I64RegClass)
115 return WebAssembly::LOCAL_GET_I64;
116 if (RC == &WebAssembly::F32RegClass)
117 return WebAssembly::LOCAL_GET_F32;
118 if (RC == &WebAssembly::F64RegClass)
119 return WebAssembly::LOCAL_GET_F64;
120 if (RC == &WebAssembly::V128RegClass)
121 return WebAssembly::LOCAL_GET_V128;
122 if (RC == &WebAssembly::FUNCREFRegClass)
123 return WebAssembly::LOCAL_GET_FUNCREF;
124 if (RC == &WebAssembly::EXTERNREFRegClass)
125 return WebAssembly::LOCAL_GET_EXTERNREF;
126 if (RC == &WebAssembly::EXNREFRegClass)
127 return WebAssembly::LOCAL_GET_EXNREF;
128 llvm_unreachable("Unexpected register class");
129}
130
131/// Get the appropriate local.set opcode for the given register class.
132static unsigned getLocalSetOpcode(const TargetRegisterClass *RC) {
133 if (RC == &WebAssembly::I32RegClass)
134 return WebAssembly::LOCAL_SET_I32;
135 if (RC == &WebAssembly::I64RegClass)
136 return WebAssembly::LOCAL_SET_I64;
137 if (RC == &WebAssembly::F32RegClass)
138 return WebAssembly::LOCAL_SET_F32;
139 if (RC == &WebAssembly::F64RegClass)
140 return WebAssembly::LOCAL_SET_F64;
141 if (RC == &WebAssembly::V128RegClass)
142 return WebAssembly::LOCAL_SET_V128;
143 if (RC == &WebAssembly::FUNCREFRegClass)
144 return WebAssembly::LOCAL_SET_FUNCREF;
145 if (RC == &WebAssembly::EXTERNREFRegClass)
146 return WebAssembly::LOCAL_SET_EXTERNREF;
147 if (RC == &WebAssembly::EXNREFRegClass)
148 return WebAssembly::LOCAL_SET_EXNREF;
149 llvm_unreachable("Unexpected register class");
150}
151
152/// Get the appropriate local.tee opcode for the given register class.
153static unsigned getLocalTeeOpcode(const TargetRegisterClass *RC) {
154 if (RC == &WebAssembly::I32RegClass)
155 return WebAssembly::LOCAL_TEE_I32;
156 if (RC == &WebAssembly::I64RegClass)
157 return WebAssembly::LOCAL_TEE_I64;
158 if (RC == &WebAssembly::F32RegClass)
159 return WebAssembly::LOCAL_TEE_F32;
160 if (RC == &WebAssembly::F64RegClass)
161 return WebAssembly::LOCAL_TEE_F64;
162 if (RC == &WebAssembly::V128RegClass)
163 return WebAssembly::LOCAL_TEE_V128;
164 if (RC == &WebAssembly::FUNCREFRegClass)
165 return WebAssembly::LOCAL_TEE_FUNCREF;
166 if (RC == &WebAssembly::EXTERNREFRegClass)
167 return WebAssembly::LOCAL_TEE_EXTERNREF;
168 if (RC == &WebAssembly::EXNREFRegClass)
169 return WebAssembly::LOCAL_TEE_EXNREF;
170 llvm_unreachable("Unexpected register class");
171}
172
173/// Get the type associated with the given register class.
175 if (RC == &WebAssembly::I32RegClass)
176 return MVT::i32;
177 if (RC == &WebAssembly::I64RegClass)
178 return MVT::i64;
179 if (RC == &WebAssembly::F32RegClass)
180 return MVT::f32;
181 if (RC == &WebAssembly::F64RegClass)
182 return MVT::f64;
183 if (RC == &WebAssembly::V128RegClass)
184 return MVT::v16i8;
185 if (RC == &WebAssembly::FUNCREFRegClass)
186 return MVT::funcref;
187 if (RC == &WebAssembly::EXTERNREFRegClass)
188 return MVT::externref;
189 if (RC == &WebAssembly::EXNREFRegClass)
190 return MVT::exnref;
191 llvm_unreachable("unrecognized register class");
192}
193
194/// Given a MachineOperand of a stackified vreg, return the instruction at the
195/// start of the expression tree.
198 const WebAssemblyFunctionInfo &MFI) {
199 Register Reg = MO.getReg();
201 MachineInstr *Def = MRI.getVRegDef(Reg);
202
203 // If this instruction has any non-stackified defs, it is the start
204 for (auto DefReg : Def->defs()) {
205 if (!MFI.isVRegStackified(DefReg.getReg())) {
206 return Def;
207 }
208 }
209
210 // Find the first stackified use and proceed from there.
211 for (MachineOperand &DefMO : Def->explicit_uses()) {
212 if (!DefMO.isReg())
213 continue;
214 return findStartOfTree(DefMO, MRI, MFI);
215 }
216
217 // If there were no stackified uses, we've reached the start.
218 return Def;
219}
220
221// FAKE_USEs are no-ops, so remove them here so that the values used by them
222// will be correctly dropped later.
225 for (auto &MBB : MF)
226 for (auto &MI : MBB)
227 if (MI.isFakeUse())
228 ToDelete.push_back(&MI);
229 for (auto *MI : ToDelete)
230 MI->eraseFromParent();
231}
232
234 LLVM_DEBUG(dbgs() << "********** Make Locals Explicit **********\n"
235 "********** Function: "
236 << MF.getName() << '\n');
237
238 bool Changed = false;
241 const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
242
243 removeFakeUses(MF);
244
245 // Map non-stackified virtual registers to their local ids.
247
248 // Handle ARGUMENTS first to ensure that they get the designated numbers.
249 for (MachineBasicBlock::iterator I = MF.begin()->begin(),
250 E = MF.begin()->end();
251 I != E;) {
252 MachineInstr &MI = *I++;
253 if (!WebAssembly::isArgument(MI.getOpcode()))
254 break;
255 Register Reg = MI.getOperand(0).getReg();
257 auto Local = static_cast<unsigned>(MI.getOperand(1).getImm());
258 Reg2Local[Reg] = Local;
259 checkFrameBase(MFI, Local, Reg);
260
261 // Update debug value to point to the local before removing.
263
264 MI.eraseFromParent();
265 Changed = true;
266 }
267
268 // Start assigning local numbers after the last parameter and after any
269 // already-assigned locals.
270 unsigned CurLocal = static_cast<unsigned>(MFI.getParams().size());
271 CurLocal += static_cast<unsigned>(MFI.getLocals().size());
272
273 // Precompute the set of registers that are unused, so that we can insert
274 // drops to their defs.
275 // And unstackify any stackified registers that don't have any uses, so that
276 // they can be dropped later. This can happen when transformations after
277 // RegStackify remove instructions using stackified registers.
278 BitVector UseEmpty(MRI.getNumVirtRegs());
279 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
281 if (MRI.use_empty(Reg)) {
282 UseEmpty[I] = true;
283 MFI.unstackifyVReg(Reg);
284 }
285 }
286
287 // Visit each instruction in the function.
288 for (MachineBasicBlock &MBB : MF) {
290 assert(!WebAssembly::isArgument(MI.getOpcode()));
291
292 if (MI.isDebugInstr() || MI.isLabel())
293 continue;
294
295 if (MI.getOpcode() == WebAssembly::IMPLICIT_DEF) {
296 MI.eraseFromParent();
297 Changed = true;
298 continue;
299 }
300
301 // Replace tee instructions with local.tee. The difference is that tee
302 // instructions have two defs, while local.tee instructions have one def
303 // and an index of a local to write to.
304 //
305 // - Before:
306 // TeeReg, Reg = TEE DefReg
307 // INST ..., TeeReg, ...
308 // INST ..., Reg, ...
309 // INST ..., Reg, ...
310 // * DefReg: may or may not be stackified
311 // * Reg: not stackified
312 // * TeeReg: stackified
313 //
314 // - After (when DefReg was already stackified):
315 // TeeReg = LOCAL_TEE LocalId1, DefReg
316 // INST ..., TeeReg, ...
317 // INST ..., Reg, ...
318 // INST ..., Reg, ...
319 // * Reg: mapped to LocalId1
320 // * TeeReg: stackified
321 //
322 // - After (when DefReg was not already stackified):
323 // NewReg = LOCAL_GET LocalId1
324 // TeeReg = LOCAL_TEE LocalId2, NewReg
325 // INST ..., TeeReg, ...
326 // INST ..., Reg, ...
327 // INST ..., Reg, ...
328 // * DefReg: mapped to LocalId1
329 // * Reg: mapped to LocalId2
330 // * TeeReg: stackified
331 if (WebAssembly::isTee(MI.getOpcode())) {
332 assert(MFI.isVRegStackified(MI.getOperand(0).getReg()));
333 assert(!MFI.isVRegStackified(MI.getOperand(1).getReg()));
334 Register DefReg = MI.getOperand(2).getReg();
335 const TargetRegisterClass *RC = MRI.getRegClass(DefReg);
336
337 // Stackify the input if it isn't stackified yet.
338 if (!MFI.isVRegStackified(DefReg)) {
339 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, DefReg);
340 Register NewReg = MRI.createVirtualRegister(RC);
341 unsigned Opc = getLocalGetOpcode(RC);
342 BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), NewReg)
343 .addImm(LocalId);
344 MI.getOperand(2).setReg(NewReg);
345 MFI.stackifyVReg(MRI, NewReg);
346 }
347
348 // Replace the TEE with a LOCAL_TEE.
349 unsigned LocalId =
350 getLocalId(Reg2Local, MFI, CurLocal, MI.getOperand(1).getReg());
351 unsigned Opc = getLocalTeeOpcode(RC);
352 BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc),
353 MI.getOperand(0).getReg())
354 .addImm(LocalId)
355 .addReg(MI.getOperand(2).getReg());
356
358
359 MI.eraseFromParent();
360 Changed = true;
361 continue;
362 }
363
364 // Insert local.sets for any defs that aren't stackified yet.
365 for (auto &Def : MI.defs()) {
366 Register OldReg = Def.getReg();
367 if (!MFI.isVRegStackified(OldReg)) {
368 const TargetRegisterClass *RC = MRI.getRegClass(OldReg);
369 Register NewReg = MRI.createVirtualRegister(RC);
370 auto InsertPt = std::next(MI.getIterator());
371 // When libcalls are emitted for thread context, the frame base vreg
372 // has an implicit use in the DW_AT_frame_base debug info, so we
373 // should not remove it.
374 bool NeedsRegForDebug =
375 MFI.isFrameBaseVirtual() && OldReg == MFI.getFrameBaseVreg() &&
376 MF.getFunction().getSubprogram() &&
377 MF.getSubtarget<WebAssemblySubtarget>().hasLibcallThreadContext();
378 if (UseEmpty[OldReg.virtRegIndex()] && !NeedsRegForDebug) {
379 unsigned Opc = getDropOpcode(RC);
380 MachineInstr *Drop =
381 BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
382 .addReg(NewReg);
383 // After the drop instruction, this reg operand will not be used
384 Drop->getOperand(0).setIsKill();
385 if (MFI.isFrameBaseVirtual() && OldReg == MFI.getFrameBaseVreg())
386 MFI.clearFrameBaseVreg();
387 } else {
388 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
389 unsigned Opc = getLocalSetOpcode(RC);
390
392
393 BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
394 .addImm(LocalId)
395 .addReg(NewReg);
396 }
397 // This register operand of the original instruction is now being used
398 // by the inserted drop or local.set instruction, so make it not dead
399 // yet.
400 Def.setReg(NewReg);
401 Def.setIsDead(false);
402 MFI.stackifyVReg(MRI, NewReg);
403 Changed = true;
404 }
405 }
406
407 // Insert local.gets for any uses that aren't stackified yet.
408 MachineInstr *InsertPt = &MI;
409 for (MachineOperand &MO : reverse(MI.explicit_uses())) {
410 if (!MO.isReg())
411 continue;
412
413 Register OldReg = MO.getReg();
414
415 // Inline asm may have a def in the middle of the operands. Our contract
416 // with inline asm register operands is to provide local indices as
417 // immediates.
418 if (MO.isDef()) {
419 assert(MI.isInlineAsm());
420 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
421 // If this register operand is tied to another operand, we can't
422 // change it to an immediate. Untie it first.
423 MI.untieRegOperand(MO.getOperandNo());
424 MO.ChangeToImmediate(LocalId);
425 continue;
426 }
427
428 // If we see a stackified register, prepare to insert subsequent
429 // local.gets before the start of its tree.
430 if (MFI.isVRegStackified(OldReg)) {
431 InsertPt = findStartOfTree(MO, MRI, MFI);
432 continue;
433 }
434
435 // Our contract with inline asm register operands is to provide local
436 // indices as immediates.
437 if (MI.isInlineAsm()) {
438 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
439 // Untie it first if this reg operand is tied to another operand.
440 MI.untieRegOperand(MO.getOperandNo());
441 MO.ChangeToImmediate(LocalId);
442 continue;
443 }
444
445 // Insert a local.get.
446 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
447 const TargetRegisterClass *RC = MRI.getRegClass(OldReg);
448 Register NewReg = MRI.createVirtualRegister(RC);
449 unsigned Opc = getLocalGetOpcode(RC);
450 // Use a InsertPt as our DebugLoc, since MI may be discontinuous from
451 // the where this local is being inserted, causing non-linear stepping
452 // in the debugger or function entry points where variables aren't live
453 // yet. Alternative is previous instruction, but that is strictly worse
454 // since it can point at the previous statement.
455 // See crbug.com/1251909, crbug.com/1249745
456 InsertPt = BuildMI(MBB, InsertPt, InsertPt->getDebugLoc(),
457 TII->get(Opc), NewReg).addImm(LocalId);
458 MO.setReg(NewReg);
459 MFI.stackifyVReg(MRI, NewReg);
460 Changed = true;
461 }
462
463 // Coalesce and eliminate COPY instructions.
464 if (WebAssembly::isCopy(MI.getOpcode())) {
465 MRI.replaceRegWith(MI.getOperand(1).getReg(),
466 MI.getOperand(0).getReg());
467 MI.eraseFromParent();
468 Changed = true;
469 }
470 }
471 }
472
473 // Define the locals.
474 // TODO: Sort the locals for better compression.
475 MFI.setNumLocals(CurLocal - MFI.getParams().size());
476 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
478 auto RL = Reg2Local.find(Reg);
479 if (RL == Reg2Local.end() || RL->second < MFI.getParams().size())
480 continue;
481
482 MFI.setLocal(RL->second - MFI.getParams().size(),
484 Changed = true;
485 }
486
487#ifndef NDEBUG
488 // Assert that all registers have been stackified at this point.
489 for (const MachineBasicBlock &MBB : MF) {
490 for (const MachineInstr &MI : MBB) {
491 if (MI.isDebugInstr() || MI.isLabel())
492 continue;
493 for (const MachineOperand &MO : MI.explicit_operands()) {
494 assert(
495 (!MO.isReg() || MRI.use_empty(MO.getReg()) ||
496 MFI.isVRegStackified(MO.getReg())) &&
497 "WebAssemblyExplicitLocals failed to stackify a register operand");
498 }
499 }
500 }
501#endif
502
503 return Changed;
504}
505
506bool WebAssemblyExplicitLocalsLegacy::runOnMachineFunction(
507 MachineFunction &MF) {
508 return explicitLocals(MF);
509}
510
511PreservedAnalyses
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file contains the declaration of the WebAssembly-specific manager for DebugValues associated wit...
static unsigned getLocalGetOpcode(const TargetRegisterClass *RC)
Get the appropriate local.get opcode for the given register class.
static unsigned getLocalId(DenseMap< unsigned, unsigned > &Reg2Local, WebAssemblyFunctionInfo &MFI, unsigned &CurLocal, unsigned Reg)
Return a local id number for the given register, assigning it a new one if it doesn't yet have one.
static MachineInstr * findStartOfTree(MachineOperand &MO, MachineRegisterInfo &MRI, const WebAssemblyFunctionInfo &MFI)
Given a MachineOperand of a stackified vreg, return the instruction at the start of the expression tr...
static bool explicitLocals(MachineFunction &MF)
static MVT typeForRegClass(const TargetRegisterClass *RC)
Get the type associated with the given register class.
static unsigned getLocalTeeOpcode(const TargetRegisterClass *RC)
Get the appropriate local.tee opcode for the given register class.
static void checkFrameBase(WebAssemblyFunctionInfo &MFI, unsigned Local, unsigned Reg)
static unsigned getLocalSetOpcode(const TargetRegisterClass *RC)
Get the appropriate local.set opcode for the given register class.
static unsigned getDropOpcode(const TargetRegisterClass *RC)
Get the appropriate drop opcode for the given register class.
static void removeFakeUses(MachineFunction &MF)
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition Pass.cpp:275
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
DISubprogram * getSubprogram() const
Get the attached subprogram.
Machine Value Type.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
unsigned virtRegIndex() const
Convert a virtual register number to a 0-based index.
Definition Register.h:87
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
void stackifyVReg(MachineRegisterInfo &MRI, Register VReg)
const std::vector< MVT > & getLocals() const
const std::vector< MVT > & getParams() const
Changed
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isArgument(unsigned Opc)
bool isCopy(unsigned Opc)
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createWebAssemblyExplicitLocalsLegacyPass()
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58