From b752daa26b641550e1d5b99d4b89230011c2c0cc Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 11 Oct 2020 10:31:17 +0100 Subject: [PATCH] [InstCombine] Replace getLogBase2 internal helper with ConstantExpr::getExactLogBase2. NFCI. This exposes the helper for other power-of-2 instcombine folds that I'm intending to add vector support to. The helper only operated on power-of-2 constants so getExactLogBase2 is a more accurate name. --- llvm/include/llvm/IR/Constants.h | 6 +++ llvm/lib/IR/Constants.cpp | 29 +++++++++++++++ .../InstCombine/InstCombineMulDivRem.cpp | 43 ++-------------------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index 6763d04..2889df0 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -1035,6 +1035,12 @@ public: return getLShr(C1, C2, true); } + /// If C is a scalar/fixed width vector of known powers of 2, then this + /// function returns a new scalar/fixed width vector obtained from logBase2 + /// of C. Undef vector elements are set to zero. + /// Return a null pointer otherwise. + static Constant *ConstantExpr::getExactLogBase2(Constant *C); + /// Return the identity constant for a binary opcode. /// The identity constant C is defined as X op C = X and C op X = X for every /// X when the binary operation is commutative. If the binop is not diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index d0c1e37..9f83861 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2547,6 +2547,35 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) { isExact ? PossiblyExactOperator::IsExact : 0); } +Constant *ConstantExpr::getExactLogBase2(Constant *C) { + Type *Ty = C->getType(); + const APInt *IVal; + if (match(C, m_APInt(IVal)) && IVal->isPowerOf2()) + return ConstantInt::get(Ty, IVal->logBase2()); + + // FIXME: We can extract pow of 2 of splat constant for scalable vectors. + auto *VecTy = dyn_cast(Ty); + if (!VecTy) + return nullptr; + + SmallVector Elts; + for (unsigned I = 0, E = VecTy->getNumElements(); I != E; ++I) { + Constant *Elt = C->getAggregateElement(I); + if (!Elt) + return nullptr; + // Note that log2(iN undef) is *NOT* iN undef, because log2(iN undef) u< N. + if (isa(Elt)) { + Elts.push_back(Constant::getNullValue(Ty->getScalarType())); + continue; + } + if (!match(Elt, m_APInt(IVal)) || !IVal->isPowerOf2()) + return nullptr; + Elts.push_back(ConstantInt::get(Ty->getScalarType(), IVal->logBase2())); + } + + return ConstantVector::get(Elts); +} + Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant) { assert(Instruction::isBinaryOp(Opcode) && "Only binops allowed"); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index e9b57cf..2da7415 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -95,41 +95,6 @@ static Value *simplifyValueKnownNonZero(Value *V, InstCombinerImpl &IC, return MadeChange ? V : nullptr; } -/// A helper routine of InstCombiner::visitMul(). -/// -/// If C is a scalar/fixed width vector of known powers of 2, then this -/// function returns a new scalar/fixed width vector obtained from logBase2 -/// of C. Undef elements in a vector are set to zero. -/// Return a null pointer otherwise. -static Constant *getLogBase2(Constant *C) { - Type *Ty = C->getType(); - const APInt *IVal; - if (match(C, m_APInt(IVal)) && IVal->isPowerOf2()) - return ConstantInt::get(Ty, IVal->logBase2()); - - // FIXME: We can extract pow of 2 of splat constant for scalable vectors. - if (!isa(Ty)) - return nullptr; - - SmallVector Elts; - for (unsigned I = 0, E = cast(Ty)->getNumElements(); I != E; - ++I) { - Constant *Elt = C->getAggregateElement(I); - if (!Elt) - return nullptr; - // Note that log2(iN undef) is *NOT* iN undef, because log2(iN undef) u< N. - if (isa(Elt)) { - Elts.push_back(Constant::getNullValue(Ty->getScalarType())); - continue; - } - if (!match(Elt, m_APInt(IVal)) || !IVal->isPowerOf2()) - return nullptr; - Elts.push_back(ConstantInt::get(Ty->getScalarType(), IVal->logBase2())); - } - - return ConstantVector::get(Elts); -} - // TODO: This is a specific form of a much more general pattern. // We could detect a select with any binop identity constant, or we // could use SimplifyBinOp to see if either arm of the select reduces. @@ -219,7 +184,7 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) { if (match(&I, m_Mul(m_Value(NewOp), m_Constant(C1)))) { // Replace X*(2^C) with X << C, where C is either a scalar or a vector. - if (Constant *NewCst = getLogBase2(C1)) { + if (Constant *NewCst = ConstantExpr::getExactLogBase2(C1)) { BinaryOperator *Shl = BinaryOperator::CreateShl(NewOp, NewCst); if (I.hasNoUnsignedWrap()) @@ -908,7 +873,7 @@ struct UDivFoldAction { static Instruction *foldUDivPow2Cst(Value *Op0, Value *Op1, const BinaryOperator &I, InstCombinerImpl &IC) { - Constant *C1 = getLogBase2(cast(Op1)); + Constant *C1 = ConstantExpr::getExactLogBase2(cast(Op1)); if (!C1) llvm_unreachable("Failed to constant fold udiv -> logbase2"); BinaryOperator *LShr = BinaryOperator::CreateLShr(Op0, C1); @@ -929,7 +894,7 @@ static Instruction *foldUDivShl(Value *Op0, Value *Op1, const BinaryOperator &I, Value *N; if (!match(ShiftLeft, m_Shl(m_Constant(CI), m_Value(N)))) llvm_unreachable("match should never fail here!"); - Constant *Log2Base = getLogBase2(CI); + Constant *Log2Base = ConstantExpr::getExactLogBase2(CI); if (!Log2Base) llvm_unreachable("getLogBase2 should never fail here!"); N = IC.Builder.CreateAdd(N, Log2Base); @@ -1146,7 +1111,7 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) { if (DivisorWasNegative) Op1 = ConstantExpr::getNeg(cast(Op1)); auto *AShr = BinaryOperator::CreateExactAShr( - Op0, getLogBase2(cast(Op1)), I.getName()); + Op0, ConstantExpr::getExactLogBase2(cast(Op1)), I.getName()); if (!DivisorWasNegative) return AShr; Builder.Insert(AShr); -- 2.7.4