| 
39 | 39 | #include "llvm/IR/Attributes.h"  | 
40 | 40 | #include "llvm/IR/BasicBlock.h"  | 
41 | 41 | #include "llvm/IR/Constant.h"  | 
 | 42 | +#include "llvm/IR/ConstantFPRange.h"  | 
42 | 43 | #include "llvm/IR/ConstantRange.h"  | 
43 | 44 | #include "llvm/IR/Constants.h"  | 
44 | 45 | #include "llvm/IR/DerivedTypes.h"  | 
@@ -9447,6 +9448,69 @@ isImpliedCondICmps(CmpPredicate LPred, const Value *L0, const Value *L1,  | 
9447 | 9448 |   return std::nullopt;  | 
9448 | 9449 | }  | 
9449 | 9450 | 
 
  | 
 | 9451 | +/// Return true if LHS implies RHS (expanded to its components as "R0 RPred R1")  | 
 | 9452 | +/// is true.  Return false if LHS implies RHS is false. Otherwise, return  | 
 | 9453 | +/// std::nullopt if we can't infer anything.  | 
 | 9454 | +static std::optional<bool>  | 
 | 9455 | +isImpliedCondFCmps(FCmpInst::Predicate LPred, const Value *L0, const Value *L1,  | 
 | 9456 | +                   FCmpInst::Predicate RPred, const Value *R0, const Value *R1,  | 
 | 9457 | +                   const DataLayout &DL, bool LHSIsTrue) {  | 
 | 9458 | +  // The rest of the logic assumes the LHS condition is true.  If that's not the  | 
 | 9459 | +  // case, invert the predicate to make it so.  | 
 | 9460 | +  if (!LHSIsTrue)  | 
 | 9461 | +    LPred = FCmpInst::getInversePredicate(LPred);  | 
 | 9462 | + | 
 | 9463 | +  // We can have non-canonical operands, so try to normalize any common operand  | 
 | 9464 | +  // to L0/R0.  | 
 | 9465 | +  if (L0 == R1) {  | 
 | 9466 | +    std::swap(R0, R1);  | 
 | 9467 | +    RPred = FCmpInst::getSwappedPredicate(RPred);  | 
 | 9468 | +  }  | 
 | 9469 | +  if (R0 == L1) {  | 
 | 9470 | +    std::swap(L0, L1);  | 
 | 9471 | +    LPred = FCmpInst::getSwappedPredicate(LPred);  | 
 | 9472 | +  }  | 
 | 9473 | +  if (L1 == R1) {  | 
 | 9474 | +    // If we have L0 == R0 and L1 == R1, then make L1/R1 the constants.  | 
 | 9475 | +    if (L0 != R0 || match(L0, m_ImmConstant())) {  | 
 | 9476 | +      std::swap(L0, L1);  | 
 | 9477 | +      LPred = ICmpInst::getSwappedCmpPredicate(LPred);  | 
 | 9478 | +      std::swap(R0, R1);  | 
 | 9479 | +      RPred = ICmpInst::getSwappedCmpPredicate(RPred);  | 
 | 9480 | +    }  | 
 | 9481 | +  }  | 
 | 9482 | + | 
 | 9483 | +  // Can we infer anything when the two compares have matching operands?  | 
 | 9484 | +  if (L0 == R0 && L1 == R1) {  | 
 | 9485 | +    if ((LPred & RPred) == LPred)  | 
 | 9486 | +      return true;  | 
 | 9487 | +    if ((LPred & ~RPred) == LPred)  | 
 | 9488 | +      return false;  | 
 | 9489 | +  }  | 
 | 9490 | + | 
 | 9491 | +  // See if we can infer anything if operand-0 matches and we have at least one  | 
 | 9492 | +  // constant.  | 
 | 9493 | +  const APFloat *L1C, *R1C;  | 
 | 9494 | +  if (L0 == R0 && match(L1, m_APFloat(L1C)) && match(R1, m_APFloat(R1C))) {  | 
 | 9495 | +    if (std::optional<ConstantFPRange> DomCR =  | 
 | 9496 | +            ConstantFPRange::makeExactFCmpRegion(LPred, *L1C)) {  | 
 | 9497 | +      if (std::optional<ConstantFPRange> ImpliedCR =  | 
 | 9498 | +              ConstantFPRange::makeExactFCmpRegion(RPred, *R1C)) {  | 
 | 9499 | +        if (ImpliedCR->contains(*DomCR))  | 
 | 9500 | +          return true;  | 
 | 9501 | +      }  | 
 | 9502 | +      if (std::optional<ConstantFPRange> ImpliedCR =  | 
 | 9503 | +              ConstantFPRange::makeExactFCmpRegion(  | 
 | 9504 | +                  FCmpInst::getInversePredicate(RPred), *R1C)) {  | 
 | 9505 | +        if (ImpliedCR->contains(*DomCR))  | 
 | 9506 | +          return false;  | 
 | 9507 | +      }  | 
 | 9508 | +    }  | 
 | 9509 | +  }  | 
 | 9510 | + | 
 | 9511 | +  return std::nullopt;  | 
 | 9512 | +}  | 
 | 9513 | + | 
