@@ -2537,14 +2537,19 @@ static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
25372537 Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
25382538 ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
25392539 AssumptionCache *AC, DominatorTree *DT) {
2540- assert (ICmpInst::isSigned (Pred) && " Not supported yet!" );
25412540 assert (!L.isLoopInvariant (VariantLHS) && " Precondition." );
25422541 assert (L.isLoopInvariant (InvariantRHS) && " Precondition." );
25432542
2543+ bool IsSigned = ICmpInst::isSigned (Pred);
2544+
25442545 // Try to represent VariantLHS as sum of invariant and variant operands.
25452546 using namespace PatternMatch ;
25462547 Value *VariantOp, *InvariantOp;
2547- if (!match (VariantLHS, m_NSWAdd (m_Value (VariantOp), m_Value (InvariantOp))))
2548+ if (IsSigned &&
2549+ !match (VariantLHS, m_NSWAdd (m_Value (VariantOp), m_Value (InvariantOp))))
2550+ return false ;
2551+ if (!IsSigned &&
2552+ !match (VariantLHS, m_NUWAdd (m_Value (VariantOp), m_Value (InvariantOp))))
25482553 return false ;
25492554
25502555 // LHS itself is a loop-variant, try to represent it in the form:
@@ -2559,17 +2564,20 @@ static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
25592564 // normal linear arithmetics). Overflows make things much more complicated, so
25602565 // we want to avoid this.
25612566 auto &DL = L.getHeader ()->getDataLayout ();
2562- bool ProvedNoOverflowAfterReassociate =
2563- computeOverflowForSignedSub (InvariantRHS, InvariantOp,
2564- SimplifyQuery (DL, DT, AC, &ICmp)) ==
2565- llvm::OverflowResult::NeverOverflows;
2566- if (!ProvedNoOverflowAfterReassociate)
2567+ SimplifyQuery SQ (DL, DT, AC, &ICmp);
2568+ if (IsSigned && computeOverflowForSignedSub (InvariantRHS, InvariantOp, SQ) !=
2569+ llvm::OverflowResult::NeverOverflows)
2570+ return false ;
2571+ if (!IsSigned &&
2572+ computeOverflowForUnsignedSub (InvariantRHS, InvariantOp, SQ) !=
2573+ llvm::OverflowResult::NeverOverflows)
25672574 return false ;
25682575 auto *Preheader = L.getLoopPreheader ();
25692576 assert (Preheader && " Loop is not in simplify form?" );
25702577 IRBuilder<> Builder (Preheader->getTerminator ());
2571- Value *NewCmpOp = Builder.CreateSub (InvariantRHS, InvariantOp, " invariant.op" ,
2572- /* HasNUW*/ false , /* HasNSW*/ true );
2578+ Value *NewCmpOp =
2579+ Builder.CreateSub (InvariantRHS, InvariantOp, " invariant.op" ,
2580+ /* HasNUW*/ !IsSigned, /* HasNSW*/ IsSigned);
25732581 ICmp.setPredicate (Pred);
25742582 ICmp.setOperand (0 , VariantOp);
25752583 ICmp.setOperand (1 , NewCmpOp);
@@ -2584,14 +2592,19 @@ static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS,
25842592 Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
25852593 ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
25862594 AssumptionCache *AC, DominatorTree *DT) {
2587- assert (ICmpInst::isSigned (Pred) && " Not supported yet!" );
25882595 assert (!L.isLoopInvariant (VariantLHS) && " Precondition." );
25892596 assert (L.isLoopInvariant (InvariantRHS) && " Precondition." );
25902597
2598+ bool IsSigned = ICmpInst::isSigned (Pred);
2599+
25912600 // Try to represent VariantLHS as sum of invariant and variant operands.
25922601 using namespace PatternMatch ;
25932602 Value *VariantOp, *InvariantOp;
2594- if (!match (VariantLHS, m_NSWSub (m_Value (VariantOp), m_Value (InvariantOp))))
2603+ if (IsSigned &&
2604+ !match (VariantLHS, m_NSWSub (m_Value (VariantOp), m_Value (InvariantOp))))
2605+ return false ;
2606+ if (!IsSigned &&
2607+ !match (VariantLHS, m_NUWSub (m_Value (VariantOp), m_Value (InvariantOp))))
25952608 return false ;
25962609
25972610 bool VariantSubtracted = false ;
@@ -2613,26 +2626,36 @@ static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS,
26132626 // "C1 - C2" does not overflow.
26142627 auto &DL = L.getHeader ()->getDataLayout ();
26152628 SimplifyQuery SQ (DL, DT, AC, &ICmp);
2616- if (VariantSubtracted) {
2629+ if (VariantSubtracted && IsSigned ) {
26172630 // C1 - LV < C2 --> LV > C1 - C2
26182631 if (computeOverflowForSignedSub (InvariantOp, InvariantRHS, SQ) !=
26192632 llvm::OverflowResult::NeverOverflows)
26202633 return false ;
2621- } else {
2634+ } else if (VariantSubtracted && !IsSigned) {
2635+ // C1 - LV < C2 --> LV > C1 - C2
2636+ if (computeOverflowForUnsignedSub (InvariantOp, InvariantRHS, SQ) !=
2637+ llvm::OverflowResult::NeverOverflows)
2638+ return false ;
2639+ } else if (!VariantSubtracted && IsSigned) {
26222640 // LV - C1 < C2 --> LV < C1 + C2
26232641 if (computeOverflowForSignedAdd (InvariantOp, InvariantRHS, SQ) !=
26242642 llvm::OverflowResult::NeverOverflows)
26252643 return false ;
2644+ } else { // !VariantSubtracted && !IsSigned
2645+ // LV - C1 < C2 --> LV < C1 + C2
2646+ if (computeOverflowForUnsignedAdd (InvariantOp, InvariantRHS, SQ) !=
2647+ llvm::OverflowResult::NeverOverflows)
2648+ return false ;
26262649 }
26272650 auto *Preheader = L.getLoopPreheader ();
26282651 assert (Preheader && " Loop is not in simplify form?" );
26292652 IRBuilder<> Builder (Preheader->getTerminator ());
26302653 Value *NewCmpOp =
26312654 VariantSubtracted
26322655 ? Builder.CreateSub (InvariantOp, InvariantRHS, " invariant.op" ,
2633- /* HasNUW*/ false , /* HasNSW*/ true )
2656+ /* HasNUW*/ !IsSigned , /* HasNSW*/ IsSigned )
26342657 : Builder.CreateAdd (InvariantOp, InvariantRHS, " invariant.op" ,
2635- /* HasNUW*/ false , /* HasNSW*/ true );
2658+ /* HasNUW*/ !IsSigned , /* HasNSW*/ IsSigned );
26362659 ICmp.setPredicate (Pred);
26372660 ICmp.setOperand (0 , VariantOp);
26382661 ICmp.setOperand (1 , NewCmpOp);
@@ -2650,10 +2673,6 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
26502673 if (!match (&I, m_ICmp (Pred, m_Value (LHS), m_Value (RHS))))
26512674 return false ;
26522675
2653- // TODO: Support unsigned predicates?
2654- if (!ICmpInst::isSigned (Pred))
2655- return false ;
2656-
26572676 // Put variant operand to LHS position.
26582677 if (L.isLoopInvariant (LHS)) {
26592678 std::swap (LHS, RHS);
0 commit comments