11cf96c0cSDan Gohman //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
21cf96c0cSDan Gohman //
31cf96c0cSDan Gohman //                     The LLVM Compiler Infrastructure
41cf96c0cSDan Gohman //
51cf96c0cSDan Gohman // This file is distributed under the University of Illinois Open Source
61cf96c0cSDan Gohman // License. See LICENSE.TXT for details.
71cf96c0cSDan Gohman //
81cf96c0cSDan Gohman //===----------------------------------------------------------------------===//
91cf96c0cSDan Gohman ///
101cf96c0cSDan Gohman /// \file
115f8f34e4SAdrian Prantl /// This file moves ARGUMENT instructions after ScheduleDAG scheduling.
121cf96c0cSDan Gohman ///
131cf96c0cSDan Gohman /// Arguments are really live-in registers, however, since we use virtual
141cf96c0cSDan Gohman /// registers and LLVM doesn't support live-in virtual registers, we're
151cf96c0cSDan Gohman /// currently making do with ARGUMENT instructions which are placed at the top
161cf96c0cSDan Gohman /// of the entry block. The trick is to get them to *stay* at the top of the
171cf96c0cSDan Gohman /// entry block.
181cf96c0cSDan Gohman ///
191cf96c0cSDan Gohman /// The ARGUMENTS physical register keeps these instructions pinned in place
201cf96c0cSDan Gohman /// during liveness-aware CodeGen passes, however one thing which does not
211cf96c0cSDan Gohman /// respect this is the ScheduleDAG scheduler. This pass is therefore run
221cf96c0cSDan Gohman /// immediately after that.
231cf96c0cSDan Gohman ///
241cf96c0cSDan Gohman /// This is all hopefully a temporary solution until we find a better solution
251cf96c0cSDan Gohman /// for describing the live-in nature of arguments.
261cf96c0cSDan Gohman ///
271cf96c0cSDan Gohman //===----------------------------------------------------------------------===//
281cf96c0cSDan Gohman 
291cf96c0cSDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
3039bf39f3SDerek Schuff #include "WebAssembly.h"
311cf96c0cSDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
3239bf39f3SDerek Schuff #include "WebAssemblySubtarget.h"
334fc4e42dSDan Gohman #include "WebAssemblyUtilities.h"
341cf96c0cSDan Gohman #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
351cf96c0cSDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
361cf96c0cSDan Gohman #include "llvm/CodeGen/Passes.h"
371cf96c0cSDan Gohman #include "llvm/Support/Debug.h"
381cf96c0cSDan Gohman #include "llvm/Support/raw_ostream.h"
391cf96c0cSDan Gohman using namespace llvm;
401cf96c0cSDan Gohman 
411cf96c0cSDan Gohman #define DEBUG_TYPE "wasm-argument-move"
421cf96c0cSDan Gohman 
431cf96c0cSDan Gohman namespace {
441cf96c0cSDan Gohman class WebAssemblyArgumentMove final : public MachineFunctionPass {
451cf96c0cSDan Gohman public:
461cf96c0cSDan Gohman   static char ID; // Pass identification, replacement for typeid
471cf96c0cSDan Gohman   WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
481cf96c0cSDan Gohman 
49117296c0SMehdi Amini   StringRef getPassName() const override { return "WebAssembly Argument Move"; }
501cf96c0cSDan Gohman 
511cf96c0cSDan Gohman   void getAnalysisUsage(AnalysisUsage &AU) const override {
521cf96c0cSDan Gohman     AU.setPreservesCFG();
531cf96c0cSDan Gohman     AU.addPreserved<MachineBlockFrequencyInfo>();
541cf96c0cSDan Gohman     AU.addPreservedID(MachineDominatorsID);
551cf96c0cSDan Gohman     MachineFunctionPass::getAnalysisUsage(AU);
561cf96c0cSDan Gohman   }
571cf96c0cSDan Gohman 
581cf96c0cSDan Gohman   bool runOnMachineFunction(MachineFunction &MF) override;
591cf96c0cSDan Gohman };
601cf96c0cSDan Gohman } // end anonymous namespace
611cf96c0cSDan Gohman 
621cf96c0cSDan Gohman char WebAssemblyArgumentMove::ID = 0;
6340926451SJacob Gravelle INITIALIZE_PASS(WebAssemblyArgumentMove, DEBUG_TYPE,
6440926451SJacob Gravelle                 "Move ARGUMENT instructions for WebAssembly", false, false)
6540926451SJacob Gravelle 
661cf96c0cSDan Gohman FunctionPass *llvm::createWebAssemblyArgumentMove() {
671cf96c0cSDan Gohman   return new WebAssemblyArgumentMove();
681cf96c0cSDan Gohman }
691cf96c0cSDan Gohman 
701cf96c0cSDan Gohman bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
71*d34e60caSNicola Zaghen   LLVM_DEBUG({
721cf96c0cSDan Gohman     dbgs() << "********** Argument Move **********\n"
731cf96c0cSDan Gohman            << "********** Function: " << MF.getName() << '\n';
741cf96c0cSDan Gohman   });
751cf96c0cSDan Gohman 
761cf96c0cSDan Gohman   bool Changed = false;
771cf96c0cSDan Gohman   MachineBasicBlock &EntryMBB = MF.front();
781cf96c0cSDan Gohman   MachineBasicBlock::iterator InsertPt = EntryMBB.end();
791cf96c0cSDan Gohman 
801cf96c0cSDan Gohman   // Look for the first NonArg instruction.
81500d0469SDuncan P. N. Exon Smith   for (MachineInstr &MI : EntryMBB) {
824fc4e42dSDan Gohman     if (!WebAssembly::isArgument(MI)) {
83500d0469SDuncan P. N. Exon Smith       InsertPt = MI;
841cf96c0cSDan Gohman       break;
851cf96c0cSDan Gohman     }
861cf96c0cSDan Gohman   }
871cf96c0cSDan Gohman 
881cf96c0cSDan Gohman   // Now move any argument instructions later in the block
891cf96c0cSDan Gohman   // to before our first NonArg instruction.
90500d0469SDuncan P. N. Exon Smith   for (MachineInstr &MI : llvm::make_range(InsertPt, EntryMBB.end())) {
914fc4e42dSDan Gohman     if (WebAssembly::isArgument(MI)) {
92500d0469SDuncan P. N. Exon Smith       EntryMBB.insert(InsertPt, MI.removeFromParent());
931cf96c0cSDan Gohman       Changed = true;
941cf96c0cSDan Gohman     }
951cf96c0cSDan Gohman   }
961cf96c0cSDan Gohman 
971cf96c0cSDan Gohman   return Changed;
981cf96c0cSDan Gohman }
99