forked from OSchip/llvm-project
[ADT] Add APInt::isNegatedPowerOf2() helper
Inspired by D111968, provide a isNegatedPowerOf2() wrapper instead of obfuscating code with (-Value).isPowerOf2() patterns, which I'm sure are likely avenues for typos..... Differential Revision: https://reviews.llvm.org/D111998
This commit is contained in:
parent
7df912c65d
commit
71e39e3f18
|
@ -430,6 +430,17 @@ public:
|
|||
return countPopulationSlowCase() == 1;
|
||||
}
|
||||
|
||||
/// Check if this APInt's negated value is a power of two greater than zero.
|
||||
bool isNegatedPowerOf2() const {
|
||||
assert(BitWidth && "zero width values not allowed");
|
||||
if (isNonNegative())
|
||||
return false;
|
||||
// NegatedPowerOf2 - shifted mask in the top bits.
|
||||
unsigned LO = countLeadingOnes();
|
||||
unsigned TZ = countTrailingZeros();
|
||||
return (LO + TZ) == BitWidth;
|
||||
}
|
||||
|
||||
/// Check if the APInt's value is returned by getSignMask.
|
||||
///
|
||||
/// \returns true if this is the value returned by getSignMask.
|
||||
|
|
|
@ -549,7 +549,7 @@ inline api_pred_ty<is_power2> m_Power2(const APInt *&V) {
|
|||
}
|
||||
|
||||
struct is_negated_power2 {
|
||||
bool isValue(const APInt &C) { return (-C).isPowerOf2(); }
|
||||
bool isValue(const APInt &C) { return C.isNegatedPowerOf2(); }
|
||||
};
|
||||
/// Match a integer or vector negated power-of-2.
|
||||
/// For vectors, this includes constants with undefined elements.
|
||||
|
|
|
@ -3841,7 +3841,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
|
|||
}
|
||||
|
||||
// fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c
|
||||
if (N1IsConst && !N1IsOpaqueConst && (-ConstValue1).isPowerOf2()) {
|
||||
if (N1IsConst && !N1IsOpaqueConst && ConstValue1.isNegatedPowerOf2()) {
|
||||
unsigned Log2Val = (-ConstValue1).logBase2();
|
||||
SDLoc DL(N);
|
||||
// FIXME: If the input is something that is easily negated (e.g. a
|
||||
|
@ -4212,7 +4212,7 @@ SDValue DAGCombiner::visitSDIVLike(SDValue N0, SDValue N1, SDNode *N) {
|
|||
return false;
|
||||
if (C->getAPIntValue().isPowerOf2())
|
||||
return true;
|
||||
if ((-C->getAPIntValue()).isPowerOf2())
|
||||
if (C->getAPIntValue().isNegatedPowerOf2())
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
|
|
@ -4150,7 +4150,7 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
|
|||
N0.getOpcode() == ISD::AND && N0.hasOneUse()) {
|
||||
if (auto *AndRHS = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
||||
const APInt &AndRHSC = AndRHS->getAPIntValue();
|
||||
if ((-AndRHSC).isPowerOf2() && (AndRHSC & C1) == C1) {
|
||||
if (AndRHSC.isNegatedPowerOf2() && (AndRHSC & C1) == C1) {
|
||||
unsigned ShiftBits = AndRHSC.countTrailingZeros();
|
||||
if (!TLI.shouldAvoidTransformToShift(ShValTy, ShiftBits)) {
|
||||
SDValue Shift =
|
||||
|
|
|
@ -4806,7 +4806,7 @@ bool AArch64FastISel::selectSDiv(const Instruction *I) {
|
|||
|
||||
const APInt &C = cast<ConstantInt>(I->getOperand(1))->getValue();
|
||||
if ((VT != MVT::i32 && VT != MVT::i64) || !C ||
|
||||
!(C.isPowerOf2() || (-C).isPowerOf2()))
|
||||
!(C.isPowerOf2() || C.isNegatedPowerOf2()))
|
||||
return selectBinaryOp(I, ISD::SDIV);
|
||||
|
||||
unsigned Lg2 = C.countTrailingZeros();
|
||||
|
|
|
@ -12802,7 +12802,7 @@ AArch64TargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
|||
// fold (sdiv X, pow2)
|
||||
EVT VT = N->getValueType(0);
|
||||
if ((VT != MVT::i32 && VT != MVT::i64) ||
|
||||
!(Divisor.isPowerOf2() || (-Divisor).isPowerOf2()))
|
||||
!(Divisor.isPowerOf2() || Divisor.isNegatedPowerOf2()))
|
||||
return SDValue();
|
||||
|
||||
SDLoc DL(N);
|
||||
|
|
|
@ -342,7 +342,7 @@ static bool isSSATMinMaxPattern(Instruction *Inst, const APInt &Imm) {
|
|||
|
||||
if (InstSPF == SPF_SMAX &&
|
||||
PatternMatch::match(RHS, PatternMatch::m_ConstantInt(C)) &&
|
||||
C->getValue() == Imm && Imm.isNegative() && (-Imm).isPowerOf2()) {
|
||||
C->getValue() == Imm && Imm.isNegative() && Imm.isNegatedPowerOf2()) {
|
||||
|
||||
auto isSSatMin = [&](Value *MinInst) {
|
||||
if (isa<SelectInst>(MinInst)) {
|
||||
|
|
|
@ -15606,13 +15606,13 @@ PPCTargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
|||
if (VT == MVT::i64 && !Subtarget.isPPC64())
|
||||
return SDValue();
|
||||
if ((VT != MVT::i32 && VT != MVT::i64) ||
|
||||
!(Divisor.isPowerOf2() || (-Divisor).isPowerOf2()))
|
||||
!(Divisor.isPowerOf2() || Divisor.isNegatedPowerOf2()))
|
||||
return SDValue();
|
||||
|
||||
SDLoc DL(N);
|
||||
SDValue N0 = N->getOperand(0);
|
||||
|
||||
bool IsNegPow2 = (-Divisor).isPowerOf2();
|
||||
bool IsNegPow2 = Divisor.isNegatedPowerOf2();
|
||||
unsigned Lg2 = (IsNegPow2 ? -Divisor : Divisor).countTrailingZeros();
|
||||
SDValue ShiftAmt = DAG.getConstant(Lg2, DL, VT);
|
||||
|
||||
|
|
|
@ -424,8 +424,8 @@ InstructionCost SystemZTTIImpl::getArithmeticInstrCost(
|
|||
(C->getType()->isVectorTy()
|
||||
? dyn_cast_or_null<const ConstantInt>(C->getSplatValue())
|
||||
: dyn_cast<const ConstantInt>(C));
|
||||
if (CVal != nullptr &&
|
||||
(CVal->getValue().isPowerOf2() || (-CVal->getValue()).isPowerOf2()))
|
||||
if (CVal && (CVal->getValue().isPowerOf2() ||
|
||||
CVal->getValue().isNegatedPowerOf2()))
|
||||
DivRemConstPow2 = true;
|
||||
else
|
||||
DivRemConst = true;
|
||||
|
|
|
@ -23263,7 +23263,7 @@ X86TargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
|||
if (isIntDivCheap(N->getValueType(0), Attr))
|
||||
return SDValue(N,0); // Lower SDIV as SDIV
|
||||
|
||||
assert((Divisor.isPowerOf2() || (-Divisor).isPowerOf2()) &&
|
||||
assert((Divisor.isPowerOf2() || Divisor.isNegatedPowerOf2()) &&
|
||||
"Unexpected divisor!");
|
||||
|
||||
// Only perform this transform if CMOV is supported otherwise the select
|
||||
|
|
|
@ -1889,7 +1889,7 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
|
|||
// X & -C == -C -> X > u ~C
|
||||
// X & -C != -C -> X <= u ~C
|
||||
// iff C is a power of 2
|
||||
if (Cmp.getOperand(1) == Y && (-C).isPowerOf2()) {
|
||||
if (Cmp.getOperand(1) == Y && C.isNegatedPowerOf2()) {
|
||||
auto NewPred =
|
||||
Pred == CmpInst::ICMP_EQ ? CmpInst::ICMP_UGT : CmpInst::ICMP_ULE;
|
||||
return new ICmpInst(NewPred, X, SubOne(cast<Constant>(Cmp.getOperand(1))));
|
||||
|
|
|
@ -620,7 +620,7 @@ Value *StraightLineStrengthReduce::emitBump(const Candidate &Basis,
|
|||
ConstantInt *Exponent = ConstantInt::get(DeltaType, IndexOffset.logBase2());
|
||||
return Builder.CreateShl(ExtendedStride, Exponent);
|
||||
}
|
||||
if ((-IndexOffset).isPowerOf2()) {
|
||||
if (IndexOffset.isNegatedPowerOf2()) {
|
||||
// If (i - i') is a power of 2, Bump = -sext/trunc(S) << log(i' - i).
|
||||
ConstantInt *Exponent =
|
||||
ConstantInt::get(DeltaType, (-IndexOffset).logBase2());
|
||||
|
|
|
@ -1785,6 +1785,32 @@ TEST(APIntTest, isPowerOf2) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(APIntTest, isNegatedPowerOf2) {
|
||||
EXPECT_FALSE(APInt(5, 0x00).isNegatedPowerOf2());
|
||||
EXPECT_TRUE(APInt(15, 0x7ffe).isNegatedPowerOf2());
|
||||
EXPECT_TRUE(APInt(16, 0xfffc).isNegatedPowerOf2());
|
||||
EXPECT_TRUE(APInt(32, 0xffffffff).isNegatedPowerOf2());
|
||||
|
||||
for (int N : {1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256}) {
|
||||
EXPECT_FALSE(APInt(N, 0).isNegatedPowerOf2());
|
||||
EXPECT_TRUE(APInt::getAllOnes(N).isNegatedPowerOf2());
|
||||
EXPECT_TRUE(APInt::getSignedMinValue(N).isNegatedPowerOf2());
|
||||
EXPECT_TRUE((-APInt::getSignedMinValue(N)).isNegatedPowerOf2());
|
||||
|
||||
APInt One(N, 1);
|
||||
for (int I = 1; I < N - 1; ++I) {
|
||||
EXPECT_FALSE(APInt::getOneBitSet(N, I).isNegatedPowerOf2());
|
||||
EXPECT_TRUE((-APInt::getOneBitSet(N, I)).isNegatedPowerOf2());
|
||||
|
||||
APInt MaskVal = One.shl(I);
|
||||
EXPECT_TRUE((-MaskVal).isNegatedPowerOf2());
|
||||
|
||||
APInt ShiftMaskVal = One.getHighBitsSet(N, I);
|
||||
EXPECT_TRUE(ShiftMaskVal.isNegatedPowerOf2());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that self-move works with EXPENSIVE_CHECKS. It calls std::shuffle which
|
||||
// does self-move on some platforms.
|
||||
#ifdef EXPENSIVE_CHECKS
|
||||
|
|
Loading…
Reference in New Issue