diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13998,20 +13998,32 @@ if (N0.isUndef()) return DAG.getUNDEF(VT); - // If the input is a BUILD_VECTOR with all constant elements, fold this now. - // Only do this before legalize types, unless both types are integer and the - // scalar type is legal. Only do this before legalize ops, since the target - // maybe depending on the bitcast. - // First check to see if this is all constant. - // TODO: Support FP bitcasts after legalize types. - if (VT.isVector() && + // If the input is a BUILD_VECTOR with all constant elements or SPLAT_VECTOR + // with a constant scalar, fold this now. Only do this before legalize types, + // unless both types are integer and the scalar type is legal. Only do this + // before legalize ops, since the target maybe depending on the bitcast. + // First check to see if this is all constant. TODO: Support FP bitcasts + // after legalize types. + if (VT.isVector() && N0->hasOneUse() && (!LegalTypes || (!LegalOperations && VT.isInteger() && N0.getValueType().isInteger() && - TLI.isTypeLegal(VT.getVectorElementType()))) && - N0.getOpcode() == ISD::BUILD_VECTOR && N0->hasOneUse() && - cast(N0)->isConstant()) - return ConstantFoldBITCASTofBUILD_VECTOR(N0.getNode(), - VT.getVectorElementType()); + TLI.isTypeLegal(VT.getVectorElementType())))) { + if (N0.getOpcode() == ISD::BUILD_VECTOR && + cast(N0)->isConstant()) + return ConstantFoldBITCASTofBUILD_VECTOR(N0.getNode(), + VT.getVectorElementType()); + + // In the case of SPLAT_VECTOR, convert it back to a BUILD_VECTOR first and + // fold it that way + if (N0.getOpcode() == ISD::SPLAT_VECTOR && + DAG.isConstantValueOfAnyType(N0.getOperand(0))) { + + auto BVN = DAG.getSplatBuildVector(N0.getValueType(), SDLoc(N0), + N0.getOperand(0)); + return ConstantFoldBITCASTofBUILD_VECTOR(BVN.getNode(), + VT.getVectorElementType()); + } + } // If the input is a constant, let getNode fold it. if (isIntOrFPConstant(N0)) { diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3030,6 +3030,14 @@ } break; } + case ISD::SPLAT_VECTOR: { + SDValue Scl = Op.getOperand(0); + if (Scl.isUndef()) + KnownUndef.setAllBits(); + if (isNullConstant(Scl) || isNullFPConstant(Scl)) + KnownZero.setAllBits(); + break; + } case ISD::CONCAT_VECTORS: { EVT SubVT = Op.getOperand(0).getValueType(); unsigned NumSubVecs = Op.getNumOperands(); diff --git a/llvm/test/CodeGen/WebAssembly/pr59626.ll b/llvm/test/CodeGen/WebAssembly/pr59626.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/pr59626.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mtriple=wasm64-- -mattr=+simd128 | FileCheck %s + +define i8 @f(ptr %0, ptr %1) { +; CHECK-LABEL: f: +; CHECK: .functype f (i64, i64) -> (i32) +; CHECK-NEXT: .local i32 +; CHECK-NEXT: # %bb.0: # %BB +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: i32.store8 2 +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: i32.store16 0 +; CHECK-NEXT: local.get 1 +; CHECK-NEXT: local.get 2 +; CHECK-NEXT: i8x16.splat +; CHECK-NEXT: v128.store16_lane 0, 0 +; CHECK-NEXT: drop +; CHECK-NEXT: i32.const 0 +; CHECK-NEXT: # fallthrough-return +BB: + store <3 x i8> zeroinitializer, ptr %0 + %S = shufflevector <3 x i128> zeroinitializer, <3 x i128> , <3 x i32> undef + %C = icmp ule <3 x i128> %S, zeroinitializer + %C1 = zext <3 x i1> %C to <3 x i8> + %E = extractelement <3 x i8> %C1, i32 0 + %B = sdiv <3 x i8> , %C1 + store <3 x i8> %B, ptr %1 + ret i8 %E +}