diff options
Diffstat (limited to 'llvm')
| -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))  | 

