[InstCombine] fix formatting for foldLogOpOfMaskedICmps and related bits; NFCI

1. Improve enum, function, and variable names.
2. Improve comments.
3. Fix variable capitalization.
4. Run clang-format.

As an existing code comment suggests, this should work with vector types / splat constants too,
so making this look right first will reduce the diffs needed for that change.

llvm-svn: 299365
This commit is contained in:
Sanjay Patel 2017-04-03 16:53:12 +00:00
parent 7a3b69d096
commit 77bf622db6
1 changed files with 157 additions and 144 deletions

View File

@ -295,107 +295,91 @@ Value *InstCombiner::insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
return Builder->CreateICmp(Pred, VMinusLo, HiMinusLo);
}
/// enum for classifying (icmp eq (A & B), C) and (icmp ne (A & B), C)
/// One of A and B is considered the mask, the other the value. This is
/// described as the "AMask" or "BMask" part of the enum. If the enum
/// contains only "Mask", then both A and B can be considered masks.
/// If A is the mask, then it was proven, that (A & C) == C. This
/// is trivial if C == A, or C == 0. If both A and C are constants, this
/// proof is also easy.
/// For the following explanations we assume that A is the mask.
/// The part "AllOnes" declares, that the comparison is true only
/// if (A & B) == A, or all bits of A are set in B.
/// Example: (icmp eq (A & 3), 3) -> FoldMskICmp_AMask_AllOnes
/// The part "AllZeroes" declares, that the comparison is true only
/// if (A & B) == 0, or all bits of A are cleared in B.
/// Example: (icmp eq (A & 3), 0) -> FoldMskICmp_Mask_AllZeroes
/// The part "Mixed" declares, that (A & B) == C and C might or might not
/// contain any number of one bits and zero bits.
/// Example: (icmp eq (A & 3), 1) -> FoldMskICmp_AMask_Mixed
/// The Part "Not" means, that in above descriptions "==" should be replaced
/// by "!=".
/// Example: (icmp ne (A & 3), 3) -> FoldMskICmp_AMask_NotAllOnes
/// Classify (icmp eq (A & B), C) and (icmp ne (A & B), C) as matching patterns
/// that can be simplified.
/// One of A and B is considered the mask. The other is the value. This is
/// described as the "AMask" or "BMask" part of the enum. If the enum contains
/// only "Mask", then both A and B can be considered masks. If A is the mask,
/// then it was proven that (A & C) == C. This is trivial if C == A or C == 0.
/// If both A and C are constants, this proof is also easy.
/// For the following explanations, we assume that A is the mask.
///
/// "AllOnes" declares that the comparison is true only if (A & B) == A or all
/// bits of A are set in B.
/// Example: (icmp eq (A & 3), 3) -> AMask_AllOnes
///
/// "AllZeros" declares that the comparison is true only if (A & B) == 0 or all
/// bits of A are cleared in B.
/// Example: (icmp eq (A & 3), 0) -> Mask_AllZeroes
///
/// "Mixed" declares that (A & B) == C and C might or might not contain any
/// number of one bits and zero bits.
/// Example: (icmp eq (A & 3), 1) -> AMask_Mixed
///
/// "Not" means that in above descriptions "==" should be replaced by "!=".
/// Example: (icmp ne (A & 3), 3) -> AMask_NotAllOnes
///
/// If the mask A contains a single bit, then the following is equivalent:
/// (icmp eq (A & B), A) equals (icmp ne (A & B), 0)
/// (icmp ne (A & B), A) equals (icmp eq (A & B), 0)
enum MaskedICmpType {
FoldMskICmp_AMask_AllOnes = 1,
FoldMskICmp_AMask_NotAllOnes = 2,
FoldMskICmp_BMask_AllOnes = 4,
FoldMskICmp_BMask_NotAllOnes = 8,
FoldMskICmp_Mask_AllZeroes = 16,
FoldMskICmp_Mask_NotAllZeroes = 32,
FoldMskICmp_AMask_Mixed = 64,
FoldMskICmp_AMask_NotMixed = 128,
FoldMskICmp_BMask_Mixed = 256,
FoldMskICmp_BMask_NotMixed = 512
AMask_AllOnes = 1,
AMask_NotAllOnes = 2,
BMask_AllOnes = 4,
BMask_NotAllOnes = 8,
Mask_AllZeros = 16,
Mask_NotAllZeros = 32,
AMask_Mixed = 64,
AMask_NotMixed = 128,
BMask_Mixed = 256,
BMask_NotMixed = 512
};
/// Return the set of pattern classes (from MaskedICmpType)
/// that (icmp SCC (A & B), C) satisfies.
static unsigned getTypeOfMaskedICmp(Value* A, Value* B, Value* C,
ICmpInst::Predicate SCC)
{
/// Return the set of patterns (from MaskedICmpType) that (icmp SCC (A & B), C)
/// satisfies.
static unsigned getMaskedICmpType(Value *A, Value *B, Value *C,
ICmpInst::Predicate Pred) {
ConstantInt *ACst = dyn_cast<ConstantInt>(A);
ConstantInt *BCst = dyn_cast<ConstantInt>(B);
ConstantInt *CCst = dyn_cast<ConstantInt>(C);
bool icmp_eq = (SCC == ICmpInst::ICMP_EQ);
bool icmp_abit = (ACst && !ACst->isZero() &&
ACst->getValue().isPowerOf2());
bool icmp_bbit = (BCst && !BCst->isZero() &&
BCst->getValue().isPowerOf2());
unsigned result = 0;
bool IsEq = (Pred == ICmpInst::ICMP_EQ);
bool IsAPow2 = (ACst && !ACst->isZero() && ACst->getValue().isPowerOf2());
bool IsBPow2 = (BCst && !BCst->isZero() && BCst->getValue().isPowerOf2());
unsigned MaskVal = 0;
if (CCst && CCst->isZero()) {
// if C is zero, then both A and B qualify as mask
result |= (icmp_eq ? (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_AMask_Mixed |
FoldMskICmp_BMask_Mixed)
: (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_AMask_NotMixed |
FoldMskICmp_BMask_NotMixed));
if (icmp_abit)
result |= (icmp_eq ? (FoldMskICmp_AMask_NotAllOnes |
FoldMskICmp_AMask_NotMixed)
: (FoldMskICmp_AMask_AllOnes |
FoldMskICmp_AMask_Mixed));
if (icmp_bbit)
result |= (icmp_eq ? (FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_BMask_NotMixed)
: (FoldMskICmp_BMask_AllOnes |
FoldMskICmp_BMask_Mixed));
return result;
MaskVal |= (IsEq ? (Mask_AllZeros | AMask_Mixed | BMask_Mixed)
: (Mask_NotAllZeros | AMask_NotMixed | BMask_NotMixed));
if (IsAPow2)
MaskVal |= (IsEq ? (AMask_NotAllOnes | AMask_NotMixed)
: (AMask_AllOnes | AMask_Mixed));
if (IsBPow2)
MaskVal |= (IsEq ? (BMask_NotAllOnes | BMask_NotMixed)
: (BMask_AllOnes | BMask_Mixed));
return MaskVal;
}
if (A == C) {
result |= (icmp_eq ? (FoldMskICmp_AMask_AllOnes |
FoldMskICmp_AMask_Mixed)
: (FoldMskICmp_AMask_NotAllOnes |
FoldMskICmp_AMask_NotMixed));
if (icmp_abit)
result |= (icmp_eq ? (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_AMask_NotMixed)
: (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_AMask_Mixed));
} else if (ACst && CCst &&
ConstantExpr::getAnd(ACst, CCst) == CCst) {
result |= (icmp_eq ? FoldMskICmp_AMask_Mixed
: FoldMskICmp_AMask_NotMixed);
MaskVal |= (IsEq ? (AMask_AllOnes | AMask_Mixed)
: (AMask_NotAllOnes | AMask_NotMixed));
if (IsAPow2)
MaskVal |= (IsEq ? (Mask_NotAllZeros | AMask_NotMixed)
: (Mask_AllZeros | AMask_Mixed));
} else if (ACst && CCst && ConstantExpr::getAnd(ACst, CCst) == CCst) {
MaskVal |= (IsEq ? AMask_Mixed : AMask_NotMixed);
}
if (B == C) {
result |= (icmp_eq ? (FoldMskICmp_BMask_AllOnes |
FoldMskICmp_BMask_Mixed)
: (FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_BMask_NotMixed));
if (icmp_bbit)
result |= (icmp_eq ? (FoldMskICmp_Mask_NotAllZeroes |
FoldMskICmp_BMask_NotMixed)
: (FoldMskICmp_Mask_AllZeroes |
FoldMskICmp_BMask_Mixed));
} else if (BCst && CCst &&
ConstantExpr::getAnd(BCst, CCst) == CCst) {
result |= (icmp_eq ? FoldMskICmp_BMask_Mixed
: FoldMskICmp_BMask_NotMixed);
MaskVal |= (IsEq ? (BMask_AllOnes | BMask_Mixed)
: (BMask_NotAllOnes | BMask_NotMixed));
if (IsBPow2)
MaskVal |= (IsEq ? (Mask_NotAllZeros | BMask_NotMixed)
: (Mask_AllZeros | BMask_Mixed));
} else if (BCst && CCst && ConstantExpr::getAnd(BCst, CCst) == CCst) {
MaskVal |= (IsEq ? BMask_Mixed : BMask_NotMixed);
}
return result;
return MaskVal;
}
/// Convert an analysis of a masked ICmp into its equivalent if all boolean
@ -404,32 +388,30 @@ static unsigned getTypeOfMaskedICmp(Value* A, Value* B, Value* C,
/// involves swapping those bits over.
static unsigned conjugateICmpMask(unsigned Mask) {
unsigned NewMask;
NewMask = (Mask & (FoldMskICmp_AMask_AllOnes | FoldMskICmp_BMask_AllOnes |
FoldMskICmp_Mask_AllZeroes | FoldMskICmp_AMask_Mixed |
FoldMskICmp_BMask_Mixed))
NewMask = (Mask & (AMask_AllOnes | BMask_AllOnes | Mask_AllZeros |
AMask_Mixed | BMask_Mixed))
<< 1;
NewMask |=
(Mask & (FoldMskICmp_AMask_NotAllOnes | FoldMskICmp_BMask_NotAllOnes |
FoldMskICmp_Mask_NotAllZeroes | FoldMskICmp_AMask_NotMixed |
FoldMskICmp_BMask_NotMixed))
>> 1;
NewMask |= (Mask & (AMask_NotAllOnes | BMask_NotAllOnes | Mask_NotAllZeros |
AMask_NotMixed | BMask_NotMixed))
>> 1;
return NewMask;
}
/// Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E)
/// Return the set of pattern classes (from MaskedICmpType)
/// that both LHS and RHS satisfy.
static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
Value*& B, Value*& C,
Value*& D, Value*& E,
ICmpInst *LHS, ICmpInst *RHS,
ICmpInst::Predicate &LHSCC,
ICmpInst::Predicate &RHSCC) {
if (LHS->getOperand(0)->getType() != RHS->getOperand(0)->getType()) return 0;
/// Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).
/// Return the set of pattern classes (from MaskedICmpType) that both LHS and
/// RHS satisfy.
static unsigned getMaskedTypeForICmpPair(Value *&A, Value *&B, Value *&C,
Value *&D, Value *&E, ICmpInst *LHS,
ICmpInst *RHS,
ICmpInst::Predicate &PredL,
ICmpInst::Predicate &PredR) {
if (LHS->getOperand(0)->getType() != RHS->getOperand(0)->getType())
return 0;
// vectors are not (yet?) supported
if (LHS->getOperand(0)->getType()->isVectorTy()) return 0;
if (LHS->getOperand(0)->getType()->isVectorTy())
return 0;
// Here comes the tricky part:
// LHS might be of the form L11 & L12 == X, X == L21 & L22,
@ -439,9 +421,9 @@ static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
// above.
Value *L1 = LHS->getOperand(0);
Value *L2 = LHS->getOperand(1);
Value *L11,*L12,*L21,*L22;
Value *L11, *L12, *L21, *L22;
// Check whether the icmp can be decomposed into a bit test.
if (decomposeBitTestICmp(LHS, LHSCC, L11, L12, L2)) {
if (decomposeBitTestICmp(LHS, PredL, L11, L12, L2)) {
L21 = L22 = L1 = nullptr;
} else {
// Look for ANDs in the LHS icmp.
@ -465,22 +447,26 @@ static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
}
// Bail if LHS was a icmp that can't be decomposed into an equality.
if (!ICmpInst::isEquality(LHSCC))
if (!ICmpInst::isEquality(PredL))
return 0;
Value *R1 = RHS->getOperand(0);
Value *R2 = RHS->getOperand(1);
Value *R11,*R12;
bool ok = false;
if (decomposeBitTestICmp(RHS, RHSCC, R11, R12, R2)) {
Value *R11, *R12;
bool Ok = false;
if (decomposeBitTestICmp(RHS, PredR, R11, R12, R2)) {
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12;
A = R11;
D = R12;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11;
A = R12;
D = R11;
} else {
return 0;
}
E = R2; R1 = nullptr; ok = true;
E = R2;
R1 = nullptr;
Ok = true;
} else if (R1->getType()->isIntegerTy()) {
if (!match(R1, m_And(m_Value(R11), m_Value(R12)))) {
// As before, model no mask as a trivial mask if it'll let us do an
@ -490,46 +476,62 @@ static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12; E = R2; ok = true;
A = R11;
D = R12;
E = R2;
Ok = true;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11; E = R2; ok = true;
A = R12;
D = R11;
E = R2;
Ok = true;
}
}
// Bail if RHS was a icmp that can't be decomposed into an equality.
if (!ICmpInst::isEquality(RHSCC))
if (!ICmpInst::isEquality(PredR))
return 0;
// Look for ANDs on the right side of the RHS icmp.
if (!ok && R2->getType()->isIntegerTy()) {
if (!Ok && R2->getType()->isIntegerTy()) {
if (!match(R2, m_And(m_Value(R11), m_Value(R12)))) {
R11 = R2;
R12 = Constant::getAllOnesValue(R2->getType());
}
if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
A = R11; D = R12; E = R1; ok = true;
A = R11;
D = R12;
E = R1;
Ok = true;
} else if (R12 == L11 || R12 == L12 || R12 == L21 || R12 == L22) {
A = R12; D = R11; E = R1; ok = true;
A = R12;
D = R11;
E = R1;
Ok = true;
} else {
return 0;
}
}
if (!ok)
if (!Ok)
return 0;
if (L11 == A) {
B = L12; C = L2;
B = L12;
C = L2;
} else if (L12 == A) {
B = L11; C = L2;
B = L11;
C = L2;
} else if (L21 == A) {
B = L22; C = L1;
B = L22;
C = L1;
} else if (L22 == A) {
B = L21; C = L1;
B = L21;
C = L1;
}
unsigned LeftType = getTypeOfMaskedICmp(A, B, C, LHSCC);
unsigned RightType = getTypeOfMaskedICmp(A, D, E, RHSCC);
unsigned LeftType = getMaskedICmpType(A, B, C, PredL);
unsigned RightType = getMaskedICmpType(A, D, E, PredR);
return LeftType & RightType;
}
@ -538,12 +540,14 @@ static unsigned foldLogOpOfMaskedICmpsHelper(Value*& A,
static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
llvm::InstCombiner::BuilderTy *Builder) {
Value *A = nullptr, *B = nullptr, *C = nullptr, *D = nullptr, *E = nullptr;
ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate();
unsigned Mask = foldLogOpOfMaskedICmpsHelper(A, B, C, D, E, LHS, RHS,
LHSCC, RHSCC);
if (Mask == 0) return nullptr;
assert(ICmpInst::isEquality(LHSCC) && ICmpInst::isEquality(RHSCC) &&
"foldLogOpOfMaskedICmpsHelper must return an equality predicate.");
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
unsigned Mask =
getMaskedTypeForICmpPair(A, B, C, D, E, LHS, RHS, PredL, PredR);
if (Mask == 0)
return nullptr;
assert(ICmpInst::isEquality(PredL) && ICmpInst::isEquality(PredR) &&
"Expected equality predicates for masked type of icmps.");
// In full generality:
// (icmp (A & B) Op C) | (icmp (A & D) Op E)
@ -564,7 +568,7 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
Mask = conjugateICmpMask(Mask);
}
if (Mask & FoldMskICmp_Mask_AllZeroes) {
if (Mask & Mask_AllZeros) {
// (icmp eq (A & B), 0) & (icmp eq (A & D), 0)
// -> (icmp eq (A & (B|D)), 0)
Value *NewOr = Builder->CreateOr(B, D);
@ -575,14 +579,14 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
Value *Zero = Constant::getNullValue(A->getType());
return Builder->CreateICmp(NewCC, NewAnd, Zero);
}
if (Mask & FoldMskICmp_BMask_AllOnes) {
if (Mask & BMask_AllOnes) {
// (icmp eq (A & B), B) & (icmp eq (A & D), D)
// -> (icmp eq (A & (B|D)), (B|D))
Value *NewOr = Builder->CreateOr(B, D);
Value *NewAnd = Builder->CreateAnd(A, NewOr);
return Builder->CreateICmp(NewCC, NewAnd, NewOr);
}
if (Mask & FoldMskICmp_AMask_AllOnes) {
if (Mask & AMask_AllOnes) {
// (icmp eq (A & B), A) & (icmp eq (A & D), A)
// -> (icmp eq (A & (B&D)), A)
Value *NewAnd1 = Builder->CreateAnd(B, D);
@ -594,11 +598,13 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
// their actual values. This isn't strictly necessary, just a "handle the
// easy cases for now" decision.
ConstantInt *BCst = dyn_cast<ConstantInt>(B);
if (!BCst) return nullptr;
if (!BCst)
return nullptr;
ConstantInt *DCst = dyn_cast<ConstantInt>(D);
if (!DCst) return nullptr;
if (!DCst)
return nullptr;
if (Mask & (FoldMskICmp_Mask_NotAllZeroes | FoldMskICmp_BMask_NotAllOnes)) {
if (Mask & (Mask_NotAllZeros | BMask_NotAllOnes)) {
// (icmp ne (A & B), 0) & (icmp ne (A & D), 0) and
// (icmp ne (A & B), B) & (icmp ne (A & D), D)
// -> (icmp ne (A & B), 0) or (icmp ne (A & D), 0)
@ -611,7 +617,8 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
else if (NewMask == DCst->getValue())
return RHS;
}
if (Mask & FoldMskICmp_AMask_NotAllOnes) {
if (Mask & AMask_NotAllOnes) {
// (icmp ne (A & B), B) & (icmp ne (A & D), D)
// -> (icmp ne (A & B), A) or (icmp ne (A & D), A)
// Only valid if one of the masks is a superset of the other (check "B|D" is
@ -623,7 +630,8 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
else if (NewMask == DCst->getValue())
return RHS;
}
if (Mask & FoldMskICmp_BMask_Mixed) {
if (Mask & BMask_Mixed) {
// (icmp eq (A & B), C) & (icmp eq (A & D), E)
// We already know that B & C == C && D & E == E.
// If we can prove that (B & D) & (C ^ E) == 0, that is, the bits of
@ -635,23 +643,28 @@ static Value *foldLogOpOfMaskedICmps(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
// (icmp ne (A & B), B) & (icmp eq (A & D), D)
// with B and D, having a single bit set.
ConstantInt *CCst = dyn_cast<ConstantInt>(C);
if (!CCst) return nullptr;
if (!CCst)
return nullptr;
ConstantInt *ECst = dyn_cast<ConstantInt>(E);
if (!ECst) return nullptr;
if (LHSCC != NewCC)
if (!ECst)
return nullptr;
if (PredL != NewCC)
CCst = cast<ConstantInt>(ConstantExpr::getXor(BCst, CCst));
if (RHSCC != NewCC)
if (PredR != NewCC)
ECst = cast<ConstantInt>(ConstantExpr::getXor(DCst, ECst));
// If there is a conflict, we should actually return a false for the
// whole construct.
if (((BCst->getValue() & DCst->getValue()) &
(CCst->getValue() ^ ECst->getValue())) != 0)
return ConstantInt::get(LHS->getType(), !IsAnd);
Value *NewOr1 = Builder->CreateOr(B, D);
Value *NewOr2 = ConstantExpr::getOr(CCst, ECst);
Value *NewAnd = Builder->CreateAnd(A, NewOr1);
return Builder->CreateICmp(NewCC, NewAnd, NewOr2);
}
return nullptr;
}