[llvm] r269273 - [WebAssembly] Fast-isel support for calls, arguments, and selects.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Wed May 11 21:19:09 PDT 2016


Author: djg
Date: Wed May 11 23:19:09 2016
New Revision: 269273

URL: http://llvm.org/viewvc/llvm-project?rev=269273&view=rev
Log:
[WebAssembly] Fast-isel support for calls, arguments, and selects.

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp
    llvm/trunk/test/CodeGen/WebAssembly/call.ll
    llvm/trunk/test/CodeGen/WebAssembly/select.ll

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp?rev=269273&r1=269272&r2=269273&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp Wed May 11 23:19:09 2016
@@ -12,10 +12,13 @@
 /// class. Some of the target-specific code is generated by tablegen in the file
 /// WebAssemblyGenFastISel.inc, which is #included here.
 ///
+/// TODO: kill flags
+///
 //===----------------------------------------------------------------------===//
 
 #include "WebAssembly.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblySubtarget.h"
 #include "WebAssemblyTargetMachine.h"
 #include "llvm/Analysis/BranchProbabilityInfo.h"
@@ -104,10 +107,12 @@ private:
     case MVT::i1:
     case MVT::i8:
     case MVT::i16:
-    case MVT::i32:
       return MVT::i32;
+    case MVT::i32:
     case MVT::i64:
-      return MVT::i64;
+    case MVT::f32:
+    case MVT::f64:
+      return VT;
     default:
       break;
     }
@@ -118,7 +123,7 @@ private:
   void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
                             MachineMemOperand *MMO);
   unsigned maskI1Value(unsigned Reg, const Value *V);
-  unsigned getRegForI1Value(const Value *V);
+  unsigned getRegForI1Value(const Value *V, bool &Not);
   unsigned zeroExtendToI32(unsigned Reg, const Value *V,
                            MVT::SimpleValueType From);
   unsigned signExtendToI32(unsigned Reg, const Value *V,
@@ -133,12 +138,17 @@ private:
   unsigned getRegForSignedValue(const Value *V);
   unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
   unsigned notValue(unsigned Reg);
+  unsigned copyValue(unsigned Reg);
 
   // Backend specific FastISel code.
   unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
   unsigned fastMaterializeConstant(const Constant *C) override;
+  bool fastLowerArguments() override;
 
   // Selection routines.
+  bool selectCall(const Instruction *I);
+  bool selectSelect(const Instruction *I);
+  bool selectTrunc(const Instruction *I);
   bool selectZExt(const Instruction *I);
   bool selectSExt(const Instruction *I);
   bool selectICmp(const Instruction *I);
@@ -221,7 +231,7 @@ bool WebAssemblyFastISel::computeAddress
     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);
+    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)) {
@@ -236,6 +246,11 @@ bool WebAssemblyFastISel::computeAddress
             TmpOffset += CI->getSExtValue() * S;
             break;
           }
+          if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
+            // An unscaled add of a register. Set it as the new base.
+            Addr.setReg(getRegForValue(Op));
+            break;
+          }
           if (canFoldAddIntoGEP(U, Op)) {
             // A compatible add with a constant operand. Fold the constant.
             ConstantInt *CI =
@@ -347,7 +362,20 @@ unsigned WebAssemblyFastISel::maskI1Valu
   return zeroExtendToI32(Reg, V, MVT::i1);
 }
 
-unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V) {
+unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
+  if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
+    if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
+      if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
+        Not = ICmp->isTrueWhenEqual();
+        return getRegForValue(ICmp->getOperand(0));
+      }
+
+  if (BinaryOperator::isNot(V)) {
+    Not = true;
+    return getRegForValue(BinaryOperator::getNotArgument(V));
+  }
+
+  Not = false;
   return maskI1Value(getRegForValue(V), V);
 }
 
@@ -357,11 +385,16 @@ unsigned WebAssemblyFastISel::zeroExtend
   case MVT::i1:
     // If the value is naturally an i1, we don't need to mask it.
     // TODO: Recursively examine selects, phis, and, or, xor, constants.
