WebAssemblyArgumentMove.cpp revision 314564
1292915Sdim//===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
2292915Sdim//
3292915Sdim//                     The LLVM Compiler Infrastructure
4292915Sdim//
5292915Sdim// This file is distributed under the University of Illinois Open Source
6292915Sdim// License. See LICENSE.TXT for details.
7292915Sdim//
8292915Sdim//===----------------------------------------------------------------------===//
9292915Sdim///
10292915Sdim/// \file
11292915Sdim/// \brief This file moves ARGUMENT instructions after ScheduleDAG scheduling.
12292915Sdim///
13292915Sdim/// Arguments are really live-in registers, however, since we use virtual
14292915Sdim/// registers and LLVM doesn't support live-in virtual registers, we're
15292915Sdim/// currently making do with ARGUMENT instructions which are placed at the top
16292915Sdim/// of the entry block. The trick is to get them to *stay* at the top of the
17292915Sdim/// entry block.
18292915Sdim///
19292915Sdim/// The ARGUMENTS physical register keeps these instructions pinned in place
20292915Sdim/// during liveness-aware CodeGen passes, however one thing which does not
21292915Sdim/// respect this is the ScheduleDAG scheduler. This pass is therefore run
22292915Sdim/// immediately after that.
23292915Sdim///
24292915Sdim/// This is all hopefully a temporary solution until we find a better solution
25292915Sdim/// for describing the live-in nature of arguments.
26292915Sdim///
27292915Sdim//===----------------------------------------------------------------------===//
28292915Sdim
29314564Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
30292915Sdim#include "WebAssembly.h"
31292915Sdim#include "WebAssemblyMachineFunctionInfo.h"
32314564Sdim#include "WebAssemblySubtarget.h"
33314564Sdim#include "WebAssemblyUtilities.h"
34292915Sdim#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
35292915Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
36292915Sdim#include "llvm/CodeGen/Passes.h"
37292915Sdim#include "llvm/Support/Debug.h"
38292915Sdim#include "llvm/Support/raw_ostream.h"
39292915Sdimusing namespace llvm;
40292915Sdim
41292915Sdim#define DEBUG_TYPE "wasm-argument-move"
42292915Sdim
43292915Sdimnamespace {
44292915Sdimclass WebAssemblyArgumentMove final : public MachineFunctionPass {
45292915Sdimpublic:
46292915Sdim  static char ID; // Pass identification, replacement for typeid
47292915Sdim  WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
48292915Sdim
49314564Sdim  StringRef getPassName() const override { return "WebAssembly Argument Move"; }
50292915Sdim
51292915Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
52292915Sdim    AU.setPreservesCFG();
53292915Sdim    AU.addPreserved<MachineBlockFrequencyInfo>();
54292915Sdim    AU.addPreservedID(MachineDominatorsID);
55292915Sdim    MachineFunctionPass::getAnalysisUsage(AU);
56292915Sdim  }
57292915Sdim
58292915Sdim  bool runOnMachineFunction(MachineFunction &MF) override;
59292915Sdim};
60292915Sdim} // end anonymous namespace
61292915Sdim
62292915Sdimchar WebAssemblyArgumentMove::ID = 0;
63292915SdimFunctionPass *llvm::createWebAssemblyArgumentMove() {
64292915Sdim  return new WebAssemblyArgumentMove();
65292915Sdim}
66292915Sdim
67292915Sdimbool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
68292915Sdim  DEBUG({
69292915Sdim    dbgs() << "********** Argument Move **********\n"
70292915Sdim           << "********** Function: " << MF.getName() << '\n';
71292915Sdim  });
72292915Sdim
73292915Sdim  bool Changed = false;
74292915Sdim  MachineBasicBlock &EntryMBB = MF.front();
75292915Sdim  MachineBasicBlock::iterator InsertPt = EntryMBB.end();
76292915Sdim
77292915Sdim  // Look for the first NonArg instruction.
78309124Sdim  for (MachineInstr &MI : EntryMBB) {
79314564Sdim    if (!WebAssembly::isArgument(MI)) {
80309124Sdim      InsertPt = MI;
81292915Sdim      break;
82292915Sdim    }
83292915Sdim  }
84292915Sdim
85292915Sdim  // Now move any argument instructions later in the block
86292915Sdim  // to before our first NonArg instruction.
87309124Sdim  for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
88314564Sdim    if (WebAssembly::isArgument(MI)) {
89309124Sdim      EntryMBB.insert(InsertPt, MI.removeFromParent());
90292915Sdim      Changed = true;
91292915Sdim    }
92292915Sdim  }
93292915Sdim
94292915Sdim  return Changed;
95292915Sdim}
96