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