@@ -2537,14 +2537,19 @@ static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS,
2537
2537
Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
2538
2538
ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
2539
2539
AssumptionCache *AC, DominatorTree *DT) {
2540
- assert (ICmpInst::isSigned (Pred) && " Not supported yet!" );
2541
2540
assert (!L.isLoopInvariant (VariantLHS) && " Precondition." );
2542
2541
assert (L.isLoopInvariant (InvariantRHS) && " Precondition." );
2543
2542
2543
+ bool IsSigned = ICmpInst::isSigned (Pred);
2544
+
2544
2545
// Try to represent VariantLHS as sum of invariant and variant operands.
2545
2546
using namespace PatternMatch ;
2546
2547
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))))
2548
2553
return false ;
2549
2554
2550
2555
// 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,
2559
2564
// normal linear arithmetics). Overflows make things much more complicated, so
2560
2565
// we want to avoid this.
2561
2566
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)
2567
2574
return false ;
2568
2575
auto *Preheader = L.getLoopPreheader ();
2569
2576
assert (Preheader && " Loop is not in simplify form?" );
2570
2577
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);
2573
2581
ICmp.setPredicate (Pred);
2574
2582
ICmp.setOperand (0 , VariantOp);
2575
2583
ICmp.setOperand (1 , NewCmpOp);
@@ -2584,14 +2592,19 @@ static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS,
2584
2592
Value *InvariantRHS, ICmpInst &ICmp, Loop &L,
2585
2593
ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU,
2586
2594
AssumptionCache *AC, DominatorTree *DT) {
2587
- assert (ICmpInst::isSigned (Pred) && " Not supported yet!" );
2588
2595
assert (!L.isLoopInvariant (VariantLHS) && " Precondition." );
2589
2596
assert (L.isLoopInvariant (InvariantRHS) && " Precondition." );
2590
2597
2598
+ bool IsSigned = ICmpInst::isSigned (Pred);
2599
+
2591
2600
// Try to represent VariantLHS as sum of invariant and variant operands.
2592
2601
using namespace PatternMatch ;
2593
2602
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))))
2595
2608
return false ;
2596
2609
2597
2610
bool VariantSubtracted = false ;
@@ -2613,26 +2626,36 @@ static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS,
2613
2626
// "C1 - C2" does not overflow.
2614
2627
auto &DL = L.getHeader ()->getDataLayout ();
2615
2628
SimplifyQuery SQ (DL, DT, AC, &ICmp);
2616
- if (VariantSubtracted) {
2629
+ if (VariantSubtracted && IsSigned ) {
2617
2630
// C1 - LV < C2 --> LV > C1 - C2
2618
2631
if (computeOverflowForSignedSub (InvariantOp, InvariantRHS, SQ) !=
2619
2632
llvm::OverflowResult::NeverOverflows)
2620
2633
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) {
2622
2640
// LV - C1 < C2 --> LV < C1 + C2
2623
2641
if (computeOverflowForSignedAdd (InvariantOp, InvariantRHS, SQ) !=
2624
2642
llvm::OverflowResult::NeverOverflows)
2625
2643
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 ;
2626
2649
}
2627
2650
auto *Preheader = L.getLoopPreheader ();
2628
2651
assert (Preheader && " Loop is not in simplify form?" );
2629
2652
IRBuilder<> Builder (Preheader->getTerminator ());
2630
2653
Value *NewCmpOp =
2631
2654
VariantSubtracted
2632
2655
? Builder.CreateSub (InvariantOp, InvariantRHS, " invariant.op" ,
2633
- /* HasNUW*/ false , /* HasNSW*/ true )
2656
+ /* HasNUW*/ !IsSigned , /* HasNSW*/ IsSigned )
2634
2657
: Builder.CreateAdd (InvariantOp, InvariantRHS, " invariant.op" ,
2635
- /* HasNUW*/ false , /* HasNSW*/ true );
2658
+ /* HasNUW*/ !IsSigned , /* HasNSW*/ IsSigned );
2636
2659
ICmp.setPredicate (Pred);
2637
2660
ICmp.setOperand (0 , VariantOp);
2638
2661
ICmp.setOperand (1 , NewCmpOp);
@@ -2650,10 +2673,6 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
2650
2673
if (!match (&I, m_ICmp (Pred, m_Value (LHS), m_Value (RHS))))
2651
2674
return false ;
2652
2675
2653
- // TODO: Support unsigned predicates?
2654
- if (!ICmpInst::isSigned (Pred))
2655
- return false ;
2656
-
2657
2676
// Put variant operand to LHS position.
2658
2677
if (L.isLoopInvariant (LHS)) {
2659
2678
std::swap (LHS, RHS);
0 commit comments