Skip to content

Commit 2a8fda4

Browse files
authored
LICM: extend hoistAddSub to unsigned case (llvm#106373)
Trivially extend dd0cf23 ([LICM] Reassociate & hoist sub expressions) to handle unsigned predicates as well. Alive2 proofs: https://alive2.llvm.org/ce/z/GdDBtT.
1 parent 8586d03 commit 2a8fda4

File tree

2 files changed

+533
-20
lines changed

2 files changed

+533
-20
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

+38-19
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)