Line data Source code
1 : //===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : ///
10 : /// \file
11 : /// This file contains the WebAssembly implementation of the
12 : /// TargetInstrInfo class.
13 : ///
14 : //===----------------------------------------------------------------------===//
15 :
16 : #include "WebAssemblyInstrInfo.h"
17 : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18 : #include "WebAssemblyMachineFunctionInfo.h"
19 : #include "WebAssemblySubtarget.h"
20 : #include "llvm/CodeGen/MachineFrameInfo.h"
21 : #include "llvm/CodeGen/MachineInstrBuilder.h"
22 : #include "llvm/CodeGen/MachineMemOperand.h"
23 : #include "llvm/CodeGen/MachineRegisterInfo.h"
24 : using namespace llvm;
25 :
26 : #define DEBUG_TYPE "wasm-instr-info"
27 :
28 : #define GET_INSTRINFO_CTOR_DTOR
29 : #include "WebAssemblyGenInstrInfo.inc"
30 :
31 293 : WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget &STI)
32 : : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN,
33 : WebAssembly::ADJCALLSTACKUP,
34 : WebAssembly::CATCHRET),
35 293 : RI(STI.getTargetTriple()) {}
36 :
37 1654 : bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
38 : const MachineInstr &MI, AliasAnalysis *AA) const {
39 1654 : switch (MI.getOpcode()) {
40 : case WebAssembly::CONST_I32:
41 : case WebAssembly::CONST_I64:
42 : case WebAssembly::CONST_F32:
43 : case WebAssembly::CONST_F64:
44 : // isReallyTriviallyReMaterializableGeneric misses these because of the
45 : // ARGUMENTS implicit def, so we manualy override it here.
46 : return true;
47 : default:
48 : return false;
49 : }
50 : }
51 :
52 76 : void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
53 : MachineBasicBlock::iterator I,
54 : const DebugLoc &DL, unsigned DestReg,
55 : unsigned SrcReg, bool KillSrc) const {
56 : // This method is called by post-RA expansion, which expects only pregs to
57 : // exist. However we need to handle both here.
58 76 : auto &MRI = MBB.getParent()->getRegInfo();
59 : const TargetRegisterClass *RC =
60 : TargetRegisterInfo::isVirtualRegister(DestReg)
61 76 : ? MRI.getRegClass(DestReg)
62 18 : : MRI.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg);
63 :
64 : unsigned CopyOpcode;
65 76 : if (RC == &WebAssembly::I32RegClass)
66 : CopyOpcode = WebAssembly::COPY_I32;
67 11 : else if (RC == &WebAssembly::I64RegClass)
68 : CopyOpcode = WebAssembly::COPY_I64;
69 6 : else if (RC == &WebAssembly::F32RegClass)
70 : CopyOpcode = WebAssembly::COPY_F32;
71 6 : else if (RC == &WebAssembly::F64RegClass)
72 : CopyOpcode = WebAssembly::COPY_F64;
73 : else
74 0 : llvm_unreachable("Unexpected register class");
75 :
76 152 : BuildMI(MBB, I, DL, get(CopyOpcode), DestReg)
77 152 : .addReg(SrcReg, KillSrc ? RegState::Kill : 0);
78 76 : }
79 :
80 6908 : MachineInstr *WebAssemblyInstrInfo::commuteInstructionImpl(
81 : MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const {
82 : // If the operands are stackified, we can't reorder them.
83 : WebAssemblyFunctionInfo &MFI =
84 6908 : *MI.getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
85 13840 : if (MFI.isVRegStackified(MI.getOperand(OpIdx1).getReg()) ||
86 6908 : MFI.isVRegStackified(MI.getOperand(OpIdx2).getReg()))
87 : return nullptr;
88 :
89 : // Otherwise use the default implementation.
90 6908 : return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
91 : }
92 :
93 : // Branch analysis.
94 31947 : bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
95 : MachineBasicBlock *&TBB,
96 : MachineBasicBlock *&FBB,
97 : SmallVectorImpl<MachineOperand> &Cond,
98 : bool /*AllowModify*/) const {
99 : bool HaveCond = false;
100 40694 : for (MachineInstr &MI : MBB.terminators()) {
101 59834 : switch (MI.getOpcode()) {
102 : default:
103 : // Unhandled instruction; bail out.
104 : return true;
105 7290 : case WebAssembly::BR_IF:
106 7290 : if (HaveCond)
107 : return true;
108 : // If we're running after CFGStackify, we can't optimize further.
109 14580 : if (!MI.getOperand(0).isMBB())
110 : return true;
111 13376 : Cond.push_back(MachineOperand::CreateImm(true));
112 13376 : Cond.push_back(MI.getOperand(1));
113 6688 : TBB = MI.getOperand(0).getMBB();
114 : HaveCond = true;
115 6688 : break;
116 2103 : case WebAssembly::BR_UNLESS:
117 2103 : if (HaveCond)
118 : return true;
119 : // If we're running after CFGStackify, we can't optimize further.
120 4206 : if (!MI.getOperand(0).isMBB())
121 : return true;
122 4118 : Cond.push_back(MachineOperand::CreateImm(false));
123 4118 : Cond.push_back(MI.getOperand(1));
124 2059 : TBB = MI.getOperand(0).getMBB();
125 : HaveCond = true;
126 2059 : break;
127 5618 : case WebAssembly::BR:
128 : // If we're running after CFGStackify, we can't optimize further.
129 11236 : if (!MI.getOperand(0).isMBB())
130 : return true;
131 5392 : if (!HaveCond)
132 2308 : TBB = MI.getOperand(0).getMBB();
133 : else
134 3084 : FBB = MI.getOperand(0).getMBB();
135 : break;
136 : }
137 14139 : if (MI.isBarrier())
138 : break;
139 : }
140 :
141 : return false;
142 : }
143 :
144 938 : unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock &MBB,
145 : int *BytesRemoved) const {
146 : assert(!BytesRemoved && "code size not handled");
147 :
148 : MachineBasicBlock::instr_iterator I = MBB.instr_end();
149 : unsigned Count = 0;
150 :
151 2154 : while (I != MBB.instr_begin()) {
152 : --I;
153 : if (I->isDebugInstr())
154 : continue;
155 2026 : if (!I->isTerminator())
156 : break;
157 : // Remove the branch.
158 1206 : I->eraseFromParent();
159 : I = MBB.instr_end();
160 1206 : ++Count;
161 : }
162 :
163 938 : return Count;
164 : }
165 :
166 920 : unsigned WebAssemblyInstrInfo::insertBranch(
167 : MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
168 : ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
169 : assert(!BytesAdded && "code size not handled");
170 :
171 920 : if (Cond.empty()) {
172 259 : if (!TBB)
173 : return 0;
174 :
175 259 : BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(TBB);
176 259 : return 1;
177 : }
178 :
179 : assert(Cond.size() == 2 && "Expected a flag and a successor block");
180 :
181 661 : if (Cond[0].getImm()) {
182 350 : BuildMI(&MBB, DL, get(WebAssembly::BR_IF)).addMBB(TBB).add(Cond[1]);
183 : } else {
184 311 : BuildMI(&MBB, DL, get(WebAssembly::BR_UNLESS)).addMBB(TBB).add(Cond[1]);
185 : }
186 661 : if (!FBB)
187 : return 1;
188 :
189 24 : BuildMI(&MBB, DL, get(WebAssembly::BR)).addMBB(FBB);
190 24 : return 2;
191 : }
192 :
193 492 : bool WebAssemblyInstrInfo::reverseBranchCondition(
194 : SmallVectorImpl<MachineOperand> &Cond) const {
195 : assert(Cond.size() == 2 && "Expected a flag and a successor block");
196 492 : Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
197 492 : return false;
198 : }
|