LLVM: lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

30using namespace llvm;

31

32#define DEBUG_TYPE "wasm-explicit-locals"

33

34namespace {

36 StringRef getPassName() const override {

37 return "WebAssembly Explicit Locals";

38 }

39

40 void getAnalysisUsage(AnalysisUsage &AU) const override {

44 }

45

47

48public:

49 static char ID;

51};

52}

53

54char WebAssemblyExplicitLocals::ID = 0;

56 "Convert registers to WebAssembly locals", false, false)

57

59 return new WebAssemblyExplicitLocals();

60}

61

63 unsigned Reg) {

64

67 dbgs() << "Allocating local " << Local << "for VReg "

69 });

71 }

72}

73

74

75

78 unsigned Reg) {

79 auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal));

80 if (P.second) {

82 ++CurLocal;

83 }

84 return P.first->second;

85}

86

87

89 if (RC == &WebAssembly::I32RegClass)

90 return WebAssembly::DROP_I32;

91 if (RC == &WebAssembly::I64RegClass)

92 return WebAssembly::DROP_I64;

93 if (RC == &WebAssembly::F32RegClass)

94 return WebAssembly::DROP_F32;

95 if (RC == &WebAssembly::F64RegClass)

96 return WebAssembly::DROP_F64;

97 if (RC == &WebAssembly::V128RegClass)

98 return WebAssembly::DROP_V128;

99 if (RC == &WebAssembly::FUNCREFRegClass)

100 return WebAssembly::DROP_FUNCREF;

101 if (RC == &WebAssembly::EXTERNREFRegClass)

102 return WebAssembly::DROP_EXTERNREF;

103 if (RC == &WebAssembly::EXNREFRegClass)

104 return WebAssembly::DROP_EXNREF;

106}

107

108

110 if (RC == &WebAssembly::I32RegClass)

111 return WebAssembly::LOCAL_GET_I32;

112 if (RC == &WebAssembly::I64RegClass)

113 return WebAssembly::LOCAL_GET_I64;

114 if (RC == &WebAssembly::F32RegClass)

115 return WebAssembly::LOCAL_GET_F32;

116 if (RC == &WebAssembly::F64RegClass)

117 return WebAssembly::LOCAL_GET_F64;

118 if (RC == &WebAssembly::V128RegClass)

119 return WebAssembly::LOCAL_GET_V128;

120 if (RC == &WebAssembly::FUNCREFRegClass)

121 return WebAssembly::LOCAL_GET_FUNCREF;

122 if (RC == &WebAssembly::EXTERNREFRegClass)

123 return WebAssembly::LOCAL_GET_EXTERNREF;

124 if (RC == &WebAssembly::EXNREFRegClass)

125 return WebAssembly::LOCAL_GET_EXNREF;

127}

128

129

131 if (RC == &WebAssembly::I32RegClass)

132 return WebAssembly::LOCAL_SET_I32;

133 if (RC == &WebAssembly::I64RegClass)

134 return WebAssembly::LOCAL_SET_I64;

135 if (RC == &WebAssembly::F32RegClass)

136 return WebAssembly::LOCAL_SET_F32;

137 if (RC == &WebAssembly::F64RegClass)

138 return WebAssembly::LOCAL_SET_F64;

139 if (RC == &WebAssembly::V128RegClass)

140 return WebAssembly::LOCAL_SET_V128;

141 if (RC == &WebAssembly::FUNCREFRegClass)

142 return WebAssembly::LOCAL_SET_FUNCREF;

143 if (RC == &WebAssembly::EXTERNREFRegClass)

144 return WebAssembly::LOCAL_SET_EXTERNREF;

145 if (RC == &WebAssembly::EXNREFRegClass)

146 return WebAssembly::LOCAL_SET_EXNREF;

148}

149

150

152 if (RC == &WebAssembly::I32RegClass)

153 return WebAssembly::LOCAL_TEE_I32;

154 if (RC == &WebAssembly::I64RegClass)

155 return WebAssembly::LOCAL_TEE_I64;

156 if (RC == &WebAssembly::F32RegClass)

157 return WebAssembly::LOCAL_TEE_F32;

158 if (RC == &WebAssembly::F64RegClass)

159 return WebAssembly::LOCAL_TEE_F64;

