[InstCombine] Use m_APInt() in asymmetric masked icmp fold

This is mostly intended as code cleanup, but it does also add
support for splat vectors to this fold.
This commit is contained in:
Nikita Popov 2022-05-24 10:56:16 +02:00
parent e1fcf998dc
commit 5abaabed22
2 changed files with 22 additions and 25 deletions

View File

@ -379,9 +379,9 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
//
// We currently handle the case of B, C, D, E are constant.
//
ConstantInt *BCst, *CCst, *DCst, *ECst;
if (!match(B, m_ConstantInt(BCst)) || !match(C, m_ConstantInt(CCst)) ||
!match(D, m_ConstantInt(DCst)) || !match(E, m_ConstantInt(ECst)))
const APInt *BCst, *CCst, *DCst, *OrigECst;
if (!match(B, m_APInt(BCst)) || !match(C, m_APInt(CCst)) ||
!match(D, m_APInt(DCst)) || !match(E, m_APInt(OrigECst)))
return nullptr;
ICmpInst::Predicate NewCC = IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
@ -390,19 +390,20 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
// canonicalized as,
// (icmp ne (A & D), 0) -> (icmp eq (A & D), D) or
// (icmp ne (A & D), D) -> (icmp eq (A & D), 0).
APInt ECst = *OrigECst;
if (PredR != NewCC)
ECst = cast<ConstantInt>(ConstantExpr::getXor(DCst, ECst));
ECst ^= *DCst;
// If B or D is zero, skip because if LHS or RHS can be trivially folded by
// other folding rules and this pattern won't apply any more.
if (BCst->getValue() == 0 || DCst->getValue() == 0)
if (*BCst == 0 || *DCst == 0)
return nullptr;
// If B and D don't intersect, ie. (B & D) == 0, no folding because we can't
// deduce anything from it.
// For example,
// (icmp ne (A & 12), 0) & (icmp eq (A & 3), 1) -> no folding.
if ((BCst->getValue() & DCst->getValue()) == 0)
if ((*BCst & *DCst) == 0)
return nullptr;
// If the following two conditions are met:
@ -421,22 +422,21 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
// For example,
// (icmp ne (A & 12), 0) & (icmp eq (A & 7), 1) -> (icmp eq (A & 15), 9)
// (icmp ne (A & 15), 0) & (icmp eq (A & 7), 0) -> (icmp eq (A & 15), 8)
if ((((BCst->getValue() & DCst->getValue()) & ECst->getValue()) == 0) &&
(BCst->getValue() & (BCst->getValue() ^ DCst->getValue())).isPowerOf2()) {
APInt BorD = BCst->getValue() | DCst->getValue();
APInt BandBxorDorE = (BCst->getValue() & (BCst->getValue() ^ DCst->getValue())) |
ECst->getValue();
Value *NewMask = ConstantInt::get(BCst->getType(), BorD);
Value *NewMaskedValue = ConstantInt::get(BCst->getType(), BandBxorDorE);
if ((((*BCst & *DCst) & ECst) == 0) &&
(*BCst & (*BCst ^ *DCst)).isPowerOf2()) {
APInt BorD = *BCst | *DCst;
APInt BandBxorDorE = (*BCst & (*BCst ^ *DCst)) | ECst;
Value *NewMask = ConstantInt::get(A->getType(), BorD);
Value *NewMaskedValue = ConstantInt::get(A->getType(), BandBxorDorE);
Value *NewAnd = Builder.CreateAnd(A, NewMask);
return Builder.CreateICmp(NewCC, NewAnd, NewMaskedValue);
}
auto IsSubSetOrEqual = [](ConstantInt *C1, ConstantInt *C2) {
return (C1->getValue() & C2->getValue()) == C1->getValue();
auto IsSubSetOrEqual = [](const APInt *C1, const APInt *C2) {
return (*C1 & *C2) == *C1;
};
auto IsSuperSetOrEqual = [](ConstantInt *C1, ConstantInt *C2) {
return (C1->getValue() & C2->getValue()) == C2->getValue();
auto IsSuperSetOrEqual = [](const APInt *C1, const APInt *C2) {
return (*C1 & *C2) == *C2;
};
// In the following, we consider only the cases where B is a superset of D, B
@ -456,7 +456,7 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
// For example,
// (icmp ne (A & 3), 0) & (icmp eq (A & 7), 0) -> false.
// (icmp ne (A & 15), 0) & (icmp eq (A & 3), 0) -> no folding.
if (ECst->isZero()) {
if (ECst.isZero()) {
if (IsSubSetOrEqual(BCst, DCst))
return ConstantInt::get(LHS->getType(), !IsAnd);
return nullptr;
@ -474,7 +474,7 @@ static Value *foldLogOpOfMaskedICmps_NotAllZeros_BMask_Mixed(
// ie. (B & E) != 0, then LHS is subsumed by RHS. For example.
// (icmp ne (A & 12), 0) & (icmp eq (A & 15), 8) -> (icmp eq (A & 15), 8).
assert(IsSubSetOrEqual(BCst, DCst) && "Precondition due to above code");
if ((BCst->getValue() & ECst->getValue()) != 0)
if ((*BCst & ECst) != 0)
return RHS;
// Otherwise, LHS and RHS contradict and the whole expression becomes false
// (or true if negated.) For example,

View File

@ -459,12 +459,9 @@ define i1 @masked_icmps_mask_notallzeros_bmask_mixed_1(i32 %x) {
define <2 x i1> @masked_icmps_mask_notallzeros_bmask_mixed_1_vector(<2 x i32> %x) {
; CHECK-LABEL: @masked_icmps_mask_notallzeros_bmask_mixed_1_vector(
; CHECK-NEXT: [[T1:%.*]] = and <2 x i32> [[X:%.*]], <i32 12, i32 12>
; CHECK-NEXT: [[T2:%.*]] = icmp ne <2 x i32> [[T1]], zeroinitializer
; CHECK-NEXT: [[T3:%.*]] = and <2 x i32> [[X]], <i32 7, i32 7>
; CHECK-NEXT: [[T4:%.*]] = icmp eq <2 x i32> [[T3]], <i32 1, i32 1>
; CHECK-NEXT: [[T5:%.*]] = and <2 x i1> [[T2]], [[T4]]
; CHECK-NEXT: ret <2 x i1> [[T5]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 15, i32 15>
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 9, i32 9>
; CHECK-NEXT: ret <2 x i1> [[TMP2]]
;
%t1 = and <2 x i32> %x, <i32 12, i32 12>
%t2 = icmp ne <2 x i32> %t1, zeroinitializer