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 @@ -14042,20 +14042,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 --- a/llvm/test/CodeGen/WebAssembly/pr59626.ll +++ b/llvm/test/CodeGen/WebAssembly/pr59626.ll @@ -12,12 +12,7 @@ ; CHECK-32-NEXT: local.get 0 ; CHECK-32-NEXT: i32.const 0 ; CHECK-32-NEXT: i32.store16 0 -; CHECK-32-NEXT: local.get 1 -; CHECK-32-NEXT: local.get 0 -; CHECK-32-NEXT: i8x16.splat -; CHECK-32-NEXT: v128.store16_lane 0, 0 -; CHECK-32-NEXT: v128.const 0, 0 -; CHECK-32-NEXT: i32x4.extract_lane 0 +; CHECK-32-NEXT: i32.const 0 ; CHECK-32-NEXT: # fallthrough-return ; ; CHECK-64-LABEL: f: @@ -35,8 +30,7 @@ ; CHECK-64-NEXT: i8x16.splat ; CHECK-64-NEXT: v128.store16_lane 0, 0 ; CHECK-64-NEXT: drop -; CHECK-64-NEXT: v128.const 0, 0 -; CHECK-64-NEXT: i32x4.extract_lane 0 +; CHECK-64-NEXT: i32.const 0 ; CHECK-64-NEXT: # fallthrough-return BB: store <3 x i8> zeroinitializer, ptr %0