[llvm] r269083 - [WebAssembly] Preliminary fast-isel support.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Tue May 10 10:39:48 PDT 2016


Author: djg
Date: Tue May 10 12:39:48 2016
New Revision: 269083

URL: http://llvm.org/viewvc/llvm-project?rev=269083&view=rev
Log:
[WebAssembly] Preliminary fast-isel support.

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
    llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify.ll
    llvm/trunk/test/CodeGen/WebAssembly/fast-isel.ll
    llvm/trunk/test/CodeGen/WebAssembly/load.ll
    llvm/trunk/test/CodeGen/WebAssembly/return-int32.ll
    llvm/trunk/test/CodeGen/WebAssembly/return-void.ll
    llvm/trunk/test/CodeGen/WebAssembly/store.ll
    llvm/trunk/test/CodeGen/WebAssembly/unreachable.ll
    llvm/trunk/test/CodeGen/WebAssembly/userstack.ll

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp Tue May 10 12:39:48 2016
@@ -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<Instruction>(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<const AllocaInst *>(Obj)) ||
+        FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
+      Opcode = I->getOpcode();
+      U = I;
+    }
+  } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
+    Opcode = C->getOpcode();
+    U = C;
+  }
+
+  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
+    if (Ty->getAddressSpace() > 255)
+      // Fast instruction selection doesn't support the special
+      // address spaces.
+      return false;
+
+  if (const GlobalValue *GV = dyn_cast<GlobalValue>(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<StructType>(*GTI)) {
+        const StructLayout *SL = DL.getStructLayout(STy);
+        unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
+        TmpOffset += SL->getElementOffset(Idx);
+      } else {
+        uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
+        for (;;) {
+          if (const ConstantInt *CI = dyn_cast<ConstantInt>(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<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
+            TmpOffset += CI->getSExtValue() * S;
+            // Iterate on the other operand.
+            Op = cast<AddOperator>(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<AllocaInst>(Obj);
+    DenseMap<const AllocaInst *, int>::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<ConstantInt>(LHS))
+      std::swap(LHS, RHS);
+
+    if (const ConstantInt *CI = dyn_cast<ConstantInt>(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<ConstantInt>(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<CmpInst>(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<const AllocaInst *, int>::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<GlobalValue>(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<unsigned>(), TRI);
+  updateValueMap(I, Reg);
+  return true;
+}
+
+bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
+  const LoadInst *Load = cast<LoadInst>(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<StoreInst>(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<BranchInst>(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<ReturnInst>(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.

Modified: llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify.ll Tue May 10 12:39:48 2016
@@ -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"
 

Modified: llvm/trunk/test/CodeGen/WebAssembly/fast-isel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/fast-isel.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/fast-isel.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/fast-isel.ll Tue May 10 12:39:48 2016
@@ -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
+}

Modified: llvm/trunk/test/CodeGen/WebAssembly/load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/load.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/load.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/load.ll Tue May 10 12:39:48 2016
@@ -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.
 

Modified: llvm/trunk/test/CodeGen/WebAssembly/return-int32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/return-int32.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/return-int32.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/return-int32.ll Tue May 10 12:39:48 2016
@@ -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"

Modified: llvm/trunk/test/CodeGen/WebAssembly/return-void.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/return-void.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/return-void.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/return-void.ll Tue May 10 12:39:48 2016
@@ -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"

Modified: llvm/trunk/test/CodeGen/WebAssembly/store.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/store.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/store.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/store.ll Tue May 10 12:39:48 2016
@@ -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.
 

Modified: llvm/trunk/test/CodeGen/WebAssembly/unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/unreachable.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/unreachable.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/unreachable.ll Tue May 10 12:39:48 2016
@@ -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

Modified: llvm/trunk/test/CodeGen/WebAssembly/userstack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/userstack.ll?rev=269083&r1=269082&r2=269083&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/userstack.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/userstack.ll Tue May 10 12:39:48 2016
@@ -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"




More information about the llvm-commits mailing list