-    if (From == MVT::i1 && V != nullptr && isa<CmpInst>(V))
-      return Reg;
+    if (From == MVT::i1 && V != nullptr) {
+      if (isa<CmpInst>(V) ||
+          (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
+        return copyValue(Reg);
+    }
+  case MVT::i8:
+  case MVT::i16:
     break;
   case MVT::i32:
-    return Reg;
+    return copyValue(Reg);
   default:
     return 0;
   }
@@ -388,9 +421,9 @@ unsigned WebAssemblyFastISel::signExtend
   case MVT::i16:
     break;
   case MVT::i32:
-    return Reg;
+    return copyValue(Reg);
   default:
-    return false;
+    return 0;
   }
 
   unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
@@ -418,7 +451,7 @@ unsigned WebAssemblyFastISel::zeroExtend
                                          MVT::SimpleValueType To) {
   if (To == MVT::i64) {
     if (From == MVT::i64)
-      return Reg;
+      return copyValue(Reg);
 
     Reg = zeroExtendToI32(Reg, V, From);
 
@@ -429,21 +462,6 @@ unsigned WebAssemblyFastISel::zeroExtend
     return Result;
   }
 
-  switch (From) {
-  case MVT::i1:
-    // If the value is naturally an i1, we don't need to mask it.
-    // TODO: Recursively examine selects, phis, and, or, xor, constants.
-    if (From == MVT::i1 && V != nullptr && isa<CmpInst>(V))
-      return Reg;
-  case MVT::i8:
-  case MVT::i16:
-    break;
-  case MVT::i32:
-    return Reg;
-  default:
-    return 0;
-  }
-
   return zeroExtendToI32(Reg, V, From);
 }
 
@@ -452,7 +470,7 @@ unsigned WebAssemblyFastISel::signExtend
                                          MVT::SimpleValueType To) {
   if (To == MVT::i64) {
     if (From == MVT::i64)
-      return Reg;
+      return copyValue(Reg);
 
     Reg = signExtendToI32(Reg, V, From);
 
@@ -463,17 +481,6 @@ unsigned WebAssemblyFastISel::signExtend
     return Result;
   }
 
-  switch (From) {
-  case MVT::i1:
-  case MVT::i8:
-  case MVT::i16:
-    break;
-  case MVT::i32:
-    return Reg;
-  default:
-    return false;
-  }
-
   return signExtendToI32(Reg, V, From);
 }
 
@@ -496,6 +503,8 @@ unsigned WebAssemblyFastISel::getRegForP
 }
 
 unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
+  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
+
   unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
           TII.get(WebAssembly::EQZ_I32), NotReg)
@@ -503,6 +512,14 @@ unsigned WebAssemblyFastISel::notValue(u
   return NotReg;
 }
 
+unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
+  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
+  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+          TII.get(WebAssembly::COPY), ResultReg)
+    .addReg(Reg);
+  return ResultReg;
+}
+
 unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
   DenseMap<const AllocaInst *, int>::iterator SI =
       FuncInfo.StaticAllocaMap.find(AI);
@@ -524,25 +541,259 @@ unsigned WebAssemblyFastISel::fastMateri
 
 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
   if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
-    unsigned Reg = createResultReg(Subtarget->hasAddr64() ?
-                                   &WebAssembly::I64RegClass :
-                                   &WebAssembly::I32RegClass);
+    unsigned ResultReg = 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)
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
        .addGlobalAddress(GV);
-    return Reg;
+    return ResultReg;
   }
 
   // Let target-independent code handle it.
   return 0;
 }
 
