1 //===-- WebAssemblyInstrInfo.cpp - WebAssembly Instruction Information ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file contains the WebAssembly implementation of the
11 /// TargetInstrInfo class.
13 //===----------------------------------------------------------------------===//
15 #include "WebAssemblyInstrInfo.h"
16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17 #include "WebAssemblyMachineFunctionInfo.h"
18 #include "WebAssemblySubtarget.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineMemOperand.h"
22 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #define DEBUG_TYPE "wasm-instr-info"
27 #define GET_INSTRINFO_CTOR_DTOR
28 #include "WebAssemblyGenInstrInfo.inc"
30 // defines WebAssembly::getNamedOperandIdx
31 #define GET_INSTRINFO_NAMED_OPS
32 #include "WebAssemblyGenInstrInfo.inc"
34 WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget
&STI
)
35 : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN
,
36 WebAssembly::ADJCALLSTACKUP
,
37 WebAssembly::CATCHRET
),
38 RI(STI
.getTargetTriple()) {}
40 bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
41 const MachineInstr
&MI
, AAResults
*AA
) const {
42 switch (MI
.getOpcode()) {
43 case WebAssembly::CONST_I32
:
44 case WebAssembly::CONST_I64
:
45 case WebAssembly::CONST_F32
:
46 case WebAssembly::CONST_F64
:
47 // isReallyTriviallyReMaterializableGeneric misses these because of the
48 // ARGUMENTS implicit def, so we manualy override it here.
55 void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
56 MachineBasicBlock::iterator I
,
57 const DebugLoc
&DL
, unsigned DestReg
,
58 unsigned SrcReg
, bool KillSrc
) const {
59 // This method is called by post-RA expansion, which expects only pregs to
60 // exist. However we need to handle both here.
61 auto &MRI
= MBB
.getParent()->getRegInfo();
62 const TargetRegisterClass
*RC
=
63 Register::isVirtualRegister(DestReg
)
64 ? MRI
.getRegClass(DestReg
)
65 : MRI
.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg
);
68 if (RC
== &WebAssembly::I32RegClass
)
69 CopyOpcode
= WebAssembly::COPY_I32
;
70 else if (RC
== &WebAssembly::I64RegClass
)
71 CopyOpcode
= WebAssembly::COPY_I64
;
72 else if (RC
== &WebAssembly::F32RegClass
)
73 CopyOpcode
= WebAssembly::COPY_F32
;
74 else if (RC
== &WebAssembly::F64RegClass
)
75 CopyOpcode
= WebAssembly::COPY_F64
;
76 else if (RC
== &WebAssembly::V128RegClass
)
77 CopyOpcode
= WebAssembly::COPY_V128
;
78 else if (RC
== &WebAssembly::EXNREFRegClass
)
79 CopyOpcode
= WebAssembly::COPY_EXNREF
;
81 llvm_unreachable("Unexpected register class");
83 BuildMI(MBB
, I
, DL
, get(CopyOpcode
), DestReg
)
84 .addReg(SrcReg
, KillSrc
? RegState::Kill
: 0);
87 MachineInstr
*WebAssemblyInstrInfo::commuteInstructionImpl(
88 MachineInstr
&MI
, bool NewMI
, unsigned OpIdx1
, unsigned OpIdx2
) const {
89 // If the operands are stackified, we can't reorder them.
90 WebAssemblyFunctionInfo
&MFI
=
91 *MI
.getParent()->getParent()->getInfo
<WebAssemblyFunctionInfo
>();
92 if (MFI
.isVRegStackified(MI
.getOperand(OpIdx1
).getReg()) ||
93 MFI
.isVRegStackified(MI
.getOperand(OpIdx2
).getReg()))
96 // Otherwise use the default implementation.
97 return TargetInstrInfo::commuteInstructionImpl(MI
, NewMI
, OpIdx1
, OpIdx2
);
101 bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
102 MachineBasicBlock
*&TBB
,
103 MachineBasicBlock
*&FBB
,
104 SmallVectorImpl
<MachineOperand
> &Cond
,
105 bool /*AllowModify*/) const {
106 const auto &MFI
= *MBB
.getParent()->getInfo
<WebAssemblyFunctionInfo
>();
107 // WebAssembly has control flow that doesn't have explicit branches or direct
108 // fallthrough (e.g. try/catch), which can't be modeled by analyzeBranch. It
109 // is created after CFGStackify.
110 if (MFI
.isCFGStackified())
113 bool HaveCond
= false;
114 for (MachineInstr
&MI
: MBB
.terminators()) {
115 switch (MI
.getOpcode()) {
117 // Unhandled instruction; bail out.
119 case WebAssembly::BR_IF
:
122 Cond
.push_back(MachineOperand::CreateImm(true));
123 Cond
.push_back(MI
.getOperand(1));
124 TBB
= MI
.getOperand(0).getMBB();
127 case WebAssembly::BR_UNLESS
:
130 Cond
.push_back(MachineOperand::CreateImm(false));
131 Cond
.push_back(MI
.getOperand(1));
132 TBB
= MI
.getOperand(0).getMBB();
135 case WebAssembly::BR
:
137 TBB
= MI
.getOperand(0).getMBB();
139 FBB
= MI
.getOperand(0).getMBB();
141 case WebAssembly::BR_ON_EXN
:
144 Cond
.push_back(MachineOperand::CreateImm(true));
145 Cond
.push_back(MI
.getOperand(2));
146 TBB
= MI
.getOperand(0).getMBB();
157 unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
158 int *BytesRemoved
) const {
159 assert(!BytesRemoved
&& "code size not handled");
161 MachineBasicBlock::instr_iterator I
= MBB
.instr_end();
164 while (I
!= MBB
.instr_begin()) {
166 if (I
->isDebugInstr())
168 if (!I
->isTerminator())
170 // Remove the branch.
171 I
->eraseFromParent();
179 unsigned WebAssemblyInstrInfo::insertBranch(
180 MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
, MachineBasicBlock
*FBB
,
181 ArrayRef
<MachineOperand
> Cond
, const DebugLoc
&DL
, int *BytesAdded
) const {
182 assert(!BytesAdded
&& "code size not handled");
188 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(TBB
);
192 assert(Cond
.size() == 2 && "Expected a flag and a successor block");
194 MachineFunction
&MF
= *MBB
.getParent();
195 auto &MRI
= MF
.getRegInfo();
196 bool IsBrOnExn
= Cond
[1].isReg() && MRI
.getRegClass(Cond
[1].getReg()) ==
197 &WebAssembly::EXNREFRegClass
;
199 if (Cond
[0].getImm()) {
201 const char *CPPExnSymbol
= MF
.createExternalSymbolName("__cpp_exception");
202 BuildMI(&MBB
, DL
, get(WebAssembly::BR_ON_EXN
))
204 .addExternalSymbol(CPPExnSymbol
)
207 BuildMI(&MBB
, DL
, get(WebAssembly::BR_IF
)).addMBB(TBB
).add(Cond
[1]);
209 assert(!IsBrOnExn
&& "br_on_exn does not have a reversed condition");
210 BuildMI(&MBB
, DL
, get(WebAssembly::BR_UNLESS
)).addMBB(TBB
).add(Cond
[1]);
215 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(FBB
);
219 bool WebAssemblyInstrInfo::reverseBranchCondition(
220 SmallVectorImpl
<MachineOperand
> &Cond
) const {
221 assert(Cond
.size() == 2 && "Expected a flag and a condition expression");
223 // br_on_exn's condition cannot be reversed
224 MachineFunction
&MF
= *Cond
[1].getParent()->getParent()->getParent();
225 auto &MRI
= MF
.getRegInfo();
226 if (Cond
[1].isReg() &&
227 MRI
.getRegClass(Cond
[1].getReg()) == &WebAssembly::EXNREFRegClass
)
230 Cond
.front() = MachineOperand::CreateImm(!Cond
.front().getImm());