Index: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h @@ -2487,8 +2487,10 @@ /// Attempt to match a unary predicate against a scalar/splat constant or /// every element of a constant BUILD_VECTOR. + /// If AllowUndef is true, then UNDEF element will pass nullptr to Match. bool matchUnaryPredicate(SDValue Op, - std::function Match); + std::function Match, + bool AllowUndefs = false); /// Attempt to match a binary predicate against a pair of scalar/splat /// constants or every element of a pair of constant BUILD_VECTORs. Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -269,15 +269,24 @@ } bool ISD::matchUnaryPredicate(SDValue Op, - std::function Match) { + std::function Match, + bool AllowUndefs) { + // FIXME: Add support for scalar UNDEF cases? if (auto *Cst = dyn_cast(Op)) return Match(Cst); + // FIXME: Add support for vector UNDEF cases? if (ISD::BUILD_VECTOR != Op.getOpcode()) return false; EVT SVT = Op.getValueType().getScalarType(); for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) { + if (AllowUndefs && Op.getOperand(i).isUndef()) { + if (!Match(nullptr)) + return false; + continue; + } + auto *Cst = dyn_cast(Op.getOperand(i)); if (!Cst || Cst->getValueType(0) != SVT || !Match(Cst)) return false; @@ -6967,11 +6976,11 @@ return X; // shift X, C >= bitwidth(X) --> undef - // All vector elements must be too big to avoid partial undefs. + // All vector elements must be too big (or undef) to avoid partial undefs. auto isShiftTooBig = [X](ConstantSDNode *Val) { - return Val->getAPIntValue().uge(X.getScalarValueSizeInBits()); + return !Val || Val->getAPIntValue().uge(X.getScalarValueSizeInBits()); }; - if (ISD::matchUnaryPredicate(Y, isShiftTooBig)) + if (ISD::matchUnaryPredicate(Y, isShiftTooBig, true)) return getUNDEF(X.getValueType()); return SDValue(); Index: llvm/trunk/test/CodeGen/X86/combine-shl.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/combine-shl.ll +++ llvm/trunk/test/CodeGen/X86/combine-shl.ll @@ -46,15 +46,9 @@ } define <4 x i32> @combine_vec_shl_outofrange3(<4 x i32> %a0) { -; SSE-LABEL: combine_vec_shl_outofrange3: -; SSE: # %bb.0: -; SSE-NEXT: xorps %xmm0, %xmm0 -; SSE-NEXT: retq -; -; AVX-LABEL: combine_vec_shl_outofrange3: -; AVX: # %bb.0: -; AVX-NEXT: vpsllvd {{.*}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: retq +; CHECK-LABEL: combine_vec_shl_outofrange3: +; CHECK: # %bb.0: +; CHECK-NEXT: retq %1 = shl <4 x i32> %a0, ret <4 x i32> %1 } Index: llvm/trunk/test/CodeGen/X86/combine-sra.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/combine-sra.ll +++ llvm/trunk/test/CodeGen/X86/combine-sra.ll @@ -51,14 +51,9 @@ } define <4 x i32> @combine_vec_ashr_outofrange2(<4 x i32> %x) { -; SSE-LABEL: combine_vec_ashr_outofrange2: -; SSE: # %bb.0: -; SSE-NEXT: retq -; -; AVX-LABEL: combine_vec_ashr_outofrange2: -; AVX: # %bb.0: -; AVX-NEXT: vpsravd {{.*}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: retq +; CHECK-LABEL: combine_vec_ashr_outofrange2: +; CHECK: # %bb.0: +; CHECK-NEXT: retq %1 = ashr <4 x i32> %x, ret <4 x i32> %1 } Index: llvm/trunk/test/CodeGen/X86/combine-srl.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/combine-srl.ll +++ llvm/trunk/test/CodeGen/X86/combine-srl.ll @@ -36,14 +36,9 @@ } define <4 x i32> @combine_vec_lshr_outofrange2(<4 x i32> %x) { -; SSE-LABEL: combine_vec_lshr_outofrange2: -; SSE: # %bb.0: -; SSE-NEXT: retq -; -; AVX-LABEL: combine_vec_lshr_outofrange2: -; AVX: # %bb.0: -; AVX-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 -; AVX-NEXT: retq +; CHECK-LABEL: combine_vec_lshr_outofrange2: +; CHECK: # %bb.0: +; CHECK-NEXT: retq %1 = lshr <4 x i32> %x, ret <4 x i32> %1 }