diff options
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h | 3 | ||||
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll | 24 |
3 files changed, 42 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 1f72c654ee8..06aee6e80a0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -897,6 +897,21 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments( return Chain; } +void WebAssemblyTargetLowering::ReplaceNodeResults( + SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const { + switch (N->getOpcode()) { + case ISD::SIGN_EXTEND_INREG: + // Do not add any results, signifying that N should not be custom lowered + // after all. This happens because simd128 turns on custom lowering for + // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an + // illegal type. + break; + default: + llvm_unreachable( + "ReplaceNodeResults not implemented for this op for WebAssembly!"); + } +} + //===----------------------------------------------------------------------===// // Custom lowering hooks. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index f899f0feee4..80fca287647 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -85,6 +85,9 @@ private: const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const override; + void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, + SelectionDAG &DAG) const override; + // Custom lowering hooks. SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll b/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll new file mode 100644 index 00000000000..20775f0ee3a --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s -mattr=+simd128 | FileCheck %s + +; Regression test for a crash caused by +; WebAssemblyTargetLowering::ReplaceNodeResults not being +; implemented. Since SIMD is enabled, sign_ext_inreg is custom lowered +; but the result is i16, an illegal value. This requires +; ReplaceNodeResults to resolve, but the default implementation is to +; abort. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-emscripten" + +; CHECK: i32.load8_s +; CHECK-NEXT: i32.store16 +define void @foo() { +entry: + %0 = load i32*, i32** undef, align 4 + %1 = load i32, i32* %0, align 4 + %2 = load i32, i32* undef, align 4 + %conv67 = trunc i32 %2 to i8 + %conv68 = sext i8 %conv67 to i16 + store i16 %conv68, i16* null, align 2 + ret void +} |