Now that SimplifyDemandedBits/SimplifyDemandedVectorElts are simplifying vector elements, we're seeing more constant BUILD_VECTOR containing UNDEFs.
This patch provides opt-in handling of UNDEF elements in matchUnaryPredicate, passing NULL instead of the ConstantSDNode* argument.
I've updated SelectionDAG::simplifyShift to demonstrate its use.
Differential Revision: https://reviews.llvm.org/D55819
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349616
91177308-0d34-0410-b5e6-
96231b3b80d8
/// 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<bool(ConstantSDNode *)> Match);
+ std::function<bool(ConstantSDNode *)> 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.
}
bool ISD::matchUnaryPredicate(SDValue Op,
- std::function<bool(ConstantSDNode *)> Match) {
+ std::function<bool(ConstantSDNode *)> Match,
+ bool AllowUndefs) {
+ // FIXME: Add support for scalar UNDEF cases?
if (auto *Cst = dyn_cast<ConstantSDNode>(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<ConstantSDNode>(Op.getOperand(i));
if (!Cst || Cst->getValueType(0) != SVT || !Match(Cst))
return false;
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();
}
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, <i32 33, i32 34, i32 35, i32 undef>
ret <4 x i32> %1
}
}
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, <i32 33, i32 34, i32 35, i32 undef>
ret <4 x i32> %1
}
}
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, <i32 33, i32 34, i32 35, i32 undef>
ret <4 x i32> %1
}