@@ -754,6 +754,12 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
754754 //
755755 // where the size of the outermost dimension is unknown (UNK).
756756
757+ auto AddOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
758+ if (!SE.willNotOverflow (Instruction::Add, /* IsSigned=*/ true , A, B))
759+ return nullptr ;
760+ return SE.getAddExpr (A, B);
761+ };
762+
757763 auto MulOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
758764 if (!SE.willNotOverflow (Instruction::Mul, /* IsSigned=*/ true , A, B))
759765 return nullptr ;
@@ -790,7 +796,9 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
790796 // (S_n - 1)
791797 // = (S_2 * ... * S_n) * I_1 +
792798 // (S_2 * ... * S_n) - 1 (can be proven by induction)
799+ // = Min + (S_2 * ... * S_n) - 1
793800 //
801+ // NOTE: I_1 can be negative, so Min is not just 0.
794802 const SCEV *Prod = SE.getOne (Sizes[0 ]->getType ());
795803 for (const SCEV *Size : Sizes) {
796804 Prod = MulOverflow (Prod, Size);
@@ -801,9 +809,13 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
801809 if (!Min)
802810 return false ;
803811
804- // Over-approximate Max as Prod * I_1 + Prod (ignoring the -1).
805- if (!SE.willNotOverflow (Instruction::Add, /* IsSigned=*/ true , Min,
806- Subscripts[0 ]))
812+ // We have already checked that Min and Prod don't overflow, so it's enough
813+ // to check whether Min + Prod - 1 doesn't overflow.
814+ const SCEV *MaxPlusOne = AddOverflow (Min, Prod);
815+ if (!MaxPlusOne)
816+ return false ;
817+ if (!SE.willNotOverflow (Instruction::Sub, /* IsSigned=*/ true , MaxPlusOne,
818+ SE.getOne (MaxPlusOne->getType ())))
807819 return false ;
808820
809821 return true ;
0 commit comments