Line data Source code
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 : /// 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 "MCTargetDesc/WebAssemblyMCTargetDesc.h"
30 : #include "WebAssembly.h"
31 : #include "WebAssemblyMachineFunctionInfo.h"
32 : #include "WebAssemblySubtarget.h"
33 : #include "WebAssemblyUtilities.h"
34 : #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
35 : #include "llvm/CodeGen/MachineRegisterInfo.h"
36 : #include "llvm/CodeGen/Passes.h"
37 : #include "llvm/Support/Debug.h"
38 : #include "llvm/Support/raw_ostream.h"
39 : using namespace llvm;
40 :
41 : #define DEBUG_TYPE "wasm-argument-move"
42 :
43 : namespace {
44 : class WebAssemblyArgumentMove final : public MachineFunctionPass {
45 : public:
46 : static char ID; // Pass identification, replacement for typeid
47 305 : WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
48 :
49 0 : StringRef getPassName() const override { return "WebAssembly Argument Move"; }
50 :
51 305 : void getAnalysisUsage(AnalysisUsage &AU) const override {
52 305 : AU.setPreservesCFG();
53 : AU.addPreserved<MachineBlockFrequencyInfo>();
54 305 : AU.addPreservedID(MachineDominatorsID);
55 305 : MachineFunctionPass::getAnalysisUsage(AU);
56 305 : }
57 :
58 : bool runOnMachineFunction(MachineFunction &MF) override;
59 : };
60 : } // end anonymous namespace
61 :
62 : char WebAssemblyArgumentMove::ID = 0;
63 199030 : INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE,
64 : "Move ARGUMENT instructions for WebAssembly", false, false)
65 :
66 305 : FunctionPass *llvm::createWebAssemblyArgumentMove() {
67 305 : return new WebAssemblyArgumentMove();
68 : }
69 :
70 2983 : bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
71 : LLVM_DEBUG({
72 : dbgs() << "********** Argument Move **********\n"
73 : << "********** Function: " << MF.getName() << '\n';
74 : });
75 :
76 : bool Changed = false;
77 : MachineBasicBlock &EntryMBB = MF.front();
78 : MachineBasicBlock::iterator InsertPt = EntryMBB.end();
79 :
80 : // Look for the first NonArg instruction.
81 6942 : for (MachineInstr &MI : EntryMBB) {
82 6929 : if (!WebAssembly::isArgument(MI)) {
83 : InsertPt = MI;
84 : break;
85 : }
86 : }
87 :
88 : // Now move any argument instructions later in the block
89 : // to before our first NonArg instruction.
90 66114 : for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
91 63131 : if (WebAssembly::isArgument(MI)) {
92 3095 : EntryMBB.insert(InsertPt, MI.removeFromParent());
93 : Changed = true;
94 : }
95 : }
96 :
97 2983 : return Changed;
98 : }
|