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 WebAssemblyInstrInfo::WebAssemblyInstrInfo(const WebAssemblySubtarget
&STI
)
31 : WebAssemblyGenInstrInfo(WebAssembly::ADJCALLSTACKDOWN
,
32 WebAssembly::ADJCALLSTACKUP
,
33 WebAssembly::CATCHRET
),
34 RI(STI
.getTargetTriple()) {}
36 bool WebAssemblyInstrInfo::isReallyTriviallyReMaterializable(
37 const MachineInstr
&MI
, AliasAnalysis
*AA
) const {
38 switch (MI
.getOpcode()) {
39 case WebAssembly::CONST_I32
:
40 case WebAssembly::CONST_I64
:
41 case WebAssembly::CONST_F32
:
42 case WebAssembly::CONST_F64
:
43 // isReallyTriviallyReMaterializableGeneric misses these because of the
44 // ARGUMENTS implicit def, so we manualy override it here.
51 void WebAssemblyInstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
52 MachineBasicBlock::iterator I
,
53 const DebugLoc
&DL
, unsigned DestReg
,
54 unsigned SrcReg
, bool KillSrc
) const {
55 // This method is called by post-RA expansion, which expects only pregs to
56 // exist. However we need to handle both here.
57 auto &MRI
= MBB
.getParent()->getRegInfo();
58 const TargetRegisterClass
*RC
=
59 TargetRegisterInfo::isVirtualRegister(DestReg
)
60 ? MRI
.getRegClass(DestReg
)
61 : MRI
.getTargetRegisterInfo()->getMinimalPhysRegClass(DestReg
);
64 if (RC
== &WebAssembly::I32RegClass
)
65 CopyOpcode
= WebAssembly::COPY_I32
;
66 else if (RC
== &WebAssembly::I64RegClass
)
67 CopyOpcode
= WebAssembly::COPY_I64
;
68 else if (RC
== &WebAssembly::F32RegClass
)
69 CopyOpcode
= WebAssembly::COPY_F32
;
70 else if (RC
== &WebAssembly::F64RegClass
)
71 CopyOpcode
= WebAssembly::COPY_F64
;
72 else if (RC
== &WebAssembly::V128RegClass
)
73 CopyOpcode
= WebAssembly::COPY_V128
;
75 llvm_unreachable("Unexpected register class");
77 BuildMI(MBB
, I
, DL
, get(CopyOpcode
), DestReg
)
78 .addReg(SrcReg
, KillSrc
? RegState::Kill
: 0);
81 MachineInstr
*WebAssemblyInstrInfo::commuteInstructionImpl(
82 MachineInstr
&MI
, bool NewMI
, unsigned OpIdx1
, unsigned OpIdx2
) const {
83 // If the operands are stackified, we can't reorder them.
84 WebAssemblyFunctionInfo
&MFI
=
85 *MI
.getParent()->getParent()->getInfo
<WebAssemblyFunctionInfo
>();
86 if (MFI
.isVRegStackified(MI
.getOperand(OpIdx1
).getReg()) ||
87 MFI
.isVRegStackified(MI
.getOperand(OpIdx2
).getReg()))
90 // Otherwise use the default implementation.
91 return TargetInstrInfo::commuteInstructionImpl(MI
, NewMI
, OpIdx1
, OpIdx2
);
95 bool WebAssemblyInstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
96 MachineBasicBlock
*&TBB
,
97 MachineBasicBlock
*&FBB
,
98 SmallVectorImpl
<MachineOperand
> &Cond
,
99 bool /*AllowModify*/) const {
100 bool HaveCond
= false;
101 for (MachineInstr
&MI
: MBB
.terminators()) {
102 switch (MI
.getOpcode()) {
104 // Unhandled instruction; bail out.
106 case WebAssembly::BR_IF
:
109 // If we're running after CFGStackify, we can't optimize further.
110 if (!MI
.getOperand(0).isMBB())
112 Cond
.push_back(MachineOperand::CreateImm(true));
113 Cond
.push_back(MI
.getOperand(1));
114 TBB
= MI
.getOperand(0).getMBB();
117 case WebAssembly::BR_UNLESS
:
120 // If we're running after CFGStackify, we can't optimize further.
121 if (!MI
.getOperand(0).isMBB())
123 Cond
.push_back(MachineOperand::CreateImm(false));
124 Cond
.push_back(MI
.getOperand(1));
125 TBB
= MI
.getOperand(0).getMBB();
128 case WebAssembly::BR
:
129 // If we're running after CFGStackify, we can't optimize further.
130 if (!MI
.getOperand(0).isMBB())
133 TBB
= MI
.getOperand(0).getMBB();
135 FBB
= MI
.getOperand(0).getMBB();
137 case WebAssembly::BR_ON_EXN
:
140 // If we're running after CFGStackify, we can't optimize further.
141 if (!MI
.getOperand(0).isMBB())
143 Cond
.push_back(MachineOperand::CreateImm(true));
144 Cond
.push_back(MI
.getOperand(2));
145 TBB
= MI
.getOperand(0).getMBB();
156 unsigned WebAssemblyInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
157 int *BytesRemoved
) const {
158 assert(!BytesRemoved
&& "code size not handled");
160 MachineBasicBlock::instr_iterator I
= MBB
.instr_end();
163 while (I
!= MBB
.instr_begin()) {
165 if (I
->isDebugInstr())
167 if (!I
->isTerminator())
169 // Remove the branch.
170 I
->eraseFromParent();
178 unsigned WebAssemblyInstrInfo::insertBranch(
179 MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
, MachineBasicBlock
*FBB
,
180 ArrayRef
<MachineOperand
> Cond
, const DebugLoc
&DL
, int *BytesAdded
) const {
181 assert(!BytesAdded
&& "code size not handled");
187 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(TBB
);
191 assert(Cond
.size() == 2 && "Expected a flag and a successor block");
193 MachineFunction
&MF
= *MBB
.getParent();
194 auto &MRI
= MF
.getRegInfo();
195 bool IsBrOnExn
= Cond
[1].isReg() && MRI
.getRegClass(Cond
[1].getReg()) ==
196 &WebAssembly::EXCEPT_REFRegClass
;
198 if (Cond
[0].getImm()) {
200 const char *CPPExnSymbol
= MF
.createExternalSymbolName("__cpp_exception");
201 BuildMI(&MBB
, DL
, get(WebAssembly::BR_ON_EXN
))
203 .addExternalSymbol(CPPExnSymbol
, WebAssemblyII::MO_SYMBOL_EVENT
)
206 BuildMI(&MBB
, DL
, get(WebAssembly::BR_IF
)).addMBB(TBB
).add(Cond
[1]);
208 assert(!IsBrOnExn
&& "br_on_exn does not have a reversed condition");
209 BuildMI(&MBB
, DL
, get(WebAssembly::BR_UNLESS
)).addMBB(TBB
).add(Cond
[1]);
214 BuildMI(&MBB
, DL
, get(WebAssembly::BR
)).addMBB(FBB
);
218 bool WebAssemblyInstrInfo::reverseBranchCondition(
219 SmallVectorImpl
<MachineOperand
> &Cond
) const {
220 assert(Cond
.size() == 2 && "Expected a flag and a condition expression");
222 // br_on_exn's condition cannot be reversed
223 MachineFunction
&MF
= *Cond
[1].getParent()->getParent()->getParent();
224 auto &MRI
= MF
.getRegInfo();
225 if (Cond
[1].isReg() &&
226 MRI
.getRegClass(Cond
[1].getReg()) == &WebAssembly::EXCEPT_REFRegClass
)
229 Cond
.front() = MachineOperand::CreateImm(!Cond
.front().getImm());