160 if (RC == &WebAssembly::V128RegClass)

161 return WebAssembly::LOCAL_TEE_V128;

162 if (RC == &WebAssembly::FUNCREFRegClass)

163 return WebAssembly::LOCAL_TEE_FUNCREF;

164 if (RC == &WebAssembly::EXTERNREFRegClass)

165 return WebAssembly::LOCAL_TEE_EXTERNREF;

166 if (RC == &WebAssembly::EXNREFRegClass)

167 return WebAssembly::LOCAL_TEE_EXNREF;

169}

170

171

173 if (RC == &WebAssembly::I32RegClass)

174 return MVT::i32;

175 if (RC == &WebAssembly::I64RegClass)

176 return MVT::i64;

177 if (RC == &WebAssembly::F32RegClass)

178 return MVT::f32;

179 if (RC == &WebAssembly::F64RegClass)

180 return MVT::f64;

181 if (RC == &WebAssembly::V128RegClass)

182 return MVT::v16i8;

183 if (RC == &WebAssembly::FUNCREFRegClass)

184 return MVT::funcref;

185 if (RC == &WebAssembly::EXTERNREFRegClass)

186 return MVT::externref;

187 if (RC == &WebAssembly::EXNREFRegClass)

188 return MVT::exnref;

190}

191

192

193

200

201

202 for (auto DefReg : Def->defs()) {

204 return Def;

205 }

206 }

207

208

210 if (!DefMO.isReg())

211 continue;

213 }

214

215

216 return Def;

217}

218

219

220

223 for (auto &MBB : MF)

224 for (auto &MI : MBB)

225 if (MI.isFakeUse())

227 for (auto *MI : ToDelete)

228 MI->eraseFromParent();

229}

230

231bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {

232 LLVM_DEBUG(dbgs() << "********** Make Locals Explicit **********\n"

233 "********** Function: "

234 << MF.getName() << '\n');

235

238 WebAssemblyFunctionInfo &MFI = *MF.getInfo();

239 const auto *TII = MF.getSubtarget().getInstrInfo();

240

242

243

244 DenseMap<unsigned, unsigned> Reg2Local;

245

246

248 E = MF.begin()->end();

249 I != E;) {

250 MachineInstr &MI = *I++;

252 break;

255 auto Local = static_cast<unsigned>(MI.getOperand(1).getImm());

258

259

260 WebAssemblyDebugValueManager(&MI).replaceWithLocal(Local);

261

262 MI.eraseFromParent();

264 }

265

266

267

268 unsigned CurLocal = static_cast<unsigned>(MFI.getParams().size());

269 CurLocal += static_cast<unsigned>(MFI.getLocals().size());

270

271

272

273

274

275

276 BitVector UseEmpty(MRI.getNumVirtRegs());

277 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {

279 if (MRI.use_empty(Reg)) {

280 UseEmpty[I] = true;

282 }

283 }

284

285

286 for (MachineBasicBlock &MBB : MF) {

289

290 if (MI.isDebugInstr() || MI.isLabel())

291 continue;

292

293 if (MI.getOpcode() == WebAssembly::IMPLICIT_DEF) {

294 MI.eraseFromParent();

296 continue;

297 }

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

332 Register DefReg = MI.getOperand(2).getReg();

333 const TargetRegisterClass *RC = MRI.getRegClass(DefReg);

334

335

337 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, DefReg);

338 Register NewReg = MRI.createVirtualRegister(RC);

342 MI.getOperand(2).setReg(NewReg);

344 }

345

346

347 unsigned LocalId =

348 getLocalId(Reg2Local, MFI, CurLocal, MI.getOperand(1).getReg());

351 MI.getOperand(0).getReg())

353 .addReg(MI.getOperand(2).getReg());

354

355 WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);

356

357 MI.eraseFromParent();

359 continue;

360 }

361

362

363 for (auto &Def : MI.defs()) {

366 const TargetRegisterClass *RC = MRI.getRegClass(OldReg);

367 Register NewReg = MRI.createVirtualRegister(RC);

368 auto InsertPt = std::next(MI.getIterator());

371 MachineInstr *Drop =

374

375 Drop->getOperand(0).setIsKill();

378 } else {

379 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);

381

382 WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);

