Skip to content

Commit

Permalink
[WebAssembly] Fix ISel crash in SIGN_EXTEND_INREG lowering
Browse files Browse the repository at this point in the history
Summary:
The code previously assumed that the index of a vector extract was
constant, but this was not always true. This patch fixes the problem
by bailing out of the lowering if the index is nonconstant and also
replaces `static_cast`s in the lowering function with `cast`s because
the latter contain type-checking asserts that would make similar
issues easier to find and debug.

Reviewers: aheejin

Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D81025
  • Loading branch information
tlively committed Jun 3, 2020
1 parent 969d2d1 commit 25af212
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
14 changes: 7 additions & 7 deletions llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
Expand Up @@ -1388,23 +1388,23 @@ WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
MVT VecT = Extract.getOperand(0).getSimpleValueType();
if (VecT.getVectorElementType().getSizeInBits() > 32)
return SDValue();
MVT ExtractedLaneT = static_cast<VTSDNode *>(Op.getOperand(1).getNode())
->getVT()
.getSimpleVT();
MVT ExtractedLaneT =
cast<VTSDNode>(Op.getOperand(1).getNode())->getVT().getSimpleVT();
MVT ExtractedVecT =
MVT::getVectorVT(ExtractedLaneT, 128 / ExtractedLaneT.getSizeInBits());
if (ExtractedVecT == VecT)
return Op;

// Bitcast vector to appropriate type to ensure ISel pattern coverage
const SDValue &Index = Extract.getOperand(1);
unsigned IndexVal =
static_cast<ConstantSDNode *>(Index.getNode())->getZExtValue();
const SDNode *Index = Extract.getOperand(1).getNode();
if (!isa<ConstantSDNode>(Index))
return SDValue();
unsigned IndexVal = cast<ConstantSDNode>(Index)->getZExtValue();
unsigned Scale =
ExtractedVecT.getVectorNumElements() / VecT.getVectorNumElements();
assert(Scale > 1);
SDValue NewIndex =
DAG.getConstant(IndexVal * Scale, DL, Index.getValueType());
DAG.getConstant(IndexVal * Scale, DL, Index->getValueType(0));
SDValue NewExtract = DAG.getNode(
ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(),
DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex);
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/WebAssembly/simd-nonconst-sext.ll
@@ -0,0 +1,20 @@
; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mattr=+simd128 | FileCheck %s

; A regression test for a bug in the lowering of SIGN_EXTEND_INREG
; with SIMD and without sign-ext where ISel would crash if the index
; of the vector extract was not a constant.

target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32"

; CHECK-LABEL: foo:
; CHECK-NEXT: .functype foo () -> (f32)
; CHECK: i32x4.load16x4_u
; CHECK: f32.convert_i32_s
define float @foo() {
%1 = load <4 x i16>, <4 x i16>* undef, align 8
%2 = load i32, i32* undef, align 4
%vecext = extractelement <4 x i16> %1, i32 %2
%conv = sitofp i16 %vecext to float
ret float %conv
}

0 comments on commit 25af212

Please sign in to comment.