diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-07-29 14:42:08 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-07-29 14:42:08 +0000 |
commit | f52eeb11237af5bda4516668d3ee1784fd3b16c5 (patch) | |
tree | 82a45959727c4735a105bb7ad2ccba267c3396c7 /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 7312206f2f3c8fe69d52d7a7c31292cfa0949735 (diff) | |
download | bcm5719-llvm-f52eeb11237af5bda4516668d3ee1784fd3b16c5.tar.gz bcm5719-llvm-f52eeb11237af5bda4516668d3ee1784fd3b16c5.zip |
[InstSimplify] refactor intrinsic simplifications; NFCI
llvm-svn: 338215
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 250 |
1 files changed, 116 insertions, 134 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 257fa705aa4..c75bc93c3fb 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4641,149 +4641,131 @@ static bool maskIsAllZeroOrUndef(Value *Mask) { return true; } -template <typename IterTy> -static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd, - const SimplifyQuery &Q, unsigned MaxRecurse) { +static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0, + const SimplifyQuery &Q) { + // Idempotent functions return the same result when called repeatedly. Intrinsic::ID IID = F->getIntrinsicID(); - unsigned NumOperands = std::distance(ArgBegin, ArgEnd); - - // Unary Ops - if (NumOperands == 1) { - // Perform idempotent optimizations - if (IsIdempotent(IID)) { - if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(*ArgBegin)) { - if (II->getIntrinsicID() == IID) - return II; - } - } + if (IsIdempotent(IID)) + if (auto *II = dyn_cast<IntrinsicInst>(Op0)) + if (II->getIntrinsicID() == IID) + return II; - Value *IIOperand = *ArgBegin; - Value *X; - switch (IID) { - case Intrinsic::fabs: { - if (SignBitMustBeZero(IIOperand, Q.TLI)) - return IIOperand; - return nullptr; - } - case Intrinsic::bswap: { - // bswap(bswap(x)) -> x - if (match(IIOperand, m_BSwap(m_Value(X)))) - return X; - return nullptr; - } - case Intrinsic::bitreverse: { - // bitreverse(bitreverse(x)) -> x - if (match(IIOperand, m_BitReverse(m_Value(X)))) - return X; - return nullptr; - } - case Intrinsic::exp: { - // exp(log(x)) -> x - if (Q.CxtI->hasAllowReassoc() && - match(IIOperand, m_Intrinsic<Intrinsic::log>(m_Value(X)))) - return X; - return nullptr; - } - case Intrinsic::exp2: { - // exp2(log2(x)) -> x - if (Q.CxtI->hasAllowReassoc() && - match(IIOperand, m_Intrinsic<Intrinsic::log2>(m_Value(X)))) - return X; - return nullptr; - } - case Intrinsic::log: { - // log(exp(x)) -> x - if (Q.CxtI->hasAllowReassoc() && - match(IIOperand, m_Intrinsic<Intrinsic::exp>(m_Value(X)))) - return X; - return nullptr; - } - case Intrinsic::log2: { - // log2(exp2(x)) -> x - if (Q.CxtI->hasAllowReassoc() && - match(IIOperand, m_Intrinsic<Intrinsic::exp2>(m_Value(X)))) { - return X; - } - return nullptr; - } - default: - return nullptr; - } + Value *X; + switch (IID) { + case Intrinsic::fabs: + if (SignBitMustBeZero(Op0, Q.TLI)) return Op0; + break; + case Intrinsic::bswap: + // bswap(bswap(x)) -> x + if (match(Op0, m_BSwap(m_Value(X)))) return X; + break; + case Intrinsic::bitreverse: + // bitreverse(bitreverse(x)) -> x + if (match(Op0, m_BitReverse(m_Value(X)))) return X; + break; + case Intrinsic::exp: + // exp(log(x)) -> x + if (Q.CxtI->hasAllowReassoc() && + match(Op0, m_Intrinsic<Intrinsic::log>(m_Value(X)))) return X; + break; + case Intrinsic::exp2: + // exp2(log2(x)) -> x + if (Q.CxtI->hasAllowReassoc() && + match(Op0, m_Intrinsic<Intrinsic::log2>(m_Value(X)))) return X; + break; + case Intrinsic::log: + // log(exp(x)) -> x + if (Q.CxtI->hasAllowReassoc() && + match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X)))) return X; + break; + case Intrinsic::log2: + // log2(exp2(x)) -> x + if (Q.CxtI->hasAllowReassoc() && + match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X)))) return X; + break; + default: + break; } - // Binary Ops - if (NumOperands == 2) { - Value *LHS = *ArgBegin; - Value *RHS = *(ArgBegin + 1); - Type *ReturnType = F->getReturnType(); + return nullptr; +} - switch (IID) { - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: { - // X - X -> { 0, false } - if (LHS == RHS) - return Constant::getNullValue(ReturnType); +static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, + const SimplifyQuery &Q) { + Intrinsic::ID IID = F->getIntrinsicID(); + Type *ReturnType = F->getReturnType(); + switch (IID) { + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + // X - X -> { 0, false } + if (Op0 == Op1) + return Constant::getNullValue(ReturnType); + // X - undef -> undef + // undef - X -> undef + if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1)) + return UndefValue::get(ReturnType); + break; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + // X + undef -> undef + if (isa<UndefValue>(Op0) || isa<UndefValue>(Op1)) + return UndefValue::get(ReturnType); + break; + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + // 0 * X -> { 0, false } + // X * 0 -> { 0, false } + if (match(Op0, m_Zero()) || match(Op1, m_Zero())) + return Constant::getNullValue(ReturnType); + // undef * X -> { 0, false } + // X * undef -> { 0, false } + if (match(Op0, m_Undef()) || match(Op1, m_Undef())) + return Constant::getNullValue(ReturnType); + break; + case Intrinsic::load_relative: + if (auto *C0 = dyn_cast<Constant>(Op0)) + if (auto *C1 = dyn_cast<Constant>(Op1)) + return SimplifyRelativeLoad(C0, C1, Q.DL); + break; + case Intrinsic::powi: + if (auto *Power = dyn_cast<ConstantInt>(Op1)) { + // powi(x, 0) -> 1.0 + if (Power->isZero()) + return ConstantFP::get(Op0->getType(), 1.0); + // powi(x, 1) -> x + if (Power->isOne()) + return Op0; + } + break; + case Intrinsic::maxnum: + case Intrinsic::minnum: + // If one argument is NaN, return the other argument. + if (match(Op0, m_NaN())) return Op1; + if (match(Op1, m_NaN())) return Op0; + break; + default: + break; + } - // X - undef -> undef - // undef - X -> undef - if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS)) - return UndefValue::get(ReturnType); + return nullptr; +} - return nullptr; - } - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: { - // X + undef -> undef - if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS)) - return UndefValue::get(ReturnType); +template <typename IterTy> +static Value *simplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd, + const SimplifyQuery &Q) { + // Intrinsics with no operands have some kind of side effect. Don't simplify. + unsigned NumOperands = std::distance(ArgBegin, ArgEnd); + if (NumOperands == 0) + return nullptr; - return nullptr; - } - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: { - // 0 * X -> { 0, false } - // X * 0 -> { 0, false } - if (match(LHS, m_Zero()) || match(RHS, m_Zero())) - return Constant::getNullValue(ReturnType); - - // undef * X -> { 0, false } - // X * undef -> { 0, false } - if (match(LHS, m_Undef()) || match(RHS, m_Undef())) - return Constant::getNullValue(ReturnType); + Intrinsic::ID IID = F->getIntrinsicID(); + if (NumOperands == 1) + return simplifyUnaryIntrinsic(F, ArgBegin[0], Q); - return nullptr; - } - case Intrinsic::load_relative: { - Constant *C0 = dyn_cast<Constant>(LHS); - Constant *C1 = dyn_cast<Constant>(RHS); - if (C0 && C1) - return SimplifyRelativeLoad(C0, C1, Q.DL); - return nullptr; - } - case Intrinsic::powi: - if (ConstantInt *Power = dyn_cast<ConstantInt>(RHS)) { - // powi(x, 0) -> 1.0 - if (Power->isZero()) - return ConstantFP::get(LHS->getType(), 1.0); - // powi(x, 1) -> x - if (Power->isOne()) - return LHS; - } - return nullptr; - case Intrinsic::maxnum: - case Intrinsic::minnum: - // If one argument is NaN, return the other argument. - if (match(LHS, m_NaN())) - return RHS; - if (match(RHS, m_NaN())) - return LHS; - return nullptr; - default: - return nullptr; - } - } + if (NumOperands == 2) + return simplifyBinaryIntrinsic(F, ArgBegin[0], ArgBegin[1], Q); - // Simplify calls to llvm.masked.load.* + // Handle intrinsics with 3 or more arguments. switch (IID) { case Intrinsic::masked_load: { Value *MaskArg = ArgBegin[2]; @@ -4817,7 +4799,7 @@ static Value *SimplifyCall(ImmutableCallSite CS, Value *V, IterTy ArgBegin, return nullptr; if (F->isIntrinsic()) - if (Value *Ret = SimplifyIntrinsic(F, ArgBegin, ArgEnd, Q, MaxRecurse)) + if (Value *Ret = simplifyIntrinsic(F, ArgBegin, ArgEnd, Q)) return Ret; if (!canConstantFoldCallTo(CS, F)) |