diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1314,15 +1314,18 @@ SelectionDAG &DAG) const { SDLoc DL(Op); // If sign extension operations are disabled, allow sext_inreg only if operand - // is a vector extract. SIMD does not depend on sign extension operations, but - // allowing sext_inreg in this context lets us have simple patterns to select - // extract_lane_s instructions. Expanding sext_inreg everywhere would be - // simpler in this file, but would necessitate large and brittle patterns to - // undo the expansion and select extract_lane_s instructions. + // is a vector extract of an i8 or i16 lane. SIMD does not depend on sign + // extension operations, but allowing sext_inreg in this context lets us have + // simple patterns to select extract_lane_s instructions. Expanding sext_inreg + // everywhere would be simpler in this file, but would necessitate large and + // brittle patterns to undo the expansion and select extract_lane_s + // instructions. assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128()); if (Op.getOperand(0).getOpcode() == ISD::EXTRACT_VECTOR_ELT) { const SDValue &Extract = Op.getOperand(0); MVT VecT = Extract.getOperand(0).getSimpleValueType(); + if (VecT.getVectorElementType().getSizeInBits() > 32) + return SDValue(); MVT ExtractedLaneT = static_cast(Op.getOperand(1).getNode()) ->getVT() .getSimpleVT(); @@ -1339,9 +1342,9 @@ assert(Scale > 1); SDValue NewIndex = DAG.getConstant(IndexVal * Scale, DL, Index.getValueType()); - SDValue NewExtract = DAG.getNode( - ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(), - DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex); + SDValue NewExtract = + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(), + DAG.getBitcast(VecT, Extract.getOperand(0)), NewIndex); return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(), NewExtract, Op.getOperand(1)); } diff --git a/llvm/test/CodeGen/WebAssembly/PR44988.ll b/llvm/test/CodeGen/WebAssembly/PR44988.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/PR44988.ll @@ -0,0 +1,27 @@ +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+unimplemented-simd128 | FileCheck %s + +; Tests that signext_inreg patterns where an i32 vector lane is +; extended to an i64 are properly lowered. This was previously an ISel +; failure. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-emscripten" + +; CHECK-LABEL: foo: +; CHECK: i32x4.extract_lane +; CHECK-NEXT: i64.extend_i32_s +; CHECK-NEXT: i64x2.replace_lane +define <4 x i32> @foo(<4 x i32> %a) { + %bc.i = bitcast <4 x i32> %a to <2 x i64> + %b = extractelement <2 x i64> %bc.i, i32 0 + %sext.i = shl i64 %b, 32 + %conv.i = ashr exact i64 %sext.i, 32 + %c = bitcast i64 %conv.i to <2 x i32> + %c_lanes.i.0.vec.expand = shufflevector <2 x i32> %c, <2 x i32> undef, <4 x i32> + %d = extractelement <4 x i32> %a, i32 2 + %conv.1.i = sext i32 %d to i64 + %e = bitcast i64 %conv.1.i to <2 x i32> + %c_lanes.i.8.vec.expand = shufflevector <2 x i32> %e, <2 x i32> undef, <4 x i32> + %c_lanes.i.8.vecblend = shufflevector <4 x i32> %c_lanes.i.0.vec.expand, <4 x i32> %c_lanes.i.8.vec.expand, <4 x i32> + ret <4 x i32> %c_lanes.i.8.vecblend +}