• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
WebAssemblyArgumentMove()45   WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
46 
getPassName() const47   const char *getPassName() const override {
48     return "WebAssembly Argument Move";
49   }
50 
getAnalysisUsage(AnalysisUsage & AU) const51   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;
createWebAssemblyArgumentMove()63 FunctionPass *llvm::createWebAssemblyArgumentMove() {
64   return new WebAssemblyArgumentMove();
65 }
66 
67 /// Test whether the given instruction is an ARGUMENT.
IsArgument(const MachineInstr & MI)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 
runOnMachineFunction(MachineFunction & MF)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 (MachineInstr &MI : EntryMBB) {
92     if (!IsArgument(MI)) {
93       InsertPt = MI;
94       break;
95     }
96   }
97 
98   // Now move any argument instructions later in the block
99   // to before our first NonArg instruction.
100   for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
101     if (IsArgument(MI)) {
102       EntryMBB.insert(InsertPt, MI.removeFromParent());
103       Changed = true;
104     }
105   }
106 
107   return Changed;
108 }
109