@@ -2572,6 +2572,68 @@ static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
25722572 return true ;
25732573}
25742574
2575+ // / Try to reassociate and hoist the following two patterns:
2576+ // / LV - C1 < C2 --> LV < C1 + C2,
2577+ // / C1 - LV < C2 --> LV > C1 - C2.
2578+ static bool hoistSub (ICmpInst::Predicate Pred, Value *VariantLHS,
2579+ Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
2580+ ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
2581+ AssumptionCache *AC, DominatorTree *DT) {
2582+ assert (ICmpInst::isSigned (Pred) && " Not supported yet!" );
2583+ assert (!L.isLoopInvariant (VariantLHS) && " Precondition." );
2584+ assert (L.isLoopInvariant (InvariantRHS) && " Precondition." );
2585+
2586+ // Try to represent VariantLHS as sum of invariant and variant operands.
2587+ using namespace PatternMatch ;
2588+ Value *VariantOp, *InvariantOp;
2589+ if (!match (VariantLHS, m_NSWSub (m_Value (VariantOp), m_Value (InvariantOp))))
2590+ return false ;
2591+
2592+ bool VariantSubtracted = false ;
2593+ // LHS itself is a loop-variant, try to represent it in the form:
2594+ // "VariantOp + InvariantOp". If it is possible, then we can reassociate. If
2595+ // the variant operand goes with minus, we use a slightly different scheme.
2596+ if (L.isLoopInvariant (VariantOp)) {
2597+ std::swap (VariantOp, InvariantOp);
2598+ VariantSubtracted = true ;
2599+ Pred = ICmpInst::getSwappedPredicate (Pred);
2600+ }
2601+ if (L.isLoopInvariant (VariantOp) || !L.isLoopInvariant (InvariantOp))
2602+ return false ;
2603+
2604+ // In order to turn "LV - C1 < C2" into "LV < C2 + C1", we need to be able to
2605+ // freely move values from left side of inequality to right side (just as in
2606+ // normal linear arithmetics). Overflows make things much more complicated, so
2607+ // we want to avoid this. Likewise, for "C1 - LV < C2" we need to prove that
2608+ // "C1 - C2" does not overflow.
2609+ auto &DL = L.getHeader ()->getModule ()->getDataLayout ();
2610+ if (VariantSubtracted) {
2611+ // C1 - LV < C2 --> LV > C1 - C2
2612+ if (computeOverflowForSignedSub (InvariantOp, InvariantRHS, DL, AC, &ICmp,
2613+ DT) != llvm::OverflowResult::NeverOverflows)
2614+ return false ;
2615+ } else {
2616+ // LV - C1 < C2 --> LV < C1 + C2
2617+ if (computeOverflowForSignedAdd (InvariantOp, InvariantRHS, DL, AC, &ICmp,
2618+ DT) != llvm::OverflowResult::NeverOverflows)
2619+ return false ;
2620+ }
2621+ auto *Preheader = L.getLoopPreheader ();
2622+ assert (Preheader && " Loop is not in simplify form?" );
2623+ IRBuilder<> Builder (Preheader->getTerminator ());
2624+ Value *NewCmpOp =
2625+ VariantSubtracted
2626+ ? Builder.CreateSub (InvariantOp, InvariantRHS, " invariant.op" ,
2627+ /* HasNUW*/ false , /* HasNSW*/ true )
2628+ : Builder.CreateAdd (InvariantOp, InvariantRHS, " invariant.op" ,
2629+ /* HasNUW*/ false , /* HasNSW*/ true );
2630+ ICmp.setPredicate (Pred);
2631+ ICmp.setOperand (0 , VariantOp);
2632+ ICmp.setOperand (1 , NewCmpOp);
2633+ eraseInstruction (cast<Instruction>(*VariantLHS), SafetyInfo, MSSAU);
2634+ return true ;
2635+ }
2636+
25752637// / Reassociate and hoist add/sub expressions.
25762638static bool hoistAddSub (Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
25772639 MemorySSAUpdater &MSSAU, AssumptionCache *AC,
@@ -2601,7 +2663,8 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
26012663 if (hoistAdd (Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
26022664 return true ;
26032665
2604- // TODO: Support Sub.
2666+ if (hoistSub (Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
2667+ return true ;
26052668
26062669 return false ;
26072670}
0 commit comments