WebAssemblyArgumentMove.cpp revision 309124
1185029Spjd//===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
2185029Spjd//
3185029Spjd//                     The LLVM Compiler Infrastructure
4185029Spjd//
5185029Spjd// This file is distributed under the University of Illinois Open Source
6185029Spjd// License. See LICENSE.TXT for details.
7185029Spjd//
8185029Spjd//===----------------------------------------------------------------------===//
9185029Spjd///
10185029Spjd/// \file
11185029Spjd/// \brief This file moves ARGUMENT instructions after ScheduleDAG scheduling.
12185029Spjd///
13185029Spjd/// Arguments are really live-in registers, however, since we use virtual
14185029Spjd/// registers and LLVM doesn't support live-in virtual registers, we're
15185029Spjd/// currently making do with ARGUMENT instructions which are placed at the top
16185029Spjd/// of the entry block. The trick is to get them to *stay* at the top of the
17185029Spjd/// entry block.
18185029Spjd///
19185029Spjd/// The ARGUMENTS physical register keeps these instructions pinned in place
20185029Spjd/// during liveness-aware CodeGen passes, however one thing which does not
21331396Smav/// respect this is the ScheduleDAG scheduler. This pass is therefore run
22185029Spjd/// immediately after that.
23219089Spjd///
24331396Smav/// This is all hopefully a temporary solution until we find a better solution
25331397Smav/// for describing the live-in nature of arguments.
26185029Spjd///
27185029Spjd//===----------------------------------------------------------------------===//
28185029Spjd
29185029Spjd#include "WebAssembly.h"
30185029Spjd#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
31185029Spjd#include "WebAssemblyMachineFunctionInfo.h"
32185029Spjd#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
33185029Spjd#include "llvm/CodeGen/MachineRegisterInfo.h"
34185029Spjd#include "llvm/CodeGen/Passes.h"
35185029Spjd#include "llvm/Support/Debug.h"
36185029Spjd#include "llvm/Support/raw_ostream.h"
37185029Spjdusing namespace llvm;
38185029Spjd
39185029Spjd#define DEBUG_TYPE "wasm-argument-move"
40185029Spjd
41185029Spjdnamespace {
42185029Spjdclass WebAssemblyArgumentMove final : public MachineFunctionPass {
43185029Spjdpublic:
44185029Spjd  static char ID; // Pass identification, replacement for typeid
45185029Spjd  WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
46185029Spjd
47185029Spjd  const char *getPassName() const override {
48185029Spjd    return "WebAssembly Argument Move";
49185029Spjd  }
50185029Spjd
51185029Spjd  void getAnalysisUsage(AnalysisUsage &AU) const override {
52185029Spjd    AU.setPreservesCFG();
53185029Spjd    AU.addPreserved<MachineBlockFrequencyInfo>();
54185029Spjd    AU.addPreservedID(MachineDominatorsID);
55185029Spjd    MachineFunctionPass::getAnalysisUsage(AU);
56185029Spjd  }
57219089Spjd
58185029Spjd  bool runOnMachineFunction(MachineFunction &MF) override;
59185029Spjd};
60185029Spjd} // end anonymous namespace
61185029Spjd
62185029Spjdchar WebAssemblyArgumentMove::ID = 0;
63185029SpjdFunctionPass *llvm::createWebAssemblyArgumentMove() {
64185029Spjd  return new WebAssemblyArgumentMove();
65185029Spjd}
66185029Spjd
67185029Spjd/// Test whether the given instruction is an ARGUMENT.
68185029Spjdstatic bool IsArgument(const MachineInstr &MI) {
69185029Spjd  switch (MI.getOpcode()) {
70185029Spjd  case WebAssembly::ARGUMENT_I32:
71185029Spjd  case WebAssembly::ARGUMENT_I64:
72185029Spjd  case WebAssembly::ARGUMENT_F32:
73185029Spjd  case WebAssembly::ARGUMENT_F64:
74185029Spjd    return true;
75185029Spjd  default:
76185029Spjd    return false;
77185029Spjd  }
78185029Spjd}
79185029Spjd
80185029Spjdbool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
81185029Spjd  DEBUG({
82185029Spjd    dbgs() << "********** Argument Move **********\n"
83185029Spjd           << "********** Function: " << MF.getName() << '\n';
84185029Spjd  });
85185029Spjd
86185029Spjd  bool Changed = false;
87185029Spjd  MachineBasicBlock &EntryMBB = MF.front();
88185029Spjd  MachineBasicBlock::iterator InsertPt = EntryMBB.end();
89185029Spjd
90185029Spjd  // Look for the first NonArg instruction.
91185029Spjd  for (MachineInstr &MI : EntryMBB) {
92185029Spjd    if (!IsArgument(MI)) {
93185029Spjd      InsertPt = MI;
94185029Spjd      break;
95185029Spjd    }
96185029Spjd  }
97185029Spjd
98185029Spjd  // Now move any argument instructions later in the block
99185029Spjd  // to before our first NonArg instruction.
100185029Spjd  for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
101185029Spjd    if (IsArgument(MI)) {
102185029Spjd      EntryMBB.insert(InsertPt, MI.removeFromParent());
103185029Spjd      Changed = true;
104185029Spjd    }
105185029Spjd  }
106185029Spjd
107185029Spjd  return Changed;
108185029Spjd}
109185029Spjd