llvm.org GIT mirror llvm / a26aa42
[WebAssembly] Added default stack-only instruction mode for MC. Summary: Made it convert from register to stack based instructions, and removed the registers. Fixes to related code that was expecting register based instructions. Added the correct testing flag to all tests, depending on what the format they were expecting so far. Translated one test to stack format as example: reg-stackify-stack.ll tested: llvm-lit -v `find test -name WebAssembly` unittests/MC/* Reviewers: dschuff, sunfish Subscribers: sbc100, jgravelle-google, eraman, aheejin, llvm-commits, jfb Differential Revision: https://reviews.llvm.org/D51241 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@340750 91177308-0d34-0410-b5e6-96231b3b80d8 Wouter van Oortmerssen 2 years ago
97 changed file(s) with 952 addition(s) and 428 deletion(s). Raw diff Collapse all Expand all
3333
3434 namespace {
3535
36 // We store register types as SimpleValueType to retain SIMD layout
37 // information, but must also be able to supply them as the (unnamed)
38 // register enum from WebAssemblyRegisterInfo.td/.inc.
39 static unsigned MVTToWasmReg(MVT::SimpleValueType Type) {
40 switch(Type) {
41 case MVT::i32: return WebAssembly::I32_0;
42 case MVT::i64: return WebAssembly::I64_0;
43 case MVT::f32: return WebAssembly::F32_0;
44 case MVT::f64: return WebAssembly::F64_0;
45 case MVT::v16i8: return WebAssembly::V128_0;
46 case MVT::v8i16: return WebAssembly::V128_0;
47 case MVT::v4i32: return WebAssembly::V128_0;
48 case MVT::v2i64: return WebAssembly::V128_0;
49 case MVT::v4f32: return WebAssembly::V128_0;
50 case MVT::v2f64: return WebAssembly::V128_0;
51 default: return MVT::INVALID_SIMPLE_VALUE_TYPE;
52 }
53 }
54
5536 /// WebAssemblyOperand - Instances of this class represent the operands in a
5637 /// parsed WASM machine instruction.
5738 struct WebAssemblyOperand : public MCParsedAsmOperand {
58 enum KindTy { Token, Local, Stack, Integer, Float, Symbol } Kind;
39 enum KindTy { Token, Integer, Float, Symbol } Kind;
5940
6041 SMLoc StartLoc, EndLoc;
6142
6344 StringRef Tok;
6445 };
6546
66 struct RegOp {
67 // This is a (virtual) local or stack register represented as 0..
68 unsigned RegNo;
69 // In most targets, the register number also encodes the type, but for
70 // wasm we have to track that seperately since we have an unbounded
71 // number of registers.
72 // This has the unfortunate side effect that we supply a different value
73 // to the table-gen matcher at different times in the process (when it
74 // calls getReg() or addRegOperands().
75 // TODO: While this works, it feels brittle. and would be nice to clean up.
76 MVT::SimpleValueType Type;
77 };
78
7947 struct IntOp {
8048 int64_t Val;
8149 };
9058
9159 union {
9260 struct TokOp Tok;
93 struct RegOp Reg;
9461 struct IntOp Int;
9562 struct FltOp Flt;
9663 struct SymOp Sym;
9865
9966 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T)
10067 : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {}
101 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, RegOp R)
102 : Kind(K), StartLoc(Start), EndLoc(End), Reg(R) {}
10368 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I)
10469 : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {}
10570 WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F)
11176 bool isImm() const override { return Kind == Integer ||
11277 Kind == Float ||
11378 Kind == Symbol; }
114 bool isReg() const override { return Kind == Local || Kind == Stack; }
11579 bool isMem() const override { return false; }
80 bool isReg() const override { return false; }
11681
11782 unsigned getReg() const override {
118 assert(isReg());
119 // This is called from the tablegen matcher (MatchInstructionImpl)
120 // where it expects to match the type of register, see RegOp above.
121 return MVTToWasmReg(Reg.Type);
83 llvm_unreachable("Assembly inspects a register operand");
84 return 0;
12285 }
12386
12487 StringRef getToken() const {
12992 SMLoc getStartLoc() const override { return StartLoc; }
13093 SMLoc getEndLoc() const override { return EndLoc; }
13194
132 void addRegOperands(MCInst &Inst, unsigned N) const {
133 assert(N == 1 && "Invalid number of operands!");
134 assert(isReg() && "Not a register operand!");
135 // This is called from the tablegen matcher (MatchInstructionImpl)
136 // where it expects to output the actual register index, see RegOp above.
137 unsigned R = Reg.RegNo;
138 if (Kind == Stack) {
139 // A stack register is represented as a large negative number.
140 // See WebAssemblyRegNumbering::runOnMachineFunction and
141 // getWARegStackId for why this | is needed.
142 R |= INT32_MIN;
143 }
144 Inst.addOperand(MCOperand::createReg(R));
95 void addRegOperands(MCInst &, unsigned) const {
96 // Required by the assembly matcher.
97 llvm_unreachable("Assembly matcher creates register operands");
14598 }
14699
147100 void addImmOperands(MCInst &Inst, unsigned N) const {
161114 case Token:
162115 OS << "Tok:" << Tok.Tok;
163116 break;
164 case Local:
165 OS << "Loc:" << Reg.RegNo << ":" << static_cast(Reg.Type);
166 break;
167 case Stack:
168 OS << "Stk:" << Reg.RegNo << ":" << static_cast(Reg.Type);
169 break;
170117 case Integer:
171118 OS << "Int:" << Int.Val;
172119 break;
183130 class WebAssemblyAsmParser final : public MCTargetAsmParser {
184131 MCAsmParser &Parser;
185132 MCAsmLexer &Lexer;
186 // These are for the current function being parsed:
187 // These are vectors since register assignments are so far non-sparse.
188 // Replace by map if necessary.
189 std::vector LocalTypes;
190 std::vector StackTypes;
191133 MCSymbol *LastLabel;
192134
193135 public:
244186 .Default(MVT::INVALID_SIMPLE_VALUE_TYPE);
245187 }
246188
247 MVT::SimpleValueType &GetType(
248 std::vector &Types, size_t i) {
249 Types.resize(std::max(i + 1, Types.size()), MVT::INVALID_SIMPLE_VALUE_TYPE);
250 return Types[i];
251 }
252
253 bool ParseReg(OperandVector &Operands, StringRef TypePrefix) {
254 if (Lexer.is(AsmToken::Integer)) {
255 auto &Local = Lexer.getTok();
256 // This is a reference to a local, turn it into a virtual register.
257 auto LocalNo = static_cast(Local.getIntVal());
258 Operands.push_back(make_unique(
259 WebAssemblyOperand::Local, Local.getLoc(),
260 Local.getEndLoc(),
261 WebAssemblyOperand::RegOp{LocalNo,
262 GetType(LocalTypes, LocalNo)}));
263 Parser.Lex();
264 } else if (Lexer.is(AsmToken::Identifier)) {
265 auto &StackRegTok = Lexer.getTok();
266 // These are push/pop/drop pseudo stack registers, which we turn
267 // into virtual registers also. The stackify pass will later turn them
268 // back into implicit stack references if possible.
269 auto StackReg = StackRegTok.getString();
270 auto StackOp = StackReg.take_while([](char c) { return isalpha(c); });
271 auto Reg = StackReg.drop_front(StackOp.size());
272 unsigned long long ParsedRegNo = 0;
273 if (!Reg.empty() && getAsUnsignedInteger(Reg, 10, ParsedRegNo))
274 return Error("Cannot parse stack register index: ", StackRegTok);
275 unsigned RegNo = static_cast(ParsedRegNo);
276 if (StackOp == "push") {
277 // This defines a result, record register type.
278 auto RegType = ParseRegType(TypePrefix);
279 GetType(StackTypes, RegNo) = RegType;
280 Operands.push_back(make_unique(
281 WebAssemblyOperand::Stack,
282 StackRegTok.getLoc(),
283 StackRegTok.getEndLoc(),
284 WebAssemblyOperand::RegOp{RegNo, RegType}));
285 } else if (StackOp == "pop") {
286 // This uses a previously defined stack value.
287 auto RegType = GetType(StackTypes, RegNo);
288 Operands.push_back(make_unique(
289 WebAssemblyOperand::Stack,
290 StackRegTok.getLoc(),
291 StackRegTok.getEndLoc(),
292 WebAssemblyOperand::RegOp{RegNo, RegType}));
293 } else if (StackOp == "drop") {
294 // This operand will be dropped, since it is part of an instruction
295 // whose result is void.
296 } else {
297 return Error("Unknown stack register prefix: ", StackRegTok);
298 }
299 Parser.Lex();
300 } else {
301 return Error(
302 "Expected identifier/integer following $, instead got: ",
303 Lexer.getTok());
304 }
305 IsNext(AsmToken::Equal);
306 return false;
307 }
308
309189 void ParseSingleInteger(bool IsNegative, OperandVector &Operands) {
310190 auto &Int = Lexer.getTok();
311191 int64_t Val = Int.getIntVal();
318198
319199 bool ParseOperandStartingWithInteger(bool IsNegative,
320200 OperandVector &Operands,
321 StringRef InstType) {
201 StringRef InstName) {
322202 ParseSingleInteger(IsNegative, Operands);
323 if (Lexer.is(AsmToken::LParen)) {
324 // Parse load/store operands of the form: offset($reg)align
325 auto &LParen = Lexer.getTok();
326 Operands.push_back(
327 make_unique(WebAssemblyOperand::Token,
328 LParen.getLoc(),
329 LParen.getEndLoc(),
330 WebAssemblyOperand::TokOp{
331 LParen.getString()}));
332 Parser.Lex();
333 if (Expect(AsmToken::Dollar, "register")) return true;
334 if (ParseReg(Operands, InstType)) return true;
335 auto &RParen = Lexer.getTok();
336 Operands.push_back(
337 make_unique(WebAssemblyOperand::Token,
338 RParen.getLoc(),
339 RParen.getEndLoc(),
340 WebAssemblyOperand::TokOp{
341 RParen.getString()}));
342 if (Expect(AsmToken::RParen, ")")) return true;
343 if (Lexer.is(AsmToken::Integer)) {
203 // FIXME: there is probably a cleaner way to do this.
204 auto IsLoadStore = InstName.startswith("load") ||
205 InstName.startswith("store") ||
206 InstName.startswith("atomic_load") ||
207 InstName.startswith("atomic_store");
208 if (IsLoadStore) {
209 // Parse load/store operands of the form: offset align
210 auto &Offset = Lexer.getTok();
211 if (Offset.is(AsmToken::Integer)) {
344212 ParseSingleInteger(false, Operands);
345213 } else {
346214 // Alignment not specified.
347215 // FIXME: correctly derive a default from the instruction.
216 // We can't just call WebAssembly::GetDefaultP2Align since we don't have
217 // an opcode until after the assembly matcher.
348218 Operands.push_back(make_unique(
349 WebAssemblyOperand::Integer, RParen.getLoc(),
350 RParen.getEndLoc(), WebAssemblyOperand::IntOp{0}));
219 WebAssemblyOperand::Integer, Offset.getLoc(),
220 Offset.getEndLoc(), WebAssemblyOperand::IntOp{0}));
351221 }
352222 }
353223 return false;
368238 while (Lexer.isNot(AsmToken::EndOfStatement)) {
369239 auto &Tok = Lexer.getTok();
370240 switch (Tok.getKind()) {
371 case AsmToken::Dollar: {
372 Parser.Lex();
373 if (ParseReg(Operands, NamePair.first)) return true;
374 break;
375 }
376241 case AsmToken::Identifier: {
377242 auto &Id = Lexer.getTok();
378243 const MCExpr *Val;
388253 Parser.Lex();
389254 if (Lexer.isNot(AsmToken::Integer))
390255 return Error("Expected integer instead got: ", Lexer.getTok());
391 if (ParseOperandStartingWithInteger(true, Operands, NamePair.first))
256 if (ParseOperandStartingWithInteger(true, Operands, NamePair.second))
392257 return true;
393258 break;
394259 case AsmToken::Integer:
395 if (ParseOperandStartingWithInteger(false, Operands, NamePair.first))
260 if (ParseOperandStartingWithInteger(false, Operands, NamePair.second))
396261 return true;
397262 break;
398263 case AsmToken::Real: {
413278 }
414279 }
415280 Parser.Lex();
416 // Call instructions are vararg, but the tablegen matcher doesn't seem to
417 // support that, so for now we strip these extra operands.
418 // This is problematic if these arguments are not simple $pop stack
419 // registers, since e.g. a local register would get lost, so we check for
420 // this. This can be the case when using -disable-wasm-explicit-locals
421 // which currently s2wasm requires.
422 // TODO: Instead, we can move this code to MatchAndEmitInstruction below and
423 // actually generate get_local instructions on the fly.
424 // Or even better, improve the matcher to support vararg?
425 auto IsIndirect = NamePair.second == "call_indirect";
426 if (IsIndirect || NamePair.second == "call") {
427 // Figure out number of fixed operands from the instruction.
428 size_t CallOperands = 1; // The name token.
429 if (!IsIndirect) CallOperands++; // The function index.
430 if (!NamePair.first.empty()) CallOperands++; // The result register.
431 if (Operands.size() > CallOperands) {
432 // Ensure operands we drop are all $pop.
433 for (size_t I = CallOperands; I < Operands.size(); I++) {
434 auto Operand =
435 reinterpret_cast(Operands[I].get());
436 if (Operand->Kind != WebAssemblyOperand::Stack)
437 Parser.Error(NameLoc,
438 "Call instruction has non-stack arguments, if this code was "
439 "generated with -disable-wasm-explicit-locals please remove it");
440 }
441 // Drop unneeded operands.
442 Operands.resize(CallOperands);
443 }
444 }
445281 // Block instructions require a signature index, but these are missing in
446282 // assembly, so we add a dummy one explicitly (since we have no control
447283 // over signature tables here, we assume these will be regenerated when
450286 Operands.push_back(make_unique(
451287 WebAssemblyOperand::Integer, NameLoc,
452288 NameLoc, WebAssemblyOperand::IntOp{-1}));
453 }
454 // These don't specify the type, which has to derived from the local index.
455 if (NamePair.second == "get_local" || NamePair.second == "tee_local") {
456 if (Operands.size() >= 3 && Operands[1]->isReg() &&
457 Operands[2]->isImm()) {
458 auto Op1 = reinterpret_cast(Operands[1].get());
459 auto Op2 = reinterpret_cast(Operands[2].get());
460 auto Type = GetType(LocalTypes, static_cast(Op2->Int.Val));
461 Op1->Reg.Type = Type;
462 GetType(StackTypes, Op1->Reg.RegNo) = Type;
463 }
464289 }
465290 return false;
466291 }
485310 IsNext(AsmToken::At) &&
486311 Lexer.is(AsmToken::Identifier)))
487312 return Error("Expected label,@type declaration, got: ", Lexer.getTok());
488 if (Lexer.getTok().getString() == "function") {
489 // Track locals from start of function.
490 LocalTypes.clear();
491 StackTypes.clear();
492 }
493313 Parser.Lex();
494314 //Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction);
495315 } else if (DirectiveID.getString() == ".param" ||
502322 while (Lexer.is(AsmToken::Identifier)) {
503323 auto RegType = ParseRegType(Lexer.getTok().getString());
504324 if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE) return true;
505 LocalTypes.push_back(RegType);
506325 if (DirectiveID.getString() == ".param") {
507326 Params.push_back(RegType);
508327 } else {
5757 // we have an extra flags operand which is not currently printed, for
5858 // compatiblity reasons.
5959 if (i != 0 &&
60 (MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID ||
60 ((MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID &&
61 MI->getOpcode() != WebAssembly::CALL_INDIRECT_VOID_S) ||
6162 i != Desc.getNumOperands()))
6263 OS << ", ";
6364 printOperand(MI, i, OS);
7171 }
7272
7373 // For br_table instructions, encode the size of the table. In the MCInst,
74 // there's an index operand, one operand for each table entry, and the
75 // default operand.
74 // there's an index operand (if not a stack instruction), one operand for
75 // each table entry, and the default operand.
76 if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
77 MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
78 encodeULEB128(MI.getNumOperands() - 1, OS);
7679 if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
7780 MI.getOpcode() == WebAssembly::BR_TABLE_I64)
7881 encodeULEB128(MI.getNumOperands() - 2, OS);
168168
169169 switch (MI->getOpcode()) {
170170 case WebAssembly::ARGUMENT_I32:
171 case WebAssembly::ARGUMENT_I32_S:
171172 case WebAssembly::ARGUMENT_I64:
173 case WebAssembly::ARGUMENT_I64_S:
172174 case WebAssembly::ARGUMENT_F32:
175 case WebAssembly::ARGUMENT_F32_S:
173176 case WebAssembly::ARGUMENT_F64:
177 case WebAssembly::ARGUMENT_F64_S:
174178 case WebAssembly::ARGUMENT_v16i8:
179 case WebAssembly::ARGUMENT_v16i8_S:
175180 case WebAssembly::ARGUMENT_v8i16:
181 case WebAssembly::ARGUMENT_v8i16_S:
176182 case WebAssembly::ARGUMENT_v4i32:
183 case WebAssembly::ARGUMENT_v4i32_S:
177184 case WebAssembly::ARGUMENT_v2i64:
185 case WebAssembly::ARGUMENT_v2i64_S:
178186 case WebAssembly::ARGUMENT_v4f32:
187 case WebAssembly::ARGUMENT_v4f32_S:
179188 case WebAssembly::ARGUMENT_v2f64:
189 case WebAssembly::ARGUMENT_v2f64_S:
180190 // These represent values which are live into the function entry, so there's
181191 // no instruction to emit.
182192 break;
183193 case WebAssembly::FALLTHROUGH_RETURN_I32:
194 case WebAssembly::FALLTHROUGH_RETURN_I32_S:
184195 case WebAssembly::FALLTHROUGH_RETURN_I64:
196 case WebAssembly::FALLTHROUGH_RETURN_I64_S:
185197 case WebAssembly::FALLTHROUGH_RETURN_F32:
198 case WebAssembly::FALLTHROUGH_RETURN_F32_S:
186199 case WebAssembly::FALLTHROUGH_RETURN_F64:
200 case WebAssembly::FALLTHROUGH_RETURN_F64_S:
187201 case WebAssembly::FALLTHROUGH_RETURN_v16i8:
202 case WebAssembly::FALLTHROUGH_RETURN_v16i8_S:
188203 case WebAssembly::FALLTHROUGH_RETURN_v8i16:
204 case WebAssembly::FALLTHROUGH_RETURN_v8i16_S:
189205 case WebAssembly::FALLTHROUGH_RETURN_v4i32:
206 case WebAssembly::FALLTHROUGH_RETURN_v4i32_S:
190207 case WebAssembly::FALLTHROUGH_RETURN_v2i64:
208 case WebAssembly::FALLTHROUGH_RETURN_v2i64_S:
191209 case WebAssembly::FALLTHROUGH_RETURN_v4f32:
192 case WebAssembly::FALLTHROUGH_RETURN_v2f64: {
210 case WebAssembly::FALLTHROUGH_RETURN_v4f32_S:
211 case WebAssembly::FALLTHROUGH_RETURN_v2f64:
212 case WebAssembly::FALLTHROUGH_RETURN_v2f64_S: {
193213 // These instructions represent the implicit return at the end of a
194 // function body. The operand is always a pop.
195 assert(MFI->isVRegStackified(MI->getOperand(0).getReg()));
196
214 // function body. Always pops one value off the stack.
197215 if (isVerbose()) {
198 OutStreamer->AddComment("fallthrough-return: $pop" +
199 Twine(MFI->getWARegStackId(
200 MFI->getWAReg(MI->getOperand(0).getReg()))));
216 OutStreamer->AddComment("fallthrough-return-value");
201217 OutStreamer->AddBlankLine();
202218 }
203219 break;
204220 }
205221 case WebAssembly::FALLTHROUGH_RETURN_VOID:
222 case WebAssembly::FALLTHROUGH_RETURN_VOID_S:
206223 // This instruction represents the implicit return at the end of a
207224 // function body with no return value.
208225 if (isVerbose()) {
209 OutStreamer->AddComment("fallthrough-return");
226 OutStreamer->AddComment("fallthrough-return-void");
210227 OutStreamer->AddBlankLine();
211228 }
212229 break;
247264 OS << MO.getImm();
248265 return false;
249266 case MachineOperand::MO_Register:
267 // FIXME: only opcode that still contains registers, as required by
268 // MachineInstr::getDebugVariable().
269 assert(MI->getOpcode() == WebAssembly::INLINEASM);
250270 OS << regToString(MO);
251271 return false;
252272 case MachineOperand::MO_GlobalAddress:
3030
3131 #define DEBUG_TYPE "wasm-explicit-locals"
3232
33 // A command-line option to disable this pass. Note that this produces output
34 // which is not valid WebAssembly, though it may be more convenient for writing
35 // LLVM unit tests with.
36 static cl::opt DisableWebAssemblyExplicitLocals(
37 "disable-wasm-explicit-locals", cl::ReallyHidden,
38 cl::desc("WebAssembly: Disable emission of get_local/set_local."),
33 // A command-line option to disable this pass, and keep implicit locals
34 // for the purpose of testing with lit/llc ONLY.
35 // This produces output which is not valid WebAssembly, and is not supported
36 // by assemblers/disassemblers and other MC based tools.
37 static cl::opt WasmDisableExplicitLocals(
38 "wasm-disable-explicit-locals", cl::Hidden,
39 cl::desc("WebAssembly: output implicit locals in"
40 " instruction output for test purposes only."),
3941 cl::init(false));
4042
4143 namespace {
161163
162164 /// Given a MachineOperand of a stackified vreg, return the instruction at the
163165 /// start of the expression tree.
164 static MachineInstr *FindStartOfTree(MachineOperand &MO,
166 static MachineInstr *findStartOfTree(MachineOperand &MO,
165167 MachineRegisterInfo &MRI,
166168 WebAssemblyFunctionInfo &MFI) {
167169 unsigned Reg = MO.getReg();
172174 for (MachineOperand &DefMO : Def->explicit_uses()) {
173175 if (!DefMO.isReg())
174176 continue;
175 return FindStartOfTree(DefMO, MRI, MFI);
177 return findStartOfTree(DefMO, MRI, MFI);
176178 }
177179
178180 // If there were no stackified uses, we've reached the start.
185187 << MF.getName() << '\n');
186188
187189 // Disable this pass if directed to do so.
188 if (DisableWebAssemblyExplicitLocals)
190 if (WasmDisableExplicitLocals)
189191 return false;
190192
191193 bool Changed = false;
205207 break;
206208 unsigned Reg = MI.getOperand(0).getReg();
207209 assert(!MFI.isVRegStackified(Reg));
208 Reg2Local[Reg] = MI.getOperand(1).getImm();
210 Reg2Local[Reg] = static_cast(MI.getOperand(1).getImm());
209211 MI.eraseFromParent();
210212 Changed = true;
211213 }
212214
213215 // Start assigning local numbers after the last parameter.
214 unsigned CurLocal = MFI.getParams().size();
216 unsigned CurLocal = static_cast(MFI.getParams().size());
215217
216218 // Precompute the set of registers that are unused, so that we can insert
217219 // drops to their defs.
218220 BitVector UseEmpty(MRI.getNumVirtRegs());
219 for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i)
220 UseEmpty[i] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(i));
221 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I)
222 UseEmpty[I] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(I));
221223
222224 // Visit each instruction in the function.
223225 for (MachineBasicBlock &MBB : MF) {
321323 // If we see a stackified register, prepare to insert subsequent
322324 // get_locals before the start of its tree.
323325 if (MFI.isVRegStackified(OldReg)) {
324 InsertPt = FindStartOfTree(MO, MRI, MFI);
326 InsertPt = findStartOfTree(MO, MRI, MFI);
325327 continue;
326328 }
327329
360362 // Define the locals.
361363 // TODO: Sort the locals for better compression.
362364 MFI.setNumLocals(CurLocal - MFI.getParams().size());
363 for (size_t i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) {
364 unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
365 auto I = Reg2Local.find(Reg);
366 if (I == Reg2Local.end() || I->second < MFI.getParams().size())
365 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
366 unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
367 auto RL = Reg2Local.find(Reg);
368 if (RL == Reg2Local.end() || RL->second < MFI.getParams().size())
367369 continue;
368370
369 MFI.setLocal(I->second - MFI.getParams().size(),
371 MFI.setLocal(RL->second - MFI.getParams().size(),
370372 typeForRegClass(MRI.getRegClass(Reg)));
371373 Changed = true;
372374 }
5252 let TSFlags{0} = 1;
5353 let TSFlags{1} = 1;
5454 }
55 def BR_TABLE_I32_S : NI<(outs), (ins I32:$index),
55 def BR_TABLE_I32_S : NI<(outs), (ins variable_ops),
5656 [], 1,
57 "br_table \t$index", 0x0e> {
57 "br_table", 0x0e> {
5858 let TSFlags{0} = 1;
5959 let TSFlags{1} = 1;
6060 }
6464 let TSFlags{0} = 1;
6565 let TSFlags{1} = 1;
6666 }
67 def BR_TABLE_I64_S : NI<(outs), (ins I64:$index),
67 def BR_TABLE_I64_S : NI<(outs), (ins variable_ops),
6868 [], 1,
69 "br_table \t$index"> {
69 "br_table"> {
7070 let TSFlags{0} = 1;
7171 let TSFlags{1} = 1;
7272 }
5656
5757 // Defines atomic and non-atomic loads, regular and extending.
5858 multiclass WebAssemblyLoad {
59 let mayLoad = 1 in
5960 defm "": I<(outs rc:$dst),
6061 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
6162 (outs), (ins P2Align:$p2align, offset32_op:$off),
6263 [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
63 !strconcat(Name, "\t${off}, ${p2align}"), Opcode>;
64 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
6465 }
6566
6667 // Basic load.
306307
307308 // Defines atomic and non-atomic stores, regular and truncating
308309 multiclass WebAssemblyStore {
310 let mayStore = 1 in
309311 defm "" : I<(outs),
310312 (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
311313 (outs),
312314 (ins P2Align:$p2align, offset32_op:$off), [],
313315 !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
314 !strconcat(Name, "\t${off}, ${p2align}"), Opcode>;
316 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
315317 }
316318 // Basic store.
317319 // Note: WebAssembly inverts SelectionDAG's usual operand order.
469471
470472 // Grow memory.
471473 defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
472 (outs), (ins i32imm:$flags, I32:$delta),
474 (outs), (ins i32imm:$flags),
473475 [(set I32:$dst,
474476 (int_wasm_memory_grow (i32 imm:$flags),
475477 I32:$delta))],
476478 "memory.grow\t$dst, $flags, $delta",
477 "memory.grow\t$flags, $delta", 0x40>,
479 "memory.grow\t$flags", 0x40>,
478480 Requires<[HasAddr32]>;
479481 defm MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
480482 (outs), (ins i32imm:$flags),
2828 #include "llvm/Support/ErrorHandling.h"
2929 #include "llvm/Support/raw_ostream.h"
3030 using namespace llvm;
31
32 // This disables the removal of registers when lowering into MC, as required
33 // by some current tests.
34 static cl::opt WasmKeepRegisters(
35 "wasm-keep-registers", cl::Hidden,
36 cl::desc("WebAssembly: output stack registers in"
37 " instruction output for test purposes only."),
38 cl::init(false));
39
40 static unsigned regInstructionToStackInstruction(unsigned OpCode);
41 static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
3142
3243 MCSymbol *
3344 WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
234245
235246 OutMI.addOperand(MCOp);
236247 }
248
249 if (!WasmKeepRegisters)
250 removeRegisterOperands(MI, OutMI);
237251 }
252
253 static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) {
254 // Remove all uses of stackified registers to bring the instruction format
255 // into its final stack form used thruout MC, and transition opcodes to
256 // their _S variant.
257 // We do this seperate from the above code that still may need these
258 // registers for e.g. call_indirect signatures.
259 // See comments in lib/Target/WebAssembly/WebAssemblyInstrFormats.td for
260 // details.
261 // TODO: the code above creates new registers which are then removed here.
262 // That code could be slightly simplified by not doing that, though maybe
263 // it is simpler conceptually to keep the code above in "register mode"
264 // until this transition point.
265 // FIXME: we are not processing inline assembly, which contains register
266 // operands, because it is used by later target generic code.
267 if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm())
268 return;
269
270 // Transform to _S instruction.
271 auto RegOpcode = OutMI.getOpcode();
272 auto StackOpcode = regInstructionToStackInstruction(RegOpcode);
273 OutMI.setOpcode(StackOpcode);
274
275 // Remove register operands.
276 for (auto I = OutMI.getNumOperands(); I; --I) {
277 auto &MO = OutMI.getOperand(I - 1);
278 if (MO.isReg()) {
279 OutMI.erase(&MO);
280 }
281 }
282 }
283
284 static unsigned regInstructionToStackInstruction(unsigned OpCode) {
285 switch (OpCode) {
286 default:
287 // You may hit this if you add new instructions, please add them below.
288 // For most of these opcodes, this function could have been implemented
289 // as "return OpCode + 1", but since table-gen alphabetically sorts them,
290 // this cannot be guaranteed (see e.g. BR and BR_IF).
291 // The approach below is the same as what the x87 backend does.
292 // TODO(wvo): to make this code cleaner, create a custom tablegen
293 // code generator that emits the table below automatically.
294 llvm_unreachable(
295 "unknown WebAssembly instruction in Explicit Locals pass");
296 case WebAssembly::ABS_F32: return WebAssembly::ABS_F32_S;
297 case WebAssembly::ABS_F64: return WebAssembly::ABS_F64_S;
298 case WebAssembly::ADD_F32: return WebAssembly::ADD_F32_S;
299 case WebAssembly::ADD_F64: return WebAssembly::ADD_F64_S;
300 case WebAssembly::ADD_I32: return WebAssembly::ADD_I32_S;
301 case WebAssembly::ADD_I64: return WebAssembly::ADD_I64_S;
302 case WebAssembly::ADD_v16i8: return WebAssembly::ADD_v16i8_S;
303 case WebAssembly::ADD_v2f64: return WebAssembly::ADD_v2f64_S;
304 case WebAssembly::ADD_v2i64: return WebAssembly::ADD_v2i64_S;
305 case WebAssembly::ADD_v4f32: return WebAssembly::ADD_v4f32_S;
306 case WebAssembly::ADD_v4i32: return WebAssembly::ADD_v4i32_S;
307 case WebAssembly::ADD_v8i16: return WebAssembly::ADD_v8i16_S;
308 case WebAssembly::ADJCALLSTACKDOWN: return WebAssembly::ADJCALLSTACKDOWN_S;
309 case WebAssembly::ADJCALLSTACKUP: return WebAssembly::ADJCALLSTACKUP_S;
310 case WebAssembly::AND_I32: return WebAssembly::AND_I32_S;
311 case WebAssembly::AND_I64: return WebAssembly::AND_I64_S;
312 case WebAssembly::ARGUMENT_EXCEPT_REF: return WebAssembly::ARGUMENT_EXCEPT_REF_S;
313 case WebAssembly::ARGUMENT_F32: return WebAssembly::ARGUMENT_F32_S;
314 case WebAssembly::ARGUMENT_F64: return WebAssembly::ARGUMENT_F64_S;
315 case WebAssembly::ARGUMENT_I32: return WebAssembly::ARGUMENT_I32_S;
316 case WebAssembly::ARGUMENT_I64: return WebAssembly::ARGUMENT_I64_S;
317 case WebAssembly::ARGUMENT_v16i8: return WebAssembly::ARGUMENT_v16i8_S;
318 case WebAssembly::ARGUMENT_v4f32: return WebAssembly::ARGUMENT_v4f32_S;
319 case WebAssembly::ARGUMENT_v4i32: return WebAssembly::ARGUMENT_v4i32_S;
320 case WebAssembly::ARGUMENT_v8i16: return WebAssembly::ARGUMENT_v8i16_S;
321 case WebAssembly::ARGUMENT_v2f64: return WebAssembly::ARGUMENT_v2f64_S;
322 case WebAssembly::ARGUMENT_v2i64: return WebAssembly::ARGUMENT_v2i64_S;
323 case WebAssembly::ATOMIC_LOAD16_U_I32: return WebAssembly::ATOMIC_LOAD16_U_I32_S;
324 case WebAssembly::ATOMIC_LOAD16_U_I64: return WebAssembly::ATOMIC_LOAD16_U_I64_S;
325 case WebAssembly::ATOMIC_LOAD32_U_I64: return WebAssembly::ATOMIC_LOAD32_U_I64_S;
326 case WebAssembly::ATOMIC_LOAD8_U_I32: return WebAssembly::ATOMIC_LOAD8_U_I32_S;
327 case WebAssembly::ATOMIC_LOAD8_U_I64: return WebAssembly::ATOMIC_LOAD8_U_I64_S;
328 case WebAssembly::ATOMIC_LOAD_I32: return WebAssembly::ATOMIC_LOAD_I32_S;
329 case WebAssembly::ATOMIC_LOAD_I64: return WebAssembly::ATOMIC_LOAD_I64_S;
330 case WebAssembly::ATOMIC_STORE16_I32: return WebAssembly::ATOMIC_STORE16_I32_S;
331 case WebAssembly::ATOMIC_STORE16_I64: return WebAssembly::ATOMIC_STORE16_I64_S;
332 case WebAssembly::ATOMIC_STORE32_I64: return WebAssembly::ATOMIC_STORE32_I64_S;
333 case WebAssembly::ATOMIC_STORE8_I32: return WebAssembly::ATOMIC_STORE8_I32_S;
334 case WebAssembly::ATOMIC_STORE8_I64: return WebAssembly::ATOMIC_STORE8_I64_S;
335 case WebAssembly::ATOMIC_STORE_I32: return WebAssembly::ATOMIC_STORE_I32_S;
336 case WebAssembly::ATOMIC_STORE_I64: return WebAssembly::ATOMIC_STORE_I64_S;
337 case WebAssembly::BLOCK: return WebAssembly::BLOCK_S;
338 case WebAssembly::BR: return WebAssembly::BR_S;
339 case WebAssembly::BR_IF: return WebAssembly::BR_IF_S;
340 case WebAssembly::BR_TABLE_I32: return WebAssembly::BR_TABLE_I32_S;
341 case WebAssembly::BR_TABLE_I64: return WebAssembly::BR_TABLE_I64_S;
342 case WebAssembly::BR_UNLESS: return WebAssembly::BR_UNLESS_S;
343 case WebAssembly::CALL_EXCEPT_REF: return WebAssembly::CALL_EXCEPT_REF_S;
344 case WebAssembly::CALL_F32: return WebAssembly::CALL_F32_S;
345 case WebAssembly::CALL_F64: return WebAssembly::CALL_F64_S;
346 case WebAssembly::CALL_I32: return WebAssembly::CALL_I32_S;
347 case WebAssembly::CALL_I64: return WebAssembly::CALL_I64_S;
348 case WebAssembly::CALL_INDIRECT_EXCEPT_REF: return WebAssembly::CALL_INDIRECT_EXCEPT_REF_S;
349 case WebAssembly::CALL_INDIRECT_F32: return WebAssembly::CALL_INDIRECT_F32_S;
350 case WebAssembly::CALL_INDIRECT_F64: return WebAssembly::CALL_INDIRECT_F64_S;
351 case WebAssembly::CALL_INDIRECT_I32: return WebAssembly::CALL_INDIRECT_I32_S;
352 case WebAssembly::CALL_INDIRECT_I64: return WebAssembly::CALL_INDIRECT_I64_S;
353 case WebAssembly::CALL_INDIRECT_VOID: return WebAssembly::CALL_INDIRECT_VOID_S;
354 case WebAssembly::CALL_INDIRECT_v16i8: return WebAssembly::CALL_INDIRECT_v16i8_S;
355 case WebAssembly::CALL_INDIRECT_v4f32: return WebAssembly::CALL_INDIRECT_v4f32_S;
356 case WebAssembly::CALL_INDIRECT_v4i32: return WebAssembly::CALL_INDIRECT_v4i32_S;
357 case WebAssembly::CALL_INDIRECT_v8i16: return WebAssembly::CALL_INDIRECT_v8i16_S;
358 case WebAssembly::CALL_VOID: return WebAssembly::CALL_VOID_S;
359 case WebAssembly::CALL_v16i8: return WebAssembly::CALL_v16i8_S;
360 case WebAssembly::CALL_v4f32: return WebAssembly::CALL_v4f32_S;
361 case WebAssembly::CALL_v4i32: return WebAssembly::CALL_v4i32_S;
362 case WebAssembly::CALL_v8i16: return WebAssembly::CALL_v8i16_S;
363 case WebAssembly::CATCHRET: return WebAssembly::CATCHRET_S;
364 case WebAssembly::CATCH_ALL: return WebAssembly::CATCH_ALL_S;
365 case WebAssembly::CATCH_I32: return WebAssembly::CATCH_I32_S;
366 case WebAssembly::CATCH_I64: return WebAssembly::CATCH_I64_S;
367 case WebAssembly::CEIL_F32: return WebAssembly::CEIL_F32_S;
368 case WebAssembly::CEIL_F64: return WebAssembly::CEIL_F64_S;
369 case WebAssembly::CLEANUPRET: return WebAssembly::CLEANUPRET_S;
370 case WebAssembly::CLZ_I32: return WebAssembly::CLZ_I32_S;
371 case WebAssembly::CLZ_I64: return WebAssembly::CLZ_I64_S;
372 case WebAssembly::CONST_F32: return WebAssembly::CONST_F32_S;
373 case WebAssembly::CONST_F64: return WebAssembly::CONST_F64_S;
374 case WebAssembly::CONST_I32: return WebAssembly::CONST_I32_S;
375 case WebAssembly::CONST_I64: return WebAssembly::CONST_I64_S;
376 case WebAssembly::COPYSIGN_F32: return WebAssembly::COPYSIGN_F32_S;
377 case WebAssembly::COPYSIGN_F64: return WebAssembly::COPYSIGN_F64_S;
378 case WebAssembly::COPY_EXCEPT_REF: return WebAssembly::COPY_EXCEPT_REF_S;
379 case WebAssembly::COPY_F32: return WebAssembly::COPY_F32_S;
380 case WebAssembly::COPY_F64: return WebAssembly::COPY_F64_S;
381 case WebAssembly::COPY_I32: return WebAssembly::COPY_I32_S;
382 case WebAssembly::COPY_I64: return WebAssembly::COPY_I64_S;
383 case WebAssembly::COPY_V128: return WebAssembly::COPY_V128_S;
384 case WebAssembly::CTZ_I32: return WebAssembly::CTZ_I32_S;
385 case WebAssembly::CTZ_I64: return WebAssembly::CTZ_I64_S;
386 case WebAssembly::CURRENT_MEMORY_I32: return WebAssembly::CURRENT_MEMORY_I32_S;
387 case WebAssembly::DIV_F32: return WebAssembly::DIV_F32_S;
388 case WebAssembly::DIV_F64: return WebAssembly::DIV_F64_S;
389 case WebAssembly::DIV_S_I32: return WebAssembly::DIV_S_I32_S;
390 case WebAssembly::DIV_S_I64: return WebAssembly::DIV_S_I64_S;
391 case WebAssembly::DIV_U_I32: return WebAssembly::DIV_U_I32_S;
392 case WebAssembly::DIV_U_I64: return WebAssembly::DIV_U_I64_S;
393 case WebAssembly::DROP_EXCEPT_REF: return WebAssembly::DROP_EXCEPT_REF_S;
394 case WebAssembly::DROP_F32: return WebAssembly::DROP_F32_S;
395 case WebAssembly::DROP_F64: return WebAssembly::DROP_F64_S;
396 case WebAssembly::DROP_I32: return WebAssembly::DROP_I32_S;
397 case WebAssembly::DROP_I64: return WebAssembly::DROP_I64_S;
398 case WebAssembly::DROP_V128: return WebAssembly::DROP_V128_S;
399 case WebAssembly::END_BLOCK: return WebAssembly::END_BLOCK_S;
400 case WebAssembly::END_FUNCTION: return WebAssembly::END_FUNCTION_S;
401 case WebAssembly::END_LOOP: return WebAssembly::END_LOOP_S;
402 case WebAssembly::END_TRY: return WebAssembly::END_TRY_S;
403 case WebAssembly::EQZ_I32: return WebAssembly::EQZ_I32_S;
404 case WebAssembly::EQZ_I64: return WebAssembly::EQZ_I64_S;
405 case WebAssembly::EQ_F32: return WebAssembly::EQ_F32_S;
406 case WebAssembly::EQ_F64: return WebAssembly::EQ_F64_S;
407 case WebAssembly::EQ_I32: return WebAssembly::EQ_I32_S;
408 case WebAssembly::EQ_I64: return WebAssembly::EQ_I64_S;
409 case WebAssembly::F32_CONVERT_S_I32: return WebAssembly::F32_CONVERT_S_I32_S;
410 case WebAssembly::F32_CONVERT_S_I64: return WebAssembly::F32_CONVERT_S_I64_S;
411 case WebAssembly::F32_CONVERT_U_I32: return WebAssembly::F32_CONVERT_U_I32_S;
412 case WebAssembly::F32_CONVERT_U_I64: return WebAssembly::F32_CONVERT_U_I64_S;
413 case WebAssembly::F32_DEMOTE_F64: return WebAssembly::F32_DEMOTE_F64_S;
414 case WebAssembly::F32_REINTERPRET_I32: return WebAssembly::F32_REINTERPRET_I32_S;
415 case WebAssembly::F64_CONVERT_S_I32: return WebAssembly::F64_CONVERT_S_I32_S;
416 case WebAssembly::F64_CONVERT_S_I64: return WebAssembly::F64_CONVERT_S_I64_S;
417 case WebAssembly::F64_CONVERT_U_I32: return WebAssembly::F64_CONVERT_U_I32_S;
418 case WebAssembly::F64_CONVERT_U_I64: return WebAssembly::F64_CONVERT_U_I64_S;
419 case WebAssembly::F64_PROMOTE_F32: return WebAssembly::F64_PROMOTE_F32_S;
420 case WebAssembly::F64_REINTERPRET_I64: return WebAssembly::F64_REINTERPRET_I64_S;
421 case WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF: return WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF_S;
422 case WebAssembly::FALLTHROUGH_RETURN_F32: return WebAssembly::FALLTHROUGH_RETURN_F32_S;
423 case WebAssembly::FALLTHROUGH_RETURN_F64: return WebAssembly::FALLTHROUGH_RETURN_F64_S;
424 case WebAssembly::FALLTHROUGH_RETURN_I32: return WebAssembly::FALLTHROUGH_RETURN_I32_S;
425 case WebAssembly::FALLTHROUGH_RETURN_I64: return WebAssembly::FALLTHROUGH_RETURN_I64_S;
426 case WebAssembly::FALLTHROUGH_RETURN_VOID: return WebAssembly::FALLTHROUGH_RETURN_VOID_S;
427 case WebAssembly::FALLTHROUGH_RETURN_v16i8: return WebAssembly::FALLTHROUGH_RETURN_v16i8_S;
428 case WebAssembly::FALLTHROUGH_RETURN_v4f32: return WebAssembly::FALLTHROUGH_RETURN_v4f32_S;
429 case WebAssembly::FALLTHROUGH_RETURN_v4i32: return WebAssembly::FALLTHROUGH_RETURN_v4i32_S;
430 case WebAssembly::FALLTHROUGH_RETURN_v8i16: return WebAssembly::FALLTHROUGH_RETURN_v8i16_S;
431 case WebAssembly::FALLTHROUGH_RETURN_v2f64: return WebAssembly::FALLTHROUGH_RETURN_v2f64_S;
432 case WebAssembly::FALLTHROUGH_RETURN_v2i64: return WebAssembly::FALLTHROUGH_RETURN_v2i64_S;
433 case WebAssembly::FLOOR_F32: return WebAssembly::FLOOR_F32_S;
434 case WebAssembly::FLOOR_F64: return WebAssembly::FLOOR_F64_S;
435 case WebAssembly::FP_TO_SINT_I32_F32: return WebAssembly::FP_TO_SINT_I32_F32_S;
436 case WebAssembly::FP_TO_SINT_I32_F64: return WebAssembly::FP_TO_SINT_I32_F64_S;
437 case WebAssembly::FP_TO_SINT_I64_F32: return WebAssembly::FP_TO_SINT_I64_F32_S;
438 case WebAssembly::FP_TO_SINT_I64_F64: return WebAssembly::FP_TO_SINT_I64_F64_S;
439 case WebAssembly::FP_TO_UINT_I32_F32: return WebAssembly::FP_TO_UINT_I32_F32_S;
440 case WebAssembly::FP_TO_UINT_I32_F64: return WebAssembly::FP_TO_UINT_I32_F64_S;
441 case WebAssembly::FP_TO_UINT_I64_F32: return WebAssembly::FP_TO_UINT_I64_F32_S;
442 case WebAssembly::FP_TO_UINT_I64_F64: return WebAssembly::FP_TO_UINT_I64_F64_S;
443 case WebAssembly::GET_GLOBAL_EXCEPT_REF: return WebAssembly::GET_GLOBAL_EXCEPT_REF_S;
444 case WebAssembly::GET_GLOBAL_F32: return WebAssembly::GET_GLOBAL_F32_S;
445 case WebAssembly::GET_GLOBAL_F64: return WebAssembly::GET_GLOBAL_F64_S;
446 case WebAssembly::GET_GLOBAL_I32: return WebAssembly::GET_GLOBAL_I32_S;
447 case WebAssembly::GET_GLOBAL_I64: return WebAssembly::GET_GLOBAL_I64_S;
448 case WebAssembly::GET_GLOBAL_V128: return WebAssembly::GET_GLOBAL_V128_S;
449 case WebAssembly::GET_LOCAL_EXCEPT_REF: return WebAssembly::GET_LOCAL_EXCEPT_REF_S;
450 case WebAssembly::GET_LOCAL_F32: return WebAssembly::GET_LOCAL_F32_S;
451 case WebAssembly::GET_LOCAL_F64: return WebAssembly::GET_LOCAL_F64_S;
452 case WebAssembly::GET_LOCAL_I32: return WebAssembly::GET_LOCAL_I32_S;
453 case WebAssembly::GET_LOCAL_I64: return WebAssembly::GET_LOCAL_I64_S;
454 case WebAssembly::GET_LOCAL_V128: return WebAssembly::GET_LOCAL_V128_S;
455 case WebAssembly::GE_F32: return WebAssembly::GE_F32_S;
456 case WebAssembly::GE_F64: return WebAssembly::GE_F64_S;
457 case WebAssembly::GE_S_I32: return WebAssembly::GE_S_I32_S;
458 case WebAssembly::GE_S_I64: return WebAssembly::GE_S_I64_S;
459 case WebAssembly::GE_U_I32: return WebAssembly::GE_U_I32_S;
460 case WebAssembly::GE_U_I64: return WebAssembly::GE_U_I64_S;
461 case WebAssembly::GROW_MEMORY_I32: return WebAssembly::GROW_MEMORY_I32_S;
462 case WebAssembly::GT_F32: return WebAssembly::GT_F32_S;
463 case WebAssembly::GT_F64: return WebAssembly::GT_F64_S;
464 case WebAssembly::GT_S_I32: return WebAssembly::GT_S_I32_S;
465 case WebAssembly::GT_S_I64: return WebAssembly::GT_S_I64_S;
466 case WebAssembly::GT_U_I32: return WebAssembly::GT_U_I32_S;
467 case WebAssembly::GT_U_I64: return WebAssembly::GT_U_I64_S;
468 case WebAssembly::I32_EXTEND16_S_I32: return WebAssembly::I32_EXTEND16_S_I32_S;
469 case WebAssembly::I32_EXTEND8_S_I32: return WebAssembly::I32_EXTEND8_S_I32_S;
470 case WebAssembly::I32_REINTERPRET_F32: return WebAssembly::I32_REINTERPRET_F32_S;
471 case WebAssembly::I32_TRUNC_S_F32: return WebAssembly::I32_TRUNC_S_F32_S;
472 case WebAssembly::I32_TRUNC_S_F64: return WebAssembly::I32_TRUNC_S_F64_S;
473 case WebAssembly::I32_TRUNC_S_SAT_F32: return WebAssembly::I32_TRUNC_S_SAT_F32_S;
474 case WebAssembly::I32_TRUNC_S_SAT_F64: return WebAssembly::I32_TRUNC_S_SAT_F64_S;
475 case WebAssembly::I32_TRUNC_U_F32: return WebAssembly::I32_TRUNC_U_F32_S;
476 case WebAssembly::I32_TRUNC_U_F64: return WebAssembly::I32_TRUNC_U_F64_S;
477 case WebAssembly::I32_TRUNC_U_SAT_F32: return WebAssembly::I32_TRUNC_U_SAT_F32_S;
478 case WebAssembly::I32_TRUNC_U_SAT_F64: return WebAssembly::I32_TRUNC_U_SAT_F64_S;
479 case WebAssembly::I32_WRAP_I64: return WebAssembly::I32_WRAP_I64_S;
480 case WebAssembly::I64_EXTEND16_S_I64: return WebAssembly::I64_EXTEND16_S_I64_S;
481 case WebAssembly::I64_EXTEND32_S_I64: return WebAssembly::I64_EXTEND32_S_I64_S;
482 case WebAssembly::I64_EXTEND8_S_I64: return WebAssembly::I64_EXTEND8_S_I64_S;
483 case WebAssembly::I64_EXTEND_S_I32: return WebAssembly::I64_EXTEND_S_I32_S;
484 case WebAssembly::I64_EXTEND_U_I32: return WebAssembly::I64_EXTEND_U_I32_S;
485 case WebAssembly::I64_REINTERPRET_F64: return WebAssembly::I64_REINTERPRET_F64_S;
486 case WebAssembly::I64_TRUNC_S_F32: return WebAssembly::I64_TRUNC_S_F32_S;
487 case WebAssembly::I64_TRUNC_S_F64: return WebAssembly::I64_TRUNC_S_F64_S;
488 case WebAssembly::I64_TRUNC_S_SAT_F32: return WebAssembly::I64_TRUNC_S_SAT_F32_S;
489 case WebAssembly::I64_TRUNC_S_SAT_F64: return WebAssembly::I64_TRUNC_S_SAT_F64_S;
490 case WebAssembly::I64_TRUNC_U_F32: return WebAssembly::I64_TRUNC_U_F32_S;
491 case WebAssembly::I64_TRUNC_U_F64: return WebAssembly::I64_TRUNC_U_F64_S;
492 case WebAssembly::I64_TRUNC_U_SAT_F32: return WebAssembly::I64_TRUNC_U_SAT_F32_S;
493 case WebAssembly::I64_TRUNC_U_SAT_F64: return WebAssembly::I64_TRUNC_U_SAT_F64_S;
494 case WebAssembly::LE_F32: return WebAssembly::LE_F32_S;
495 case WebAssembly::LE_F64: return WebAssembly::LE_F64_S;
496 case WebAssembly::LE_S_I32: return WebAssembly::LE_S_I32_S;
497 case WebAssembly::LE_S_I64: return WebAssembly::LE_S_I64_S;
498 case WebAssembly::LE_U_I32: return WebAssembly::LE_U_I32_S;
499 case WebAssembly::LE_U_I64: return WebAssembly::LE_U_I64_S;
500 case WebAssembly::LOAD16_S_I32: return WebAssembly::LOAD16_S_I32_S;
501 case WebAssembly::LOAD16_S_I64: return WebAssembly::LOAD16_S_I64_S;
502 case WebAssembly::LOAD16_U_I32: return WebAssembly::LOAD16_U_I32_S;
503 case WebAssembly::LOAD16_U_I64: return WebAssembly::LOAD16_U_I64_S;
504 case WebAssembly::LOAD32_S_I64: return WebAssembly::LOAD32_S_I64_S;
505 case WebAssembly::LOAD32_U_I64: return WebAssembly::LOAD32_U_I64_S;
506 case WebAssembly::LOAD8_S_I32: return WebAssembly::LOAD8_S_I32_S;
507 case WebAssembly::LOAD8_S_I64: return WebAssembly::LOAD8_S_I64_S;
508 case WebAssembly::LOAD8_U_I32: return WebAssembly::LOAD8_U_I32_S;
509 case WebAssembly::LOAD8_U_I64: return WebAssembly::LOAD8_U_I64_S;
510 case WebAssembly::LOAD_F32: return WebAssembly::LOAD_F32_S;
511 case WebAssembly::LOAD_F64: return WebAssembly::LOAD_F64_S;
512 case WebAssembly::LOAD_I32: return WebAssembly::LOAD_I32_S;
513 case WebAssembly::LOAD_I64: return WebAssembly::LOAD_I64_S;
514 case WebAssembly::LOOP: return WebAssembly::LOOP_S;
515 case WebAssembly::LT_F32: return WebAssembly::LT_F32_S;
516 case WebAssembly::LT_F64: return WebAssembly::LT_F64_S;
517 case WebAssembly::LT_S_I32: return WebAssembly::LT_S_I32_S;
518 case WebAssembly::LT_S_I64: return WebAssembly::LT_S_I64_S;
519 case WebAssembly::LT_U_I32: return WebAssembly::LT_U_I32_S;
520 case WebAssembly::LT_U_I64: return WebAssembly::LT_U_I64_S;
521 case WebAssembly::MAX_F32: return WebAssembly::MAX_F32_S;
522 case WebAssembly::MAX_F64: return WebAssembly::MAX_F64_S;
523 case WebAssembly::MEMORY_GROW_I32: return WebAssembly::MEMORY_GROW_I32_S;
524 case WebAssembly::MEMORY_SIZE_I32: return WebAssembly::MEMORY_SIZE_I32_S;
525 case WebAssembly::MEM_GROW_I32: return WebAssembly::MEM_GROW_I32_S;
526 case WebAssembly::MEM_SIZE_I32: return WebAssembly::MEM_SIZE_I32_S;
527 case WebAssembly::MIN_F32: return WebAssembly::MIN_F32_S;
528 case WebAssembly::MIN_F64: return WebAssembly::MIN_F64_S;
529 case WebAssembly::MUL_F32: return WebAssembly::MUL_F32_S;
530 case WebAssembly::MUL_F64: return WebAssembly::MUL_F64_S;
531 case WebAssembly::MUL_I32: return WebAssembly::MUL_I32_S;
532 case WebAssembly::MUL_I64: return WebAssembly::MUL_I64_S;
533 case WebAssembly::MUL_v16i8: return WebAssembly::MUL_v16i8_S;
534 case WebAssembly::MUL_v2f64: return WebAssembly::MUL_v2f64_S;
535 case WebAssembly::MUL_v4f32: return WebAssembly::MUL_v4f32_S;
536 case WebAssembly::MUL_v4i32: return WebAssembly::MUL_v4i32_S;
537 case WebAssembly::MUL_v8i16: return WebAssembly::MUL_v8i16_S;
538 case WebAssembly::NEAREST_F32: return WebAssembly::NEAREST_F32_S;
539 case WebAssembly::NEAREST_F64: return WebAssembly::NEAREST_F64_S;
540 case WebAssembly::NEG_F32: return WebAssembly::NEG_F32_S;
541 case WebAssembly::NEG_F64: return WebAssembly::NEG_F64_S;
542 case WebAssembly::NE_F32: return WebAssembly::NE_F32_S;
543 case WebAssembly::NE_F64: return WebAssembly::NE_F64_S;
544 case WebAssembly::NE_I32: return WebAssembly::NE_I32_S;
545 case WebAssembly::NE_I64: return WebAssembly::NE_I64_S;
546 case WebAssembly::NOP: return WebAssembly::NOP_S;
547 case WebAssembly::OR_I32: return WebAssembly::OR_I32_S;
548 case WebAssembly::OR_I64: return WebAssembly::OR_I64_S;
549 case WebAssembly::PCALL_INDIRECT_EXCEPT_REF: return WebAssembly::PCALL_INDIRECT_EXCEPT_REF_S;
550 case WebAssembly::PCALL_INDIRECT_F32: return WebAssembly::PCALL_INDIRECT_F32_S;
551 case WebAssembly::PCALL_INDIRECT_F64: return WebAssembly::PCALL_INDIRECT_F64_S;
552 case WebAssembly::PCALL_INDIRECT_I32: return WebAssembly::PCALL_INDIRECT_I32_S;
553 case WebAssembly::PCALL_INDIRECT_I64: return WebAssembly::PCALL_INDIRECT_I64_S;
554 case WebAssembly::PCALL_INDIRECT_VOID: return WebAssembly::PCALL_INDIRECT_VOID_S;
555 case WebAssembly::PCALL_INDIRECT_v16i8: return WebAssembly::PCALL_INDIRECT_v16i8_S;
556 case WebAssembly::PCALL_INDIRECT_v4f32: return WebAssembly::PCALL_INDIRECT_v4f32_S;
557 case WebAssembly::PCALL_INDIRECT_v4i32: return WebAssembly::PCALL_INDIRECT_v4i32_S;
558 case WebAssembly::PCALL_INDIRECT_v8i16: return WebAssembly::PCALL_INDIRECT_v8i16_S;
559 case WebAssembly::POPCNT_I32: return WebAssembly::POPCNT_I32_S;
560 case WebAssembly::POPCNT_I64: return WebAssembly::POPCNT_I64_S;
561 case WebAssembly::REM_S_I32: return WebAssembly::REM_S_I32_S;
562 case WebAssembly::REM_S_I64: return WebAssembly::REM_S_I64_S;
563 case WebAssembly::REM_U_I32: return WebAssembly::REM_U_I32_S;
564 case WebAssembly::REM_U_I64: return WebAssembly::REM_U_I64_S;
565 case WebAssembly::RETHROW: return WebAssembly::RETHROW_S;
566 case WebAssembly::RETHROW_TO_CALLER: return WebAssembly::RETHROW_TO_CALLER_S;
567 case WebAssembly::RETURN_EXCEPT_REF: return WebAssembly::RETURN_EXCEPT_REF_S;
568 case WebAssembly::RETURN_F32: return WebAssembly::RETURN_F32_S;
569 case WebAssembly::RETURN_F64: return WebAssembly::RETURN_F64_S;
570 case WebAssembly::RETURN_I32: return WebAssembly::RETURN_I32_S;
571 case WebAssembly::RETURN_I64: return WebAssembly::RETURN_I64_S;
572 case WebAssembly::RETURN_VOID: return WebAssembly::RETURN_VOID_S;
573 case WebAssembly::RETURN_v16i8: return WebAssembly::RETURN_v16i8_S;
574 case WebAssembly::RETURN_v4f32: return WebAssembly::RETURN_v4f32_S;
575 case WebAssembly::RETURN_v4i32: return WebAssembly::RETURN_v4i32_S;
576 case WebAssembly::RETURN_v8i16: return WebAssembly::RETURN_v8i16_S;
577 case WebAssembly::ROTL_I32: return WebAssembly::ROTL_I32_S;
578 case WebAssembly::ROTL_I64: return WebAssembly::ROTL_I64_S;
579 case WebAssembly::ROTR_I32: return WebAssembly::ROTR_I32_S;
580 case WebAssembly::ROTR_I64: return WebAssembly::ROTR_I64_S;
581 case WebAssembly::SELECT_EXCEPT_REF: return WebAssembly::SELECT_EXCEPT_REF_S;
582 case WebAssembly::SELECT_F32: return WebAssembly::SELECT_F32_S;
583 case WebAssembly::SELECT_F64: return WebAssembly::SELECT_F64_S;
584 case WebAssembly::SELECT_I32: return WebAssembly::SELECT_I32_S;
585 case WebAssembly::SELECT_I64: return WebAssembly::SELECT_I64_S;
586 case WebAssembly::SET_GLOBAL_EXCEPT_REF: return WebAssembly::SET_GLOBAL_EXCEPT_REF_S;
587 case WebAssembly::SET_GLOBAL_F32: return WebAssembly::SET_GLOBAL_F32_S;
588 case WebAssembly::SET_GLOBAL_F64: return WebAssembly::SET_GLOBAL_F64_S;
589 case WebAssembly::SET_GLOBAL_I32: return WebAssembly::SET_GLOBAL_I32_S;
590 case WebAssembly::SET_GLOBAL_I64: return WebAssembly::SET_GLOBAL_I64_S;
591 case WebAssembly::SET_GLOBAL_V128: return WebAssembly::SET_GLOBAL_V128_S;
592 case WebAssembly::SET_LOCAL_EXCEPT_REF: return WebAssembly::SET_LOCAL_EXCEPT_REF_S;
593 case WebAssembly::SET_LOCAL_F32: return WebAssembly::SET_LOCAL_F32_S;
594 case WebAssembly::SET_LOCAL_F64: return WebAssembly::SET_LOCAL_F64_S;
595 case WebAssembly::SET_LOCAL_I32: return WebAssembly::SET_LOCAL_I32_S;
596 case WebAssembly::SET_LOCAL_I64: return WebAssembly::SET_LOCAL_I64_S;
597 case WebAssembly::SET_LOCAL_V128: return WebAssembly::SET_LOCAL_V128_S;
598 case WebAssembly::SHL_I32: return WebAssembly::SHL_I32_S;
599 case WebAssembly::SHL_I64: return WebAssembly::SHL_I64_S;
600 case WebAssembly::SHR_S_I32: return WebAssembly::SHR_S_I32_S;
601 case WebAssembly::SHR_S_I64: return WebAssembly::SHR_S_I64_S;
602 case WebAssembly::SHR_U_I32: return WebAssembly::SHR_U_I32_S;
603 case WebAssembly::SHR_U_I64: return WebAssembly::SHR_U_I64_S;
604 case WebAssembly::SQRT_F32: return WebAssembly::SQRT_F32_S;
605 case WebAssembly::SQRT_F64: return WebAssembly::SQRT_F64_S;
606 case WebAssembly::STORE16_I32: return WebAssembly::STORE16_I32_S;
607 case WebAssembly::STORE16_I64: return WebAssembly::STORE16_I64_S;
608 case WebAssembly::STORE32_I64: return WebAssembly::STORE32_I64_S;
609 case WebAssembly::STORE8_I32: return WebAssembly::STORE8_I32_S;
610 case WebAssembly::STORE8_I64: return WebAssembly::STORE8_I64_S;
611 case WebAssembly::STORE_F32: return WebAssembly::STORE_F32_S;
612 case WebAssembly::STORE_F64: return WebAssembly::STORE_F64_S;
613 case WebAssembly::STORE_I32: return WebAssembly::STORE_I32_S;
614 case WebAssembly::STORE_I64: return WebAssembly::STORE_I64_S;
615 case WebAssembly::SUB_F32: return WebAssembly::SUB_F32_S;
616 case WebAssembly::SUB_F64: return WebAssembly::SUB_F64_S;
617 case WebAssembly::SUB_I32: return WebAssembly::SUB_I32_S;
618 case WebAssembly::SUB_I64: return WebAssembly::SUB_I64_S;
619 case WebAssembly::SUB_v16i8: return WebAssembly::SUB_v16i8_S;
620 case WebAssembly::SUB_v2f64: return WebAssembly::SUB_v2f64_S;
621 case WebAssembly::SUB_v2i64: return WebAssembly::SUB_v2i64_S;
622 case WebAssembly::SUB_v4f32: return WebAssembly::SUB_v4f32_S;
623 case WebAssembly::SUB_v4i32: return WebAssembly::SUB_v4i32_S;
624 case WebAssembly::SUB_v8i16: return WebAssembly::SUB_v8i16_S;
625 case WebAssembly::TEE_EXCEPT_REF: return WebAssembly::TEE_EXCEPT_REF_S;
626 case WebAssembly::TEE_F32: return WebAssembly::TEE_F32_S;
627 case WebAssembly::TEE_F64: return WebAssembly::TEE_F64_S;
628 case WebAssembly::TEE_I32: return WebAssembly::TEE_I32_S;
629 case WebAssembly::TEE_I64: return WebAssembly::TEE_I64_S;
630 case WebAssembly::TEE_LOCAL_EXCEPT_REF: return WebAssembly::TEE_LOCAL_EXCEPT_REF_S;
631 case WebAssembly::TEE_LOCAL_F32: return WebAssembly::TEE_LOCAL_F32_S;
632 case WebAssembly::TEE_LOCAL_F64: return WebAssembly::TEE_LOCAL_F64_S;
633 case WebAssembly::TEE_LOCAL_I32: return WebAssembly::TEE_LOCAL_I32_S;
634 case WebAssembly::TEE_LOCAL_I64: return WebAssembly::TEE_LOCAL_I64_S;
635 case WebAssembly::TEE_LOCAL_V128: return WebAssembly::TEE_LOCAL_V128_S;
636 case WebAssembly::TEE_V128: return WebAssembly::TEE_V128_S;
637 case WebAssembly::THROW_I32: return WebAssembly::THROW_I32_S;
638 case WebAssembly::THROW_I64: return WebAssembly::THROW_I64_S;
639 case WebAssembly::TRUNC_F32: return WebAssembly::TRUNC_F32_S;
640 case WebAssembly::TRUNC_F64: return WebAssembly::TRUNC_F64_S;
641 case WebAssembly::TRY: return WebAssembly::TRY_S;
642 case WebAssembly::UNREACHABLE: return WebAssembly::UNREACHABLE_S;
643 case WebAssembly::XOR_I32: return WebAssembly::XOR_I32_S;
644 case WebAssembly::XOR_I64: return WebAssembly::XOR_I64_S;
645 }
646 }
2727 bool WebAssembly::isArgument(const MachineInstr &MI) {
2828 switch (MI.getOpcode()) {
2929 case WebAssembly::ARGUMENT_I32:
30 case WebAssembly::ARGUMENT_I32_S:
3031 case WebAssembly::ARGUMENT_I64:
32 case WebAssembly::ARGUMENT_I64_S:
3133 case WebAssembly::ARGUMENT_F32:
34 case WebAssembly::ARGUMENT_F32_S:
3235 case WebAssembly::ARGUMENT_F64:
36 case WebAssembly::ARGUMENT_F64_S:
3337 case WebAssembly::ARGUMENT_v16i8:
38 case WebAssembly::ARGUMENT_v16i8_S:
3439 case WebAssembly::ARGUMENT_v8i16:
40 case WebAssembly::ARGUMENT_v8i16_S:
3541 case WebAssembly::ARGUMENT_v4i32:
42 case WebAssembly::ARGUMENT_v4i32_S:
3643 case WebAssembly::ARGUMENT_v2i64:
44 case WebAssembly::ARGUMENT_v2i64_S:
3745 case WebAssembly::ARGUMENT_v4f32:
46 case WebAssembly::ARGUMENT_v4f32_S:
3847 case WebAssembly::ARGUMENT_v2f64:
48 case WebAssembly::ARGUMENT_v2f64_S:
3949 return true;
4050 default:
4151 return false;
4555 bool WebAssembly::isCopy(const MachineInstr &MI) {
4656 switch (MI.getOpcode()) {
4757 case WebAssembly::COPY_I32:
58 case WebAssembly::COPY_I32_S:
4859 case WebAssembly::COPY_I64:
60 case WebAssembly::COPY_I64_S:
4961 case WebAssembly::COPY_F32:
62 case WebAssembly::COPY_F32_S:
5063 case WebAssembly::COPY_F64:
64 case WebAssembly::COPY_F64_S:
5165 return true;
5266 default:
5367 return false;
5771 bool WebAssembly::isTee(const MachineInstr &MI) {
5872 switch (MI.getOpcode()) {
5973 case WebAssembly::TEE_I32:
74 case WebAssembly::TEE_I32_S:
6075 case WebAssembly::TEE_I64:
76 case WebAssembly::TEE_I64_S:
6177 case WebAssembly::TEE_F32:
78 case WebAssembly::TEE_F32_S:
6279 case WebAssembly::TEE_F64:
80 case WebAssembly::TEE_F64_S:
6381 return true;
6482 default:
6583 return false;
82100 bool WebAssembly::isCallDirect(const MachineInstr &MI) {
83101 switch (MI.getOpcode()) {
84102 case WebAssembly::CALL_VOID:
103 case WebAssembly::CALL_VOID_S:
85104 case WebAssembly::CALL_I32:
105 case WebAssembly::CALL_I32_S:
86106 case WebAssembly::CALL_I64:
107 case WebAssembly::CALL_I64_S:
87108 case WebAssembly::CALL_F32:
109 case WebAssembly::CALL_F32_S:
88110 case WebAssembly::CALL_F64:
111 case WebAssembly::CALL_F64_S:
89112 case WebAssembly::CALL_v16i8:
113 case WebAssembly::CALL_v16i8_S:
90114 case WebAssembly::CALL_v8i16:
115 case WebAssembly::CALL_v8i16_S:
91116 case WebAssembly::CALL_v4i32:
117 case WebAssembly::CALL_v4i32_S:
92118 case WebAssembly::CALL_v2i64:
119 case WebAssembly::CALL_v2i64_S:
93120 case WebAssembly::CALL_v4f32:
121 case WebAssembly::CALL_v4f32_S:
94122 case WebAssembly::CALL_v2f64:
123 case WebAssembly::CALL_v2f64_S:
95124 case WebAssembly::CALL_EXCEPT_REF:
125 case WebAssembly::CALL_EXCEPT_REF_S:
96126 return true;
97127 default:
98128 return false;
102132 bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
103133 switch (MI.getOpcode()) {
104134 case WebAssembly::CALL_INDIRECT_VOID:
135 case WebAssembly::CALL_INDIRECT_VOID_S:
105136 case WebAssembly::CALL_INDIRECT_I32:
137 case WebAssembly::CALL_INDIRECT_I32_S:
106138 case WebAssembly::CALL_INDIRECT_I64:
139 case WebAssembly::CALL_INDIRECT_I64_S:
107140 case WebAssembly::CALL_INDIRECT_F32:
141 case WebAssembly::CALL_INDIRECT_F32_S:
108142 case WebAssembly::CALL_INDIRECT_F64:
143 case WebAssembly::CALL_INDIRECT_F64_S:
109144 case WebAssembly::CALL_INDIRECT_v16i8:
145 case WebAssembly::CALL_INDIRECT_v16i8_S:
110146 case WebAssembly::CALL_INDIRECT_v8i16:
147 case WebAssembly::CALL_INDIRECT_v8i16_S:
111148 case WebAssembly::CALL_INDIRECT_v4i32:
149 case WebAssembly::CALL_INDIRECT_v4i32_S:
112150 case WebAssembly::CALL_INDIRECT_v2i64:
151 case WebAssembly::CALL_INDIRECT_v2i64_S:
113152 case WebAssembly::CALL_INDIRECT_v4f32:
153 case WebAssembly::CALL_INDIRECT_v4f32_S:
114154 case WebAssembly::CALL_INDIRECT_v2f64:
155 case WebAssembly::CALL_INDIRECT_v2f64_S:
115156 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
157 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
116158 return true;
117159 default:
118160 return false;
122164 unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
123165 switch (MI.getOpcode()) {
124166 case WebAssembly::CALL_VOID:
167 case WebAssembly::CALL_VOID_S:
125168 case WebAssembly::CALL_INDIRECT_VOID:
169 case WebAssembly::CALL_INDIRECT_VOID_S:
126170 return 0;
127171 case WebAssembly::CALL_I32:
172 case WebAssembly::CALL_I32_S:
128173 case WebAssembly::CALL_I64:
174 case WebAssembly::CALL_I64_S:
129175 case WebAssembly::CALL_F32:
176 case WebAssembly::CALL_F32_S:
130177 case WebAssembly::CALL_F64:
178 case WebAssembly::CALL_F64_S:
131179 case WebAssembly::CALL_EXCEPT_REF:
180 case WebAssembly::CALL_EXCEPT_REF_S:
132181 case WebAssembly::CALL_INDIRECT_I32:
182 case WebAssembly::CALL_INDIRECT_I32_S:
133183 case WebAssembly::CALL_INDIRECT_I64:
184 case WebAssembly::CALL_INDIRECT_I64_S:
134185 case WebAssembly::CALL_INDIRECT_F32:
186 case WebAssembly::CALL_INDIRECT_F32_S:
135187 case WebAssembly::CALL_INDIRECT_F64:
188 case WebAssembly::CALL_INDIRECT_F64_S:
136189 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
190 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
137191 return 1;
138192 default:
139193 llvm_unreachable("Not a call instruction");
143197 bool WebAssembly::isMarker(const MachineInstr &MI) {
144198 switch (MI.getOpcode()) {
145199 case WebAssembly::BLOCK:
200 case WebAssembly::BLOCK_S:
146201 case WebAssembly::END_BLOCK:
202 case WebAssembly::END_BLOCK_S:
147203 case WebAssembly::LOOP:
204 case WebAssembly::LOOP_S:
148205 case WebAssembly::END_LOOP:
206 case WebAssembly::END_LOOP_S:
149207 case WebAssembly::TRY:
208 case WebAssembly::TRY_S:
150209 case WebAssembly::END_TRY:
210 case WebAssembly::END_TRY_S:
151211 return true;
152212 default:
153213 return false;
157217 bool WebAssembly::isThrow(const MachineInstr &MI) {
158218 switch (MI.getOpcode()) {
159219 case WebAssembly::THROW_I32:
220 case WebAssembly::THROW_I32_S:
160221 case WebAssembly::THROW_I64:
222 case WebAssembly::THROW_I64_S:
161223 return true;
162224 default:
163225 return false;
167229 bool WebAssembly::isRethrow(const MachineInstr &MI) {
168230 switch (MI.getOpcode()) {
169231 case WebAssembly::RETHROW:
232 case WebAssembly::RETHROW_S:
170233 case WebAssembly::RETHROW_TO_CALLER:
234 case WebAssembly::RETHROW_TO_CALLER_S:
171235 return true;
172236 default:
173237 return false;
177241 bool WebAssembly::isCatch(const MachineInstr &MI) {
178242 switch (MI.getOpcode()) {
179243 case WebAssembly::CATCH_I32:
244 case WebAssembly::CATCH_I32_S:
180245 case WebAssembly::CATCH_I64:
246 case WebAssembly::CATCH_I64_S:
181247 case WebAssembly::CATCH_ALL:
248 case WebAssembly::CATCH_ALL_S:
182249 return true;
183250 default:
184251 return false;
188255 bool WebAssembly::mayThrow(const MachineInstr &MI) {
189256 switch (MI.getOpcode()) {
190257 case WebAssembly::THROW_I32:
258 case WebAssembly::THROW_I32_S:
191259 case WebAssembly::THROW_I64:
260 case WebAssembly::THROW_I64_S:
192261 case WebAssembly::RETHROW:
262 case WebAssembly::RETHROW_S:
193263 return true;
194264 }
195265 if (isCallIndirect(MI))
217287 bool SeenCatch = false;
218288 for (auto &MI : MBB) {
219289 if (MI.getOpcode() == WebAssembly::CATCH_I32 ||
220 MI.getOpcode() == WebAssembly::CATCH_I64)
290 MI.getOpcode() == WebAssembly::CATCH_I64 ||
291 MI.getOpcode() == WebAssembly::CATCH_I32_S ||
292 MI.getOpcode() == WebAssembly::CATCH_I64_S)
221293 SeenCatch = true;
222294 if (SeenCatch && MI.isCall()) {
223295 const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
234306 return false;
235307 bool SeenCatchAll = false;
236308 for (auto &MI : MBB) {
237 if (MI.getOpcode() == WebAssembly::CATCH_ALL)
309 if (MI.getOpcode() == WebAssembly::CATCH_ALL ||
310 MI.getOpcode() == WebAssembly::CATCH_ALL_S)
238311 SeenCatchAll = true;
239312 if (SeenCatchAll && MI.isCall()) {
240313 const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test folding constant offsets and symbols into load and store addresses under
33 ; a variety of circumstances.
0 ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics,+sign-ext | FileCheck %s
22
33 ; Currently all wasm atomic memory access instructions are sequentially
44 ; consistent, so even if LLVM IR specifies weaker orderings than that, we
None ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s
0 ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics,+sign-ext | FileCheck %s
22
33 ; Test atomic RMW (read-modify-write) instructions are assembled properly.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs -fast-isel | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -fast-isel | FileCheck %s
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-temporary-workarounds=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -wasm-temporary-workarounds=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false | FileCheck %s
22
33 ; Test that basic call operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -tail-dup-placement=0 -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 | FileCheck -check-prefix=OPT %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -tail-dup-placement=0 -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 | FileCheck -check-prefix=OPT %s
22
33 ; Test the CFG stackifier pass.
44
None ; RUN: opt -S -lowertypetests < %s | llc -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: opt -S -lowertypetests < %s | llc -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Tests that we correctly assign indexes for control flow integrity.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 32-bit floating-point comparison operations assemble as
33 ; expected.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 64-bit floating-point comparison operations assemble as
33 ; expected.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic 32-bit integer comparison operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic 64-bit integer comparison operations assemble as expected.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-nontrapping-fptoint | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s
11
22 ; Test that basic conversion operations assemble as expected using
33 ; the trapping opcodes and explicit code to suppress the trapping.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+nontrapping-fptoint | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s
11
22 ; Test that basic conversion operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; DAGCombiner oddly folds casts into the rhs of copysign. Test that they get
33 ; unfolded.
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; Test that integer div and rem by constant are optimized appropriately.
33
None ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -exception-model=wasm
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s
0 ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
None # RUN: llc -mtriple=wasm32-unknown-unknown -run-pass wasm-explicit-locals %s -o - | FileCheck %s
0 # RUN: llc -mtriple=wasm32-unknown-unknown -run-pass wasm-explicit-locals -wasm-keep-registers %s -o - | FileCheck %s
11
22 # When a drop instruction is inserted to drop a dead register operand, the
33 # original operand should be marked not dead anymore because it is now used by
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel | FileCheck %s
22
33 ; Test that f16 is expanded.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 32-bit floating-point operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 64-bit floating-point operations assemble as expected.
33
None ; RUN: llc < %s -fast-isel -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -fast-isel -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -O0
0 ; RUN: llc < %s -O0 -wasm-keep-registers
11 ; PR36564
22 ; PR37546
33
None ; RUN: llc < %s -O0
0 ; RUN: llc < %s -O0 -wasm-keep-registers
11 ; PR36564
22 ; PR37546
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers -fast-isel -verify-machineinstrs | FileCheck %s
22
33 ; Test that FastISel does not generate instructions with NoReg
44
0 ; RUN: llc < %s -asm-verbose=false \
11 ; RUN: -fast-isel -fast-isel-abort=1 -verify-machineinstrs \
2 ; RUN: -disable-wasm-explicit-locals \
2 ; RUN: -wasm-disable-explicit-locals -wasm-keep-registers \
33 ; RUN: | FileCheck %s
44
55 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that the frem instruction works.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic functions assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false -wasm-keep-registers | FileCheck %s
11
22 ; Test that function pointer casts casting away varargs are replaced with
33 ; wrappers.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s
11
22 ; Test that function pointer casts are replaced with wrappers.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that globals assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 128-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test loads and stores with custom alignment values.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 32-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test loads and stores with custom alignment values.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic 64-bit integer operations assemble as expected.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; Test llvm.ident.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic immediates assemble as expected.
33
None ; RUN: llc -o - %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc -o - %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
22 target triple = "wasm32-unknown-unknown"
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs -fast-isel | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -verify-machineinstrs -fast-isel | FileCheck %s
22
33 ; ModuleID = 'test/dot_s/indirect-import.c'
44 source_filename = "test/dot_s/indirect-import.c"
None ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -no-integrated-as
0 ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -no-integrated-as
11
22 ; Test basic inline assembly "m" operands, which are unsupported. Pass
33 ; -no-integrated-as since these aren't actually valid assembly syntax.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -no-integrated-as | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -no-integrated-as | FileCheck %s
11
22 ; Test basic inline assembly. Pass -no-integrated-as since these aren't
33 ; actually valid assembly syntax.
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-block-placement -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-block-placement -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test irreducible CFG handling.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test various types and operators that need to be legalized.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 ; Test a subset of compiler-rt/libm libcalls expected to be emitted by the wasm backend
33
None ; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that extending loads are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that extending loads are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that i1 extending loads and truncating stores are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic loads are assembled properly.
44
3838 %arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf, i32 0, i32 0
3939 call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #1
4040 unreachable
41 ; SJLJ: i32.call ${{[a-zA-Z0-9]+}}=, saveSetjmp@FUNCTION
42 ; SJLJ: i32.call ${{[a-zA-Z0-9]+}}=, testSetjmp@FUNCTION
43 ; NONE: i32.call ${{[a-zA-Z0-9]+}}=, setjmp@FUNCTION
41 ; SJLJ: i32.call saveSetjmp@FUNCTION
42 ; SJLJ: i32.call testSetjmp@FUNCTION
43 ; NONE: i32.call setjmp@FUNCTION
4444 ; NONE: call longjmp@FUNCTION
4545 }
4646
None ; RUN: llc < %s -asm-verbose=false | FileCheck --check-prefix=CHECK --check-prefix=FINI --check-prefix=NULL %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck --check-prefix=CHECK --check-prefix=FINI --check-prefix=NULL %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -tail-dup-placement=0 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -tail-dup-placement=0 | FileCheck %s
11
22 ; Test memcpy, memmove, and memset intrinsics.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that basic memory operations assemble as expected with 32-bit addresses.
33
None ; RUN: llc -asm-verbose=false < %s | FileCheck %s
0 ; RUN: llc -asm-verbose=false < %s -wasm-keep-registers | FileCheck %s
11
22 ; Test that 128-bit smul.with.overflow assembles as expected.
33
None ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
0 ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics,+sign-ext | FileCheck %s
22
33 ; Test that atomic loads are assembled properly.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
11
22 ; TODO: Merge this with offset.ll when fast-isel matches better.
33
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; Test that constant offsets can be folded into global addresses.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 ; Test constant load and store address offsets.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs | FileCheck %s
11
22 ; Test that phis are lowered.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s --check-prefix=NOREGS
12
23 ; Test the register stackifier pass.
4
5 ; We have two sets of tests, one with registers and implicit locals, and
6 ; a stack / explicit locals based version (NOREGS).
37
48 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
59 target triple = "wasm32-unknown-unknown"
812
913 ; CHECK-LABEL: no0:
1014 ; CHECK: return $1{{$}}
15 ; NOREGS-LABEL: no0:
16 ; NOREGS: return{{$}}
1117 define i32 @no0(i32* %p, i32* %q) {
1218 %t = load i32, i32* %q
1319 store i32 0, i32* %p
1824
1925 ; CHECK-LABEL: no1:
2026 ; CHECK: return $1{{$}}
27 ; NOREGS-LABEL: no1:
28 ; NOREGS: return{{$}}
2129 define i32 @no1(i32* %p, i32* dereferenceable(4) %q) {
2230 %t = load volatile i32, i32* %q, !invariant.load !0
2331 store volatile i32 0, i32* %p
2836
2937 ; CHECK-LABEL: yes0:
3038 ; CHECK: return $pop{{[0-9]+}}{{$}}
39 ; NOREGS-LABEL: yes0:
40 ; NOREGS: return{{$}}
3141 define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) {
3242 %t = load i32, i32* %q, !invariant.load !0
3343 store i32 0, i32* %p
3848
3949 ; CHECK-LABEL: yes1:
4050 ; CHECK: return $pop0{{$}}
51 ; NOREGS-LABEL: yes1:
52 ; NOREGS: return{{$}}
4153 define i32 @yes1(i32* %q) {
4254 %t = load volatile i32, i32* %q
4355 ret i32 %t
4759
4860 ; CHECK-LABEL: sink_trap:
4961 ; CHECK: return $pop{{[0-9]+}}{{$}}
62 ; NOREGS-LABEL: sink_trap:
63 ; NOREGS: return{{$}}
5064 define i32 @sink_trap(i32 %x, i32 %y, i32* %p) {
5165 %t = sdiv i32 %x, %y
5266 store volatile i32 0, i32* %p
5771
5872 ; CHECK-LABEL: sink_readnone_call:
5973 ; CHECK: return $pop0{{$}}
74 ; NOREGS-LABEL: sink_readnone_call:
75 ; NOREGS: return{{$}}
6076 declare i32 @readnone_callee() readnone nounwind
6177 define i32 @sink_readnone_call(i32 %x, i32 %y, i32* %p) {
6278 %t = call i32 @readnone_callee()
6884
6985 ; CHECK-LABEL: no_sink_readonly_call:
7086 ; CHECK: return ${{[0-9]+}}{{$}}
87 ; NOREGS-LABEL: no_sink_readonly_call:
88 ; NOREGS: return{{$}}
7189 declare i32 @readonly_callee() readonly nounwind
7290 define i32 @no_sink_readonly_call(i32 %x, i32 %y, i32* %p) {
7391 %t = call i32 @readonly_callee()
104122 ; CHECK-NEXT: end_block{{$}}
105123 ; CHECK-NEXT: i32.const $push14=, 1{{$}}
106124 ; CHECK-NEXT: return $pop14{{$}}
125 ; NOREGS-LABEL: stack_uses:
126 ; NOREGS: .param i32, i32, i32, i32{{$}}
127 ; NOREGS-NEXT: .result i32{{$}}
128 ; NOREGS-NEXT: block {{$}}
129 ; NOREGS-NEXT: get_local 0{{$}}
130 ; NOREGS-NEXT: i32.const 1{{$}}
131 ; NOREGS-NEXT: i32.lt_s
132 ; NOREGS-NEXT: get_local 1{{$}}
133 ; NOREGS-NEXT: i32.const 2{{$}}
134 ; NOREGS-NEXT: i32.lt_s
135 ; NOREGS-NEXT: i32.xor {{$}}
136 ; NOREGS-NEXT: get_local 2{{$}}
137 ; NOREGS-NEXT: i32.const 1{{$}}
138 ; NOREGS-NEXT: i32.lt_s
139 ; NOREGS-NEXT: get_local 3{{$}}
140 ; NOREGS-NEXT: i32.const 2{{$}}
141 ; NOREGS-NEXT: i32.lt_s
142 ; NOREGS-NEXT: i32.xor {{$}}
143 ; NOREGS-NEXT: i32.xor {{$}}
144 ; NOREGS-NEXT: i32.const 1{{$}}
145 ; NOREGS-NEXT: i32.ne {{$}}
146 ; NOREGS-NEXT: br_if 0{{$}}
147 ; NOREGS-NEXT: i32.const 0{{$}}
148 ; NOREGS-NEXT: return{{$}}
149 ; NOREGS-NEXT: .LBB7_2:
150 ; NOREGS-NEXT: end_block{{$}}
151 ; NOREGS-NEXT: i32.const 1{{$}}
152 ; NOREGS-NEXT: return{{$}}
107153 define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) {
108154 entry:
109155 %c = icmp sle i32 %x, 0
136182 ; CHECK-NEXT: .LBB8_3:
137183 ; CHECK-NEXT: end_block{{$}}
138184 ; CHECK-NEXT: return{{$}}
185 ; NOREGS-LABEL: multiple_uses:
186 ; NOREGS: .param i32, i32, i32{{$}}
187 ; NOREGS: .local i32{{$}}
188 ; NOREGS-NEXT: block {{$}}
189 ; NOREGS-NEXT: get_local 2{{$}}
190 ; NOREGS-NEXT: i32.load 0{{$}}
191 ; NOREGS-NEXT: tee_local 3{{$}}
192 ; NOREGS-NEXT: get_local 1{{$}}
193 ; NOREGS-NEXT: i32.ge_u
194 ; NOREGS-NEXT: br_if 0{{$}}
195 ; NOREGS-NEXT: get_local 3{{$}}
196 ; NOREGS-NEXT: get_local 0{{$}}
197 ; NOREGS-NEXT: i32.lt_u
198 ; NOREGS-NEXT: br_if 0{{$}}
199 ; NOREGS-NEXT: get_local 2{{$}}
200 ; NOREGS-NEXT: get_local 3{{$}}
201 ; NOREGS-NEXT: i32.store 0{{$}}
202 ; NOREGS-NEXT: .LBB8_3:
203 ; NOREGS-NEXT: end_block{{$}}
204 ; NOREGS-NEXT: return{{$}}
139205 define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
140206 bb:
141207 br label %loop
166232 ; CHECK-NEXT: call
167233 ; CHECK: store
168234 ; CHECK-NEXT: call
235 ; NOREGS: side_effects:
236 ; NOREGS: store
237 ; NOREGS-NEXT: call
238 ; NOREGS: store
239 ; NOREGS-NEXT: call
169240 declare void @evoke_side_effects()
170241 define hidden void @stackify_store_across_side_effects(double* nocapture %d) {
171242 entry:
199270 ; CHECK-NEXT: i32.div_s $push[[L13:[0-9]+]]=, $pop[[L9]], $pop[[L12]]{{$}}
200271 ; CHECK-NEXT: i32.div_s $push[[L14:[0-9]+]]=, $pop[[L6]], $pop[[L13]]{{$}}
201272 ; CHECK-NEXT: return $pop[[L14]]{{$}}
273 ; NOREGS-LABEL: div_tree:
274 ; NOREGS: .param i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}}
275 ; NOREGS-NEXT: .result i32{{$}}
276 ; NOREGS-NEXT: get_local 0{{$}}
277 ; NOREGS-NEXT: get_local 1{{$}}
278 ; NOREGS-NEXT: i32.div_s{{$}}
279 ; NOREGS-NEXT: get_local 2{{$}}
280 ; NOREGS-NEXT: get_local 3{{$}}
281 ; NOREGS-NEXT: i32.div_s{{$}}
282 ; NOREGS-NEXT: i32.div_s{{$}}
283 ; NOREGS-NEXT: get_local 4{{$}}
284 ; NOREGS-NEXT: get_local 5{{$}}
285 ; NOREGS-NEXT: i32.div_s{{$}}
286 ; NOREGS-NEXT: get_local 6{{$}}
287 ; NOREGS-NEXT: get_local 7{{$}}
288 ; NOREGS-NEXT: i32.div_s{{$}}
289 ; NOREGS-NEXT: i32.div_s{{$}}
290 ; NOREGS-NEXT: i32.div_s{{$}}
291 ; NOREGS-NEXT: get_local 8{{$}}
292 ; NOREGS-NEXT: get_local 9{{$}}
293 ; NOREGS-NEXT: i32.div_s{{$}}
294 ; NOREGS-NEXT: get_local 10{{$}}
295 ; NOREGS-NEXT: get_local 11{{$}}
296 ; NOREGS-NEXT: i32.div_s{{$}}
297 ; NOREGS-NEXT: i32.div_s{{$}}
298 ; NOREGS-NEXT: get_local 12{{$}}
299 ; NOREGS-NEXT: get_local 13{{$}}
300 ; NOREGS-NEXT: i32.div_s{{$}}
301 ; NOREGS-NEXT: get_local 14{{$}}
302 ; NOREGS-NEXT: get_local 15{{$}}
303 ; NOREGS-NEXT: i32.div_s{{$}}
304 ; NOREGS-NEXT: i32.div_s{{$}}
305 ; NOREGS-NEXT: i32.div_s{{$}}
306 ; NOREGS-NEXT: i32.div_s{{$}}
307 ; NOREGS-NEXT: return{{$}}
202308 define i32 @div_tree(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p) {
203309 entry:
204310 %div = sdiv i32 %a, %b
228334 ; CHECK-NEXT: call use_a@FUNCTION, $pop[[NUM1]]{{$}}
229335 ; CHECK-NEXT: call use_b@FUNCTION, $[[NUM2]]{{$}}
230336 ; CHECK-NEXT: return{{$}}
337 ; NOREGS-LABEL: simple_multiple_use:
338 ; NOREGS: .param i32, i32{{$}}
339 ; NOREGS-NEXT: get_local 1{{$}}
340 ; NOREGS-NEXT: get_local 0{{$}}
341 ; NOREGS-NEXT: i32.mul
342 ; NOREGS-NEXT: tee_local 1{{$}}
343 ; NOREGS-NEXT: call use_a@FUNCTION{{$}}
344 ; NOREGS-NEXT: get_local 1{{$}}
345 ; NOREGS-NEXT: call use_b@FUNCTION{{$}}
346 ; NOREGS-NEXT: return{{$}}
231347 declare void @use_a(i32)
232348 declare void @use_b(i32)
233349 define void @simple_multiple_use(i32 %x, i32 %y) {
245361 ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}}
246362 ; CHECK-NEXT: call use_2@FUNCTION, $pop[[NUM1]], $[[NUM2]]{{$}}
247363 ; CHECK-NEXT: return{{$}}
364 ; NOREGS-LABEL: multiple_uses_in_same_insn:
365 ; NOREGS: .param i32, i32{{$}}
366 ; NOREGS-NEXT: get_local 1{{$}}
367 ; NOREGS-NEXT: get_local 0{{$}}
368 ; NOREGS-NEXT: i32.mul
369 ; NOREGS-NEXT: tee_local 1{{$}}
370 ; NOREGS-NEXT: get_local 1{{$}}
371 ; NOREGS-NEXT: call use_2@FUNCTION{{$}}
372 ; NOREGS-NEXT: return{{$}}
248373 declare void @use_2(i32, i32)
249374 define void @multiple_uses_in_same_insn(i32 %x, i32 %y) {
250375 %mul = mul i32 %y, %x
263388 ; CHECK-NEXT: i32.call $push3=, blue@FUNCTION{{$}}
264389 ; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}}
265390 ; CHECK-NEXT: return $pop4{{$}}
391 ; NOREGS-LABEL: commute:
392 ; NOREGS-NOT: param
393 ; NOREGS: .result i32{{$}}
394 ; NOREGS-NEXT: i32.call red@FUNCTION{{$}}
395 ; NOREGS-NEXT: i32.call green@FUNCTION{{$}}
396 ; NOREGS-NEXT: i32.add {{$}}
397 ; NOREGS-NEXT: i32.call blue@FUNCTION{{$}}
398 ; NOREGS-NEXT: i32.add {{$}}
399 ; NOREGS-NEXT: return{{$}}
266400 declare i32 @red()
267401 declare i32 @green()
268402 declare i32 @blue()
286420 ; CHECK-NEXT: i32.sub $push3=, $pop2, $1
287421 ; CHECK-NEXT: i32.div_s $push4=, $pop3, $1
288422 ; CHECK-NEXT: return $pop4
423 ; NOREGS-LABEL: no_stackify_past_use:
424 ; NOREGS: get_local 0{{$}}
425 ; NOREGS-NEXT: i32.call callee@FUNCTION
426 ; NOREGS-NEXT: set_local 1{{$}}
427 ; NOREGS-NEXT: get_local 0{{$}}
428 ; NOREGS-NEXT: i32.const 1
429 ; NOREGS-NEXT: i32.add
430 ; NOREGS-NEXT: i32.call callee@FUNCTION
431 ; NOREGS-NEXT: get_local 1{{$}}
432 ; NOREGS-NEXT: i32.sub
433 ; NOREGS-NEXT: get_local 1{{$}}
434 ; NOREGS-NEXT: i32.div_s
435 ; NOREGS-NEXT: return
289436 declare i32 @callee(i32)
290437 define i32 @no_stackify_past_use(i32 %arg) {
291438 %tmp1 = call i32 @callee(i32 %arg)
308455 ; CHECK: i32.add $push3=, $1, $pop2
309456 ; CHECK: i32.mul $push4=, $pop[[L1]], $pop3
310457 ; CHECK: return $pop4
458 ; NOREGS-LABEL: commute_to_fix_ordering:
459 ; NOREGS: get_local 0{{$}}
460 ; NOREGS: i32.call callee@FUNCTION
461 ; NOREGS: tee_local 1
462 ; NOREGS: get_local 1{{$}}
463 ; NOREGS: get_local 0{{$}}
464 ; NOREGS: i32.const 1
465 ; NOREGS: i32.add
466 ; NOREGS: i32.call callee@FUNCTION
467 ; NOREGS: i32.add
468 ; NOREGS: i32.mul
469 ; NOREGS: return
311470 define i32 @commute_to_fix_ordering(i32 %arg) {
312471 %tmp1 = call i32 @callee(i32 %arg)
313472 %tmp2 = add i32 %arg, 1
324483 ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}}
325484 ; CHECK-NEXT: f64.select $push{{[0-9]+}}=, $pop{{[0-9]+}}, $pop[[NUM1]], ${{[0-9]+}}{{$}}
326485 ; CHECK: $[[NUM2]]=,
486 ; NOREGS-LABEL: multiple_defs:
487 ; NOREGS: f64.add
488 ; NOREGS: tee_local
489 ; NOREGS: f64.select
327490 define void @multiple_defs(i32 %arg, i32 %arg1, i1 %arg2, i1 %arg3, i1 %arg4) {
328491 bb:
329492 br label %bb5
366529 ; CHECK: i32.call $0=, red
367530 ; CHECK: i32.const $push0=, 0
368531 ; CHECK: i32.load $1=, count($pop0)
532 ; NOREGS-LABEL: no_stackify_call_past_load:
533 ; NOREGS: i32.call red
534 ; NOREGS: i32.const 0
535 ; NOREGS: i32.load count
369536 @count = hidden global i32 0, align 4
370537 define i32 @no_stackify_call_past_load() {
371538 %a = call i32 @red()
380547 ; CHECK: i32.store 0($1), $0
381548 ; CHECK: i32.load {{.*}}, 0($2)
382549 ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0{{$}}
550 ; NOREGS-LABEL: no_stackify_store_past_load
551 ; NOREGS: i32.store 0
552 ; NOREGS: i32.load 0
553 ; NOREGS: i32.call callee@FUNCTION{{$}}
383554 define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) {
384555 store i32 %a, i32* %p1
385556 %b = load i32, i32* %p2, align 4
393564 ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0
394565 ; CHECK: i32.load $push{{.*}}, 0($2)
395566 ; CHECK: return $pop
567 ; NOREGS-LABEL: store_past_invar_load
568 ; NOREGS: i32.store 0
569 ; NOREGS: i32.call callee@FUNCTION
570 ; NOREGS: i32.load 0
571 ; NOREGS: return
396572 define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) {
397573 store i32 %a, i32* %p1
398574 %b = load i32, i32* %p2, !invariant.load !0
403579 ; CHECK-LABEL: ignore_dbg_value:
404580 ; CHECK-NEXT: .Lfunc_begin
405581 ; CHECK-NEXT: unreachable
582 ; NOREGS-LABEL: ignore_dbg_value:
583 ; NOREGS-NEXT: .Lfunc_begin
584 ; NOREGS-NEXT: unreachable
406585 declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
407586 define void @ignore_dbg_value() {
408587 call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !7, metadata !9), !dbg !10
414593
415594 ; CHECK-LABEL: no_stackify_past_epilogue:
416595 ; CHECK: return ${{[0-9]+}}{{$}}
596 ; NOREGS-LABEL: no_stackify_past_epilogue:
597 ; NOREGS: return{{$}}
417598 declare i32 @use_memory(i32*)
418599 define i32 @no_stackify_past_epilogue() {
419600 %x = alloca i32
428609 ; CHECK-NEXT: i32.add $push[[L4:.+]]=, $[[R0:.+]], $pop[[L5]]{{$}}
429610 ; CHECK-NEXT: tee_local $push[[L3:.+]]=, $[[R0]]=, $pop[[L4]]{{$}}
430611 ; CHECK-NEXT: i32.ne $push[[L2:.+]]=, $0, $pop[[L3]]{{$}}
612 ; NOREGS-LABEL: stackify_indvar:
613 ; NOREGS: i32.const 1{{$}}
614 ; NOREGS-NEXT: i32.add
615 ; NOREGS-NEXT: tee_local 2{{$}}
616 ; NOREGS-NEXT: i32.ne
431617 define void @stackify_indvar(i32 %tmp, i32* %v) #0 {
432618 bb:
433619 br label %bb3
450636 ; CHECK-LABEL: stackpointer_dependency:
451637 ; CHECK: call {{.+}}, stackpointer_callee@FUNCTION,
452638 ; CHECK-NEXT: set_global __stack_pointer@GLOBAL,
639 ; NOREGS-LABEL: stackpointer_dependency:
640 ; NOREGS: call stackpointer_callee@FUNCTION
641 ; NOREGS: set_global __stack_pointer
453642 declare i32 @stackpointer_callee(i8* readnone, i8* readnone)
454643 declare i8* @llvm.frameaddress(i32)
455644 define i32 @stackpointer_dependency(i8* readnone) {
466655 ; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0)
467656 ; CHECK-NEXT: i32.load $push[[L1:.+]]=, 0($pop[[L0]])
468657 ; CHECK-NEXT: i32.call_indirect $push{{.+}}=, $pop[[L3]], $1, $pop[[L1]]
658 ; NOREGS-LABEL: call_indirect_stackify:
659 ; NOREGS: i32.load 0
660 ; NOREGS-NEXT: tee_local 0
661 ; NOREGS: i32.load 0
662 ; NOREGS-NEXT: i32.load 0
663 ; NOREGS-NEXT: i32.call_indirect
469664 %class.call_indirect = type { i32 (...)** }
470665 define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) {
471666 %obj = load %class.call_indirect*, %class.call_indirect** %objptr
490685 !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
491686 !9 = !DIExpression()
492687 !10 = !DILocation(line: 15, column: 6, scope: !5)
688
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
2525
2626 true:
2727 store i32 0, i32* null
28 ret i32 1
28 ret i32 1
2929
3030 false:
3131 store i32 2, i32* null
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that the "returned" attribute is optimized effectively.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that wasm select instruction is selected from LLVM select instruction.
44
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -mattr=+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s --check-prefix=NOSIGNEXT
0 ; RUN: llc < %s -mattr=+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=NOSIGNEXT
22
33 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
44 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test zeroext and signext ABI keywords
33
None ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
1 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
2 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
3 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
4 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
5 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
0 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
1 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
2 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
3 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
4 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
5 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 -fast-isel --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
66
77 ; Test that basic SIMD128 arithmetic operations assemble as expected.
88
None ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -wasm-enable-unimplemented-simd -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
1 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
2 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
0 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128
1 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,SIMD128-VM
2 ; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128,+sign-ext --show-mc-encoding | FileCheck %s --check-prefixes CHECK,NO-SIMD128
33
44 ; Test that basic SIMD128 vector manipulation operations assemble as expected.
55
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that truncating stores are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Test that truncating stores are assembled properly.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 | FileCheck %s
22
33 ; Test that basic stores are assembled properly.
44
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs | FileCheck %s
11
22 ; Test switch instructions. Block placement is disabled because it reorders
33 ; the blocks in a way that isn't interesting here.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -thread-model=single | FileCheck --check-prefix=SINGLE %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -thread-model=single | FileCheck --check-prefix=SINGLE %s
11 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
22 target triple = "wasm32-unknown-unknown"
33
None ; RUN: llc < %s -mtriple=wasm32 | FileCheck %s --check-prefixes=WASM32
0 ; RUN: llc < %s -mtriple=wasm32 -wasm-keep-registers | FileCheck %s --check-prefixes=WASM32
11 ; NOTE: did not compile on wasm64 at the time the test was created!
22
33 define { i128, i8 } @muloti_test(i128 %l, i128 %r) unnamed_addr #0 {
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11 ; Test that UMULO works correctly on 64-bit operands.
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
11
22 ; Test that function pointer casts that require conversions of arguments or
33 ; return types are converted to unreachable.
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
11
22 ; Make sure that argument offsets are correct even if some arguments are unused.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
33 target triple = "wasm32-unknown-unknown"
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs | FileCheck %s
11
22 ; Test varargs constructs.
33
None ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFONAME
1 ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=VTABLE
2 ; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFO
0 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFONAME
1 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=VTABLE
2 ; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s --check-prefix=TYPEINFO
33
44 ; Test that simple vtables assemble as expected.
55 ;
1010 # CHECK: i64.const -1
1111 0x42 0x7F
1212
13 # CHECK: i64.load32_u 16, :p2align=1
14 # FIXME: fix p2align output in WebAssemblyInstPrinter
13 # CHECK: i64.load32_u 16:p2align=1
1514 0x35 0x01 0x10
1615
1716 # CHECK: block
66 .param i32, i64
77 .local f32, f64, v128, v128
88 # Explicit getlocal/setlocal:
9 get_local $push0=, 2
10 set_local 2, $pop0=
11 # Implicit locals & immediates:
12 i32.const $0=, -1
13 f64.const $3=, 0x1.999999999999ap1
14 v128.const $4=, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
15 v128.const $5=, 0, 1, 2, 3, 4, 5, 6, 7
9 get_local 2
10 set_local 2
11 # Immediates:
12 i32.const -1
13 f64.const 0x1.999999999999ap1
14 v128.const 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
15 v128.const 0, 1, 2, 3, 4, 5, 6, 7
1616 # Indirect addressing:
17 get_local $push1=, 0
18 f64.store 0($pop1), $3
17 get_local 0
18 f64.store 0
1919 # Loops, conditionals, binary ops, calls etc:
2020 block
21 i32.const $push2=, 1
22 get_local $push7=, 0
23 i32.ge_s $push0=, $pop2, $pop7
24 br_if 0, $pop0 # 0: down to label0
21 i32.const 1
22 get_local 0
23 i32.ge_s
24 br_if 0 # 0: down to label0
2525 .LBB0_1:
2626 loop # label1:
27 call $drop=, something1@FUNCTION
28 i64.const $push10=, 1234
29 i32.call $push8=, something2@FUNCTION, $pop10
30 i32.const $push11=, 0
31 call_indirect $pop11
32 i32.const $push5=, 1
33 i32.add $push4=, $pop8, $pop5
34 tee_local $push3=, 0, $pop4
35 get_local $push9=, 0
36 i32.lt_s $push1=, $pop3, $pop9
37 br_if 0, $pop1 # 0: up to label1
27 call something1@FUNCTION
28 i64.const 1234
29 i32.call something2@FUNCTION
30 i32.const 0
31 call_indirect
32 i32.const 1
33 i32.add
34 tee_local 0
35 get_local 0
36 i32.lt_s
37 br_if 0 # 0: up to label1
3838 .LBB0_2:
3939 end_loop
4040 end_block # label0:
41 get_local $push12=, 4
42 get_local $push13=, 5
43 f32x4.add $4=, $pop12, $pop13
41 get_local 4
42 get_local 5
43 f32x4.add
4444 end_function
4545
4646
4848 # CHECK-LABEL: test0:
4949 # CHECK-NEXT: .param i32, i64
5050 # CHECK-NEXT: .local f32, f64
51 # CHECK-NEXT: get_local $push0=, 2
52 # CHECK-NEXT: set_local 2, $pop0
53 # CHECK-NEXT: i32.const $0=, -1
54 # CHECK-NEXT: f64.const $3=, 0x1.999999999999ap1
55 # CHECK-NEXT: v128.const $4=, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
56 # CHECK-NEXT: v128.const $5=, 0, 1, 2, 3, 4, 5, 6, 7
57 # CHECK-NEXT: get_local $push1=, 0
58 # CHECK-NEXT: f64.store 0($pop1):p2align=0, $3
51 # CHECK-NEXT: get_local 2
52 # CHECK-NEXT: set_local 2
53 # CHECK-NEXT: i32.const -1
54 # CHECK-NEXT: f64.const 0x1.999999999999ap1
55 # CHECK-NEXT: v128.const 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
56 # CHECK-NEXT: v128.const 0, 1, 2, 3, 4, 5, 6, 7
57 # CHECK-NEXT: get_local 0
58 # CHECK-NEXT: f64.store 0:p2align=0
5959 # CHECK-NEXT: block
60 # CHECK-NEXT: i32.const $push2=, 1
61 # CHECK-NEXT: get_local $push7=, 0
62 # CHECK-NEXT: i32.ge_s $push0=, $pop2, $pop7
63 # CHECK-NEXT: br_if 0, $pop0 # 0: down to label0
60 # CHECK-NEXT: i32.const 1
61 # CHECK-NEXT: get_local 0
62 # CHECK-NEXT: i32.ge_s
63 # CHECK-NEXT: br_if 0 # 0: down to label0
6464 # CHECK-NEXT: .LBB0_1:
6565 # CHECK-NEXT: loop # label1:
6666 # CHECK-NEXT: call something1@FUNCTION
67 # CHECK-NEXT: i64.const $push10=, 1234
68 # CHECK-NEXT: i32.call $push8=, something2@FUNCTION
69 # CHECK-NEXT: i32.const $push11=, 0
67 # CHECK-NEXT: i64.const 1234
68 # CHECK-NEXT: i32.call something2@FUNCTION
69 # CHECK-NEXT: i32.const 0
7070 # CHECK-NEXT: call_indirect
71 # CHECK-NEXT: i32.const $push5=, 1
72 # CHECK-NEXT: i32.add $push4=, $pop8, $pop5
73 # CHECK-NEXT: tee_local $push3=, 0, $pop4
74 # CHECK-NEXT: get_local $push9=, 0
75 # CHECK-NEXT: i32.lt_s $push1=, $pop3, $pop9
76 # CHECK-NEXT: br_if 0, $pop1 # 0: up to label1
71 # CHECK-NEXT: i32.const 1
72 # CHECK-NEXT: i32.add
73 # CHECK-NEXT: tee_local 0
74 # CHECK-NEXT: get_local 0
75 # CHECK-NEXT: i32.lt_s
76 # CHECK-NEXT: br_if 0 # 0: up to label1
7777 # CHECK-NEXT: .LBB0_2:
7878 # CHECK-NEXT: end_loop
7979 # CHECK-NEXT: end_block # label0:
80 # CHECK-NEXT: get_local $push12=, 4
81 # CHECK-NEXT: get_local $push13=, 5
82 # CHECK-NEXT: f32x4.add $4=, $pop12, $pop13
80 # CHECK-NEXT: get_local 4
81 # CHECK-NEXT: get_local 5
82 # CHECK-NEXT: f32x4.add
8383 # CHECK-NEXT: end_function
None ; RUN: llc -filetype=obj %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s
0 ; RUN: llc -filetype=obj -wasm-keep-registers %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s
11
22 target triple = "wasm32-unknown-unknown"
33
None ; RUN: llc -filetype=obj %s -o %t.o
0 ; RUN: llc -filetype=obj -wasm-keep-registers %s -o %t.o
11 ; RUN: obj2yaml %t.o | FileCheck %s
22 ; RUN: llvm-objdump -t %t.o | FileCheck --check-prefix=CHECK-SYMS %s
33
4646 }
4747
4848 ; CHECK: - Type: TYPE
49 ; CHECK-NEXT: Signatures:
49 ; CHECK-NEXT: Signatures:
5050 ; CHECK-NEXT: - Index: 0
5151 ; CHECK-NEXT: ReturnType: I32
52 ; CHECK-NEXT: ParamTypes:
52 ; CHECK-NEXT: ParamTypes:
5353 ; CHECK-NEXT: - Type: IMPORT
5454 ; CHECK-NEXT: Imports:
5555 ; CHECK-NEXT: - Module: env
6767 ; CHECK-NEXT: - Type: FUNCTION
6868 ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ]
6969 ; CHECK-NEXT: - Type: ELEM
70 ; CHECK-NEXT: Segments:
71 ; CHECK-NEXT: - Offset:
70 ; CHECK-NEXT: Segments:
71 ; CHECK-NEXT: - Offset:
7272 ; CHECK-NEXT: Opcode: I32_CONST
7373 ; CHECK-NEXT: Value: 1
7474 ; CHECK-NEXT: Functions: [ 0 ]
7575 ; CHECK-NEXT: - Type: CODE
76 ; CHECK-NEXT: Relocations:
76 ; CHECK-NEXT: Relocations:
7777 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
7878 ; CHECK-NEXT: Index: 0
7979 ; CHECK-NEXT: Offset: 0x00000009
9292 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB
9393 ; CHECK-NEXT: Index: 0
9494 ; CHECK-NEXT: Offset: 0x00000037
95 ; CHECK-NEXT: Functions:
96 ; CHECK-NEXT: - Index: 0
97 ; CHECK-NEXT: Locals:
95 ; CHECK-NEXT: Functions:
96 ; CHECK-NEXT: - Index: 0
97 ; CHECK-NEXT: Locals:
9898 ; CHECK-NEXT: Body: 41000B
9999 ; CHECK-NEXT: - Index: 1
100 ; CHECK-NEXT: Locals:
100 ; CHECK-NEXT: Locals:
101101 ; CHECK-NEXT: Body: 1080808080000B
102102 ; CHECK-NEXT: - Index: 2
103 ; CHECK-NEXT: Locals:
103 ; CHECK-NEXT: Locals:
104104 ; CHECK-NEXT: Body: 1080808080000B
105105 ; CHECK-NEXT: - Index: 3
106 ; CHECK-NEXT: Locals:
106 ; CHECK-NEXT: Locals:
107107 ; CHECK-NEXT: Body: 410028028880808000118080808000000B
108108 ; CHECK-NEXT: - Index: 4
109 ; CHECK-NEXT: Locals:
109 ; CHECK-NEXT: Locals:
110110 ; CHECK-NEXT: Body: 410028029080808000118080808000000B
111111 ; CHECK-NEXT: - Type: DATA
112 ; CHECK-NEXT: Relocations:
112 ; CHECK-NEXT: Relocations:
113113 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
114114 ; CHECK-NEXT: Index: 0
115115 ; CHECK-NEXT: Offset: 0x0000000F
116116 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
117117 ; CHECK-NEXT: Index: 3
118118 ; CHECK-NEXT: Offset: 0x00000018
119 ; CHECK-NEXT: Segments:
119 ; CHECK-NEXT: Segments:
120120 ; CHECK-NEXT: - SectionOffset: 6
121121 ; CHECK-NEXT: MemoryIndex: 0
122 ; CHECK-NEXT: Offset:
122 ; CHECK-NEXT: Offset:
123123 ; CHECK-NEXT: Opcode: I32_CONST
124124 ; CHECK-NEXT: Value: 0
125125 ; CHECK-NEXT: Content: '07000000'
126126 ; CHECK-NEXT: - SectionOffset: 15
127127 ; CHECK-NEXT: MemoryIndex: 0
128 ; CHECK-NEXT: Offset:
128 ; CHECK-NEXT: Offset:
129129 ; CHECK-NEXT: Opcode: I32_CONST
130130 ; CHECK-NEXT: Value: 8
131131 ; CHECK-NEXT: Content: '01000000'
138138 ; CHECK-NEXT: - Type: CUSTOM
139139 ; CHECK-NEXT: Name: linking
140140 ; CHECK-NEXT: Version: 1
141 ; CHECK-NEXT: SymbolTable:
141 ; CHECK-NEXT: SymbolTable:
142142 ; CHECK-NEXT: - Index: 0
143143 ; CHECK-NEXT: Kind: FUNCTION
144144 ; CHECK-NEXT: Name: foo
193193 ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ]
194194 ; CHECK-NEXT: Segment: 0
195195 ; CHECK-NEXT: Size: 4
196 ; CHECK-NEXT: SegmentInfo:
196 ; CHECK-NEXT: SegmentInfo:
197197 ; CHECK-NEXT: - Index: 0
198198 ; CHECK-NEXT: Name: .data.bar
199199 ; CHECK-NEXT: Alignment: 8
100100 InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,
101101 OutStringSize);
102102 EXPECT_EQ(InstSize, 3U);
103 EXPECT_EQ(StringRef(OutString), "\ti64.load32_u\t16, :p2align=1");
103 EXPECT_EQ(StringRef(OutString), "\ti64.load32_u\t16:p2align=1");
104104
105105 LLVMDisasmDispose(DCR);
106106 }