Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / WebAssembly / WebAssemblyUtilities.cpp
blob4edd54602fb2e94dd0dd7c3e4ed6a210abdd641b
1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements several utility functions for WebAssembly.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "WebAssemblyUtilities.h"
15 #include "WebAssemblyMachineFunctionInfo.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineLoopInfo.h"
18 using namespace llvm;
20 const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate";
21 const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
22 const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
23 const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
24 const char *const WebAssembly::PersonalityWrapperFn =
25 "_Unwind_Wasm_CallPersonality";
27 bool WebAssembly::isArgument(const MachineInstr &MI) {
28 switch (MI.getOpcode()) {
29 case WebAssembly::ARGUMENT_i32:
30 case WebAssembly::ARGUMENT_i32_S:
31 case WebAssembly::ARGUMENT_i64:
32 case WebAssembly::ARGUMENT_i64_S:
33 case WebAssembly::ARGUMENT_f32:
34 case WebAssembly::ARGUMENT_f32_S:
35 case WebAssembly::ARGUMENT_f64:
36 case WebAssembly::ARGUMENT_f64_S:
37 case WebAssembly::ARGUMENT_v16i8:
38 case WebAssembly::ARGUMENT_v16i8_S:
39 case WebAssembly::ARGUMENT_v8i16:
40 case WebAssembly::ARGUMENT_v8i16_S:
41 case WebAssembly::ARGUMENT_v4i32:
42 case WebAssembly::ARGUMENT_v4i32_S:
43 case WebAssembly::ARGUMENT_v2i64:
44 case WebAssembly::ARGUMENT_v2i64_S:
45 case WebAssembly::ARGUMENT_v4f32:
46 case WebAssembly::ARGUMENT_v4f32_S:
47 case WebAssembly::ARGUMENT_v2f64:
48 case WebAssembly::ARGUMENT_v2f64_S:
49 return true;
50 default:
51 return false;
55 bool WebAssembly::isCopy(const MachineInstr &MI) {
56 switch (MI.getOpcode()) {
57 case WebAssembly::COPY_I32:
58 case WebAssembly::COPY_I32_S:
59 case WebAssembly::COPY_I64:
60 case WebAssembly::COPY_I64_S:
61 case WebAssembly::COPY_F32:
62 case WebAssembly::COPY_F32_S:
63 case WebAssembly::COPY_F64:
64 case WebAssembly::COPY_F64_S:
65 case WebAssembly::COPY_V128:
66 case WebAssembly::COPY_V128_S:
67 return true;
68 default:
69 return false;
73 bool WebAssembly::isTee(const MachineInstr &MI) {
74 switch (MI.getOpcode()) {
75 case WebAssembly::TEE_I32:
76 case WebAssembly::TEE_I32_S:
77 case WebAssembly::TEE_I64:
78 case WebAssembly::TEE_I64_S:
79 case WebAssembly::TEE_F32:
80 case WebAssembly::TEE_F32_S:
81 case WebAssembly::TEE_F64:
82 case WebAssembly::TEE_F64_S:
83 case WebAssembly::TEE_V128:
84 case WebAssembly::TEE_V128_S:
85 return true;
86 default:
87 return false;
91 /// Test whether MI is a child of some other node in an expression tree.
92 bool WebAssembly::isChild(const MachineInstr &MI,
93 const WebAssemblyFunctionInfo &MFI) {
94 if (MI.getNumOperands() == 0)
95 return false;
96 const MachineOperand &MO = MI.getOperand(0);
97 if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
98 return false;
99 unsigned Reg = MO.getReg();
100 return TargetRegisterInfo::isVirtualRegister(Reg) &&
101 MFI.isVRegStackified(Reg);
104 bool WebAssembly::isCallDirect(const MachineInstr &MI) {
105 switch (MI.getOpcode()) {
106 case WebAssembly::CALL_VOID:
107 case WebAssembly::CALL_VOID_S:
108 case WebAssembly::CALL_I32:
109 case WebAssembly::CALL_I32_S:
110 case WebAssembly::CALL_I64:
111 case WebAssembly::CALL_I64_S:
112 case WebAssembly::CALL_F32:
113 case WebAssembly::CALL_F32_S:
114 case WebAssembly::CALL_F64:
115 case WebAssembly::CALL_F64_S:
116 case WebAssembly::CALL_v16i8:
117 case WebAssembly::CALL_v16i8_S:
118 case WebAssembly::CALL_v8i16:
119 case WebAssembly::CALL_v8i16_S:
120 case WebAssembly::CALL_v4i32:
121 case WebAssembly::CALL_v4i32_S:
122 case WebAssembly::CALL_v2i64:
123 case WebAssembly::CALL_v2i64_S:
124 case WebAssembly::CALL_v4f32:
125 case WebAssembly::CALL_v4f32_S:
126 case WebAssembly::CALL_v2f64:
127 case WebAssembly::CALL_v2f64_S:
128 case WebAssembly::CALL_EXCEPT_REF:
129 case WebAssembly::CALL_EXCEPT_REF_S:
130 return true;
131 default:
132 return false;
136 bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
137 switch (MI.getOpcode()) {
138 case WebAssembly::CALL_INDIRECT_VOID:
139 case WebAssembly::CALL_INDIRECT_VOID_S:
140 case WebAssembly::CALL_INDIRECT_I32:
141 case WebAssembly::CALL_INDIRECT_I32_S:
142 case WebAssembly::CALL_INDIRECT_I64:
143 case WebAssembly::CALL_INDIRECT_I64_S:
144 case WebAssembly::CALL_INDIRECT_F32:
145 case WebAssembly::CALL_INDIRECT_F32_S:
146 case WebAssembly::CALL_INDIRECT_F64:
147 case WebAssembly::CALL_INDIRECT_F64_S:
148 case WebAssembly::CALL_INDIRECT_v16i8:
149 case WebAssembly::CALL_INDIRECT_v16i8_S:
150 case WebAssembly::CALL_INDIRECT_v8i16:
151 case WebAssembly::CALL_INDIRECT_v8i16_S:
152 case WebAssembly::CALL_INDIRECT_v4i32:
153 case WebAssembly::CALL_INDIRECT_v4i32_S:
154 case WebAssembly::CALL_INDIRECT_v2i64:
155 case WebAssembly::CALL_INDIRECT_v2i64_S:
156 case WebAssembly::CALL_INDIRECT_v4f32:
157 case WebAssembly::CALL_INDIRECT_v4f32_S:
158 case WebAssembly::CALL_INDIRECT_v2f64:
159 case WebAssembly::CALL_INDIRECT_v2f64_S:
160 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
161 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
162 return true;
163 default:
164 return false;
168 unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
169 switch (MI.getOpcode()) {
170 case WebAssembly::CALL_VOID:
171 case WebAssembly::CALL_VOID_S:
172 case WebAssembly::CALL_INDIRECT_VOID:
173 case WebAssembly::CALL_INDIRECT_VOID_S:
174 return 0;
175 case WebAssembly::CALL_I32:
176 case WebAssembly::CALL_I32_S:
177 case WebAssembly::CALL_I64:
178 case WebAssembly::CALL_I64_S:
179 case WebAssembly::CALL_F32:
180 case WebAssembly::CALL_F32_S:
181 case WebAssembly::CALL_F64:
182 case WebAssembly::CALL_F64_S:
183 case WebAssembly::CALL_v16i8:
184 case WebAssembly::CALL_v16i8_S:
185 case WebAssembly::CALL_v8i16:
186 case WebAssembly::CALL_v8i16_S:
187 case WebAssembly::CALL_v4i32:
188 case WebAssembly::CALL_v4i32_S:
189 case WebAssembly::CALL_v2i64:
190 case WebAssembly::CALL_v2i64_S:
191 case WebAssembly::CALL_v4f32:
192 case WebAssembly::CALL_v4f32_S:
193 case WebAssembly::CALL_v2f64:
194 case WebAssembly::CALL_v2f64_S:
195 case WebAssembly::CALL_EXCEPT_REF:
196 case WebAssembly::CALL_EXCEPT_REF_S:
197 case WebAssembly::CALL_INDIRECT_I32:
198 case WebAssembly::CALL_INDIRECT_I32_S:
199 case WebAssembly::CALL_INDIRECT_I64:
200 case WebAssembly::CALL_INDIRECT_I64_S:
201 case WebAssembly::CALL_INDIRECT_F32:
202 case WebAssembly::CALL_INDIRECT_F32_S:
203 case WebAssembly::CALL_INDIRECT_F64:
204 case WebAssembly::CALL_INDIRECT_F64_S:
205 case WebAssembly::CALL_INDIRECT_v16i8:
206 case WebAssembly::CALL_INDIRECT_v16i8_S:
207 case WebAssembly::CALL_INDIRECT_v8i16:
208 case WebAssembly::CALL_INDIRECT_v8i16_S:
209 case WebAssembly::CALL_INDIRECT_v4i32:
210 case WebAssembly::CALL_INDIRECT_v4i32_S:
211 case WebAssembly::CALL_INDIRECT_v2i64:
212 case WebAssembly::CALL_INDIRECT_v2i64_S:
213 case WebAssembly::CALL_INDIRECT_v4f32:
214 case WebAssembly::CALL_INDIRECT_v4f32_S:
215 case WebAssembly::CALL_INDIRECT_v2f64:
216 case WebAssembly::CALL_INDIRECT_v2f64_S:
217 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
218 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
219 return 1;
220 default:
221 llvm_unreachable("Not a call instruction");
225 bool WebAssembly::isMarker(const MachineInstr &MI) {
226 switch (MI.getOpcode()) {
227 case WebAssembly::BLOCK:
228 case WebAssembly::BLOCK_S:
229 case WebAssembly::END_BLOCK:
230 case WebAssembly::END_BLOCK_S:
231 case WebAssembly::LOOP:
232 case WebAssembly::LOOP_S:
233 case WebAssembly::END_LOOP:
234 case WebAssembly::END_LOOP_S:
235 case WebAssembly::TRY:
236 case WebAssembly::TRY_S:
237 case WebAssembly::END_TRY:
238 case WebAssembly::END_TRY_S:
239 return true;
240 default:
241 return false;
245 bool WebAssembly::mayThrow(const MachineInstr &MI) {
246 switch (MI.getOpcode()) {
247 case WebAssembly::THROW:
248 case WebAssembly::THROW_S:
249 case WebAssembly::RETHROW:
250 case WebAssembly::RETHROW_S:
251 return true;
253 if (isCallIndirect(MI))
254 return true;
255 if (!MI.isCall())
256 return false;
258 const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI));
259 assert(MO.isGlobal());
260 const auto *F = dyn_cast<Function>(MO.getGlobal());
261 if (!F)
262 return true;
263 if (F->doesNotThrow())
264 return false;
265 // These functions never throw
266 if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
267 F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
268 return false;
269 return true;