Index: lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp =================================================================== --- lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -34,27 +34,10 @@ namespace { -// We store register types as SimpleValueType to retain SIMD layout -// information, but must also be able to supply them as the (unnamed) -// register enum from WebAssemblyRegisterInfo.td/.inc. -static unsigned MVTToWasmReg(MVT::SimpleValueType Type) { - switch(Type) { - case MVT::i32: return WebAssembly::I32_0; - case MVT::i64: return WebAssembly::I64_0; - case MVT::f32: return WebAssembly::F32_0; - case MVT::f64: return WebAssembly::F64_0; - case MVT::v16i8: return WebAssembly::V128_0; - case MVT::v8i16: return WebAssembly::V128_0; - case MVT::v4i32: return WebAssembly::V128_0; - case MVT::v4f32: return WebAssembly::V128_0; - default: return MVT::INVALID_SIMPLE_VALUE_TYPE; - } -} - /// WebAssemblyOperand - Instances of this class represent the operands in a /// parsed WASM machine instruction. struct WebAssemblyOperand : public MCParsedAsmOperand { - enum KindTy { Token, Local, Stack, Integer, Float, Symbol } Kind; + enum KindTy { Token, Integer, Float, Symbol } Kind; SMLoc StartLoc, EndLoc; @@ -62,19 +45,6 @@ StringRef Tok; }; - struct RegOp { - // This is a (virtual) local or stack register represented as 0.. - unsigned RegNo; - // In most targets, the register number also encodes the type, but for - // wasm we have to track that seperately since we have an unbounded - // number of registers. - // This has the unfortunate side effect that we supply a different value - // to the table-gen matcher at different times in the process (when it - // calls getReg() or addRegOperands(). - // TODO: While this works, it feels brittle. and would be nice to clean up. - MVT::SimpleValueType Type; - }; - struct IntOp { int64_t Val; }; @@ -89,7 +59,6 @@ union { struct TokOp Tok; - struct RegOp Reg; struct IntOp Int; struct FltOp Flt; struct SymOp Sym; @@ -97,8 +66,6 @@ WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, TokOp T) : Kind(K), StartLoc(Start), EndLoc(End), Tok(T) {} - WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, RegOp R) - : Kind(K), StartLoc(Start), EndLoc(End), Reg(R) {} WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, IntOp I) : Kind(K), StartLoc(Start), EndLoc(End), Int(I) {} WebAssemblyOperand(KindTy K, SMLoc Start, SMLoc End, FltOp F) @@ -110,14 +77,12 @@ bool isImm() const override { return Kind == Integer || Kind == Float || Kind == Symbol; } - bool isReg() const override { return Kind == Local || Kind == Stack; } bool isMem() const override { return false; } + bool isReg() const override { return false; } unsigned getReg() const override { - assert(isReg()); - // This is called from the tablegen matcher (MatchInstructionImpl) - // where it expects to match the type of register, see RegOp above. - return MVTToWasmReg(Reg.Type); + llvm_unreachable("Assembly inspects a register operand"); + return 0; } StringRef getToken() const { @@ -128,19 +93,9 @@ SMLoc getStartLoc() const override { return StartLoc; } SMLoc getEndLoc() const override { return EndLoc; } - void addRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - assert(isReg() && "Not a register operand!"); - // This is called from the tablegen matcher (MatchInstructionImpl) - // where it expects to output the actual register index, see RegOp above. - unsigned R = Reg.RegNo; - if (Kind == Stack) { - // A stack register is represented as a large negative number. - // See WebAssemblyRegNumbering::runOnMachineFunction and - // getWARegStackId for why this | is needed. - R |= INT32_MIN; - } - Inst.addOperand(MCOperand::createReg(R)); + void addRegOperands(MCInst &, unsigned) const { + // Required by the assembly matcher. + llvm_unreachable("Assembly matcher creates register operands"); } void addImmOperands(MCInst &Inst, unsigned N) const { @@ -160,12 +115,6 @@ case Token: OS << "Tok:" << Tok.Tok; break; - case Local: - OS << "Loc:" << Reg.RegNo << ":" << static_cast(Reg.Type); - break; - case Stack: - OS << "Stk:" << Reg.RegNo << ":" << static_cast(Reg.Type); - break; case Integer: OS << "Int:" << Int.Val; break; @@ -182,11 +131,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { MCAsmParser &Parser; MCAsmLexer &Lexer; - // These are for the current function being parsed: - // These are vectors since register assignments are so far non-sparse. - // Replace by map if necessary. - std::vector LocalTypes; - std::vector StackTypes; MCSymbol *LastLabel; public: @@ -236,68 +180,6 @@ .Default(MVT::INVALID_SIMPLE_VALUE_TYPE); } - MVT::SimpleValueType &GetType( - std::vector &Types, size_t i) { - Types.resize(std::max(i + 1, Types.size()), MVT::INVALID_SIMPLE_VALUE_TYPE); - return Types[i]; - } - - bool ParseReg(OperandVector &Operands, StringRef TypePrefix) { - if (Lexer.is(AsmToken::Integer)) { - auto &Local = Lexer.getTok(); - // This is a reference to a local, turn it into a virtual register. - auto LocalNo = static_cast(Local.getIntVal()); - Operands.push_back(make_unique( - WebAssemblyOperand::Local, Local.getLoc(), - Local.getEndLoc(), - WebAssemblyOperand::RegOp{LocalNo, - GetType(LocalTypes, LocalNo)})); - Parser.Lex(); - } else if (Lexer.is(AsmToken::Identifier)) { - auto &StackRegTok = Lexer.getTok(); - // These are push/pop/drop pseudo stack registers, which we turn - // into virtual registers also. The stackify pass will later turn them - // back into implicit stack references if possible. - auto StackReg = StackRegTok.getString(); - auto StackOp = StackReg.take_while([](char c) { return isalpha(c); }); - auto Reg = StackReg.drop_front(StackOp.size()); - unsigned long long ParsedRegNo = 0; - if (!Reg.empty() && getAsUnsignedInteger(Reg, 10, ParsedRegNo)) - return Error("Cannot parse stack register index: ", StackRegTok); - unsigned RegNo = static_cast(ParsedRegNo); - if (StackOp == "push") { - // This defines a result, record register type. - auto RegType = ParseRegType(TypePrefix); - GetType(StackTypes, RegNo) = RegType; - Operands.push_back(make_unique( - WebAssemblyOperand::Stack, - StackRegTok.getLoc(), - StackRegTok.getEndLoc(), - WebAssemblyOperand::RegOp{RegNo, RegType})); - } else if (StackOp == "pop") { - // This uses a previously defined stack value. - auto RegType = GetType(StackTypes, RegNo); - Operands.push_back(make_unique( - WebAssemblyOperand::Stack, - StackRegTok.getLoc(), - StackRegTok.getEndLoc(), - WebAssemblyOperand::RegOp{RegNo, RegType})); - } else if (StackOp == "drop") { - // This operand will be dropped, since it is part of an instruction - // whose result is void. - } else { - return Error("Unknown stack register prefix: ", StackRegTok); - } - Parser.Lex(); - } else { - return Error( - "Expected identifier/integer following $, instead got: ", - Lexer.getTok()); - } - IsNext(AsmToken::Equal); - return false; - } - void ParseSingleInteger(bool IsNegative, OperandVector &Operands) { auto &Int = Lexer.getTok(); int64_t Val = Int.getIntVal(); @@ -310,36 +192,26 @@ bool ParseOperandStartingWithInteger(bool IsNegative, OperandVector &Operands, - StringRef InstType) { + StringRef InstName) { ParseSingleInteger(IsNegative, Operands); - if (Lexer.is(AsmToken::LParen)) { - // Parse load/store operands of the form: offset($reg)align - auto &LParen = Lexer.getTok(); - Operands.push_back( - make_unique(WebAssemblyOperand::Token, - LParen.getLoc(), - LParen.getEndLoc(), - WebAssemblyOperand::TokOp{ - LParen.getString()})); - Parser.Lex(); - if (Expect(AsmToken::Dollar, "register")) return true; - if (ParseReg(Operands, InstType)) return true; - auto &RParen = Lexer.getTok(); - Operands.push_back( - make_unique(WebAssemblyOperand::Token, - RParen.getLoc(), - RParen.getEndLoc(), - WebAssemblyOperand::TokOp{ - RParen.getString()})); - if (Expect(AsmToken::RParen, ")")) return true; - if (Lexer.is(AsmToken::Integer)) { + // FIXME: there is probably a cleaner way to do this. + auto IsLoadStore = InstName.startswith("load") || + InstName.startswith("store") || + InstName.startswith("atomic_load") || + InstName.startswith("atomic_store"); + if (IsLoadStore) { + // Parse load/store operands of the form: offset align + auto &Offset = Lexer.getTok(); + if (Offset.is(AsmToken::Integer)) { ParseSingleInteger(false, Operands); } else { // Alignment not specified. // FIXME: correctly derive a default from the instruction. + // We can't just call WebAssembly::GetDefaultP2Align since we don't have + // an opcode until after the assembly matcher. Operands.push_back(make_unique( - WebAssemblyOperand::Integer, RParen.getLoc(), - RParen.getEndLoc(), WebAssemblyOperand::IntOp{0})); + WebAssemblyOperand::Integer, Offset.getLoc(), + Offset.getEndLoc(), WebAssemblyOperand::IntOp{0})); } } return false; @@ -360,11 +232,6 @@ while (Lexer.isNot(AsmToken::EndOfStatement)) { auto &Tok = Lexer.getTok(); switch (Tok.getKind()) { - case AsmToken::Dollar: { - Parser.Lex(); - if (ParseReg(Operands, NamePair.first)) return true; - break; - } case AsmToken::Identifier: { auto &Id = Lexer.getTok(); const MCExpr *Val; @@ -380,11 +247,11 @@ Parser.Lex(); if (Lexer.isNot(AsmToken::Integer)) return Error("Expected integer instead got: ", Lexer.getTok()); - if (ParseOperandStartingWithInteger(true, Operands, NamePair.first)) + if (ParseOperandStartingWithInteger(true, Operands, NamePair.second)) return true; break; case AsmToken::Integer: - if (ParseOperandStartingWithInteger(false, Operands, NamePair.first)) + if (ParseOperandStartingWithInteger(false, Operands, NamePair.second)) return true; break; case AsmToken::Real: { @@ -405,35 +272,6 @@ } } Parser.Lex(); - // Call instructions are vararg, but the tablegen matcher doesn't seem to - // support that, so for now we strip these extra operands. - // This is problematic if these arguments are not simple $pop stack - // registers, since e.g. a local register would get lost, so we check for - // this. This can be the case when using -disable-wasm-explicit-locals - // which currently s2wasm requires. - // TODO: Instead, we can move this code to MatchAndEmitInstruction below and - // actually generate get_local instructions on the fly. - // Or even better, improve the matcher to support vararg? - auto IsIndirect = NamePair.second == "call_indirect"; - if (IsIndirect || NamePair.second == "call") { - // Figure out number of fixed operands from the instruction. - size_t CallOperands = 1; // The name token. - if (!IsIndirect) CallOperands++; // The function index. - if (!NamePair.first.empty()) CallOperands++; // The result register. - if (Operands.size() > CallOperands) { - // Ensure operands we drop are all $pop. - for (size_t I = CallOperands; I < Operands.size(); I++) { - auto Operand = - reinterpret_cast(Operands[I].get()); - if (Operand->Kind != WebAssemblyOperand::Stack) - Parser.Error(NameLoc, - "Call instruction has non-stack arguments, if this code was " - "generated with -disable-wasm-explicit-locals please remove it"); - } - // Drop unneeded operands. - Operands.resize(CallOperands); - } - } // Block instructions require a signature index, but these are missing in // assembly, so we add a dummy one explicitly (since we have no control // over signature tables here, we assume these will be regenerated when @@ -443,17 +281,6 @@ WebAssemblyOperand::Integer, NameLoc, NameLoc, WebAssemblyOperand::IntOp{-1})); } - // These don't specify the type, which has to derived from the local index. - if (NamePair.second == "get_local" || NamePair.second == "tee_local") { - if (Operands.size() >= 3 && Operands[1]->isReg() && - Operands[2]->isImm()) { - auto Op1 = reinterpret_cast(Operands[1].get()); - auto Op2 = reinterpret_cast(Operands[2].get()); - auto Type = GetType(LocalTypes, static_cast(Op2->Int.Val)); - Op1->Reg.Type = Type; - GetType(StackTypes, Op1->Reg.RegNo) = Type; - } - } return false; } @@ -477,11 +304,6 @@ IsNext(AsmToken::At) && Lexer.is(AsmToken::Identifier))) return Error("Expected label,@type declaration, got: ", Lexer.getTok()); - if (Lexer.getTok().getString() == "function") { - // Track locals from start of function. - LocalTypes.clear(); - StackTypes.clear(); - } Parser.Lex(); //Out.EmitSymbolAttribute(??, MCSA_ELF_TypeFunction); } else if (DirectiveID.getString() == ".param" || @@ -494,7 +316,6 @@ while (Lexer.is(AsmToken::Identifier)) { auto RegType = ParseRegType(Lexer.getTok().getString()); if (RegType == MVT::INVALID_SIMPLE_VALUE_TYPE) return true; - LocalTypes.push_back(RegType); if (DirectiveID.getString() == ".param") { Params.push_back(RegType); } else { Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -169,41 +169,54 @@ switch (MI->getOpcode()) { case WebAssembly::ARGUMENT_I32: + case WebAssembly::ARGUMENT_I32_S: case WebAssembly::ARGUMENT_I64: + case WebAssembly::ARGUMENT_I64_S: case WebAssembly::ARGUMENT_F32: + case WebAssembly::ARGUMENT_F32_S: case WebAssembly::ARGUMENT_F64: + case WebAssembly::ARGUMENT_F64_S: case WebAssembly::ARGUMENT_v16i8: + case WebAssembly::ARGUMENT_v16i8_S: case WebAssembly::ARGUMENT_v8i16: + case WebAssembly::ARGUMENT_v8i16_S: case WebAssembly::ARGUMENT_v4i32: + case WebAssembly::ARGUMENT_v4i32_S: case WebAssembly::ARGUMENT_v4f32: + case WebAssembly::ARGUMENT_v4f32_S: // These represent values which are live into the function entry, so there's // no instruction to emit. break; case WebAssembly::FALLTHROUGH_RETURN_I32: + case WebAssembly::FALLTHROUGH_RETURN_I32_S: case WebAssembly::FALLTHROUGH_RETURN_I64: + case WebAssembly::FALLTHROUGH_RETURN_I64_S: case WebAssembly::FALLTHROUGH_RETURN_F32: + case WebAssembly::FALLTHROUGH_RETURN_F32_S: case WebAssembly::FALLTHROUGH_RETURN_F64: + case WebAssembly::FALLTHROUGH_RETURN_F64_S: case WebAssembly::FALLTHROUGH_RETURN_v16i8: + case WebAssembly::FALLTHROUGH_RETURN_v16i8_S: case WebAssembly::FALLTHROUGH_RETURN_v8i16: + case WebAssembly::FALLTHROUGH_RETURN_v8i16_S: case WebAssembly::FALLTHROUGH_RETURN_v4i32: - case WebAssembly::FALLTHROUGH_RETURN_v4f32: { + case WebAssembly::FALLTHROUGH_RETURN_v4i32_S: + case WebAssembly::FALLTHROUGH_RETURN_v4f32: + case WebAssembly::FALLTHROUGH_RETURN_v4f32_S: { // These instructions represent the implicit return at the end of a - // function body. The operand is always a pop. - assert(MFI->isVRegStackified(MI->getOperand(0).getReg())); - + // function body. Always pops one value off the stack. if (isVerbose()) { - OutStreamer->AddComment("fallthrough-return: $pop" + - Twine(MFI->getWARegStackId( - MFI->getWAReg(MI->getOperand(0).getReg())))); + OutStreamer->AddComment("fallthrough-return-value"); OutStreamer->AddBlankLine(); } break; } case WebAssembly::FALLTHROUGH_RETURN_VOID: + case WebAssembly::FALLTHROUGH_RETURN_VOID_S: // This instruction represents the implicit return at the end of a // function body with no return value. if (isVerbose()) { - OutStreamer->AddComment("fallthrough-return"); + OutStreamer->AddComment("fallthrough-return-void"); OutStreamer->AddBlankLine(); } break; @@ -244,6 +257,9 @@ OS << MO.getImm(); return false; case MachineOperand::MO_Register: + // FIXME: only opcode that still contains registers, as required by + // MachineInstr::getDebugVariable(). + assert(MI->getOpcode() == WebAssembly::INLINEASM); OS << regToString(MO); return false; case MachineOperand::MO_GlobalAddress: Index: lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp +++ lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp @@ -31,12 +31,21 @@ #define DEBUG_TYPE "wasm-explicit-locals" -// A command-line option to disable this pass. Note that this produces output -// which is not valid WebAssembly, though it may be more convenient for writing -// LLVM unit tests with. -static cl::opt DisableWebAssemblyExplicitLocals( - "disable-wasm-explicit-locals", cl::ReallyHidden, - cl::desc("WebAssembly: Disable emission of get_local/set_local."), +// A command-line option to disable this pass, and keep implicit locals and +// stackified registers for the purpose of testing with lit/llc ONLY. +// This produces output which is not valid WebAssembly, and is not supported +// by assemblers/disassemblers and other MC based tools. +static cl::opt RegisterCodeGenTestMode( + "wasm-register-codegen-test-mode", cl::Hidden, + cl::desc("WebAssembly: output stack registers and implicit locals in" + " instruction output for test purposes only."), + cl::init(false)); +// This one does explicit locals but keeps stackified registers, as required +// by some current tests. +static cl::opt ExplicitLocalsCodeGenTestMode( + "wasm-explicit-locals-codegen-test-mode", cl::Hidden, + cl::desc("WebAssembly: output stack registers and explicit locals in" + " instruction output for test purposes only."), cl::init(false)); namespace { @@ -59,6 +68,8 @@ }; } // end anonymous namespace +unsigned regInstructionToStackInstruction(unsigned OpCode); + char WebAssemblyExplicitLocals::ID = 0; INITIALIZE_PASS(WebAssemblyExplicitLocals, DEBUG_TYPE, "Convert registers to WebAssembly locals", false, false) @@ -162,7 +173,7 @@ /// Given a MachineOperand of a stackified vreg, return the instruction at the /// start of the expression tree. -static MachineInstr *FindStartOfTree(MachineOperand &MO, +static MachineInstr *findStartOfTree(MachineOperand &MO, MachineRegisterInfo &MRI, WebAssemblyFunctionInfo &MFI) { unsigned Reg = MO.getReg(); @@ -173,7 +184,7 @@ for (MachineOperand &DefMO : Def->explicit_uses()) { if (!DefMO.isReg()) continue; - return FindStartOfTree(DefMO, MRI, MFI); + return findStartOfTree(DefMO, MRI, MFI); } // If there were no stackified uses, we've reached the start. @@ -186,7 +197,7 @@ << MF.getName() << '\n'); // Disable this pass if directed to do so. - if (DisableWebAssemblyExplicitLocals) + if (RegisterCodeGenTestMode) return false; bool Changed = false; @@ -206,19 +217,19 @@ break; unsigned Reg = MI.getOperand(0).getReg(); assert(!MFI.isVRegStackified(Reg)); - Reg2Local[Reg] = MI.getOperand(1).getImm(); + Reg2Local[Reg] = static_cast(MI.getOperand(1).getImm()); MI.eraseFromParent(); Changed = true; } // Start assigning local numbers after the last parameter. - unsigned CurLocal = MFI.getParams().size(); + unsigned CurLocal = static_cast(MFI.getParams().size()); // Precompute the set of registers that are unused, so that we can insert // drops to their defs. BitVector UseEmpty(MRI.getNumVirtRegs()); - for (unsigned i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) - UseEmpty[i] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(i)); + for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) + UseEmpty[I] = MRI.use_empty(TargetRegisterInfo::index2VirtReg(I)); // Visit each instruction in the function. for (MachineBasicBlock &MBB : MF) { @@ -322,7 +333,7 @@ // If we see a stackified register, prepare to insert subsequent // get_locals before the start of its tree. if (MFI.isVRegStackified(OldReg)) { - InsertPt = FindStartOfTree(MO, MRI, MFI); + InsertPt = findStartOfTree(MO, MRI, MFI); continue; } @@ -356,37 +367,410 @@ Changed = true; } } + + if (!ExplicitLocalsCodeGenTestMode) { + // Remove all uses of stackified registers to bring the instruction format + // into its final stack form, and transition opcodes to their _S variant. + // We do this in a seperate loop, since the previous loop adds/removes + // instructions. + // See comments in lib/Target/WebAssembly/WebAssemblyInstrFormats.td for + // details. + // TODO: the code above creates new registers which are then removed here. + // That code could be slightly simplified by not doing that, though maybe + // it is simpler conceptually to keep the code above in "register mode" + // until this transition point. + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E;) { + MachineInstr &MI = *I++; + // FIXME: we are not processing inline assembly, which contains register + // operands, because it is used by later target generic code. + if (MI.isDebugInstr() || MI.isLabel() || MI.isInlineAsm()) + continue; + auto RegOpcode = MI.getOpcode(); + auto StackOpcode = regInstructionToStackInstruction(RegOpcode); + MI.setDesc(TII->get(StackOpcode)); + // Now remove all register operands. + for (auto I = MI.getNumOperands(); I; --I) { + auto &MO = MI.getOperand(I - 1); + if (MO.isReg()) { + MI.RemoveOperand(I - 1); + // TODO: we should also update the MFI here or below to reflect the + // removed registers? The MFI is about to be deleted anyway, so + // maybe that is not worth it? + } + } + } + } } // Define the locals. // TODO: Sort the locals for better compression. MFI.setNumLocals(CurLocal - MFI.getParams().size()); - for (size_t i = 0, e = MRI.getNumVirtRegs(); i < e; ++i) { - unsigned Reg = TargetRegisterInfo::index2VirtReg(i); - auto I = Reg2Local.find(Reg); - if (I == Reg2Local.end() || I->second < MFI.getParams().size()) + for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(I); + auto RL = Reg2Local.find(Reg); + if (RL == Reg2Local.end() || RL->second < MFI.getParams().size()) continue; - MFI.setLocal(I->second - MFI.getParams().size(), + MFI.setLocal(RL->second - MFI.getParams().size(), typeForRegClass(MRI.getRegClass(Reg))); Changed = true; } -#ifndef NDEBUG - // Assert that all registers have been stackified at this point. - for (const MachineBasicBlock &MBB : MF) { - for (const MachineInstr &MI : MBB) { - if (MI.isDebugInstr() || MI.isLabel()) - continue; - for (const MachineOperand &MO : MI.explicit_operands()) { - assert( - (!MO.isReg() || MRI.use_empty(MO.getReg()) || - MFI.isVRegStackified(MO.getReg())) && - "WebAssemblyExplicitLocals failed to stackify a register operand"); - } - } - } -#endif - return Changed; } + +unsigned regInstructionToStackInstruction(unsigned OpCode) { + switch (OpCode) { + default: + // You may hit this if you add new instructions, please add them below. + // For most of these opcodes, this function could have been implemented + // as "return OpCode + 1", but since table-gen alphabetically sorts them, + // this cannot be guaranteed (see e.g. BR and BR_IF). + // The approach below is the same as what the x87 backend does. + // TODO(wvo): to make this code cleaner, create a custom tablegen + // code generator that emits the table below automatically. + llvm_unreachable( + "unknown WebAssembly instruction in Explicit Locals pass"); + case WebAssembly::ABS_F32: return WebAssembly::ABS_F32_S; + case WebAssembly::ABS_F64: return WebAssembly::ABS_F64_S; + case WebAssembly::ADD_F32: return WebAssembly::ADD_F32_S; + case WebAssembly::ADD_F32x4: return WebAssembly::ADD_F32x4_S; + case WebAssembly::ADD_F64: return WebAssembly::ADD_F64_S; + case WebAssembly::ADD_I16x8: return WebAssembly::ADD_I16x8_S; + case WebAssembly::ADD_I32: return WebAssembly::ADD_I32_S; + case WebAssembly::ADD_I32x4: return WebAssembly::ADD_I32x4_S; + case WebAssembly::ADD_I64: return WebAssembly::ADD_I64_S; + case WebAssembly::ADD_I8x16: return WebAssembly::ADD_I8x16_S; + case WebAssembly::ADJCALLSTACKDOWN: return WebAssembly::ADJCALLSTACKDOWN_S; + case WebAssembly::ADJCALLSTACKUP: return WebAssembly::ADJCALLSTACKUP_S; + case WebAssembly::AND_I32: return WebAssembly::AND_I32_S; + case WebAssembly::AND_I64: return WebAssembly::AND_I64_S; + case WebAssembly::ARGUMENT_EXCEPT_REF: return WebAssembly::ARGUMENT_EXCEPT_REF_S; + case WebAssembly::ARGUMENT_F32: return WebAssembly::ARGUMENT_F32_S; + case WebAssembly::ARGUMENT_F64: return WebAssembly::ARGUMENT_F64_S; + case WebAssembly::ARGUMENT_I32: return WebAssembly::ARGUMENT_I32_S; + case WebAssembly::ARGUMENT_I64: return WebAssembly::ARGUMENT_I64_S; + case WebAssembly::ARGUMENT_v16i8: return WebAssembly::ARGUMENT_v16i8_S; + case WebAssembly::ARGUMENT_v4f32: return WebAssembly::ARGUMENT_v4f32_S; + case WebAssembly::ARGUMENT_v4i32: return WebAssembly::ARGUMENT_v4i32_S; + case WebAssembly::ARGUMENT_v8i16: return WebAssembly::ARGUMENT_v8i16_S; + case WebAssembly::ATOMIC_LOAD16_U_I32: return WebAssembly::ATOMIC_LOAD16_U_I32_S; + case WebAssembly::ATOMIC_LOAD16_U_I64: return WebAssembly::ATOMIC_LOAD16_U_I64_S; + case WebAssembly::ATOMIC_LOAD32_U_I64: return WebAssembly::ATOMIC_LOAD32_U_I64_S; + case WebAssembly::ATOMIC_LOAD8_U_I32: return WebAssembly::ATOMIC_LOAD8_U_I32_S; + case WebAssembly::ATOMIC_LOAD8_U_I64: return WebAssembly::ATOMIC_LOAD8_U_I64_S; + case WebAssembly::ATOMIC_LOAD_I32: return WebAssembly::ATOMIC_LOAD_I32_S; + case WebAssembly::ATOMIC_LOAD_I64: return WebAssembly::ATOMIC_LOAD_I64_S; + case WebAssembly::ATOMIC_STORE16_I32: return WebAssembly::ATOMIC_STORE16_I32_S; + case WebAssembly::ATOMIC_STORE16_I64: return WebAssembly::ATOMIC_STORE16_I64_S; + case WebAssembly::ATOMIC_STORE32_I64: return WebAssembly::ATOMIC_STORE32_I64_S; + case WebAssembly::ATOMIC_STORE8_I32: return WebAssembly::ATOMIC_STORE8_I32_S; + case WebAssembly::ATOMIC_STORE8_I64: return WebAssembly::ATOMIC_STORE8_I64_S; + case WebAssembly::ATOMIC_STORE_I32: return WebAssembly::ATOMIC_STORE_I32_S; + case WebAssembly::ATOMIC_STORE_I64: return WebAssembly::ATOMIC_STORE_I64_S; + case WebAssembly::BLOCK: return WebAssembly::BLOCK_S; + case WebAssembly::BR: return WebAssembly::BR_S; + case WebAssembly::BR_IF: return WebAssembly::BR_IF_S; + case WebAssembly::BR_TABLE_I32: return WebAssembly::BR_TABLE_I32_S; + case WebAssembly::BR_TABLE_I64: return WebAssembly::BR_TABLE_I64_S; + case WebAssembly::BR_UNLESS: return WebAssembly::BR_UNLESS_S; + case WebAssembly::CALL_EXCEPT_REF: return WebAssembly::CALL_EXCEPT_REF_S; + case WebAssembly::CALL_F32: return WebAssembly::CALL_F32_S; + case WebAssembly::CALL_F64: return WebAssembly::CALL_F64_S; + case WebAssembly::CALL_I32: return WebAssembly::CALL_I32_S; + case WebAssembly::CALL_I64: return WebAssembly::CALL_I64_S; + case WebAssembly::CALL_INDIRECT_EXCEPT_REF: return WebAssembly::CALL_INDIRECT_EXCEPT_REF_S; + case WebAssembly::CALL_INDIRECT_F32: return WebAssembly::CALL_INDIRECT_F32_S; + case WebAssembly::CALL_INDIRECT_F64: return WebAssembly::CALL_INDIRECT_F64_S; + case WebAssembly::CALL_INDIRECT_I32: return WebAssembly::CALL_INDIRECT_I32_S; + case WebAssembly::CALL_INDIRECT_I64: return WebAssembly::CALL_INDIRECT_I64_S; + case WebAssembly::CALL_INDIRECT_VOID: return WebAssembly::CALL_INDIRECT_VOID_S; + case WebAssembly::CALL_INDIRECT_v16i8: return WebAssembly::CALL_INDIRECT_v16i8_S; + case WebAssembly::CALL_INDIRECT_v4f32: return WebAssembly::CALL_INDIRECT_v4f32_S; + case WebAssembly::CALL_INDIRECT_v4i32: return WebAssembly::CALL_INDIRECT_v4i32_S; + case WebAssembly::CALL_INDIRECT_v8i16: return WebAssembly::CALL_INDIRECT_v8i16_S; + case WebAssembly::CALL_VOID: return WebAssembly::CALL_VOID_S; + case WebAssembly::CALL_v16i8: return WebAssembly::CALL_v16i8_S; + case WebAssembly::CALL_v4f32: return WebAssembly::CALL_v4f32_S; + case WebAssembly::CALL_v4i32: return WebAssembly::CALL_v4i32_S; + case WebAssembly::CALL_v8i16: return WebAssembly::CALL_v8i16_S; + case WebAssembly::CATCHRET: return WebAssembly::CATCHRET_S; + case WebAssembly::CATCH_ALL: return WebAssembly::CATCH_ALL_S; + case WebAssembly::CATCH_I32: return WebAssembly::CATCH_I32_S; + case WebAssembly::CATCH_I64: return WebAssembly::CATCH_I64_S; + case WebAssembly::CEIL_F32: return WebAssembly::CEIL_F32_S; + case WebAssembly::CEIL_F64: return WebAssembly::CEIL_F64_S; + case WebAssembly::CLEANUPRET: return WebAssembly::CLEANUPRET_S; + case WebAssembly::CLZ_I32: return WebAssembly::CLZ_I32_S; + case WebAssembly::CLZ_I64: return WebAssembly::CLZ_I64_S; + case WebAssembly::CONST_F32: return WebAssembly::CONST_F32_S; + case WebAssembly::CONST_F64: return WebAssembly::CONST_F64_S; + case WebAssembly::CONST_I32: return WebAssembly::CONST_I32_S; + case WebAssembly::CONST_I64: return WebAssembly::CONST_I64_S; + case WebAssembly::COPYSIGN_F32: return WebAssembly::COPYSIGN_F32_S; + case WebAssembly::COPYSIGN_F64: return WebAssembly::COPYSIGN_F64_S; + case WebAssembly::COPY_EXCEPT_REF: return WebAssembly::COPY_EXCEPT_REF_S; + case WebAssembly::COPY_F32: return WebAssembly::COPY_F32_S; + case WebAssembly::COPY_F64: return WebAssembly::COPY_F64_S; + case WebAssembly::COPY_I32: return WebAssembly::COPY_I32_S; + case WebAssembly::COPY_I64: return WebAssembly::COPY_I64_S; + case WebAssembly::COPY_V128: return WebAssembly::COPY_V128_S; + case WebAssembly::CTZ_I32: return WebAssembly::CTZ_I32_S; + case WebAssembly::CTZ_I64: return WebAssembly::CTZ_I64_S; + case WebAssembly::CURRENT_MEMORY_I32: return WebAssembly::CURRENT_MEMORY_I32_S; + case WebAssembly::DIV_F32: return WebAssembly::DIV_F32_S; + case WebAssembly::DIV_F64: return WebAssembly::DIV_F64_S; + case WebAssembly::DIV_S_I32: return WebAssembly::DIV_S_I32_S; + case WebAssembly::DIV_S_I64: return WebAssembly::DIV_S_I64_S; + case WebAssembly::DIV_U_I32: return WebAssembly::DIV_U_I32_S; + case WebAssembly::DIV_U_I64: return WebAssembly::DIV_U_I64_S; + case WebAssembly::DROP_EXCEPT_REF: return WebAssembly::DROP_EXCEPT_REF_S; + case WebAssembly::DROP_F32: return WebAssembly::DROP_F32_S; + case WebAssembly::DROP_F64: return WebAssembly::DROP_F64_S; + case WebAssembly::DROP_I32: return WebAssembly::DROP_I32_S; + case WebAssembly::DROP_I64: return WebAssembly::DROP_I64_S; + case WebAssembly::DROP_V128: return WebAssembly::DROP_V128_S; + case WebAssembly::END_BLOCK: return WebAssembly::END_BLOCK_S; + case WebAssembly::END_FUNCTION: return WebAssembly::END_FUNCTION_S; + case WebAssembly::END_LOOP: return WebAssembly::END_LOOP_S; + case WebAssembly::END_TRY: return WebAssembly::END_TRY_S; + case WebAssembly::EQZ_I32: return WebAssembly::EQZ_I32_S; + case WebAssembly::EQZ_I64: return WebAssembly::EQZ_I64_S; + case WebAssembly::EQ_F32: return WebAssembly::EQ_F32_S; + case WebAssembly::EQ_F64: return WebAssembly::EQ_F64_S; + case WebAssembly::EQ_I32: return WebAssembly::EQ_I32_S; + case WebAssembly::EQ_I64: return WebAssembly::EQ_I64_S; + case WebAssembly::F32_CONVERT_S_I32: return WebAssembly::F32_CONVERT_S_I32_S; + case WebAssembly::F32_CONVERT_S_I64: return WebAssembly::F32_CONVERT_S_I64_S; + case WebAssembly::F32_CONVERT_U_I32: return WebAssembly::F32_CONVERT_U_I32_S; + case WebAssembly::F32_CONVERT_U_I64: return WebAssembly::F32_CONVERT_U_I64_S; + case WebAssembly::F32_DEMOTE_F64: return WebAssembly::F32_DEMOTE_F64_S; + case WebAssembly::F32_REINTERPRET_I32: return WebAssembly::F32_REINTERPRET_I32_S; + case WebAssembly::F64_CONVERT_S_I32: return WebAssembly::F64_CONVERT_S_I32_S; + case WebAssembly::F64_CONVERT_S_I64: return WebAssembly::F64_CONVERT_S_I64_S; + case WebAssembly::F64_CONVERT_U_I32: return WebAssembly::F64_CONVERT_U_I32_S; + case WebAssembly::F64_CONVERT_U_I64: return WebAssembly::F64_CONVERT_U_I64_S; + case WebAssembly::F64_PROMOTE_F32: return WebAssembly::F64_PROMOTE_F32_S; + case WebAssembly::F64_REINTERPRET_I64: return WebAssembly::F64_REINTERPRET_I64_S; + case WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF: return WebAssembly::FALLTHROUGH_RETURN_EXCEPT_REF_S; + case WebAssembly::FALLTHROUGH_RETURN_F32: return WebAssembly::FALLTHROUGH_RETURN_F32_S; + case WebAssembly::FALLTHROUGH_RETURN_F64: return WebAssembly::FALLTHROUGH_RETURN_F64_S; + case WebAssembly::FALLTHROUGH_RETURN_I32: return WebAssembly::FALLTHROUGH_RETURN_I32_S; + case WebAssembly::FALLTHROUGH_RETURN_I64: return WebAssembly::FALLTHROUGH_RETURN_I64_S; + case WebAssembly::FALLTHROUGH_RETURN_VOID: return WebAssembly::FALLTHROUGH_RETURN_VOID_S; + case WebAssembly::FALLTHROUGH_RETURN_v16i8: return WebAssembly::FALLTHROUGH_RETURN_v16i8_S; + case WebAssembly::FALLTHROUGH_RETURN_v4f32: return WebAssembly::FALLTHROUGH_RETURN_v4f32_S; + case WebAssembly::FALLTHROUGH_RETURN_v4i32: return WebAssembly::FALLTHROUGH_RETURN_v4i32_S; + case WebAssembly::FALLTHROUGH_RETURN_v8i16: return WebAssembly::FALLTHROUGH_RETURN_v8i16_S; + case WebAssembly::FLOOR_F32: return WebAssembly::FLOOR_F32_S; + case WebAssembly::FLOOR_F64: return WebAssembly::FLOOR_F64_S; + case WebAssembly::FP_TO_SINT_I32_F32: return WebAssembly::FP_TO_SINT_I32_F32_S; + case WebAssembly::FP_TO_SINT_I32_F64: return WebAssembly::FP_TO_SINT_I32_F64_S; + case WebAssembly::FP_TO_SINT_I64_F32: return WebAssembly::FP_TO_SINT_I64_F32_S; + case WebAssembly::FP_TO_SINT_I64_F64: return WebAssembly::FP_TO_SINT_I64_F64_S; + case WebAssembly::FP_TO_UINT_I32_F32: return WebAssembly::FP_TO_UINT_I32_F32_S; + case WebAssembly::FP_TO_UINT_I32_F64: return WebAssembly::FP_TO_UINT_I32_F64_S; + case WebAssembly::FP_TO_UINT_I64_F32: return WebAssembly::FP_TO_UINT_I64_F32_S; + case WebAssembly::FP_TO_UINT_I64_F64: return WebAssembly::FP_TO_UINT_I64_F64_S; + case WebAssembly::GET_GLOBAL_EXCEPT_REF: return WebAssembly::GET_GLOBAL_EXCEPT_REF_S; + case WebAssembly::GET_GLOBAL_F32: return WebAssembly::GET_GLOBAL_F32_S; + case WebAssembly::GET_GLOBAL_F64: return WebAssembly::GET_GLOBAL_F64_S; + case WebAssembly::GET_GLOBAL_I32: return WebAssembly::GET_GLOBAL_I32_S; + case WebAssembly::GET_GLOBAL_I64: return WebAssembly::GET_GLOBAL_I64_S; + case WebAssembly::GET_GLOBAL_V128: return WebAssembly::GET_GLOBAL_V128_S; + case WebAssembly::GET_LOCAL_EXCEPT_REF: return WebAssembly::GET_LOCAL_EXCEPT_REF_S; + case WebAssembly::GET_LOCAL_F32: return WebAssembly::GET_LOCAL_F32_S; + case WebAssembly::GET_LOCAL_F64: return WebAssembly::GET_LOCAL_F64_S; + case WebAssembly::GET_LOCAL_I32: return WebAssembly::GET_LOCAL_I32_S; + case WebAssembly::GET_LOCAL_I64: return WebAssembly::GET_LOCAL_I64_S; + case WebAssembly::GET_LOCAL_V128: return WebAssembly::GET_LOCAL_V128_S; + case WebAssembly::GE_F32: return WebAssembly::GE_F32_S; + case WebAssembly::GE_F64: return WebAssembly::GE_F64_S; + case WebAssembly::GE_S_I32: return WebAssembly::GE_S_I32_S; + case WebAssembly::GE_S_I64: return WebAssembly::GE_S_I64_S; + case WebAssembly::GE_U_I32: return WebAssembly::GE_U_I32_S; + case WebAssembly::GE_U_I64: return WebAssembly::GE_U_I64_S; + case WebAssembly::GROW_MEMORY_I32: return WebAssembly::GROW_MEMORY_I32_S; + case WebAssembly::GT_F32: return WebAssembly::GT_F32_S; + case WebAssembly::GT_F64: return WebAssembly::GT_F64_S; + case WebAssembly::GT_S_I32: return WebAssembly::GT_S_I32_S; + case WebAssembly::GT_S_I64: return WebAssembly::GT_S_I64_S; + case WebAssembly::GT_U_I32: return WebAssembly::GT_U_I32_S; + case WebAssembly::GT_U_I64: return WebAssembly::GT_U_I64_S; + case WebAssembly::I32_EXTEND16_S_I32: return WebAssembly::I32_EXTEND16_S_I32_S; + case WebAssembly::I32_EXTEND8_S_I32: return WebAssembly::I32_EXTEND8_S_I32_S; + case WebAssembly::I32_REINTERPRET_F32: return WebAssembly::I32_REINTERPRET_F32_S; + case WebAssembly::I32_TRUNC_S_F32: return WebAssembly::I32_TRUNC_S_F32_S; + case WebAssembly::I32_TRUNC_S_F64: return WebAssembly::I32_TRUNC_S_F64_S; + case WebAssembly::I32_TRUNC_S_SAT_F32: return WebAssembly::I32_TRUNC_S_SAT_F32_S; + case WebAssembly::I32_TRUNC_S_SAT_F64: return WebAssembly::I32_TRUNC_S_SAT_F64_S; + case WebAssembly::I32_TRUNC_U_F32: return WebAssembly::I32_TRUNC_U_F32_S; + case WebAssembly::I32_TRUNC_U_F64: return WebAssembly::I32_TRUNC_U_F64_S; + case WebAssembly::I32_TRUNC_U_SAT_F32: return WebAssembly::I32_TRUNC_U_SAT_F32_S; + case WebAssembly::I32_TRUNC_U_SAT_F64: return WebAssembly::I32_TRUNC_U_SAT_F64_S; + case WebAssembly::I32_WRAP_I64: return WebAssembly::I32_WRAP_I64_S; + case WebAssembly::I64_EXTEND16_S_I64: return WebAssembly::I64_EXTEND16_S_I64_S; + case WebAssembly::I64_EXTEND32_S_I64: return WebAssembly::I64_EXTEND32_S_I64_S; + case WebAssembly::I64_EXTEND8_S_I64: return WebAssembly::I64_EXTEND8_S_I64_S; + case WebAssembly::I64_EXTEND_S_I32: return WebAssembly::I64_EXTEND_S_I32_S; + case WebAssembly::I64_EXTEND_U_I32: return WebAssembly::I64_EXTEND_U_I32_S; + case WebAssembly::I64_REINTERPRET_F64: return WebAssembly::I64_REINTERPRET_F64_S; + case WebAssembly::I64_TRUNC_S_F32: return WebAssembly::I64_TRUNC_S_F32_S; + case WebAssembly::I64_TRUNC_S_F64: return WebAssembly::I64_TRUNC_S_F64_S; + case WebAssembly::I64_TRUNC_S_SAT_F32: return WebAssembly::I64_TRUNC_S_SAT_F32_S; + case WebAssembly::I64_TRUNC_S_SAT_F64: return WebAssembly::I64_TRUNC_S_SAT_F64_S; + case WebAssembly::I64_TRUNC_U_F32: return WebAssembly::I64_TRUNC_U_F32_S; + case WebAssembly::I64_TRUNC_U_F64: return WebAssembly::I64_TRUNC_U_F64_S; + case WebAssembly::I64_TRUNC_U_SAT_F32: return WebAssembly::I64_TRUNC_U_SAT_F32_S; + case WebAssembly::I64_TRUNC_U_SAT_F64: return WebAssembly::I64_TRUNC_U_SAT_F64_S; + case WebAssembly::LE_F32: return WebAssembly::LE_F32_S; + case WebAssembly::LE_F64: return WebAssembly::LE_F64_S; + case WebAssembly::LE_S_I32: return WebAssembly::LE_S_I32_S; + case WebAssembly::LE_S_I64: return WebAssembly::LE_S_I64_S; + case WebAssembly::LE_U_I32: return WebAssembly::LE_U_I32_S; + case WebAssembly::LE_U_I64: return WebAssembly::LE_U_I64_S; + case WebAssembly::LOAD16_S_I32: return WebAssembly::LOAD16_S_I32_S; + case WebAssembly::LOAD16_S_I64: return WebAssembly::LOAD16_S_I64_S; + case WebAssembly::LOAD16_U_I32: return WebAssembly::LOAD16_U_I32_S; + case WebAssembly::LOAD16_U_I64: return WebAssembly::LOAD16_U_I64_S; + case WebAssembly::LOAD32_S_I64: return WebAssembly::LOAD32_S_I64_S; + case WebAssembly::LOAD32_U_I64: return WebAssembly::LOAD32_U_I64_S; + case WebAssembly::LOAD8_S_I32: return WebAssembly::LOAD8_S_I32_S; + case WebAssembly::LOAD8_S_I64: return WebAssembly::LOAD8_S_I64_S; + case WebAssembly::LOAD8_U_I32: return WebAssembly::LOAD8_U_I32_S; + case WebAssembly::LOAD8_U_I64: return WebAssembly::LOAD8_U_I64_S; + case WebAssembly::LOAD_F32: return WebAssembly::LOAD_F32_S; + case WebAssembly::LOAD_F64: return WebAssembly::LOAD_F64_S; + case WebAssembly::LOAD_I32: return WebAssembly::LOAD_I32_S; + case WebAssembly::LOAD_I64: return WebAssembly::LOAD_I64_S; + case WebAssembly::LOOP: return WebAssembly::LOOP_S; + case WebAssembly::LT_F32: return WebAssembly::LT_F32_S; + case WebAssembly::LT_F64: return WebAssembly::LT_F64_S; + case WebAssembly::LT_S_I32: return WebAssembly::LT_S_I32_S; + case WebAssembly::LT_S_I64: return WebAssembly::LT_S_I64_S; + case WebAssembly::LT_U_I32: return WebAssembly::LT_U_I32_S; + case WebAssembly::LT_U_I64: return WebAssembly::LT_U_I64_S; + case WebAssembly::MAX_F32: return WebAssembly::MAX_F32_S; + case WebAssembly::MAX_F64: return WebAssembly::MAX_F64_S; + case WebAssembly::MEMORY_GROW_I32: return WebAssembly::MEMORY_GROW_I32_S; + case WebAssembly::MEMORY_SIZE_I32: return WebAssembly::MEMORY_SIZE_I32_S; + case WebAssembly::MEM_GROW_I32: return WebAssembly::MEM_GROW_I32_S; + case WebAssembly::MEM_SIZE_I32: return WebAssembly::MEM_SIZE_I32_S; + case WebAssembly::MIN_F32: return WebAssembly::MIN_F32_S; + case WebAssembly::MIN_F64: return WebAssembly::MIN_F64_S; + case WebAssembly::MUL_F32: return WebAssembly::MUL_F32_S; + case WebAssembly::MUL_F32x4: return WebAssembly::MUL_F32x4_S; + case WebAssembly::MUL_F64: return WebAssembly::MUL_F64_S; + case WebAssembly::MUL_I16x8: return WebAssembly::MUL_I16x8_S; + case WebAssembly::MUL_I32: return WebAssembly::MUL_I32_S; + case WebAssembly::MUL_I32x4: return WebAssembly::MUL_I32x4_S; + case WebAssembly::MUL_I64: return WebAssembly::MUL_I64_S; + case WebAssembly::MUL_I8x16: return WebAssembly::MUL_I8x16_S; + case WebAssembly::NEAREST_F32: return WebAssembly::NEAREST_F32_S; + case WebAssembly::NEAREST_F64: return WebAssembly::NEAREST_F64_S; + case WebAssembly::NEG_F32: return WebAssembly::NEG_F32_S; + case WebAssembly::NEG_F64: return WebAssembly::NEG_F64_S; + case WebAssembly::NE_F32: return WebAssembly::NE_F32_S; + case WebAssembly::NE_F64: return WebAssembly::NE_F64_S; + case WebAssembly::NE_I32: return WebAssembly::NE_I32_S; + case WebAssembly::NE_I64: return WebAssembly::NE_I64_S; + case WebAssembly::NOP: return WebAssembly::NOP_S; + case WebAssembly::OR_I32: return WebAssembly::OR_I32_S; + case WebAssembly::OR_I64: return WebAssembly::OR_I64_S; + case WebAssembly::PCALL_INDIRECT_EXCEPT_REF: return WebAssembly::PCALL_INDIRECT_EXCEPT_REF_S; + case WebAssembly::PCALL_INDIRECT_F32: return WebAssembly::PCALL_INDIRECT_F32_S; + case WebAssembly::PCALL_INDIRECT_F64: return WebAssembly::PCALL_INDIRECT_F64_S; + case WebAssembly::PCALL_INDIRECT_I32: return WebAssembly::PCALL_INDIRECT_I32_S; + case WebAssembly::PCALL_INDIRECT_I64: return WebAssembly::PCALL_INDIRECT_I64_S; + case WebAssembly::PCALL_INDIRECT_VOID: return WebAssembly::PCALL_INDIRECT_VOID_S; + case WebAssembly::PCALL_INDIRECT_v16i8: return WebAssembly::PCALL_INDIRECT_v16i8_S; + case WebAssembly::PCALL_INDIRECT_v4f32: return WebAssembly::PCALL_INDIRECT_v4f32_S; + case WebAssembly::PCALL_INDIRECT_v4i32: return WebAssembly::PCALL_INDIRECT_v4i32_S; + case WebAssembly::PCALL_INDIRECT_v8i16: return WebAssembly::PCALL_INDIRECT_v8i16_S; + case WebAssembly::POPCNT_I32: return WebAssembly::POPCNT_I32_S; + case WebAssembly::POPCNT_I64: return WebAssembly::POPCNT_I64_S; + case WebAssembly::REM_S_I32: return WebAssembly::REM_S_I32_S; + case WebAssembly::REM_S_I64: return WebAssembly::REM_S_I64_S; + case WebAssembly::REM_U_I32: return WebAssembly::REM_U_I32_S; + case WebAssembly::REM_U_I64: return WebAssembly::REM_U_I64_S; + case WebAssembly::RETHROW: return WebAssembly::RETHROW_S; + case WebAssembly::RETHROW_TO_CALLER: return WebAssembly::RETHROW_TO_CALLER_S; + case WebAssembly::RETURN_EXCEPT_REF: return WebAssembly::RETURN_EXCEPT_REF_S; + case WebAssembly::RETURN_F32: return WebAssembly::RETURN_F32_S; + case WebAssembly::RETURN_F64: return WebAssembly::RETURN_F64_S; + case WebAssembly::RETURN_I32: return WebAssembly::RETURN_I32_S; + case WebAssembly::RETURN_I64: return WebAssembly::RETURN_I64_S; + case WebAssembly::RETURN_VOID: return WebAssembly::RETURN_VOID_S; + case WebAssembly::RETURN_v16i8: return WebAssembly::RETURN_v16i8_S; + case WebAssembly::RETURN_v4f32: return WebAssembly::RETURN_v4f32_S; + case WebAssembly::RETURN_v4i32: return WebAssembly::RETURN_v4i32_S; + case WebAssembly::RETURN_v8i16: return WebAssembly::RETURN_v8i16_S; + case WebAssembly::ROTL_I32: return WebAssembly::ROTL_I32_S; + case WebAssembly::ROTL_I64: return WebAssembly::ROTL_I64_S; + case WebAssembly::ROTR_I32: return WebAssembly::ROTR_I32_S; + case WebAssembly::ROTR_I64: return WebAssembly::ROTR_I64_S; + case WebAssembly::SELECT_EXCEPT_REF: return WebAssembly::SELECT_EXCEPT_REF_S; + case WebAssembly::SELECT_F32: return WebAssembly::SELECT_F32_S; + case WebAssembly::SELECT_F64: return WebAssembly::SELECT_F64_S; + case WebAssembly::SELECT_I32: return WebAssembly::SELECT_I32_S; + case WebAssembly::SELECT_I64: return WebAssembly::SELECT_I64_S; + case WebAssembly::SET_GLOBAL_EXCEPT_REF: return WebAssembly::SET_GLOBAL_EXCEPT_REF_S; + case WebAssembly::SET_GLOBAL_F32: return WebAssembly::SET_GLOBAL_F32_S; + case WebAssembly::SET_GLOBAL_F64: return WebAssembly::SET_GLOBAL_F64_S; + case WebAssembly::SET_GLOBAL_I32: return WebAssembly::SET_GLOBAL_I32_S; + case WebAssembly::SET_GLOBAL_I64: return WebAssembly::SET_GLOBAL_I64_S; + case WebAssembly::SET_GLOBAL_V128: return WebAssembly::SET_GLOBAL_V128_S; + case WebAssembly::SET_LOCAL_EXCEPT_REF: return WebAssembly::SET_LOCAL_EXCEPT_REF_S; + case WebAssembly::SET_LOCAL_F32: return WebAssembly::SET_LOCAL_F32_S; + case WebAssembly::SET_LOCAL_F64: return WebAssembly::SET_LOCAL_F64_S; + case WebAssembly::SET_LOCAL_I32: return WebAssembly::SET_LOCAL_I32_S; + case WebAssembly::SET_LOCAL_I64: return WebAssembly::SET_LOCAL_I64_S; + case WebAssembly::SET_LOCAL_V128: return WebAssembly::SET_LOCAL_V128_S; + case WebAssembly::SHL_I32: return WebAssembly::SHL_I32_S; + case WebAssembly::SHL_I64: return WebAssembly::SHL_I64_S; + case WebAssembly::SHR_S_I32: return WebAssembly::SHR_S_I32_S; + case WebAssembly::SHR_S_I64: return WebAssembly::SHR_S_I64_S; + case WebAssembly::SHR_U_I32: return WebAssembly::SHR_U_I32_S; + case WebAssembly::SHR_U_I64: return WebAssembly::SHR_U_I64_S; + case WebAssembly::SQRT_F32: return WebAssembly::SQRT_F32_S; + case WebAssembly::SQRT_F64: return WebAssembly::SQRT_F64_S; + case WebAssembly::STORE16_I32: return WebAssembly::STORE16_I32_S; + case WebAssembly::STORE16_I64: return WebAssembly::STORE16_I64_S; + case WebAssembly::STORE32_I64: return WebAssembly::STORE32_I64_S; + case WebAssembly::STORE8_I32: return WebAssembly::STORE8_I32_S; + case WebAssembly::STORE8_I64: return WebAssembly::STORE8_I64_S; + case WebAssembly::STORE_F32: return WebAssembly::STORE_F32_S; + case WebAssembly::STORE_F64: return WebAssembly::STORE_F64_S; + case WebAssembly::STORE_I32: return WebAssembly::STORE_I32_S; + case WebAssembly::STORE_I64: return WebAssembly::STORE_I64_S; + case WebAssembly::SUB_F32: return WebAssembly::SUB_F32_S; + case WebAssembly::SUB_F32x4: return WebAssembly::SUB_F32x4_S; + case WebAssembly::SUB_F64: return WebAssembly::SUB_F64_S; + case WebAssembly::SUB_I16x8: return WebAssembly::SUB_I16x8_S; + case WebAssembly::SUB_I32: return WebAssembly::SUB_I32_S; + case WebAssembly::SUB_I32x4: return WebAssembly::SUB_I32x4_S; + case WebAssembly::SUB_I64: return WebAssembly::SUB_I64_S; + case WebAssembly::SUB_I8x16: return WebAssembly::SUB_I8x16_S; + case WebAssembly::TEE_EXCEPT_REF: return WebAssembly::TEE_EXCEPT_REF_S; + case WebAssembly::TEE_F32: return WebAssembly::TEE_F32_S; + case WebAssembly::TEE_F64: return WebAssembly::TEE_F64_S; + case WebAssembly::TEE_I32: return WebAssembly::TEE_I32_S; + case WebAssembly::TEE_I64: return WebAssembly::TEE_I64_S; + case WebAssembly::TEE_LOCAL_EXCEPT_REF: return WebAssembly::TEE_LOCAL_EXCEPT_REF_S; + case WebAssembly::TEE_LOCAL_F32: return WebAssembly::TEE_LOCAL_F32_S; + case WebAssembly::TEE_LOCAL_F64: return WebAssembly::TEE_LOCAL_F64_S; + case WebAssembly::TEE_LOCAL_I32: return WebAssembly::TEE_LOCAL_I32_S; + case WebAssembly::TEE_LOCAL_I64: return WebAssembly::TEE_LOCAL_I64_S; + case WebAssembly::TEE_LOCAL_V128: return WebAssembly::TEE_LOCAL_V128_S; + case WebAssembly::TEE_V128: return WebAssembly::TEE_V128_S; + case WebAssembly::THROW_I32: return WebAssembly::THROW_I32_S; + case WebAssembly::THROW_I64: return WebAssembly::THROW_I64_S; + case WebAssembly::TRUNC_F32: return WebAssembly::TRUNC_F32_S; + case WebAssembly::TRUNC_F64: return WebAssembly::TRUNC_F64_S; + case WebAssembly::TRY: return WebAssembly::TRY_S; + case WebAssembly::UNREACHABLE: return WebAssembly::UNREACHABLE_S; + case WebAssembly::XOR_I32: return WebAssembly::XOR_I32_S; + case WebAssembly::XOR_I64: return WebAssembly::XOR_I64_S; + } +} Index: lib/Target/WebAssembly/WebAssemblyInstrMemory.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -57,11 +57,12 @@ // Defines atomic and non-atomic loads, regular and extending. multiclass WebAssemblyLoad { + let mayLoad = 1 in defm "": I<(outs rc:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), - !strconcat(Name, "\t${off}, ${p2align}"), Opcode>; + !strconcat(Name, "\t${off}${p2align}"), Opcode>; } // Basic load. @@ -307,12 +308,13 @@ // Defines atomic and non-atomic stores, regular and truncating multiclass WebAssemblyStore { + let mayStore = 1 in defm "" : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), (outs), (ins P2Align:$p2align, offset32_op:$off), [], !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), - !strconcat(Name, "\t${off}, ${p2align}"), Opcode>; + !strconcat(Name, "\t${off}${p2align}"), Opcode>; } // Basic store. // Note: WebAssembly inverts SelectionDAG's usual operand order. @@ -470,12 +472,12 @@ // Grow memory. defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), - (outs), (ins i32imm:$flags, I32:$delta), + (outs), (ins i32imm:$flags), [(set I32:$dst, (int_wasm_memory_grow (i32 imm:$flags), I32:$delta))], "memory.grow\t$dst, $flags, $delta", - "memory.grow\t$flags, $delta", 0x3f>, + "memory.grow\t$flags", 0x3f>, Requires<[HasAddr32]>; defm MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), (outs), (ins i32imm:$flags), Index: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -317,9 +317,6 @@ // converted into a local. addPass(createWebAssemblyFixIrreducibleControlFlow()); - // Insert explicit get_local and set_local operators. - addPass(createWebAssemblyExplicitLocals()); - // Do various transformations for exception handling addPass(createWebAssemblyLateEHPrepare()); @@ -337,6 +334,9 @@ if (getOptLevel() != CodeGenOpt::None) addPass(createWebAssemblyPeephole()); + // Insert explicit get_local and set_local operators. + addPass(createWebAssemblyExplicitLocals()); + // Create a mapping from LLVM CodeGen virtual registers to wasm registers. addPass(createWebAssemblyRegNumbering()); } Index: test/CodeGen/WebAssembly/address-offsets.ll =================================================================== --- test/CodeGen/WebAssembly/address-offsets.ll +++ test/CodeGen/WebAssembly/address-offsets.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test folding constant offsets and symbols into load and store addresses under ; a variety of circumstances. Index: test/CodeGen/WebAssembly/atomic-rmw.ll =================================================================== --- test/CodeGen/WebAssembly/atomic-rmw.ll +++ test/CodeGen/WebAssembly/atomic-rmw.ll @@ -1,5 +1,5 @@ -; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s +; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=+atomics,+sign-ext | FileCheck %s ; Test atomic RMW (read-modify-write) instructions are assembled properly. Index: test/CodeGen/WebAssembly/byval.ll =================================================================== --- test/CodeGen/WebAssembly/byval.ll +++ test/CodeGen/WebAssembly/byval.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs -fast-isel | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs -fast-isel | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/call.ll =================================================================== --- test/CodeGen/WebAssembly/call.ll +++ test/CodeGen/WebAssembly/call.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-temporary-workarounds=false | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 -wasm-temporary-workarounds=false | FileCheck %s ; Test that basic call operations assemble as expected. Index: test/CodeGen/WebAssembly/cfg-stackify.ll =================================================================== --- test/CodeGen/WebAssembly/cfg-stackify.ll +++ test/CodeGen/WebAssembly/cfg-stackify.ll @@ -1,5 +1,5 @@ -; 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 -; 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 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -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 ; Test the CFG stackifier pass. Index: test/CodeGen/WebAssembly/cfi.ll =================================================================== --- test/CodeGen/WebAssembly/cfi.ll +++ test/CodeGen/WebAssembly/cfi.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -lowertypetests < %s | llc -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: opt -S -lowertypetests < %s | llc -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Tests that we correctly assign indexes for control flow integrity. Index: test/CodeGen/WebAssembly/comparisons_f32.ll =================================================================== --- test/CodeGen/WebAssembly/comparisons_f32.ll +++ test/CodeGen/WebAssembly/comparisons_f32.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 32-bit floating-point comparison operations assemble as ; expected. Index: test/CodeGen/WebAssembly/comparisons_f64.ll =================================================================== --- test/CodeGen/WebAssembly/comparisons_f64.ll +++ test/CodeGen/WebAssembly/comparisons_f64.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 64-bit floating-point comparison operations assemble as ; expected. Index: test/CodeGen/WebAssembly/comparisons_i32.ll =================================================================== --- test/CodeGen/WebAssembly/comparisons_i32.ll +++ test/CodeGen/WebAssembly/comparisons_i32.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic 32-bit integer comparison operations assemble as expected. Index: test/CodeGen/WebAssembly/comparisons_i64.ll =================================================================== --- test/CodeGen/WebAssembly/comparisons_i64.ll +++ test/CodeGen/WebAssembly/comparisons_i64.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic 64-bit integer comparison operations assemble as expected. Index: test/CodeGen/WebAssembly/conv-trap.ll =================================================================== --- test/CodeGen/WebAssembly/conv-trap.ll +++ test/CodeGen/WebAssembly/conv-trap.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-nontrapping-fptoint | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=-nontrapping-fptoint | FileCheck %s ; Test that basic conversion operations assemble as expected using ; the trapping opcodes and explicit code to suppress the trapping. Index: test/CodeGen/WebAssembly/conv.ll =================================================================== --- test/CodeGen/WebAssembly/conv.ll +++ test/CodeGen/WebAssembly/conv.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+nontrapping-fptoint | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=+nontrapping-fptoint | FileCheck %s ; Test that basic conversion operations assemble as expected. Index: test/CodeGen/WebAssembly/copysign-casts.ll =================================================================== --- test/CodeGen/WebAssembly/copysign-casts.ll +++ test/CodeGen/WebAssembly/copysign-casts.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; DAGCombiner oddly folds casts into the rhs of copysign. Test that they get ; unfolded. Index: test/CodeGen/WebAssembly/divrem-constant.ll =================================================================== --- test/CodeGen/WebAssembly/divrem-constant.ll +++ test/CodeGen/WebAssembly/divrem-constant.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that integer div and rem by constant are optimized appropriately. Index: test/CodeGen/WebAssembly/exception.ll =================================================================== --- test/CodeGen/WebAssembly/exception.ll +++ test/CodeGen/WebAssembly/exception.ll @@ -1,5 +1,5 @@ -; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -exception-model=wasm -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s +; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -exception-model=wasm +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -exception-model=wasm -mattr=+exception-handling | FileCheck -allow-deprecated-dag-overlap %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/explicit-locals.mir =================================================================== --- test/CodeGen/WebAssembly/explicit-locals.mir +++ test/CodeGen/WebAssembly/explicit-locals.mir @@ -1,4 +1,4 @@ -# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass wasm-explicit-locals %s -o - | FileCheck %s +# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass wasm-explicit-locals -wasm-explicit-locals-codegen-test-mode %s -o - | FileCheck %s # When a drop instruction is inserted to drop a dead register operand, the # original operand should be marked not dead anymore because it is now used by Index: test/CodeGen/WebAssembly/f16.ll =================================================================== --- test/CodeGen/WebAssembly/f16.ll +++ test/CodeGen/WebAssembly/f16.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel | FileCheck %s ; Test that f16 is expanded. Index: test/CodeGen/WebAssembly/f32.ll =================================================================== --- test/CodeGen/WebAssembly/f32.ll +++ test/CodeGen/WebAssembly/f32.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 32-bit floating-point operations assemble as expected. Index: test/CodeGen/WebAssembly/f64.ll =================================================================== --- test/CodeGen/WebAssembly/f64.ll +++ test/CodeGen/WebAssembly/f64.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 64-bit floating-point operations assemble as expected. Index: test/CodeGen/WebAssembly/fast-isel-br-i1.ll =================================================================== --- test/CodeGen/WebAssembly/fast-isel-br-i1.ll +++ test/CodeGen/WebAssembly/fast-isel-br-i1.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -fast-isel -asm-verbose=false | FileCheck %s +; RUN: llc < %s -fast-isel -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/fast-isel-i24.ll =================================================================== --- test/CodeGen/WebAssembly/fast-isel-i24.ll +++ test/CodeGen/WebAssembly/fast-isel-i24.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -O0 +; RUN: llc < %s -O0 -wasm-explicit-locals-codegen-test-mode ; PR36564 ; PR37546 Index: test/CodeGen/WebAssembly/fast-isel-i256.ll =================================================================== --- test/CodeGen/WebAssembly/fast-isel-i256.ll +++ test/CodeGen/WebAssembly/fast-isel-i256.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -O0 +; RUN: llc < %s -O0 -wasm-explicit-locals-codegen-test-mode ; PR36564 ; PR37546 Index: test/CodeGen/WebAssembly/fast-isel-noreg.ll =================================================================== --- test/CodeGen/WebAssembly/fast-isel-noreg.ll +++ test/CodeGen/WebAssembly/fast-isel-noreg.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -asm-verbose=false -fast-isel -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode -fast-isel -verify-machineinstrs | FileCheck %s ; Test that FastISel does not generate instructions with NoReg Index: test/CodeGen/WebAssembly/fast-isel.ll =================================================================== --- test/CodeGen/WebAssembly/fast-isel.ll +++ test/CodeGen/WebAssembly/fast-isel.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s -asm-verbose=false \ ; RUN: -fast-isel -fast-isel-abort=1 -verify-machineinstrs \ -; RUN: -disable-wasm-explicit-locals \ +; RUN: -wasm-register-codegen-test-mode \ ; RUN: | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" Index: test/CodeGen/WebAssembly/frem.ll =================================================================== --- test/CodeGen/WebAssembly/frem.ll +++ test/CodeGen/WebAssembly/frem.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that the frem instruction works. Index: test/CodeGen/WebAssembly/func.ll =================================================================== --- test/CodeGen/WebAssembly/func.ll +++ test/CodeGen/WebAssembly/func.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that basic functions assemble as expected. Index: test/CodeGen/WebAssembly/function-bitcasts-varargs.ll =================================================================== --- test/CodeGen/WebAssembly/function-bitcasts-varargs.ll +++ test/CodeGen/WebAssembly/function-bitcasts-varargs.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-temporary-workarounds=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that function pointer casts casting away varargs are replaced with ; wrappers. Index: test/CodeGen/WebAssembly/function-bitcasts.ll =================================================================== --- test/CodeGen/WebAssembly/function-bitcasts.ll +++ test/CodeGen/WebAssembly/function-bitcasts.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode -enable-emscripten-cxx-exceptions -wasm-temporary-workarounds=false | FileCheck %s ; Test that function pointer casts are replaced with wrappers. Index: test/CodeGen/WebAssembly/global.ll =================================================================== --- test/CodeGen/WebAssembly/global.ll +++ test/CodeGen/WebAssembly/global.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that globals assemble as expected. Index: test/CodeGen/WebAssembly/i128.ll =================================================================== --- test/CodeGen/WebAssembly/i128.ll +++ test/CodeGen/WebAssembly/i128.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 128-bit integer operations assemble as expected. Index: test/CodeGen/WebAssembly/i32-load-store-alignment.ll =================================================================== --- test/CodeGen/WebAssembly/i32-load-store-alignment.ll +++ test/CodeGen/WebAssembly/i32-load-store-alignment.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test loads and stores with custom alignment values. Index: test/CodeGen/WebAssembly/i32.ll =================================================================== --- test/CodeGen/WebAssembly/i32.ll +++ test/CodeGen/WebAssembly/i32.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 32-bit integer operations assemble as expected. Index: test/CodeGen/WebAssembly/i64-load-store-alignment.ll =================================================================== --- test/CodeGen/WebAssembly/i64-load-store-alignment.ll +++ test/CodeGen/WebAssembly/i64-load-store-alignment.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test loads and stores with custom alignment values. Index: test/CodeGen/WebAssembly/i64.ll =================================================================== --- test/CodeGen/WebAssembly/i64.ll +++ test/CodeGen/WebAssembly/i64.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic 64-bit integer operations assemble as expected. Index: test/CodeGen/WebAssembly/ident.ll =================================================================== --- test/CodeGen/WebAssembly/ident.ll +++ test/CodeGen/WebAssembly/ident.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test llvm.ident. Index: test/CodeGen/WebAssembly/immediates.ll =================================================================== --- test/CodeGen/WebAssembly/immediates.ll +++ test/CodeGen/WebAssembly/immediates.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that basic immediates assemble as expected. Index: test/CodeGen/WebAssembly/implicit-def.ll =================================================================== --- test/CodeGen/WebAssembly/implicit-def.ll +++ test/CodeGen/WebAssembly/implicit-def.ll @@ -1,4 +1,4 @@ -; RUN: llc -o - %s -asm-verbose=false | FileCheck %s +; RUN: llc -o - %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/import-module.ll =================================================================== --- test/CodeGen/WebAssembly/import-module.ll +++ test/CodeGen/WebAssembly/import-module.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/indirect-import.ll =================================================================== --- test/CodeGen/WebAssembly/indirect-import.ll +++ test/CodeGen/WebAssembly/indirect-import.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs -fast-isel | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -verify-machineinstrs -fast-isel | FileCheck %s ; ModuleID = 'test/dot_s/indirect-import.c' source_filename = "test/dot_s/indirect-import.c" Index: test/CodeGen/WebAssembly/inline-asm-m.ll =================================================================== --- test/CodeGen/WebAssembly/inline-asm-m.ll +++ test/CodeGen/WebAssembly/inline-asm-m.ll @@ -1,4 +1,4 @@ -; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -no-integrated-as +; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -no-integrated-as ; Test basic inline assembly "m" operands, which are unsupported. Pass ; -no-integrated-as since these aren't actually valid assembly syntax. Index: test/CodeGen/WebAssembly/inline-asm.ll =================================================================== --- test/CodeGen/WebAssembly/inline-asm.ll +++ test/CodeGen/WebAssembly/inline-asm.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -no-integrated-as | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -no-integrated-as | FileCheck %s ; Test basic inline assembly. Pass -no-integrated-as since these aren't ; actually valid assembly syntax. Index: test/CodeGen/WebAssembly/irreducible-cfg.ll =================================================================== --- test/CodeGen/WebAssembly/irreducible-cfg.ll +++ test/CodeGen/WebAssembly/irreducible-cfg.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-block-placement -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-block-placement -wasm-register-codegen-test-mode | FileCheck %s ; Test irreducible CFG handling. Index: test/CodeGen/WebAssembly/legalize.ll =================================================================== --- test/CodeGen/WebAssembly/legalize.ll +++ test/CodeGen/WebAssembly/legalize.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test various types and operators that need to be legalized. Index: test/CodeGen/WebAssembly/libcalls.ll =================================================================== --- test/CodeGen/WebAssembly/libcalls.ll +++ test/CodeGen/WebAssembly/libcalls.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test a subset of compiler-rt/libm libcalls expected to be emitted by the wasm backend Index: test/CodeGen/WebAssembly/load-ext-atomic.ll =================================================================== --- test/CodeGen/WebAssembly/load-ext-atomic.ll +++ test/CodeGen/WebAssembly/load-ext-atomic.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that extending loads are assembled properly. Index: test/CodeGen/WebAssembly/load-ext.ll =================================================================== --- test/CodeGen/WebAssembly/load-ext.ll +++ test/CodeGen/WebAssembly/load-ext.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that extending loads are assembled properly. Index: test/CodeGen/WebAssembly/load-store-i1.ll =================================================================== --- test/CodeGen/WebAssembly/load-store-i1.ll +++ test/CodeGen/WebAssembly/load-store-i1.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that i1 extending loads and truncating stores are assembled properly. Index: test/CodeGen/WebAssembly/load.ll =================================================================== --- test/CodeGen/WebAssembly/load.ll +++ test/CodeGen/WebAssembly/load.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic loads are assembled properly. Index: test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll =================================================================== --- test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll +++ test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll @@ -39,9 +39,9 @@ %arraydecay1 = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %buf, i32 0, i32 0 call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 1) #1 unreachable -; SJLJ: i32.call ${{[a-zA-Z0-9]+}}=, saveSetjmp@FUNCTION -; SJLJ: i32.call ${{[a-zA-Z0-9]+}}=, testSetjmp@FUNCTION -; NONE: i32.call ${{[a-zA-Z0-9]+}}=, setjmp@FUNCTION +; SJLJ: i32.call saveSetjmp@FUNCTION +; SJLJ: i32.call testSetjmp@FUNCTION +; NONE: i32.call setjmp@FUNCTION ; NONE: call longjmp@FUNCTION } Index: test/CodeGen/WebAssembly/lower-global-dtors.ll =================================================================== --- test/CodeGen/WebAssembly/lower-global-dtors.ll +++ test/CodeGen/WebAssembly/lower-global-dtors.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck --check-prefix=CHECK --check-prefix=FINI --check-prefix=NULL %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck --check-prefix=CHECK --check-prefix=FINI --check-prefix=NULL %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/mem-intrinsics.ll =================================================================== --- test/CodeGen/WebAssembly/mem-intrinsics.ll +++ test/CodeGen/WebAssembly/mem-intrinsics.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -tail-dup-placement=0 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -tail-dup-placement=0 | FileCheck %s ; Test memcpy, memmove, and memset intrinsics. Index: test/CodeGen/WebAssembly/memory-addr32.ll =================================================================== --- test/CodeGen/WebAssembly/memory-addr32.ll +++ test/CodeGen/WebAssembly/memory-addr32.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that basic memory operations assemble as expected with 32-bit addresses. Index: test/CodeGen/WebAssembly/muloti4.ll =================================================================== --- test/CodeGen/WebAssembly/muloti4.ll +++ test/CodeGen/WebAssembly/muloti4.ll @@ -1,4 +1,4 @@ -; RUN: llc -asm-verbose=false < %s | FileCheck %s +; RUN: llc -asm-verbose=false < %s -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that 128-bit smul.with.overflow assembles as expected. Index: test/CodeGen/WebAssembly/negative-base-reg.ll =================================================================== --- test/CodeGen/WebAssembly/negative-base-reg.ll +++ test/CodeGen/WebAssembly/negative-base-reg.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/offset-atomics.ll =================================================================== --- test/CodeGen/WebAssembly/offset-atomics.ll +++ test/CodeGen/WebAssembly/offset-atomics.ll @@ -1,5 +1,5 @@ ; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=+atomics,+sign-ext | FileCheck %s ; Test that atomic loads are assembled properly. Index: test/CodeGen/WebAssembly/offset-fastisel.ll =================================================================== --- test/CodeGen/WebAssembly/offset-fastisel.ll +++ test/CodeGen/WebAssembly/offset-fastisel.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; TODO: Merge this with offset.ll when fast-isel matches better. Index: test/CodeGen/WebAssembly/offset-folding.ll =================================================================== --- test/CodeGen/WebAssembly/offset-folding.ll +++ test/CodeGen/WebAssembly/offset-folding.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that constant offsets can be folded into global addresses. Index: test/CodeGen/WebAssembly/offset.ll =================================================================== --- test/CodeGen/WebAssembly/offset.ll +++ test/CodeGen/WebAssembly/offset.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode -disable-wasm-fallthrough-return-opt | FileCheck %s ; Test constant load and store address offsets. Index: test/CodeGen/WebAssembly/phi.ll =================================================================== --- test/CodeGen/WebAssembly/phi.ll +++ test/CodeGen/WebAssembly/phi.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs | FileCheck %s ; Test that phis are lowered. Index: test/CodeGen/WebAssembly/reg-stackify.ll =================================================================== --- test/CodeGen/WebAssembly/reg-stackify.ll +++ test/CodeGen/WebAssembly/reg-stackify.ll @@ -1,7 +1,11 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s --check-prefix=NOREGS ; Test the register stackifier pass. +; We have two sets of tests, one with registers and implicit locals, and +; a stack / explicit locals based version (NOREGS). + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -9,6 +13,8 @@ ; CHECK-LABEL: no0: ; CHECK: return $1{{$}} +; NOREGS-LABEL: no0: +; NOREGS: return{{$}} define i32 @no0(i32* %p, i32* %q) { %t = load i32, i32* %q store i32 0, i32* %p @@ -19,6 +25,8 @@ ; CHECK-LABEL: no1: ; CHECK: return $1{{$}} +; NOREGS-LABEL: no1: +; NOREGS: return{{$}} define i32 @no1(i32* %p, i32* dereferenceable(4) %q) { %t = load volatile i32, i32* %q, !invariant.load !0 store volatile i32 0, i32* %p @@ -29,6 +37,8 @@ ; CHECK-LABEL: yes0: ; CHECK: return $pop{{[0-9]+}}{{$}} +; NOREGS-LABEL: yes0: +; NOREGS: return{{$}} define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) { %t = load i32, i32* %q, !invariant.load !0 store i32 0, i32* %p @@ -39,6 +49,8 @@ ; CHECK-LABEL: yes1: ; CHECK: return $pop0{{$}} +; NOREGS-LABEL: yes1: +; NOREGS: return{{$}} define i32 @yes1(i32* %q) { %t = load volatile i32, i32* %q ret i32 %t @@ -48,6 +60,8 @@ ; CHECK-LABEL: sink_trap: ; CHECK: return $pop{{[0-9]+}}{{$}} +; NOREGS-LABEL: sink_trap: +; NOREGS: return{{$}} define i32 @sink_trap(i32 %x, i32 %y, i32* %p) { %t = sdiv i32 %x, %y store volatile i32 0, i32* %p @@ -58,6 +72,8 @@ ; CHECK-LABEL: sink_readnone_call: ; CHECK: return $pop0{{$}} +; NOREGS-LABEL: sink_readnone_call: +; NOREGS: return{{$}} declare i32 @readnone_callee() readnone nounwind define i32 @sink_readnone_call(i32 %x, i32 %y, i32* %p) { %t = call i32 @readnone_callee() @@ -69,6 +85,8 @@ ; CHECK-LABEL: no_sink_readonly_call: ; CHECK: return ${{[0-9]+}}{{$}} +; NOREGS-LABEL: no_sink_readonly_call: +; NOREGS: return{{$}} declare i32 @readonly_callee() readonly nounwind define i32 @no_sink_readonly_call(i32 %x, i32 %y, i32* %p) { %t = call i32 @readonly_callee() @@ -105,6 +123,34 @@ ; CHECK-NEXT: end_block{{$}} ; CHECK-NEXT: i32.const $push14=, 1{{$}} ; CHECK-NEXT: return $pop14{{$}} +; NOREGS-LABEL: stack_uses: +; NOREGS: .param i32, i32, i32, i32{{$}} +; NOREGS-NEXT: .result i32{{$}} +; NOREGS-NEXT: block {{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.const 2{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.const 2{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.ne {{$}} +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: i32.const 0{{$}} +; NOREGS-NEXT: return{{$}} +; NOREGS-NEXT: .LBB7_2: +; NOREGS-NEXT: end_block{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: return{{$}} define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) { entry: %c = icmp sle i32 %x, 0 @@ -137,6 +183,26 @@ ; CHECK-NEXT: .LBB8_3: ; CHECK-NEXT: end_block{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: multiple_uses: +; NOREGS: .param i32, i32, i32{{$}} +; NOREGS: .local i32{{$}} +; NOREGS-NEXT: block {{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: i32.load 0{{$}} +; NOREGS-NEXT: tee_local 3{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.ge_u +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.lt_u +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.store 0{{$}} +; NOREGS-NEXT: .LBB8_3: +; NOREGS-NEXT: end_block{{$}} +; NOREGS-NEXT: return{{$}} define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind { bb: br label %loop @@ -167,6 +233,11 @@ ; CHECK-NEXT: call ; CHECK: store ; CHECK-NEXT: call +; NOREGS: side_effects: +; NOREGS: store +; NOREGS-NEXT: call +; NOREGS: store +; NOREGS-NEXT: call declare void @evoke_side_effects() define hidden void @stackify_store_across_side_effects(double* nocapture %d) { entry: @@ -200,6 +271,41 @@ ; CHECK-NEXT: i32.div_s $push[[L13:[0-9]+]]=, $pop[[L9]], $pop[[L12]]{{$}} ; CHECK-NEXT: i32.div_s $push[[L14:[0-9]+]]=, $pop[[L6]], $pop[[L13]]{{$}} ; CHECK-NEXT: return $pop[[L14]]{{$}} +; NOREGS-LABEL: div_tree: +; NOREGS: .param i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}} +; NOREGS-NEXT: .result i32{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 4{{$}} +; NOREGS-NEXT: get_local 5{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 6{{$}} +; NOREGS-NEXT: get_local 7{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 8{{$}} +; NOREGS-NEXT: get_local 9{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 10{{$}} +; NOREGS-NEXT: get_local 11{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 12{{$}} +; NOREGS-NEXT: get_local 13{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 14{{$}} +; NOREGS-NEXT: get_local 15{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: return{{$}} 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) { entry: %div = sdiv i32 %a, %b @@ -229,6 +335,16 @@ ; CHECK-NEXT: call use_a@FUNCTION, $pop[[NUM1]]{{$}} ; CHECK-NEXT: call use_b@FUNCTION, $[[NUM2]]{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: simple_multiple_use: +; NOREGS: .param i32, i32{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.mul +; NOREGS-NEXT: tee_local 1{{$}} +; NOREGS-NEXT: call use_a@FUNCTION{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: call use_b@FUNCTION{{$}} +; NOREGS-NEXT: return{{$}} declare void @use_a(i32) declare void @use_b(i32) define void @simple_multiple_use(i32 %x, i32 %y) { @@ -246,6 +362,15 @@ ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}} ; CHECK-NEXT: call use_2@FUNCTION, $pop[[NUM1]], $[[NUM2]]{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: multiple_uses_in_same_insn: +; NOREGS: .param i32, i32{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.mul +; NOREGS-NEXT: tee_local 1{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: call use_2@FUNCTION{{$}} +; NOREGS-NEXT: return{{$}} declare void @use_2(i32, i32) define void @multiple_uses_in_same_insn(i32 %x, i32 %y) { %mul = mul i32 %y, %x @@ -264,6 +389,15 @@ ; CHECK-NEXT: i32.call $push3=, blue@FUNCTION{{$}} ; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} ; CHECK-NEXT: return $pop4{{$}} +; NOREGS-LABEL: commute: +; NOREGS-NOT: param +; NOREGS: .result i32{{$}} +; NOREGS-NEXT: i32.call red@FUNCTION{{$}} +; NOREGS-NEXT: i32.call green@FUNCTION{{$}} +; NOREGS-NEXT: i32.add {{$}} +; NOREGS-NEXT: i32.call blue@FUNCTION{{$}} +; NOREGS-NEXT: i32.add {{$}} +; NOREGS-NEXT: return{{$}} declare i32 @red() declare i32 @green() declare i32 @blue() @@ -287,6 +421,19 @@ ; CHECK-NEXT: i32.sub $push3=, $pop2, $1 ; CHECK-NEXT: i32.div_s $push4=, $pop3, $1 ; CHECK-NEXT: return $pop4 +; NOREGS-LABEL: no_stackify_past_use: +; NOREGS: get_local 0{{$}} +; NOREGS-NEXT: i32.call callee@FUNCTION +; NOREGS-NEXT: set_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.const 1 +; NOREGS-NEXT: i32.add +; NOREGS-NEXT: i32.call callee@FUNCTION +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.sub +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.div_s +; NOREGS-NEXT: return declare i32 @callee(i32) define i32 @no_stackify_past_use(i32 %arg) { %tmp1 = call i32 @callee(i32 %arg) @@ -309,6 +456,18 @@ ; CHECK: i32.add $push3=, $1, $pop2 ; CHECK: i32.mul $push4=, $pop[[L1]], $pop3 ; CHECK: return $pop4 +; NOREGS-LABEL: commute_to_fix_ordering: +; NOREGS: get_local 0{{$}} +; NOREGS: i32.call callee@FUNCTION +; NOREGS: tee_local 1 +; NOREGS: get_local 1{{$}} +; NOREGS: get_local 0{{$}} +; NOREGS: i32.const 1 +; NOREGS: i32.add +; NOREGS: i32.call callee@FUNCTION +; NOREGS: i32.add +; NOREGS: i32.mul +; NOREGS: return define i32 @commute_to_fix_ordering(i32 %arg) { %tmp1 = call i32 @callee(i32 %arg) %tmp2 = add i32 %arg, 1 @@ -325,6 +484,10 @@ ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}} ; CHECK-NEXT: f64.select $push{{[0-9]+}}=, $pop{{[0-9]+}}, $pop[[NUM1]], ${{[0-9]+}}{{$}} ; CHECK: $[[NUM2]]=, +; NOREGS-LABEL: multiple_defs: +; NOREGS: f64.add +; NOREGS: tee_local +; NOREGS: f64.select define void @multiple_defs(i32 %arg, i32 %arg1, i1 %arg2, i1 %arg3, i1 %arg4) { bb: br label %bb5 @@ -367,6 +530,10 @@ ; CHECK: i32.call $0=, red ; CHECK: i32.const $push0=, 0 ; CHECK: i32.load $1=, count($pop0) +; NOREGS-LABEL: no_stackify_call_past_load: +; NOREGS: i32.call red +; NOREGS: i32.const 0 +; NOREGS: i32.load count @count = hidden global i32 0, align 4 define i32 @no_stackify_call_past_load() { %a = call i32 @red() @@ -381,6 +548,10 @@ ; CHECK: i32.store 0($1), $0 ; CHECK: i32.load {{.*}}, 0($2) ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0{{$}} +; NOREGS-LABEL: no_stackify_store_past_load +; NOREGS: i32.store 0 +; NOREGS: i32.load 0 +; NOREGS: i32.call callee@FUNCTION{{$}} define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) { store i32 %a, i32* %p1 %b = load i32, i32* %p2, align 4 @@ -394,6 +565,11 @@ ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0 ; CHECK: i32.load $push{{.*}}, 0($2) ; CHECK: return $pop +; NOREGS-LABEL: store_past_invar_load +; NOREGS: i32.store 0 +; NOREGS: i32.call callee@FUNCTION +; NOREGS: i32.load 0 +; NOREGS: return define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) { store i32 %a, i32* %p1 %b = load i32, i32* %p2, !invariant.load !0 @@ -404,6 +580,9 @@ ; CHECK-LABEL: ignore_dbg_value: ; CHECK-NEXT: .Lfunc_begin ; CHECK-NEXT: unreachable +; NOREGS-LABEL: ignore_dbg_value: +; NOREGS-NEXT: .Lfunc_begin +; NOREGS-NEXT: unreachable declare void @llvm.dbg.value(metadata, i64, metadata, metadata) define void @ignore_dbg_value() { call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !7, metadata !9), !dbg !10 @@ -415,6 +594,8 @@ ; CHECK-LABEL: no_stackify_past_epilogue: ; CHECK: return ${{[0-9]+}}{{$}} +; NOREGS-LABEL: no_stackify_past_epilogue: +; NOREGS: return{{$}} declare i32 @use_memory(i32*) define i32 @no_stackify_past_epilogue() { %x = alloca i32 @@ -429,6 +610,11 @@ ; CHECK-NEXT: i32.add $push[[L4:.+]]=, $[[R0:.+]], $pop[[L5]]{{$}} ; CHECK-NEXT: tee_local $push[[L3:.+]]=, $[[R0]]=, $pop[[L4]]{{$}} ; CHECK-NEXT: i32.ne $push[[L2:.+]]=, $0, $pop[[L3]]{{$}} +; NOREGS-LABEL: stackify_indvar: +; NOREGS: i32.const 1{{$}} +; NOREGS-NEXT: i32.add +; NOREGS-NEXT: tee_local 2{{$}} +; NOREGS-NEXT: i32.ne define void @stackify_indvar(i32 %tmp, i32* %v) #0 { bb: br label %bb3 @@ -451,6 +637,9 @@ ; CHECK-LABEL: stackpointer_dependency: ; CHECK: call {{.+}}, stackpointer_callee@FUNCTION, ; CHECK-NEXT: set_global __stack_pointer, +; NOREGS-LABEL: stackpointer_dependency: +; NOREGS: call stackpointer_callee@FUNCTION +; NOREGS: set_global __stack_pointer declare i32 @stackpointer_callee(i8* readnone, i8* readnone) declare i8* @llvm.frameaddress(i32) define i32 @stackpointer_dependency(i8* readnone) { @@ -467,6 +656,12 @@ ; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0) ; CHECK-NEXT: i32.load $push[[L1:.+]]=, 0($pop[[L0]]) ; CHECK-NEXT: i32.call_indirect $push{{.+}}=, $pop[[L3]], $1, $pop[[L1]] +; NOREGS-LABEL: call_indirect_stackify: +; NOREGS: i32.load 0 +; NOREGS-NEXT: tee_local 0 +; NOREGS: i32.load 0 +; NOREGS-NEXT: i32.load 0 +; NOREGS-NEXT: i32.call_indirect %class.call_indirect = type { i32 (...)** } define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) { %obj = load %class.call_indirect*, %class.call_indirect** %objptr @@ -491,3 +686,4 @@ !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !DIExpression() !10 = !DILocation(line: 15, column: 6, scope: !5) + Index: test/CodeGen/WebAssembly/return-int32.ll =================================================================== --- test/CodeGen/WebAssembly/return-int32.ll +++ test/CodeGen/WebAssembly/return-int32.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s -; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -26,7 +26,7 @@ true: store i32 0, i32* null - ret i32 1 + ret i32 1 false: store i32 2, i32* null Index: test/CodeGen/WebAssembly/returned.ll =================================================================== --- test/CodeGen/WebAssembly/returned.ll +++ test/CodeGen/WebAssembly/returned.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test that the "returned" attribute is optimized effectively. Index: test/CodeGen/WebAssembly/select.ll =================================================================== --- test/CodeGen/WebAssembly/select.ll +++ test/CodeGen/WebAssembly/select.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that wasm select instruction is selected from LLVM select instruction. Index: test/CodeGen/WebAssembly/signext-arg.ll =================================================================== --- test/CodeGen/WebAssembly/signext-arg.ll +++ test/CodeGen/WebAssembly/signext-arg.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/signext-inreg.ll =================================================================== --- test/CodeGen/WebAssembly/signext-inreg.ll +++ test/CodeGen/WebAssembly/signext-inreg.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -mattr=+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s --check-prefix=NOSIGNEXT +; RUN: llc < %s -mattr=+sign-ext -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s --check-prefix=NOSIGNEXT target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/signext-zeroext.ll =================================================================== --- test/CodeGen/WebAssembly/signext-zeroext.ll +++ test/CodeGen/WebAssembly/signext-zeroext.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Test zeroext and signext ABI keywords Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -1,7 +1,7 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128 -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128 -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128 -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128 +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128 ; Test that basic SIMD128 arithmetic operations assemble as expected. Index: test/CodeGen/WebAssembly/stack-alignment.ll =================================================================== --- test/CodeGen/WebAssembly/stack-alignment.ll +++ test/CodeGen/WebAssembly/stack-alignment.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/store-trunc-atomic.ll =================================================================== --- test/CodeGen/WebAssembly/store-trunc-atomic.ll +++ test/CodeGen/WebAssembly/store-trunc-atomic.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -mattr=+atomics,+sign-ext -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s ; Test that truncating stores are assembled properly. Index: test/CodeGen/WebAssembly/store-trunc.ll =================================================================== --- test/CodeGen/WebAssembly/store-trunc.ll +++ test/CodeGen/WebAssembly/store-trunc.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s ; Test that truncating stores are assembled properly. Index: test/CodeGen/WebAssembly/store.ll =================================================================== --- test/CodeGen/WebAssembly/store.ll +++ test/CodeGen/WebAssembly/store.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -fast-isel -fast-isel-abort=1 | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic stores are assembled properly. Index: test/CodeGen/WebAssembly/switch.ll =================================================================== --- test/CodeGen/WebAssembly/switch.ll +++ test/CodeGen/WebAssembly/switch.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-block-placement -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -disable-block-placement -verify-machineinstrs | FileCheck %s ; Test switch instructions. Block placement is disabled because it reorders ; the blocks in a way that isn't interesting here. Index: test/CodeGen/WebAssembly/tls.ll =================================================================== --- test/CodeGen/WebAssembly/tls.ll +++ test/CodeGen/WebAssembly/tls.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -thread-model=single | FileCheck --check-prefix=SINGLE %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -thread-model=single | FileCheck --check-prefix=SINGLE %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/umulo-i64.ll =================================================================== --- test/CodeGen/WebAssembly/umulo-i64.ll +++ test/CodeGen/WebAssembly/umulo-i64.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s ; Test that UMULO works correctly on 64-bit operands. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" Index: test/CodeGen/WebAssembly/unsupported-function-bitcasts.ll =================================================================== --- test/CodeGen/WebAssembly/unsupported-function-bitcasts.ll +++ test/CodeGen/WebAssembly/unsupported-function-bitcasts.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -wasm-explicit-locals-codegen-test-mode | FileCheck %s ; Test that function pointer casts that require conversions are not converted ; to wrappers. In theory some conversions could be supported, but currently no Index: test/CodeGen/WebAssembly/unused-argument.ll =================================================================== --- test/CodeGen/WebAssembly/unused-argument.ll +++ test/CodeGen/WebAssembly/unused-argument.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode | FileCheck %s ; Make sure that argument offsets are correct even if some arguments are unused. Index: test/CodeGen/WebAssembly/userstack.ll =================================================================== --- test/CodeGen/WebAssembly/userstack.ll +++ test/CodeGen/WebAssembly/userstack.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-explicit-locals-codegen-test-mode | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -138,7 +138,7 @@ ; Target independent codegen bumps the stack pointer. ; CHECK: i32.sub ; Check that SP is written back to memory after decrement - ; CHECK: set_global __stack_pointer, + ; CHECK: set_global __stack_pointer, %r = alloca i32, i32 %alloc ; Target-independent codegen also calculates the store addr ; CHECK: call ext_func_i32@FUNCTION Index: test/CodeGen/WebAssembly/varargs.ll =================================================================== --- test/CodeGen/WebAssembly/varargs.ll +++ test/CodeGen/WebAssembly/varargs.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs | FileCheck %s ; Test varargs constructs. Index: test/CodeGen/WebAssembly/vtable.ll =================================================================== --- test/CodeGen/WebAssembly/vtable.ll +++ test/CodeGen/WebAssembly/vtable.ll @@ -1,6 +1,6 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFONAME -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=VTABLE -; RUN: llc < %s -asm-verbose=false -disable-wasm-explicit-locals | FileCheck %s --check-prefix=TYPEINFO +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s --check-prefix=TYPEINFONAME +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s --check-prefix=VTABLE +; RUN: llc < %s -asm-verbose=false -wasm-register-codegen-test-mode | FileCheck %s --check-prefix=TYPEINFO ; Test that simple vtables assemble as expected. ; Index: test/MC/Disassembler/WebAssembly/wasm.txt =================================================================== --- test/MC/Disassembler/WebAssembly/wasm.txt +++ test/MC/Disassembler/WebAssembly/wasm.txt @@ -11,8 +11,7 @@ # CHECK: i64.const -1 0x42 0x7F -# CHECK: i64.load32_u 16, :p2align=1 -# FIXME: fix p2align output in WebAssemblyInstPrinter +# CHECK: i64.load32_u 16:p2align=1 0x35 0x01 0x10 # CHECK: block Index: test/MC/WebAssembly/basic-assembly.s =================================================================== --- test/MC/WebAssembly/basic-assembly.s +++ test/MC/WebAssembly/basic-assembly.s @@ -7,33 +7,33 @@ .param i32, i64 .local f32, f64 #, i8x16, i16x8, i32x4, f32x4 # Explicit getlocal/setlocal: - get_local $push0=, 2 - set_local 2, $pop0= - # Implicit locals & immediates: - i32.const $0=, -1 - f64.const $3=, 0x1.999999999999ap1 + get_local 2 + set_local 2 + # Immediates: + i32.const -1 + f64.const 0x1.999999999999ap1 # Indirect addressing: - get_local $push1=, 0 - f64.store 0($pop1), $3 + get_local 0 + f64.store 0 # Loops, conditionals, binary ops, calls etc: block - i32.const $push2=, 1 - get_local $push7=, 0 - i32.ge_s $push0=, $pop2, $pop7 - br_if 0, $pop0 # 0: down to label0 + i32.const 1 + get_local 0 + i32.ge_s + br_if 0 # 0: down to label0 .LBB0_1: loop # label1: - call $drop=, something1@FUNCTION - i64.const $push10=, 1234 - i32.call $push8=, something2@FUNCTION, $pop10 - i32.const $push11=, 0 - call_indirect $pop11 - i32.const $push5=, 1 - i32.add $push4=, $pop8, $pop5 - tee_local $push3=, 0, $pop4 - get_local $push9=, 0 - i32.lt_s $push1=, $pop3, $pop9 - br_if 0, $pop1 # 0: up to label1 + call something1@FUNCTION + i64.const 1234 + i32.call something2@FUNCTION + i32.const 0 + call_indirect + i32.const 1 + i32.add + tee_local 0 + get_local 0 + i32.lt_s + br_if 0 # 0: up to label1 .LBB0_2: end_loop end_block # label0: @@ -44,30 +44,30 @@ # CHECK-LABEL: test0: # CHECK-NEXT: .param i32, i64 # CHECK-NEXT: .local f32, f64 -# CHECK-NEXT: get_local $push0=, 2 -# CHECK-NEXT: set_local 2, $pop0 -# CHECK-NEXT: i32.const $0=, -1 -# CHECK-NEXT: f64.const $3=, 0x1.999999999999ap1 -# CHECK-NEXT: get_local $push1=, 0 -# CHECK-NEXT: f64.store 0($pop1):p2align=0, $3 +# CHECK-NEXT: get_local 2 +# CHECK-NEXT: set_local 2 +# CHECK-NEXT: i32.const -1 +# CHECK-NEXT: f64.const 0x1.999999999999ap1 +# CHECK-NEXT: get_local 0 +# CHECK-NEXT: f64.store 0:p2align=0 # CHECK-NEXT: block -# CHECK-NEXT: i32.const $push2=, 1 -# CHECK-NEXT: get_local $push7=, 0 -# CHECK-NEXT: i32.ge_s $push0=, $pop2, $pop7 -# CHECK-NEXT: br_if 0, $pop0 # 0: down to label0 +# CHECK-NEXT: i32.const 1 +# CHECK-NEXT: get_local 0 +# CHECK-NEXT: i32.ge_s +# CHECK-NEXT: br_if 0 # 0: down to label0 # CHECK-NEXT: .LBB0_1: # CHECK-NEXT: loop # label1: # CHECK-NEXT: call something1@FUNCTION -# CHECK-NEXT: i64.const $push10=, 1234 -# CHECK-NEXT: i32.call $push8=, something2@FUNCTION -# CHECK-NEXT: i32.const $push11=, 0 +# CHECK-NEXT: i64.const 1234 +# CHECK-NEXT: i32.call something2@FUNCTION +# CHECK-NEXT: i32.const 0 # CHECK-NEXT: call_indirect -# CHECK-NEXT: i32.const $push5=, 1 -# CHECK-NEXT: i32.add $push4=, $pop8, $pop5 -# CHECK-NEXT: tee_local $push3=, 0, $pop4 -# CHECK-NEXT: get_local $push9=, 0 -# CHECK-NEXT: i32.lt_s $push1=, $pop3, $pop9 -# CHECK-NEXT: br_if 0, $pop1 # 0: up to label1 +# CHECK-NEXT: i32.const 1 +# CHECK-NEXT: i32.add +# CHECK-NEXT: tee_local 0 +# CHECK-NEXT: get_local 0 +# CHECK-NEXT: i32.lt_s +# CHECK-NEXT: br_if 0 # 0: up to label1 # CHECK-NEXT: .LBB0_2: # CHECK-NEXT: end_loop # CHECK-NEXT: end_block # label0: Index: test/MC/WebAssembly/reloc-code.ll =================================================================== --- test/MC/WebAssembly/reloc-code.ll +++ test/MC/WebAssembly/reloc-code.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s +; RUN: llc -filetype=obj -wasm-explicit-locals-codegen-test-mode %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s target triple = "wasm32-unknown-unknown" Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -1,4 +1,4 @@ -; RUN: llc -filetype=obj %s -o %t.o +; RUN: llc -filetype=obj -wasm-explicit-locals-codegen-test-mode %s -o %t.o ; RUN: obj2yaml %t.o | FileCheck %s ; RUN: llvm-objdump -t %t.o | FileCheck --check-prefix=CHECK-SYMS %s @@ -47,10 +47,10 @@ } ; CHECK: - Type: TYPE -; CHECK-NEXT: Signatures: +; CHECK-NEXT: Signatures: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: ReturnType: I32 -; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: ParamTypes: ; CHECK-NEXT: - Type: IMPORT ; CHECK-NEXT: Imports: ; CHECK-NEXT: - Module: env @@ -68,13 +68,13 @@ ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] ; CHECK-NEXT: - Type: ELEM -; CHECK-NEXT: Segments: -; CHECK-NEXT: - Offset: +; CHECK-NEXT: Segments: +; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 ; CHECK-NEXT: Functions: [ 0 ] ; CHECK-NEXT: - Type: CODE -; CHECK-NEXT: Relocations: +; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000009 @@ -93,40 +93,40 @@ ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TYPE_INDEX_LEB ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000037 -; CHECK-NEXT: Functions: +; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Locals: +; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 41000B ; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Locals: +; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 1080808080000B ; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Locals: +; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 1080808080000B ; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Locals: +; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 410028028880808000118080808000000B ; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Locals: +; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 410028029080808000118080808000000B ; CHECK-NEXT: - Type: DATA -; CHECK-NEXT: Relocations: +; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 3 ; CHECK-NEXT: Offset: 0x00000018 -; CHECK-NEXT: Segments: +; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 ; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 0 ; CHECK-NEXT: Content: '07000000' ; CHECK-NEXT: - SectionOffset: 15 ; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: +; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000' @@ -139,7 +139,7 @@ ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: Version: 1 -; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: SymbolTable: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: Name: foo @@ -194,7 +194,7 @@ ; CHECK-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN ] ; CHECK-NEXT: Segment: 0 ; CHECK-NEXT: Size: 4 -; CHECK-NEXT: SegmentInfo: +; CHECK-NEXT: SegmentInfo: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: .data.bar ; CHECK-NEXT: Alignment: 8 Index: unittests/MC/Disassembler.cpp =================================================================== --- unittests/MC/Disassembler.cpp +++ unittests/MC/Disassembler.cpp @@ -101,7 +101,7 @@ InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, OutStringSize); EXPECT_EQ(InstSize, 3U); - EXPECT_EQ(StringRef(OutString), "\ti64.load32_u\t16, :p2align=1"); + EXPECT_EQ(StringRef(OutString), "\ti64.load32_u\t16:p2align=1"); LLVMDisasmDispose(DCR); }