llvm.org GIT mirror llvm / 4c8fe28
[WebAssembly] Reintroduce ARGUMENT moving logic Reinteroduce the code for moving ARGUMENTS back to the top of the basic block. While the ARGUMENTS physical register prevents sinking and scheduling from moving them, it does not appear to be sufficient to prevent SelectionDAG from moving them down in the initial schedule. This patch introduces a patch that moves them back to the top immediately after SelectionDAG runs. This is still hopefully a temporary solution. http://reviews.llvm.org/D14750 is one alternative, though the review has not been favorable, and proposed alternatives are longer-term and have other downsides. This fixes the main outstanding -verify-machineinstrs failures, so it adds -verify-machineinstrs to several tests. Differential Revision: http://reviews.llvm.org/D15377 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255125 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 4 years ago
10 changed file(s) with 123 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
1010
1111 add_llvm_target(WebAssemblyCodeGen
1212 Relooper.cpp
13 WebAssemblyArgumentMove.cpp
1314 WebAssemblyAsmPrinter.cpp
1415 WebAssemblyCFGStackify.cpp
1516 WebAssemblyFastISel.cpp
2626
2727 FunctionPass *createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
2828 CodeGenOpt::Level OptLevel);
29 FunctionPass *createWebAssemblyArgumentMove();
2930
3031 FunctionPass *createWebAssemblyStoreResults();
3132 FunctionPass *createWebAssemblyRegStackify();
0 //===-- WebAssemblyArgumentMove.cpp - Argument instruction moving ---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// \brief This file moves ARGUMENT instructions after ScheduleDAG scheduling.
11 ///
12 /// Arguments are really live-in registers, however, since we use virtual
13 /// registers and LLVM doesn't support live-in virtual registers, we're
14 /// currently making do with ARGUMENT instructions which are placed at the top
15 /// of the entry block. The trick is to get them to *stay* at the top of the
16 /// entry block.
17 ///
18 /// The ARGUMENTS physical register keeps these instructions pinned in place
19 /// during liveness-aware CodeGen passes, however one thing which does not
20 /// respect this is the ScheduleDAG scheduler. This pass is therefore run
21 /// immediately after that.
22 ///
23 /// This is all hopefully a temporary solution until we find a better solution
24 /// for describing the live-in nature of arguments.
25 ///
26 //===----------------------------------------------------------------------===//
27
28 #include "WebAssembly.h"
29 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
30 #include "WebAssemblyMachineFunctionInfo.h"
31 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
32 #include "llvm/CodeGen/MachineRegisterInfo.h"
33 #include "llvm/CodeGen/Passes.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/raw_ostream.h"
36 using namespace llvm;
37
38 #define DEBUG_TYPE "wasm-argument-move"
39
40 namespace {
41 class WebAssemblyArgumentMove final : public MachineFunctionPass {
42 public:
43 static char ID; // Pass identification, replacement for typeid
44 WebAssemblyArgumentMove() : MachineFunctionPass(ID) {}
45
46 const char *getPassName() const override {
47 return "WebAssembly Argument Move";
48 }
49
50 void getAnalysisUsage(AnalysisUsage &AU) const override {
51 AU.setPreservesCFG();
52 AU.addPreserved();
53 AU.addPreservedID(MachineDominatorsID);
54 MachineFunctionPass::getAnalysisUsage(AU);
55 }
56
57 bool runOnMachineFunction(MachineFunction &MF) override;
58 };
59 } // end anonymous namespace
60
61 char WebAssemblyArgumentMove::ID = 0;
62 FunctionPass *llvm::createWebAssemblyArgumentMove() {
63 return new WebAssemblyArgumentMove();
64 }
65
66 /// Test whether the given instruction is an ARGUMENT.
67 static bool IsArgument(const MachineInstr *MI) {
68 switch (MI->getOpcode()) {
69 case WebAssembly::ARGUMENT_I32:
70 case WebAssembly::ARGUMENT_I64:
71 case WebAssembly::ARGUMENT_F32:
72 case WebAssembly::ARGUMENT_F64:
73 return true;
74 default:
75 return false;
76 }
77 }
78
79 bool WebAssemblyArgumentMove::runOnMachineFunction(MachineFunction &MF) {
80 DEBUG({
81 dbgs() << "********** Argument Move **********\n"
82 << "********** Function: " << MF.getName() << '\n';
83 });
84
85 bool Changed = false;
86 MachineBasicBlock &EntryMBB = MF.front();
87 MachineBasicBlock::iterator InsertPt = EntryMBB.end();
88
89 // Look for the first NonArg instruction.
90 for (auto MII = EntryMBB.begin(), MIE = EntryMBB.end(); MII != MIE; ++MII) {
91 MachineInstr *MI = MII;
92 if (!IsArgument(MI)) {
93 InsertPt = MII;
94 break;
95 }
96 }
97
98 // Now move any argument instructions later in the block
99 // to before our first NonArg instruction.
100 for (auto I = InsertPt, E = EntryMBB.end(); I != E; ++I) {
101 MachineInstr *MI = I;
102 if (IsArgument(MI)) {
103 EntryMBB.insert(InsertPt, MI->removeFromParent());
104 Changed = true;
105 }
106 }
107
108 return Changed;
109 }
148148 (void)TargetPassConfig::addInstSelector();
149149 addPass(
150150 createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
151 // Run the argument-move pass immediately after the ScheduleDAG scheduler
152 // so that we can fix up the ARGUMENT instructions before anything else
153 // sees them in the wrong place.
154 addPass(createWebAssemblyArgumentMove());
151155 return false;
152156 }
153157
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
11
22 ; Check that unused vregs aren't assigned registers.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
11
22 ; Test that phis are lowered.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
11
22 ; Test the register stackifier pass.
33
None ; RUN: llc < %s -asm-verbose=false -disable-block-placement | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-block-placement -verify-machineinstrs | FileCheck %s
11
22 ; Test switch instructions. Block placement is disabled because it reorders
33 ; the blocks in a way that isn't interesting here.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -verify-machineinstrs | FileCheck %s
22
33 ; Test that LLVM unreachable instruction and trap intrinsic are lowered to
44 ; wasm unreachable
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
11
22 ; Test varargs constructs.
33