| //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file moves ARGUMENT instructions after ScheduleDAG scheduling. |
| /// |
| /// Arguments are really live-in registers, however, since we use virtual |
| /// registers and LLVM doesn't support live-in virtual registers, we're |
| /// currently making do with ARGUMENT instructions which are placed at the top |
| /// of the entry block. The trick is to get them to *stay* at the top of the |
| /// entry block. |
| /// |
| /// The ARGUMENTS physical register keeps these instructions pinned in place |
| /// during liveness-aware CodeGen passes, however one thing which does not |
| /// respect this is the ScheduleDAG scheduler. This pass is therefore run |
| /// immediately after that. |
| /// |
| /// This is all hopefully a temporary solution until we find a better solution |
| /// for describing the live-in nature of arguments. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" |
| #include "Utils/WebAssemblyUtilities.h" |
| #include "WebAssembly.h" |
| #include "WebAssemblyMachineFunctionInfo.h" |
| #include "WebAssemblySubtarget.h" |
| #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/Passes.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/raw_ostream.h" |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "wasm-argument-move" |
| |
| namespace { |
| class WebAssemblyArgumentMove final : public MachineFunctionPass { |
| public: |
| static char ID; // Pass identification, replacement for typeid |
| WebAssemblyArgumentMove() : MachineFunctionPass(ID) {} |
| |
| StringRef getPassName() const override { return "WebAssembly Argument Move"; } |
| |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| AU.setPreservesCFG(); |
| AU.addPreserved<MachineBlockFrequencyInfo>(); |
| AU.addPreservedID(MachineDominatorsID); |
| MachineFunctionPass::getAnalysisUsage(AU); |
| } |
| |
| bool runOnMachineFunction(MachineFunction &MF) override; |
| }; |
| } // end anonymous namespace |
| |
| char WebAssemblyArgumentMove::ID = 0; |
| INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE, |
| "Move ARGUMENT instructions for WebAssembly", false, false) |
| |
| FunctionPass *llvm::createWebAssemblyArgumentMove() { |
| return new WebAssemblyArgumentMove(); |
| } |
| |
| bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) { |
| LLVM_DEBUG({ |
| dbgs() << "********** Argument Move **********\n" |
| << "********** Function: " << MF.getName() << '\n'; |
| }); |
| |
| bool Changed = false; |
| MachineBasicBlock &EntryMBB = MF.front(); |
| MachineBasicBlock::iterator InsertPt = EntryMBB.end(); |
| |
| // Look for the first NonArg instruction. |
| for (MachineInstr &MI : EntryMBB) { |
| if (!WebAssembly::isArgument(MI.getOpcode())) { |
| InsertPt = MI; |
| break; |
| } |
| } |
| |
| // Now move any argument instructions later in the block |
| // to before our first NonArg instruction. |
| for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) { |
| if (WebAssembly::isArgument(MI.getOpcode())) { |
| EntryMBB.insert(InsertPt, MI.removeFromParent()); |
| Changed = true; |
| } |
| } |
| |
| return Changed; |
| } |