@@ -43,19 +43,20 @@ struct TNumMulInterval {
4343 if (rv == 0 || lv == 0 ) {
4444 return NUdf::TUnboxedValuePod (ret);
4545 }
46+ i64 i64Max = std::numeric_limits<i64 >::max ();
4647 if constexpr (std::is_same_v<ui64, typename TLeft::TLayout>) {
47- if (left.Get <ui64>() > static_cast <ui64>(std::numeric_limits< i64 >:: max () )) {
48+ if (left.Get <ui64>() >= static_cast <ui64>(i64Max )) {
4849 return NUdf::TUnboxedValuePod ();
4950 }
5051 }
5152 if constexpr (std::is_same_v<ui64, typename TRight::TLayout>) {
52- if (right.Get <ui64>() > static_cast <ui64>(std::numeric_limits< i64 >:: max () )) {
53+ if (right.Get <ui64>() >= static_cast <ui64>(i64Max )) {
5354 return NUdf::TUnboxedValuePod ();
5455 }
5556 }
56- i64 lvAbs = (lv >= 0 ) ? lv : -lv ;
57- i64 rvAbs = (rv >= 0 ) ? rv : -rv ;
58- if (rvAbs ! = 0 && (std::numeric_limits< i64 >:: max () / rvAbs < lvAbs )) {
57+ auto div = i64Max / rv ;
58+ auto divAbs = (div >= 0 ) ? div : -div ;
59+ if ((lv > = 0 ) ? (lv > divAbs) : (lv < -divAbs )) {
5960 return NUdf::TUnboxedValuePod ();
6061 }
6162 return IsBadInterval<TOutput>(ret) ? NUdf::TUnboxedValuePod () : NUdf::TUnboxedValuePod (ret);
@@ -85,23 +86,26 @@ struct TNumMulInterval {
8586
8687 block = bbMain;
8788
88- const auto lhsAbs = SelectInst::Create (
89- CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGE, lhs, zero, " lhsPos" , block),
90- lhs,
91- BinaryOperator::CreateNeg (lhs, " lhsNeg" , block),
92- " lhsAbs" , block);
93- const auto rhsAbs = SelectInst::Create (
94- CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGE, rhs, zero, " rhsPos" , block),
95- rhs,
96- BinaryOperator::CreateNeg (rhs, " rhsNeg" , block),
97- " rhsAbs" , block);
9889 const auto i64Max = ConstantInt::get (Type::getInt64Ty (context), std::numeric_limits<i64 >::max ());
99- const auto div = BinaryOperator::CreateSDiv (i64Max, rhsAbs, " div" , block);
100- const auto mulOverflow = CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGT, lhsAbs, div, " mulOverflow" , block);
90+ const auto div = BinaryOperator::CreateSDiv (i64Max, rhs, " div" , block);
91+ const auto divAbs = SelectInst::Create (
92+ CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGE, div, zero, " divPos" , block),
93+ div,
94+ BinaryOperator::CreateNeg (div, " divNeg" , block),
95+ " divAbs" , block);
96+ const auto divAbsNeg = BinaryOperator::CreateNeg (divAbs, " divAbsNeg" , block);
97+
98+ const auto mulOverflow = SelectInst::Create (
99+ CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGE, lhs, zero, " lhsPos" , block),
100+ CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SGT, lhs, divAbs, " lhsDiv" , block),
101+ CmpInst::Create (Instruction::ICmp, ICmpInst::ICMP_SLT, lhs, divAbsNeg, " lhsDivAbsNeg" , block),
102+ " mulOverflow" , block);
103+
101104 const auto i64Overflow = BinaryOperator::CreateOr (
102105 GenIsInt64Overflow<typename TLeft::TLayout>(lv, context, block),
103106 GenIsInt64Overflow<typename TRight::TLayout>(rv, context, block),
104107 " i64Overflow" , block);
108+
105109 const auto bad = BinaryOperator::CreateOr (
106110 BinaryOperator::CreateOr (i64Overflow, mulOverflow, " overflow" , block),
107111 GenIsBadInterval<TOutput>(mul, context, block),
0 commit comments