@@ -2572,6 +2572,68 @@ static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
2572
2572
return true ;
2573
2573
}
2574
2574
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
+
2575
2637
// / Reassociate and hoist add/sub expressions.
2576
2638
static bool hoistAddSub (Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
2577
2639
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
@@ -2601,7 +2663,8 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
2601
2663
if (hoistAdd (Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
2602
2664
return true ;
2603
2665
2604
- // TODO: Support Sub.
2666
+ if (hoistSub (Pred, LHS, RHS, cast<ICmpInst>(I), L, SafetyInfo, MSSAU, AC, DT))
2667
+ return true ;
2605
2668
2606
2669
return false ;
2607
2670
}
0 commit comments