11cf96c0cSDan Gohman //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
21cf96c0cSDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf96c0cSDan Gohman //
71cf96c0cSDan Gohman //===----------------------------------------------------------------------===//
81cf96c0cSDan Gohman ///
91cf96c0cSDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file moves ARGUMENT instructions after ScheduleDAG scheduling.
111cf96c0cSDan Gohman ///
121cf96c0cSDan Gohman /// Arguments are really live-in registers, however, since we use virtual
131cf96c0cSDan Gohman /// registers and LLVM doesn't support live-in virtual registers, we're
141cf96c0cSDan Gohman /// currently making do with ARGUMENT instructions which are placed at the top
151cf96c0cSDan Gohman /// of the entry block. The trick is to get them to *stay* at the top of the
161cf96c0cSDan Gohman /// entry block.
171cf96c0cSDan Gohman ///
181cf96c0cSDan Gohman /// The ARGUMENTS physical register keeps these instructions pinned in place
191cf96c0cSDan Gohman /// during liveness-aware CodeGen passes, however one thing which does not
201cf96c0cSDan Gohman /// respect this is the ScheduleDAG scheduler. This pass is therefore run
211cf96c0cSDan Gohman /// immediately after that.
221cf96c0cSDan Gohman ///
231cf96c0cSDan Gohman /// This is all hopefully a temporary solution until we find a better solution
241cf96c0cSDan Gohman /// for describing the live-in nature of arguments.
251cf96c0cSDan Gohman ///
261cf96c0cSDan Gohman //===----------------------------------------------------------------------===//
271cf96c0cSDan Gohman
281cf96c0cSDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
29*0b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h"
3039bf39f3SDerek Schuff #include "WebAssembly.h"
311cf96c0cSDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
3239bf39f3SDerek Schuff #include "WebAssemblySubtarget.h"
331cf96c0cSDan Gohman #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
341cf96c0cSDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
351cf96c0cSDan Gohman #include "llvm/CodeGen/Passes.h"
361cf96c0cSDan Gohman #include "llvm/Support/Debug.h"
371cf96c0cSDan Gohman #include "llvm/Support/raw_ostream.h"
381cf96c0cSDan Gohman using namespace llvm;
391cf96c0cSDan Gohman
401cf96c0cSDan Gohman #define DEBUG_TYPE "wasm-argument-move"
411cf96c0cSDan Gohman
421cf96c0cSDan Gohman namespace {
431cf96c0cSDan Gohman class WebAssemblyArgumentMove final : public MachineFunctionPass {
441cf96c0cSDan Gohman public:
451cf96c0cSDan Gohman static char ID; // Pass identification, replacement for typeid
WebAssemblyArgumentMove()461cf96c0cSDan Gohman WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
471cf96c0cSDan Gohman
getPassName() const48117296c0SMehdi Amini StringRef getPassName() const override { return "WebAssembly Argument Move"; }
491cf96c0cSDan Gohman
getAnalysisUsage(AnalysisUsage & AU) const501cf96c0cSDan Gohman void getAnalysisUsage(AnalysisUsage &AU) const override {
511cf96c0cSDan Gohman AU.setPreservesCFG();
521cf96c0cSDan Gohman AU.addPreserved<MachineBlockFrequencyInfo>();
531cf96c0cSDan Gohman AU.addPreservedID(MachineDominatorsID);
541cf96c0cSDan Gohman MachineFunctionPass::getAnalysisUsage(AU);
551cf96c0cSDan Gohman }
561cf96c0cSDan Gohman
571cf96c0cSDan Gohman bool runOnMachineFunction(MachineFunction &MF) override;
581cf96c0cSDan Gohman };
591cf96c0cSDan Gohman } // end anonymous namespace
601cf96c0cSDan Gohman
611cf96c0cSDan Gohman char WebAssemblyArgumentMove::ID = 0;
6240926451SJacob Gravelle INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE,
6340926451SJacob Gravelle "Move ARGUMENT instructions for WebAssembly", false, false)
6440926451SJacob Gravelle
createWebAssemblyArgumentMove()651cf96c0cSDan Gohman FunctionPass *llvm::createWebAssemblyArgumentMove() {
661cf96c0cSDan Gohman return new WebAssemblyArgumentMove();
671cf96c0cSDan Gohman }
681cf96c0cSDan Gohman
runOnMachineFunction(MachineFunction & MF)691cf96c0cSDan Gohman bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
70d34e60caSNicola Zaghen LLVM_DEBUG({
711cf96c0cSDan Gohman dbgs() << "********** Argument Move **********\n"
721cf96c0cSDan Gohman << "********** Function: " << MF.getName() << '\n';
731cf96c0cSDan Gohman });
741cf96c0cSDan Gohman
751cf96c0cSDan Gohman bool Changed = false;
761cf96c0cSDan Gohman MachineBasicBlock &EntryMBB = MF.front();
771cf96c0cSDan Gohman MachineBasicBlock::iterator InsertPt = EntryMBB.end();
781cf96c0cSDan Gohman
791cf96c0cSDan Gohman // Look for the first NonArg instruction.
80500d0469SDuncan P. N. Exon Smith for (MachineInstr &MI : EntryMBB) {
81d8ddf839SWouter van Oortmerssen if (!WebAssembly::isArgument(MI.getOpcode())) {
82500d0469SDuncan P. N. Exon Smith InsertPt = MI;
831cf96c0cSDan Gohman break;
841cf96c0cSDan Gohman }
851cf96c0cSDan Gohman }
861cf96c0cSDan Gohman
871cf96c0cSDan Gohman // Now move any argument instructions later in the block
881cf96c0cSDan Gohman // to before our first NonArg instruction.
89500d0469SDuncan P. N. Exon Smith for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
90d8ddf839SWouter van Oortmerssen if (WebAssembly::isArgument(MI.getOpcode())) {
91500d0469SDuncan P. N. Exon Smith EntryMBB.insert(InsertPt, MI.removeFromParent());
921cf96c0cSDan Gohman Changed = true;
931cf96c0cSDan Gohman }
941cf96c0cSDan Gohman }
951cf96c0cSDan Gohman
961cf96c0cSDan Gohman return Changed;
971cf96c0cSDan Gohman }
98