383

387 }

388

389

390

391 Def.setReg(NewReg);

392 Def.setIsDead(false);

395 }

396 }

397

398

399 MachineInstr *InsertPt = &MI;

400 for (MachineOperand &MO : reverse(MI.explicit_uses())) {

401 if (!MO.isReg())

402 continue;

403

404 Register OldReg = MO.getReg();

405

406

407

408

409 if (MO.isDef()) {

411 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);

412

413

414 MI.untieRegOperand(MO.getOperandNo());

415 MO.ChangeToImmediate(LocalId);

416 continue;

417 }

418

419

420

423 continue;

424 }

425

426

427

428 if (MI.isInlineAsm()) {

429 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);

430

431 MI.untieRegOperand(MO.getOperandNo());

432 MO.ChangeToImmediate(LocalId);

433 continue;

434 }

435

436

437 unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);

438 const TargetRegisterClass *RC = MRI.getRegClass(OldReg);

439 Register NewReg = MRI.createVirtualRegister(RC);

441

442

443

444

445

446

449 MO.setReg(NewReg);

452 }

453

454

456 MRI.replaceRegWith(MI.getOperand(1).getReg(),

457 MI.getOperand(0).getReg());

458 MI.eraseFromParent();

460 }

461 }

462 }

463

464

465

467 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {

469 auto RL = Reg2Local.find(Reg);

470 if (RL == Reg2Local.end() || RL->second < MFI.getParams().size())

471 continue;

472

476 }

477

478#ifndef NDEBUG

479

480 for (const MachineBasicBlock &MBB : MF) {

481 for (const MachineInstr &MI : MBB) {

482 if (MI.isDebugInstr() || MI.isLabel())

483 continue;

484 for (const MachineOperand &MO : MI.explicit_operands()) {

486 (!MO.isReg() || MRI.use_empty(MO.getReg()) ||

488 "WebAssemblyExplicitLocals failed to stackify a register operand");

489 }

490 }

491 }

492#endif

493

495}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

Promote Memory to Register

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

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.

Definition WebAssemblyExplicitLocals.cpp:109

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.

Definition WebAssemblyExplicitLocals.cpp:76

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

Definition WebAssemblyExplicitLocals.cpp:194

static MVT typeForRegClass(const TargetRegisterClass *RC)

Get the type associated with the given register class.

Definition WebAssemblyExplicitLocals.cpp:172

static unsigned getLocalTeeOpcode(const TargetRegisterClass *RC)

Get the appropriate local.tee opcode for the given register class.

Definition WebAssemblyExplicitLocals.cpp:151

static void checkFrameBase(WebAssemblyFunctionInfo &MFI, unsigned Local, unsigned Reg)

Definition WebAssemblyExplicitLocals.cpp:62

static unsigned getLocalSetOpcode(const TargetRegisterClass *RC)

Get the appropriate local.set opcode for the given register class.

Definition WebAssemblyExplicitLocals.cpp:130

static unsigned getDropOpcode(const TargetRegisterClass *RC)

Get the appropriate drop opcode for the given register class.

Definition WebAssemblyExplicitLocals.cpp:88

static void removeFakeUses(MachineFunction &MF)

Definition WebAssemblyExplicitLocals.cpp:221

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.

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

iterator find(const_arg_type_t< KeyT > Val)

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

FunctionPass class - This class is used to implement most global optimizations.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

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.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register 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,...

Wrapper class representing virtual and physical registers.

unsigned virtRegIndex() const

Convert a virtual register number to a 0-based index.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...

void stackifyVReg(MachineRegisterInfo &MRI, Register VReg)

void setLocal(size_t i, MVT VT)

void setNumLocals(size_t NumLocals)

unsigned getFrameBaseVreg() const

void setFrameBaseLocal(unsigned Local)

bool isVRegStackified(Register VReg) const

const std::vector< MVT > & getLocals() const

void clearFrameBaseVreg()

bool isFrameBaseVirtual() const

void unstackifyVReg(Register VReg)

const std::vector< MVT > & getParams() const

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

bool isArgument(unsigned Opc)

bool isCopy(unsigned Opc)

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

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.

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

auto reverse(ContainerTy &&C)

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.

FunctionPass * createWebAssemblyExplicitLocals()