+bool WebAssemblyFastISel::fastLowerArguments() {
+  if (!FuncInfo.CanLowerReturn)
+    return false;
+
+  const Function *F = FuncInfo.Fn;
+  if (F->isVarArg())
+    return false;
+
+  unsigned i = 0;
+  for (auto const &Arg : F->args()) {
+    const AttributeSet &Attrs = F->getAttributes();
+    if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
+        Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
+        Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
+        Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
+        Attrs.hasAttribute(i+1, Attribute::Nest))
+      return false;
+
+    Type *ArgTy = Arg.getType();
+    if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy())
+      return false;
+
+    unsigned Opc;
+    const TargetRegisterClass *RC;
+    switch (getSimpleType(ArgTy)) {
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+    case MVT::i32:
+      Opc = WebAssembly::ARGUMENT_I32;
+      RC = &WebAssembly::I32RegClass;
+      break;
+    case MVT::i64:
+      Opc = WebAssembly::ARGUMENT_I64;
+      RC = &WebAssembly::I64RegClass;
+      break;
+    case MVT::f32:
+      Opc = WebAssembly::ARGUMENT_F32;
+      RC = &WebAssembly::F32RegClass;
+      break;
+    case MVT::f64:
+      Opc = WebAssembly::ARGUMENT_F64;
+      RC = &WebAssembly::F64RegClass;
+      break;
+    default:
+      return false;
+    }
+    unsigned ResultReg = createResultReg(RC);
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+      .addImm(i);
+    updateValueMap(&Arg, ResultReg);
+
+    ++i;
+  }
+
+  MRI.addLiveIn(WebAssembly::ARGUMENTS);
+
+  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
+  for (auto const &Arg : F->args())
+    MFI->addParam(getLegalType(getSimpleType(Arg.getType())));
+
+  return true;
+}
+
+bool WebAssemblyFastISel::selectCall(const Instruction *I) {
+  const CallInst *Call = cast<CallInst>(I);
+
+  if (Call->isMustTailCall() || Call->isInlineAsm() ||
+      Call->getFunctionType()->isVarArg())
+    return false;
+
+  Function *Func = Call->getCalledFunction();
+  if (Func && Func->isIntrinsic())
+    return false;
+
+  FunctionType *FuncTy = Call->getFunctionType();
+  unsigned Opc;
+  bool IsDirect = Func != nullptr;
+  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
+  unsigned ResultReg;
+  if (IsVoid) {
+    Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::CALL_INDIRECT_VOID;
+  } else {
+    MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
+    switch (RetTy) {
+    case MVT::i1:
+    case MVT::i8:
+    case MVT::i16:
+    case MVT::i32:
+      Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::CALL_INDIRECT_I32;
+      ResultReg = createResultReg(&WebAssembly::I32RegClass);
+      break;
+    case MVT::i64:
+      Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::CALL_INDIRECT_I64;
+      ResultReg = createResultReg(&WebAssembly::I64RegClass);
+      break;
+    case MVT::f32:
+      Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::CALL_INDIRECT_F32;
+      ResultReg = createResultReg(&WebAssembly::F32RegClass);
+      break;
+    case MVT::f64:
+      Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::CALL_INDIRECT_F64;
+      ResultReg = createResultReg(&WebAssembly::F64RegClass);
+      break;
+    default:
+      return false;
+    }
+  }
+
+  SmallVector<unsigned, 8> Args;
+  for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
+    Value *V = Call->getArgOperand(i);
+    MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
+    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
+      return false;
+
+    const AttributeSet &Attrs = Call->getAttributes();
+    if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
+        Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
+        Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
+        Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
+        Attrs.hasAttribute(i+1, Attribute::Nest))
+      return false;
+
+    unsigned Reg;
+
+    if (Attrs.hasAttribute(i+1, Attribute::SExt))
+      Reg = getRegForSignedValue(V);
+    else if (Attrs.hasAttribute(i+1, Attribute::ZExt))
+      Reg = getRegForUnsignedValue(V);
+    else
+      Reg = getRegForValue(V);
+
+    if (Reg == 0)
+      return false;
+
+    Args.push_back(Reg);
+  }
+
+  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
+
+  if (!IsVoid)
+    MIB.addReg(ResultReg, RegState::Define);
+
+  if (IsDirect)
+    MIB.addGlobalAddress(Func);
+  else
+    MIB.addReg(getRegForValue(Call->getCalledValue()));
+
+  for (unsigned ArgReg : Args)
+    MIB.addReg(ArgReg);
+
+  if (!IsVoid)
+    updateValueMap(Call, ResultReg);
+  return true;
+}
+
+bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
+  const SelectInst *Select = cast<SelectInst>(I);
+
+  bool Not;
+  unsigned CondReg  = getRegForI1Value(Select->getCondition(), Not);
+  if (CondReg == 0)
+    return false;
+
+  unsigned TrueReg  = getRegForValue(Select->getTrueValue());
+  if (TrueReg == 0)
+    return false;
+
+  unsigned FalseReg = getRegForValue(Select->getFalseValue());
+  if (FalseReg == 0)
+    return false;
+
+  if (Not)
+    std::swap(TrueReg, FalseReg);
+
+  unsigned Opc;
+  const TargetRegisterClass *RC;
+  switch (getSimpleType(Select->getType())) {
+  case MVT::i1:
+  case MVT::i8:
+  case MVT::i16:
+  case MVT::i32:
+    Opc = WebAssembly::SELECT_I32;
+    RC = &WebAssembly::I32RegClass;
+    break;
+  case MVT::i64:
+    Opc = WebAssembly::SELECT_I64;
+    RC = &WebAssembly::I64RegClass;
+    break;
+  case MVT::f32:
+    Opc = WebAssembly::SELECT_F32;
+    RC = &WebAssembly::F32RegClass;
+    break;
+  case MVT::f64:
+    Opc = WebAssembly::SELECT_F64;
+    RC = &WebAssembly::F64RegClass;
+    break;
+  default:
+    return false;
+  }
+
+  unsigned ResultReg = createResultReg(RC);
+  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+    .addReg(TrueReg)
+    .addReg(FalseReg)
+    .addReg(CondReg);
+
+  updateValueMap(Select, ResultReg);
+  return true;
+}
+
+bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
+  const TruncInst *Trunc = cast<TruncInst>(I);
+
+  unsigned Reg = getRegForValue(Trunc->getOperand(0));
+  if (Reg == 0)
+    return false;
+
+  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
+    unsigned Result = createResultReg(&WebAssembly::I32RegClass);
+    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
+            TII.get(WebAssembly::I32_WRAP_I64), Result)
+        .addReg(Reg);
+    Reg = Result;
+  }
+
+  updateValueMap(Trunc, Reg);
+  return true;
+}
+
 bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
   const ZExtInst *ZExt = cast<ZExtInst>(I);
 
