[WebAssembly] Use TSFlags instead of keeping a list of special-case opcodes.
[oota-llvm.git] / lib / Target / WebAssembly / WebAssemblyArgumentMove.cpp
1 //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file moves ARGUMENT instructions after ScheduleDAG scheduling.
12 ///
13 /// Arguments are really live-in registers, however, since we use virtual
14 /// registers and LLVM doesn't support live-in virtual registers, we're
15 /// currently making do with ARGUMENT instructions which are placed at the top
16 /// of the entry block. The trick is to get them to *stay* at the top of the
17 /// entry block.
18 ///
19 /// The ARGUMENTS physical register keeps these instructions pinned in place
20 /// during liveness-aware CodeGen passes, however one thing which does not
21 /// respect this is the ScheduleDAG scheduler. This pass is therefore run
22 /// immediately after that.
23 ///
24 /// This is all hopefully a temporary solution until we find a better solution
25 /// for describing the live-in nature of arguments.
26 ///
27 //===----------------------------------------------------------------------===//
28
29 #include "WebAssembly.h"
30 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
31 #include "WebAssemblyMachineFunctionInfo.h"
32 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
33 #include "llvm/CodeGen/MachineRegisterInfo.h"
34 #include "llvm/CodeGen/Passes.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/raw_ostream.h"
37 using namespace llvm;
38
39 #define DEBUG_TYPE "wasm-argument-move"
40
41 namespace {
42 class WebAssemblyArgumentMove final : public MachineFunctionPass {
43 public:
44   static char ID; // Pass identification, replacement for typeid
45   WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
46
47   const char *getPassName() const override {
48     return "WebAssembly Argument Move";
49   }
50
51   void getAnalysisUsage(AnalysisUsage &AU) const override {
52     AU.setPreservesCFG();
53     AU.addPreserved<MachineBlockFrequencyInfo>();
54     AU.addPreservedID(MachineDominatorsID);
55     MachineFunctionPass::getAnalysisUsage(AU);
56   }
57
58   bool runOnMachineFunction(MachineFunction &MF) override;
59 };
60 } // end anonymous namespace
61
62 char WebAssemblyArgumentMove::ID = 0;
63 FunctionPass *llvm::createWebAssemblyArgumentMove() {
64   return new WebAssemblyArgumentMove();
65 }
66
67 /// Test whether the given instruction is an ARGUMENT.
68 static bool IsArgument(const MachineInstr *MI) {
69   switch (MI->getOpcode()) {
70   case WebAssembly::ARGUMENT_I32:
71   case WebAssembly::ARGUMENT_I64:
72   case WebAssembly::ARGUMENT_F32:
73   case WebAssembly::ARGUMENT_F64:
74     return true;
75   default:
76     return false;
77   }
78 }
79
80 bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
81   DEBUG({
82     dbgs() << "********** Argument Move **********\n"
83            << "********** Function: " << MF.getName() << '\n';
84   });
85
86   bool Changed = false;
87   MachineBasicBlock &EntryMBB = MF.front();
88   MachineBasicBlock::iterator InsertPt = EntryMBB.end();
89
90   // Look for the first NonArg instruction.
91   for (auto MII = EntryMBB.begin(), MIE = EntryMBB.end(); MII != MIE; ++MII) {
92     MachineInstr *MI = MII;
93     if (!IsArgument(MI)) {
94       InsertPt = MII;
95       break;
96     }
97   }
98
99   // Now move any argument instructions later in the block
100   // to before our first NonArg instruction.
101   for (auto I = InsertPt, E = EntryMBB.end(); I != E; ++I) {
102     MachineInstr *MI = I;
103     if (IsArgument(MI)) {
104       EntryMBB.insert(InsertPt, MI->removeFromParent());
105       Changed = true;
106     }
107   }
108
109   return Changed;
110 }