9450 | 9514 | /// Return true if LHS implies RHS is true.  Return false if LHS implies RHS is  | 
9451 | 9515 | /// false.  Otherwise, return std::nullopt if we can't infer anything.  We  | 
9452 | 9516 | /// expect the RHS to be an icmp and the LHS to be an 'and', 'or', or a 'select'  | 
@@ -9502,15 +9566,24 @@ llvm::isImpliedCondition(const Value *LHS, CmpPredicate RHSPred,  | 
9502 | 9566 |     LHSIsTrue = !LHSIsTrue;  | 
9503 | 9567 | 
 
  | 
9504 | 9568 |   // Both LHS and RHS are icmps.  | 
9505 |  | -  if (const auto *LHSCmp = dyn_cast<ICmpInst>(LHS))  | 
9506 |  | -    return isImpliedCondICmps(LHSCmp->getCmpPredicate(), LHSCmp->getOperand(0),  | 
9507 |  | -                              LHSCmp->getOperand(1), RHSPred, RHSOp0, RHSOp1,  | 
9508 |  | -                              DL, LHSIsTrue);  | 
9509 |  | -  const Value *V;  | 
9510 |  | -  if (match(LHS, m_NUWTrunc(m_Value(V))))  | 
9511 |  | -    return isImpliedCondICmps(CmpInst::ICMP_NE, V,  | 
9512 |  | -                              ConstantInt::get(V->getType(), 0), RHSPred,  | 
9513 |  | -                              RHSOp0, RHSOp1, DL, LHSIsTrue);  | 
 | 9569 | +  if (RHSOp0->getType()->getScalarType()->isIntOrPtrTy()) {  | 
 | 9570 | +    if (const auto *LHSCmp = dyn_cast<ICmpInst>(LHS))  | 
 | 9571 | +      return isImpliedCondICmps(LHSCmp->getCmpPredicate(),  | 
 | 9572 | +                                LHSCmp->getOperand(0), LHSCmp->getOperand(1),  | 
 | 9573 | +                                RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue);  | 
 | 9574 | +    const Value *V;  | 
 | 9575 | +    if (match(LHS, m_NUWTrunc(m_Value(V))))  | 
 | 9576 | +      return isImpliedCondICmps(CmpInst::ICMP_NE, V,  | 
 | 9577 | +                                ConstantInt::get(V->getType(), 0), RHSPred,  | 
 | 9578 | +                                RHSOp0, RHSOp1, DL, LHSIsTrue);  | 
 | 9579 | +  } else {  | 
 | 9580 | +    assert(RHSOp0->getType()->isFPOrFPVectorTy() &&  | 
 | 9581 | +           "Expected floating point type only!");  | 
 | 9582 | +    if (const auto *LHSCmp = dyn_cast<FCmpInst>(LHS))  | 
 | 9583 | +      return isImpliedCondFCmps(LHSCmp->getPredicate(), LHSCmp->getOperand(0),  | 
 | 9584 | +                                LHSCmp->getOperand(1), RHSPred, RHSOp0, RHSOp1,  | 
 | 9585 | +                                DL, LHSIsTrue);  | 
 | 9586 | +  }  | 
9514 | 9587 | 
 
  | 
9515 | 9588 |   /// The LHS should be an 'or', 'and', or a 'select' instruction.  We expect  | 
9516 | 9589 |   /// the RHS to be an icmp.  | 
@@ -9547,6 +9620,13 @@ std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,  | 
9547 | 9620 |       return InvertRHS ? !*Implied : *Implied;  | 
9548 | 9621 |     return std::nullopt;  | 
9549 | 9622 |   }  | 
 | 9623 | +  if (const FCmpInst *RHSCmp = dyn_cast<FCmpInst>(RHS)) {  | 
 | 9624 | +    if (auto Implied = isImpliedCondition(  | 
 | 9625 | +            LHS, RHSCmp->getPredicate(), RHSCmp->getOperand(0),  | 
 | 9626 | +            RHSCmp->getOperand(1), DL, LHSIsTrue, Depth))  | 
 | 9627 | +      return InvertRHS ? !*Implied : *Implied;  | 
 | 9628 | +    return std::nullopt;  | 
 | 9629 | +  }  | 
9550 | 9630 | 
 
  | 
9551 | 9631 |   const Value *V;  | 
9552 | 9632 |   if (match(RHS, m_NUWTrunc(m_Value(V)))) {  | 
 | 
0 commit comments