[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