-  unsigned Reg = getRegForUnsignedValue(ZExt->getOperand(0));
+  const Value *Op = ZExt->getOperand(0);
+  MVT::SimpleValueType From = getSimpleType(Op->getType());
+  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
+  unsigned Reg = zeroExtend(getRegForValue(Op), Op, From, To);
   if (Reg == 0)
     return false;
 
@@ -553,7 +804,10 @@ bool WebAssemblyFastISel::selectZExt(con
 bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
   const SExtInst *SExt = cast<SExtInst>(I);
 
-  unsigned Reg = getRegForSignedValue(SExt->getOperand(0));
+  const Value *Op = SExt->getOperand(0);
+  MVT::SimpleValueType From = getSimpleType(Op->getType());
+  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
+  unsigned Reg = signExtend(getRegForValue(Op), Op, From, To);
   if (Reg == 0)
     return false;
 
@@ -694,6 +948,13 @@ bool WebAssemblyFastISel::selectBitCast(
   EVT RetVT = TLI.getValueType(DL, I->getType());
   if (!VT.isSimple() || !RetVT.isSimple())
     return false;
+
+  if (VT == RetVT) {
+    // No-op bitcast.
+    updateValueMap(I, getRegForValue(I->getOperand(0)));
+    return true;
+  }
+
   unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
                                         getRegForValue(I->getOperand(0)),
                                         I->getOperand(0)->hasOneUse());
@@ -831,14 +1092,13 @@ bool WebAssemblyFastISel::selectBr(const
   MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
   MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
 
-  Value *Cond = Br->getCondition();
+  bool Not;
+  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
+
   unsigned Opc = WebAssembly::BR_IF;
-  if (BinaryOperator::isNot(Cond)) {
-    Cond = BinaryOperator::getNotArgument(Cond);
+  if (Not)
     Opc = WebAssembly::BR_UNLESS;
-  }
 
-  unsigned CondReg = getRegForI1Value(Cond);
   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
       .addMBB(TBB)
       .addReg(CondReg);
@@ -874,7 +1134,14 @@ bool WebAssemblyFastISel::selectRet(cons
   default: return false;
   }
 
-  unsigned Reg = getRegForValue(RV);
+  unsigned Reg;
+  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
+    Reg = getRegForSignedValue(RV);
+  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
+    Reg = getRegForUnsignedValue(RV);
+  else
+    Reg = getRegForValue(RV);
+
   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
   return true;
 }
@@ -887,6 +1154,12 @@ bool WebAssemblyFastISel::selectUnreacha
 
 bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
   switch (I->getOpcode()) {
+  case Instruction::Call:
+    if (selectCall(I))
+      return true;
+    break;
+  case Instruction::Select:      return selectSelect(I);
+  case Instruction::Trunc:       return selectTrunc(I);
   case Instruction::ZExt:        return selectZExt(I);
   case Instruction::SExt:        return selectSExt(I);
   case Instruction::ICmp:        return selectICmp(I);

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp?rev=269273&r1=269272&r2=269273&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp Wed May 11 23:19:09 2016
@@ -297,13 +297,14 @@ static MachineInstr *MoveAndTeeForMultiU
   unsigned NewReg = MRI.createVirtualRegister(RegClass);
   unsigned TeeReg = MRI.createVirtualRegister(RegClass);
   unsigned DefReg = MRI.createVirtualRegister(RegClass);
+  MachineOperand &DefMO = Def->getOperand(0);
   MRI.replaceRegWith(Reg, NewReg);
   MachineInstr *Tee = BuildMI(MBB, Insert, Insert->getDebugLoc(),
                               TII->get(GetTeeLocalOpcode(RegClass)), TeeReg)
                           .addReg(NewReg, RegState::Define)
-                          .addReg(DefReg);
+                          .addReg(DefReg, getUndefRegState(DefMO.isDead()));
   Op.setReg(TeeReg);
-  Def->getOperand(0).setReg(DefReg);
+  DefMO.setReg(DefReg);
   LIS.InsertMachineInstrInMaps(*Tee);
   LIS.removeInterval(Reg);
   LIS.createAndComputeVirtRegInterval(NewReg);

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp?rev=269273&r1=269272&r2=269273&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyStoreResults.cpp Wed May 11 23:19:09 2016
@@ -115,9 +115,11 @@ static bool ReplaceDominatedUses(Machine
     O.setReg(ToReg);
 
     // If the store's def was previously dead, it is no longer.
-    MI.getOperand(0).setIsDead(false);
+    if (!O.isUndef()) {
+      MI.getOperand(0).setIsDead(false);
 
-    Indices.push_back(WhereIdx.getRegSlot());
+      Indices.push_back(WhereIdx.getRegSlot());
+    }
   }
 
   if (Changed) {

Modified: llvm/trunk/test/CodeGen/WebAssembly/call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/call.ll?rev=269273&r1=269272&r2=269273&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/call.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/call.ll Wed May 11 23:19:09 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 call operations assemble as expected.
 

Modified: llvm/trunk/test/CodeGen/WebAssembly/select.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/select.ll?rev=269273&r1=269272&r2=269273&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/select.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/select.ll Wed May 11 23:19:09 2016
@@ -1,5 +1,5 @@
 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
-; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -fast-isel -fast-isel-abort=1 | FileCheck %s
 
 ; Test that wasm select instruction is selected from LLVM select instruction.
 




More information about the llvm-commits mailing list