diff options
| author | Derek Schuff <dschuff@google.com> | 2016-08-04 18:01:52 +0000 |
|---|---|---|
| committer | Derek Schuff <dschuff@google.com> | 2016-08-04 18:01:52 +0000 |
| commit | 732636d9015c458c97f9fef6389a213dd54bfecf (patch) | |
| tree | b61d57f9a78558023ff30fdaa6b8c11650fd0e57 | |
| parent | ad547d361e8c7a3ad645fa09433842979deae9e1 (diff) | |
[WebAssembly] Check return value of getRegForValue in FastISel
Previously, FastISel for WebAssembly wasn't checking the return value of
`getRegForValue` in certain cases, which would generate instructions
referencing NoReg. This patch fixes this behavior.
Patch by Dominic Chen
Differential Revision: https://reviews.llvm.org/D23100
llvm-svn: 277742
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 13 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/fast-isel-noreg.ll | 35 |
2 files changed, 48 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index b4786e5518f9..2f4096227956 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -388,6 +388,9 @@ unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) { unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V, MVT::SimpleValueType From) { + if (Reg == 0) + return 0; + switch (From) { case MVT::i1: // If the value is naturally an i1, we don't need to mask it. @@ -422,6 +425,9 @@ unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V, unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V, MVT::SimpleValueType From) { + if (Reg == 0) + return 0; + switch (From) { case MVT::i1: case MVT::i8: @@ -1121,6 +1127,8 @@ bool WebAssemblyFastISel::selectStore(const Instruction *I) { materializeLoadStoreOperands(Addr); unsigned ValueReg = getRegForValue(Store->getValueOperand()); + if (ValueReg == 0) + return false; if (VTIsi1) ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); @@ -1147,6 +1155,8 @@ bool WebAssemblyFastISel::selectBr(const Instruction *I) { bool Not; unsigned CondReg = getRegForI1Value(Br->getCondition(), Not); + if (CondReg == 0) + return false; unsigned Opc = WebAssembly::BR_IF; if (Not) @@ -1214,6 +1224,9 @@ bool WebAssemblyFastISel::selectRet(const Instruction *I) { else Reg = getRegForValue(RV); + if (Reg == 0) + return false; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg); return true; } diff --git a/llvm/test/CodeGen/WebAssembly/fast-isel-noreg.ll b/llvm/test/CodeGen/WebAssembly/fast-isel-noreg.ll new file mode 100644 index 000000000000..5b3c2a0522a2 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/fast-isel-noreg.ll @@ -0,0 +1,35 @@ +; 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 + +; Test that FastISel does not generate instructions with NoReg + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; CHECK: i32.const $push0=, 0 +define hidden i32 @a() #0 { +entry: + ret i32 zext (i1 icmp eq (void (...)* inttoptr (i32 10 to void (...)*), void (...)* null) to i32) +} + +; CHECK: i32.const $push0=, 1 +; CHECK: br_if 0, $pop0 +define hidden i32 @b() #0 { +entry: + br i1 icmp eq (void (...)* inttoptr (i32 10 to void (...)*), void (...)* null), label %a, label %b +a: + unreachable +b: + ret i32 0 +} + +; CHECK: i32.const $push1=, 0 +; CHECK: i32.const $push2=, 0 +; CHECK: i32.store $drop=, 0($pop1), $pop2 +define hidden i32 @c() #0 { +entry: + store i32 zext (i1 icmp eq (void (...)* inttoptr (i32 10 to void (...)*), void (...)* null) to i32), i32* inttoptr (i32 0 to i32 *) + ret i32 0 +} + +attributes #0 = { noinline optnone } |
