From f02416f9adebf9fe7cf05f211d475b2636a7336b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 10 May 2016 17:39:48 +0000 Subject: [PATCH] [WebAssembly] Preliminary fast-isel support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269083 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../WebAssembly/WebAssemblyFastISel.cpp | 546 +++++++++++++++++- test/CodeGen/WebAssembly/cfg-stackify.ll | 7 +- test/CodeGen/WebAssembly/fast-isel.ll | 28 + test/CodeGen/WebAssembly/load.ll | 1 + test/CodeGen/WebAssembly/return-int32.ll | 1 + test/CodeGen/WebAssembly/return-void.ll | 1 + test/CodeGen/WebAssembly/store.ll | 1 + test/CodeGen/WebAssembly/unreachable.ll | 2 +- test/CodeGen/WebAssembly/userstack.ll | 2 - 9 files changed, 580 insertions(+), 9 deletions(-) diff --git a/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 1b761b1a9d7..a057959ec5d 100644 --- a/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -41,13 +41,78 @@ using namespace llvm; namespace { class WebAssemblyFastISel final : public FastISel { + // All possible address modes. + class Address { + public: + typedef enum { RegBase, FrameIndexBase } BaseKind; + + private: + BaseKind Kind; + union { + unsigned Reg; + int FI; + } Base; + + int64_t Offset; + + const GlobalValue *GV; + + public: + // Innocuous defaults for our address. + Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; } + void setKind(BaseKind K) { Kind = K; } + BaseKind getKind() const { return Kind; } + bool isRegBase() const { return Kind == RegBase; } + bool isFIBase() const { return Kind == FrameIndexBase; } + void setReg(unsigned Reg) { + assert(isRegBase() && "Invalid base register access!"); + Base.Reg = Reg; + } + unsigned getReg() const { + assert(isRegBase() && "Invalid base register access!"); + return Base.Reg; + } + void setFI(unsigned FI) { + assert(isFIBase() && "Invalid base frame index access!"); + Base.FI = FI; + } + unsigned getFI() const { + assert(isFIBase() && "Invalid base frame index access!"); + return Base.FI; + } + + void setOffset(int64_t Offset_) { Offset = Offset_; } + int64_t getOffset() const { return Offset; } + void setGlobalValue(const GlobalValue *G) { GV = G; } + const GlobalValue *getGlobalValue() const { return GV; } + }; + /// Keep a pointer to the WebAssemblySubtarget around so that we can make the /// right decision when generating code for different targets. const WebAssemblySubtarget *Subtarget; LLVMContext *Context; - // Call handling routines. private: + // Utility helper routines + bool computeAddress(const Value *Obj, Address &Addr); + void materializeLoadStoreOperands(Address &Addr); + void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB, + MachineMemOperand *MMO); + unsigned maskI1Value(unsigned Reg, const TargetRegisterClass *RC, const Value *V); + unsigned getRegForI1Value(const Value *V); + + // Backend specific FastISel code. + unsigned fastMaterializeAlloca(const AllocaInst *AI) override; + unsigned fastMaterializeConstant(const Constant *C) override; + + // Selection routines. + bool selectBitCast(const Instruction *I); + bool selectLoad(const Instruction *I); + bool selectStore(const Instruction *I); + bool selectBr(const Instruction *I); + bool selectRet(const Instruction *I); + bool selectUnreachable(const Instruction *I); + public: // Backend specific FastISel code. WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo, @@ -64,11 +129,484 @@ public: } // end anonymous namespace -bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) { - switch (I->getOpcode()) { +bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { + + const User *U = nullptr; + unsigned Opcode = Instruction::UserOp1; + if (const Instruction *I = dyn_cast(Obj)) { + // Don't walk into other basic blocks unless the object is an alloca from + // another block, otherwise it may not have a virtual register assigned. + if (FuncInfo.StaticAllocaMap.count(static_cast(Obj)) || + FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { + Opcode = I->getOpcode(); + U = I; + } + } else if (const ConstantExpr *C = dyn_cast(Obj)) { + Opcode = C->getOpcode(); + U = C; + } + + if (auto *Ty = dyn_cast(Obj->getType())) + if (Ty->getAddressSpace() > 255) + // Fast instruction selection doesn't support the special + // address spaces. + return false; + + if (const GlobalValue *GV = dyn_cast(Obj)) { + if (Addr.getGlobalValue()) + return false; + Addr.setGlobalValue(GV); + return true; + } + + switch (Opcode) { default: break; - // TODO: add fast-isel selection cases here... + case Instruction::BitCast: { + // Look through bitcasts. + return computeAddress(U->getOperand(0), Addr); + } + case Instruction::IntToPtr: { + // Look past no-op inttoptrs. + if (TLI.getValueType(DL, U->getOperand(0)->getType()) == + TLI.getPointerTy(DL)) + return computeAddress(U->getOperand(0), Addr); + break; + } + case Instruction::PtrToInt: { + // Look past no-op ptrtoints. + if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) + return computeAddress(U->getOperand(0), Addr); + break; + } + case Instruction::GetElementPtr: { + Address SavedAddr = Addr; + uint64_t TmpOffset = Addr.getOffset(); + // Iterate through the GEP folding the constants into offsets where + // we can. + for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U); + GTI != E; ++GTI) { + const Value *Op = GTI.getOperand(); + if (StructType *STy = dyn_cast(*GTI)) { + const StructLayout *SL = DL.getStructLayout(STy); + unsigned Idx = cast(Op)->getZExtValue(); + TmpOffset += SL->getElementOffset(Idx); + } else { + uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); + for (;;) { + if (const ConstantInt *CI = dyn_cast(Op)) { + // Constant-offset addressing. + TmpOffset += CI->getSExtValue() * S; + break; + } + if (canFoldAddIntoGEP(U, Op)) { + // A compatible add with a constant operand. Fold the constant. + ConstantInt *CI = + cast(cast(Op)->getOperand(1)); + TmpOffset += CI->getSExtValue() * S; + // Iterate on the other operand. + Op = cast(Op)->getOperand(0); + continue; + } + // Unsupported + goto unsupported_gep; + } + } + } + // Try to grab the base operand now. + Addr.setOffset(TmpOffset); + if (computeAddress(U->getOperand(0), Addr)) + return true; + // We failed, restore everything and try the other options. + Addr = SavedAddr; + unsupported_gep: + break; + } + case Instruction::Alloca: { + const AllocaInst *AI = cast(Obj); + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + Addr.setKind(Address::FrameIndexBase); + Addr.setFI(SI->second); + return true; + } + break; + } + case Instruction::Add: { + // Adds of constants are common and easy enough. + const Value *LHS = U->getOperand(0); + const Value *RHS = U->getOperand(1); + + if (isa(LHS)) + std::swap(LHS, RHS); + + if (const ConstantInt *CI = dyn_cast(RHS)) { + Addr.setOffset(Addr.getOffset() + CI->getSExtValue()); + return computeAddress(LHS, Addr); + } + + Address Backup = Addr; + if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr)) + return true; + Addr = Backup; + + break; + } + case Instruction::Sub: { + // Subs of constants are common and easy enough. + const Value *LHS = U->getOperand(0); + const Value *RHS = U->getOperand(1); + + if (const ConstantInt *CI = dyn_cast(RHS)) { + Addr.setOffset(Addr.getOffset() - CI->getSExtValue()); + return computeAddress(LHS, Addr); + } + break; + } + } + Addr.setReg(getRegForValue(Obj)); + return Addr.getReg() != 0; +} + +void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) { + if (Addr.isRegBase()) { + unsigned Reg = Addr.getReg(); + if (Reg == 0) { + Reg = createResultReg(Subtarget->hasAddr64() ? + &WebAssembly::I64RegClass : + &WebAssembly::I32RegClass); + unsigned Opc = Subtarget->hasAddr64() ? + WebAssembly::CONST_I64 : + WebAssembly::CONST_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) + .addImm(0); + Addr.setReg(Reg); + } + } +} + +void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr, + const MachineInstrBuilder &MIB, + MachineMemOperand *MMO) { + if (const GlobalValue *GV = Addr.getGlobalValue()) + MIB.addGlobalAddress(GV, Addr.getOffset()); + else + MIB.addImm(Addr.getOffset()); + + if (Addr.isRegBase()) + MIB.addReg(Addr.getReg()); + else + MIB.addFrameIndex(Addr.getFI()); + + // Set the alignment operand (this is rewritten in SetP2AlignOperands). + // TODO: Disable SetP2AlignOperands for FastISel and just do it here. + MIB.addImm(0); + + MIB.addMemOperand(MMO); +} + +unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, + const TargetRegisterClass *RC, + const Value *V) { + // If the value is naturally an i1, we don't need to mask it. + // TODO: Recursively examine selects, phis, and, or, xor, constants. + if (isa(V)) + return Reg; + + unsigned MaskReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(WebAssembly::CONST_I32), MaskReg) + .addImm(1); + + unsigned NewReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(WebAssembly::AND_I32), NewReg) + .addReg(Reg) + .addReg(MaskReg); + + return NewReg; +} + +unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V) { + return maskI1Value(getRegForValue(V), &WebAssembly::I32RegClass, V); +} + +unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) { + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + + if (SI != FuncInfo.StaticAllocaMap.end()) { + unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ? + &WebAssembly::I64RegClass : + &WebAssembly::I32RegClass); + unsigned Opc = Subtarget->hasAddr64() ? + WebAssembly::COPY_LOCAL_I64 : + WebAssembly::COPY_LOCAL_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) + .addFrameIndex(SI->second); + return ResultReg; + } + + return 0; +} + +unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) { + if (const GlobalValue *GV = dyn_cast(C)) { + unsigned Reg = createResultReg(Subtarget->hasAddr64() ? + &WebAssembly::I64RegClass : + &WebAssembly::I32RegClass); + unsigned Opc = Subtarget->hasAddr64() ? + WebAssembly::CONST_I64 : + WebAssembly::CONST_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) + .addGlobalAddress(GV); + return Reg; + } + + // Let target-independent code handle it. + return 0; +} + +bool WebAssemblyFastISel::selectBitCast(const Instruction *I) { + // Target-independent code can handle this, except it doesn't set the dead + // flag on the ARGUMENTS clobber, so we have to do that manually in order + // to satisfy code that expects this of isBitcast() instructions. + EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType()); + EVT RetVT = TLI.getValueType(DL, I->getType()); + if (!VT.isSimple() || !RetVT.isSimple()) + return false; + unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), + getRegForValue(I->getOperand(0)), + I->getOperand(0)->hasOneUse()); + if (!Reg) + return false; + MachineBasicBlock::iterator Iter = FuncInfo.InsertPt; + --Iter; + assert(Iter->isBitcast()); + Iter->setPhysRegsDeadExcept(ArrayRef(), TRI); + updateValueMap(I, Reg); + return true; +} + +bool WebAssemblyFastISel::selectLoad(const Instruction *I) { + const LoadInst *Load = cast(I); + if (Load->isAtomic()) + return false; + + Address Addr; + if (!computeAddress(Load->getPointerOperand(), Addr)) + return false; + + // TODO: Fold a following sign-/zero-extend into the load instruction. + + unsigned Opc; + const TargetRegisterClass *RC; + switch (Load->getType()->getTypeID()) { + case Type::PointerTyID: + if (Subtarget->hasAddr64()) + goto i64_load_addr; + goto i32_load_addr; + case Type::IntegerTyID: + switch (Load->getType()->getPrimitiveSizeInBits()) { + case 1: case 8: + Opc = WebAssembly::LOAD8_U_I32; + RC = &WebAssembly::I32RegClass; + break; + case 16: + Opc = WebAssembly::LOAD16_U_I32; + RC = &WebAssembly::I32RegClass; + break; + case 32: + i32_load_addr: + Opc = WebAssembly::LOAD_I32; + RC = &WebAssembly::I32RegClass; + break; + case 64: + i64_load_addr: + Opc = WebAssembly::LOAD_I64; + RC = &WebAssembly::I64RegClass; + break; + default: return false; + } + break; + case Type::FloatTyID: + Opc = WebAssembly::LOAD_F32; + RC = &WebAssembly::F32RegClass; + break; + case Type::DoubleTyID: + Opc = WebAssembly::LOAD_F64; + RC = &WebAssembly::F64RegClass; + break; + default: return false; + } + + materializeLoadStoreOperands(Addr); + + unsigned ResultReg = createResultReg(RC); + auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), + ResultReg); + + addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load)); + + updateValueMap(Load, ResultReg); + return true; +} + +bool WebAssemblyFastISel::selectStore(const Instruction *I) { + const StoreInst *Store = cast(I); + if (Store->isAtomic()) + return false; + + Address Addr; + if (!computeAddress(Store->getPointerOperand(), Addr)) + return false; + + unsigned Opc; + const TargetRegisterClass *RC; + bool VTIsi1 = false; + switch (Store->getValueOperand()->getType()->getTypeID()) { + case Type::PointerTyID: + if (Subtarget->hasAddr64()) + goto i64_store_addr; + goto i32_store_addr; + case Type::IntegerTyID: + switch (Store->getValueOperand()->getType()->getPrimitiveSizeInBits()) { + case 1: + VTIsi1 = true; + case 8: + Opc = WebAssembly::STORE8_I32; + RC = &WebAssembly::I32RegClass; + break; + case 16: + Opc = WebAssembly::STORE16_I32; + RC = &WebAssembly::I32RegClass; + break; + case 32: + i32_store_addr: + Opc = WebAssembly::STORE_I32; + RC = &WebAssembly::I32RegClass; + break; + case 64: + i64_store_addr: + Opc = WebAssembly::STORE_I64; + RC = &WebAssembly::I64RegClass; + break; + default: return false; + } + break; + case Type::FloatTyID: + Opc = WebAssembly::STORE_F32; + RC = &WebAssembly::F32RegClass; + break; + case Type::DoubleTyID: + Opc = WebAssembly::STORE_F64; + RC = &WebAssembly::F64RegClass; + break; + default: return false; + } + + materializeLoadStoreOperands(Addr); + + unsigned ValueReg = getRegForValue(Store->getValueOperand()); + if (VTIsi1) + ValueReg = maskI1Value(ValueReg, RC, Store->getValueOperand()); + + unsigned ResultReg = createResultReg(RC); + auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), + ResultReg); + + addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); + + MIB.addReg(ValueReg); + return true; +} + +bool WebAssemblyFastISel::selectBr(const Instruction *I) { + const BranchInst *Br = cast(I); + if (Br->isUnconditional()) { + MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)]; + fastEmitBranch(MSucc, Br->getDebugLoc()); + return true; + } + + MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)]; + MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)]; + + Value *Cond = Br->getCondition(); + unsigned Opc = WebAssembly::BR_IF; + if (BinaryOperator::isNot(Cond)) { + Cond = BinaryOperator::getNotArgument(Cond); + Opc = WebAssembly::BR_UNLESS; + } + + unsigned CondReg = getRegForI1Value(Cond); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) + .addMBB(TBB) + .addReg(CondReg); + + finishCondBranch(Br->getParent(), TBB, FBB); + return true; +} + +bool WebAssemblyFastISel::selectRet(const Instruction *I) { + if (!FuncInfo.CanLowerReturn) + return false; + + const ReturnInst *Ret = cast(I); + + if (Ret->getNumOperands() == 0) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(WebAssembly::RETURN_VOID)); + return true; + } + + Value *RV = Ret->getOperand(0); + unsigned Opc; + switch (RV->getType()->getTypeID()) { + case Type::PointerTyID: + if (Subtarget->hasAddr64()) + goto i64_ret_value; + goto i32_ret_value; + case Type::IntegerTyID: + switch (RV->getType()->getPrimitiveSizeInBits()) { + case 1: case 8: + case 16: case 32: + i32_ret_value: + Opc = WebAssembly::RETURN_I32; + break; + case 64: + i64_ret_value: + Opc = WebAssembly::RETURN_I64; + break; + default: return false; + } + break; + case Type::FloatTyID: Opc = WebAssembly::RETURN_F32; break; + case Type::DoubleTyID: Opc = WebAssembly::RETURN_F64; break; + default: return false; + } + + unsigned Reg = getRegForValue(RV); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg); + return true; +} + +bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(WebAssembly::UNREACHABLE)); + return true; +} + +bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) { + switch (I->getOpcode()) { + case Instruction::BitCast: return selectBitCast(I); + case Instruction::Load: return selectLoad(I); + case Instruction::Store: return selectStore(I); + case Instruction::Br: return selectBr(I); + case Instruction::Ret: return selectRet(I); + case Instruction::Unreachable: return selectUnreachable(I); + default: break; } // Fall back to target-independent instruction selection. diff --git a/test/CodeGen/WebAssembly/cfg-stackify.ll b/test/CodeGen/WebAssembly/cfg-stackify.ll index 442d0d4ea25..b29cd8860a2 100644 --- a/test/CodeGen/WebAssembly/cfg-stackify.ll +++ b/test/CodeGen/WebAssembly/cfg-stackify.ll @@ -1,8 +1,11 @@ -; RUN: llc < %s -asm-verbose=false -disable-block-placement -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck -check-prefix=OPT %s +; RUN: llc < %s -asm-verbose=false -disable-block-placement -verify-machineinstrs -fast-isel=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -fast-isel=false | FileCheck -check-prefix=OPT %s ; Test the CFG stackifier pass. +; Explicitly disable fast-isel, since it gets implicitly enabled in the +; optnone test. + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" diff --git a/test/CodeGen/WebAssembly/fast-isel.ll b/test/CodeGen/WebAssembly/fast-isel.ll index 7f9f20fa708..d3ee77632bc 100644 --- a/test/CodeGen/WebAssembly/fast-isel.ll +++ b/test/CodeGen/WebAssembly/fast-isel.ll @@ -18,3 +18,31 @@ define float @immediate_f32() { define double @immediate_f64() { ret double 2.5 } + +; CHECK-LABEL: bitcast_i32_f32: +; CHECK: i32.reinterpret/f32 $push{{[0-9]+}}=, $0{{$}} +define i32 @bitcast_i32_f32(float %x) { + %y = bitcast float %x to i32 + ret i32 %y +} + +; CHECK-LABEL: bitcast_f32_i32: +; CHECK: f32.reinterpret/i32 $push{{[0-9]+}}=, $0{{$}} +define float @bitcast_f32_i32(i32 %x) { + %y = bitcast i32 %x to float + ret float %y +} + +; CHECK-LABEL: bitcast_i64_f64: +; CHECK: i64.reinterpret/f64 $push{{[0-9]+}}=, $0{{$}} +define i64 @bitcast_i64_f64(double %x) { + %y = bitcast double %x to i64 + ret i64 %y +} + +; CHECK-LABEL: bitcast_f64_i64: +; CHECK: f64.reinterpret/i64 $push{{[0-9]+}}=, $0{{$}} +define double @bitcast_f64_i64(i64 %x) { + %y = bitcast i64 %x to double + ret double %y +} diff --git a/test/CodeGen/WebAssembly/load.ll b/test/CodeGen/WebAssembly/load.ll index 243fa9d50ad..776dba36bf0 100644 --- a/test/CodeGen/WebAssembly/load.ll +++ b/test/CodeGen/WebAssembly/load.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic loads are assembled properly. diff --git a/test/CodeGen/WebAssembly/return-int32.ll b/test/CodeGen/WebAssembly/return-int32.ll index a93a0f6c438..cbc9ec99703 100644 --- a/test/CodeGen/WebAssembly/return-int32.ll +++ b/test/CodeGen/WebAssembly/return-int32.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -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" diff --git a/test/CodeGen/WebAssembly/return-void.ll b/test/CodeGen/WebAssembly/return-void.ll index 65ff5f32571..cf4d16858c0 100644 --- a/test/CodeGen/WebAssembly/return-void.ll +++ b/test/CodeGen/WebAssembly/return-void.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -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" diff --git a/test/CodeGen/WebAssembly/store.ll b/test/CodeGen/WebAssembly/store.ll index dc93ebbbadb..a8c03325382 100644 --- a/test/CodeGen/WebAssembly/store.ll +++ b/test/CodeGen/WebAssembly/store.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s +; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s ; Test that basic stores are assembled properly. diff --git a/test/CodeGen/WebAssembly/unreachable.ll b/test/CodeGen/WebAssembly/unreachable.ll index 7b23bf3cecf..77fda44d5ff 100644 --- a/test/CodeGen/WebAssembly/unreachable.ll +++ b/test/CodeGen/WebAssembly/unreachable.ll @@ -1,5 +1,5 @@ ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s -; RUN: llc < %s -asm-verbose=false -fast-isel -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 -verify-machineinstrs | FileCheck %s ; Test that LLVM unreachable instruction and trap intrinsic are lowered to ; wasm unreachable diff --git a/test/CodeGen/WebAssembly/userstack.ll b/test/CodeGen/WebAssembly/userstack.ll index e4ba583b2ac..a83ce531546 100644 --- a/test/CodeGen/WebAssembly/userstack.ll +++ b/test/CodeGen/WebAssembly/userstack.ll @@ -1,6 +1,4 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s -; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s - target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" -- 2.50.1