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
, AliasAnalysis
*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 TargetRegisterInfo::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
;
79 llvm_unreachable("Unexpected register class");
81 BuildMI(MBB
, I
, DL
, get(CopyOpcode
), DestReg
)
82 .addReg(SrcReg
, KillSrc
? RegState::Kill
: 0);
85 MachineInstr
*WebAssemblyInstrInfo::commuteInstructionImpl(
86 MachineInstr
&MI
, bool NewMI
, unsigned OpIdx1
, unsigned OpIdx2
) const {
87 // If the operands are stackified, we can't reorder them.
88 WebAssemblyFunctionInfo
&MFI
=
89 *MI
.getParent()->getParent()->getInfo
<WebAssemblyFunctionInfo
>();
90 if (MFI
.isVRegStackified(MI
.getOperand(OpIdx1
).getReg()) ||
91 MFI
.isVRegStackified(MI
.getOperand(OpIdx2
).getReg()))
94 // Otherwise use the default implementation.
95 return TargetInstrInfo::commuteInstructionImpl(MI
, NewMI
, OpIdx1
, OpIdx2
);
99 bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
100 MachineBasicBlock
*&TBB
,
101 MachineBasicBlock
*&FBB
,
102 SmallVectorImpl
<MachineOperand
> &Cond
,
103 bool /*AllowModify*/) const {
104 const auto &MFI
= *MBB
.getParent()->getInfo
<WebAssemblyFunctionInfo
>();
105 // WebAssembly has control flow that doesn't have explicit branches or direct
106 // fallthrough (e.g. try/catch), which can't be modeled by analyzeBranch. It
107 // is created after CFGStackify.
108 if (MFI
.isCFGStackified())
111 bool HaveCond
= false;
112 for (MachineInstr
&MI
: MBB
.terminators()) {
113 switch (MI
.getOpcode()) {
115 // Unhandled instruction; bail out.
117 case WebAssembly::BR_IF
:
120 Cond
.push_back(MachineOperand::CreateImm(true));
121 Cond
.push_back(MI
.getOperand(1));
122 TBB
= MI
.getOperand(0).getMBB();
125 case WebAssembly::BR_UNLESS
:
128 Cond
.push_back(MachineOperand::CreateImm(false));
129 Cond
.push_back(MI
.getOperand(1));
130 TBB
= MI
.getOperand(0).getMBB();
133 case WebAssembly::BR
:
135 TBB
= MI
.getOperand(0).getMBB();
137 FBB
= MI
.getOperand(0).getMBB();
139 case WebAssembly::BR_ON_EXN
:
142 Cond
.push_back(MachineOperand::CreateImm(true));
143 Cond
.push_back(MI
.getOperand(2));
144 TBB
= MI
.getOperand(0).getMBB();
155 unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
156 int *BytesRemoved
) const {
157 assert(!BytesRemoved
&& "code size not handled");
159 MachineBasicBlock::instr_iterator I
= MBB
.instr_end();
162 while (I
!= MBB
.instr_begin()) {
164 if (I
->isDebugInstr())
166 if (!I
->isTerminator())
168 // Remove the branch.
169 I
->eraseFromParent();
177 unsigned WebAssemblyInstrInfo::insertBranch(
178 MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
, MachineBasicBlock
*FBB
,
179 ArrayRef
<MachineOperand
> Cond
, const DebugLoc
&DL
, int *BytesAdded
) const {
180 assert(!BytesAdded
&& "code size not handled");
186 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(TBB
);
190 assert(Cond
.size() == 2 && "Expected a flag and a successor block");
192 MachineFunction
&MF
= *MBB
.getParent();
193 auto &MRI
= MF
.getRegInfo();
194 bool IsBrOnExn
= Cond
[1].isReg() && MRI
.getRegClass(Cond
[1].getReg()) ==
195 &WebAssembly::EXCEPT_REFRegClass
;
197 if (Cond
[0].getImm()) {
199 const char *CPPExnSymbol
= MF
.createExternalSymbolName("__cpp_exception");
200 BuildMI(&MBB
, DL
, get(WebAssembly::BR_ON_EXN
))
202 .addExternalSymbol(CPPExnSymbol
)
205 BuildMI(&MBB
, DL
, get(WebAssembly::BR_IF
)).addMBB(TBB
).add(Cond
[1]);
207 assert(!IsBrOnExn
&& "br_on_exn does not have a reversed condition");
208 BuildMI(&MBB
, DL
, get(WebAssembly::BR_UNLESS
)).addMBB(TBB
).add(Cond
[1]);
213 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(FBB
);
217 bool WebAssemblyInstrInfo::reverseBranchCondition(
218 SmallVectorImpl
<MachineOperand
> &Cond
) const {
219 assert(Cond
.size() == 2 && "Expected a flag and a condition expression");
221 // br_on_exn's condition cannot be reversed
222 MachineFunction
&MF
= *Cond
[1].getParent()->getParent()->getParent();
223 auto &MRI
= MF
.getRegInfo();
224 if (Cond
[1].isReg() &&
225 MRI
.getRegClass(Cond
[1].getReg()) == &WebAssembly::EXCEPT_REFRegClass
)
228 Cond
.front() = MachineOperand::CreateImm(!Cond
.front().getImm());