diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 105 | 
1 files changed, 62 insertions, 43 deletions
| diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index f4d8b79a5311..535a7736454c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1660,8 +1660,9 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {      Constant *MulC;      if (match(&I, m_c_FAdd(m_FMul(m_Value(X), m_ImmConstant(MulC)),                             m_Deferred(X)))) { -      MulC = ConstantExpr::getFAdd(MulC, ConstantFP::get(I.getType(), 1.0)); -      return BinaryOperator::CreateFMulFMF(X, MulC, &I); +      if (Constant *NewMulC = ConstantFoldBinaryOpOperands( +              Instruction::FAdd, MulC, ConstantFP::get(I.getType(), 1.0), DL)) +        return BinaryOperator::CreateFMulFMF(X, NewMulC, &I);      }      if (Value *V = FAddCombine(Builder).simplify(&I)) @@ -1750,6 +1751,52 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,    return Builder.CreateIntCast(Result, Ty, true);  } +static Instruction *foldSubOfMinMax(BinaryOperator &I, +                                    InstCombiner::BuilderTy &Builder) { +  Value *Op0 = I.getOperand(0); +  Value *Op1 = I.getOperand(1); +  Type *Ty = I.getType(); +  auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op1); +  if (!MinMax) +    return nullptr; + +  // sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y) +  // sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y) +  Value *X = MinMax->getLHS(); +  Value *Y = MinMax->getRHS(); +  if (match(Op0, m_c_Add(m_Specific(X), m_Specific(Y))) && +      (Op0->hasOneUse() || Op1->hasOneUse())) { +    Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID()); +    Function *F = Intrinsic::getDeclaration(I.getModule(), InvID, Ty); +    return CallInst::Create(F, {X, Y}); +  } + +  // sub(add(X,Y),umin(Y,Z)) --> add(X,usub.sat(Y,Z)) +  // sub(add(X,Z),umin(Y,Z)) --> add(X,usub.sat(Z,Y)) +  Value *Z; +  if (match(Op1, m_OneUse(m_UMin(m_Value(Y), m_Value(Z))))) { +    if (match(Op0, m_OneUse(m_c_Add(m_Specific(Y), m_Value(X))))) { +      Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, Ty, {Y, Z}); +      return BinaryOperator::CreateAdd(X, USub); +    } +    if (match(Op0, m_OneUse(m_c_Add(m_Specific(Z), m_Value(X))))) { +      Value *USub = Builder.CreateIntrinsic(Intrinsic::usub_sat, Ty, {Z, Y}); +      return BinaryOperator::CreateAdd(X, USub); +    } +  } + +  // sub Op0, smin((sub nsw Op0, Z), 0) --> smax Op0, Z +  // sub Op0, smax((sub nsw Op0, Z), 0) --> smin Op0, Z +  if (MinMax->isSigned() && match(Y, m_ZeroInt()) && +      match(X, m_NSWSub(m_Specific(Op0), m_Value(Z)))) { +    Intrinsic::ID InvID = getInverseMinMaxIntrinsic(MinMax->getIntrinsicID()); +    Function *F = Intrinsic::getDeclaration(I.getModule(), InvID, Ty); +    return CallInst::Create(F, {Op0, Z}); +  } + +  return nullptr; +} +  Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {    if (Value *V = simplifySubInst(I.getOperand(0), I.getOperand(1),                                   I.hasNoSignedWrap(), I.hasNoUnsignedWrap(), @@ -1919,14 +1966,12 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {        return BinaryOperator::CreateAdd(X, ConstantExpr::getSub(C, C2));    } +  // If there's no chance any bit will need to borrow from an adjacent bit: +  // sub C, X --> xor X, C    const APInt *Op0C; -  if (match(Op0, m_APInt(Op0C)) && Op0C->isMask()) { -    // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known -    // zero. -    KnownBits RHSKnown = computeKnownBits(Op1, 0, &I); -    if ((*Op0C | RHSKnown.Zero).isAllOnes()) -      return BinaryOperator::CreateXor(Op1, Op0); -  } +  if (match(Op0, m_APInt(Op0C)) && +      (~computeKnownBits(Op1, 0, &I).Zero).isSubsetOf(*Op0C)) +    return BinaryOperator::CreateXor(Op1, Op0);    {      Value *Y; @@ -2016,36 +2061,8 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {      }    } -  if (auto *II = dyn_cast<MinMaxIntrinsic>(Op1)) { -    { -      // sub(add(X,Y), s/umin(X,Y)) --> s/umax(X,Y) -      // sub(add(X,Y), s/umax(X,Y)) --> s/umin(X,Y) -      Value *X = II->getLHS(); -      Value *Y = II->getRHS(); -      if (match(Op0, m_c_Add(m_Specific(X), m_Specific(Y))) && -          (Op0->hasOneUse() || Op1->hasOneUse())) { -        Intrinsic::ID InvID = getInverseMinMaxIntrinsic(II->getIntrinsicID()); -        Value *InvMaxMin = Builder.CreateBinaryIntrinsic(InvID, X, Y); -        return replaceInstUsesWith(I, InvMaxMin); -      } -    } - -    { -      // sub(add(X,Y),umin(Y,Z)) --> add(X,usub.sat(Y,Z)) -      // sub(add(X,Z),umin(Y,Z)) --> add(X,usub.sat(Z,Y)) -      Value *X, *Y, *Z; -      if (match(Op1, m_OneUse(m_UMin(m_Value(Y), m_Value(Z))))) { -        if (match(Op0, m_OneUse(m_c_Add(m_Specific(Y), m_Value(X))))) -          return BinaryOperator::CreateAdd( -              X, Builder.CreateIntrinsic(Intrinsic::usub_sat, I.getType(), -                                         {Y, Z})); -        if (match(Op0, m_OneUse(m_c_Add(m_Specific(Z), m_Value(X))))) -          return BinaryOperator::CreateAdd( -              X, Builder.CreateIntrinsic(Intrinsic::usub_sat, I.getType(), -                                         {Z, Y})); -      } -    } -  } +  if (Instruction *R = foldSubOfMinMax(I, Builder)) +    return R;    {      // If we have a subtraction between some value and a select between @@ -2437,13 +2454,15 @@ Instruction *InstCombinerImpl::visitFSub(BinaryOperator &I) {      // (X * C) - X --> X * (C - 1.0)      if (match(Op0, m_FMul(m_Specific(Op1), m_Constant(C)))) { -      Constant *CSubOne = ConstantExpr::getFSub(C, ConstantFP::get(Ty, 1.0)); -      return BinaryOperator::CreateFMulFMF(Op1, CSubOne, &I); +      if (Constant *CSubOne = ConstantFoldBinaryOpOperands( +              Instruction::FSub, C, ConstantFP::get(Ty, 1.0), DL)) +        return BinaryOperator::CreateFMulFMF(Op1, CSubOne, &I);      }      // X - (X * C) --> X * (1.0 - C)      if (match(Op1, m_FMul(m_Specific(Op0), m_Constant(C)))) { -      Constant *OneSubC = ConstantExpr::getFSub(ConstantFP::get(Ty, 1.0), C); -      return BinaryOperator::CreateFMulFMF(Op0, OneSubC, &I); +      if (Constant *OneSubC = ConstantFoldBinaryOpOperands( +              Instruction::FSub, ConstantFP::get(Ty, 1.0), C, DL)) +        return BinaryOperator::CreateFMulFMF(Op0, OneSubC, &I);      }      // Reassociate fsub/fadd sequences to create more fadd instructions and | 
