Skip to content

Commit a0684ce

Browse files
committed
[APInt] add sfloordiv_ov APInt's member function
for mlir fold to avoid too many overflow state check
1 parent 83fe0b1 commit a0684ce

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

llvm/include/llvm/ADT/APInt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ class [[nodiscard]] APInt {
996996
APInt sshl_ov(unsigned Amt, bool &Overflow) const;
997997
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
998998
APInt ushl_ov(unsigned Amt, bool &Overflow) const;
999+
APInt sfloordiv_ov(const APInt &RHS, bool &Overflow) const;
9991000

10001001
// Operations that saturate
10011002
APInt sadd_sat(const APInt &RHS) const;

llvm/lib/Support/APInt.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,14 @@ APInt APInt::ushl_ov(unsigned ShAmt, bool &Overflow) const {
20222022
return *this << ShAmt;
20232023
}
20242024

2025+
APInt APInt::sfloordiv_ov(const APInt &RHS, bool &Overflow) const {
2026+
auto quotient = sdiv_ov(RHS, Overflow);
2027+
if ((quotient * RHS != *this) && (isNegative() != RHS.isNegative()))
2028+
return quotient - 1;
2029+
else
2030+
return quotient;
2031+
}
2032+
20252033
APInt APInt::sadd_sat(const APInt &RHS) const {
20262034
bool Overflow;
20272035
APInt Res = sadd_ov(RHS, Overflow);

llvm/unittests/ADT/APIntTest.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/Support/Alignment.h"
1515
#include "gtest/gtest.h"
1616
#include <array>
17+
#include <limits>
1718
#include <optional>
1819

1920
using namespace llvm;
@@ -2928,6 +2929,43 @@ TEST(APIntTest, smul_ov) {
29282929
}
29292930
}
29302931

2932+
TEST(APIntTest, sfloordiv_ov) {
2933+
// test negative quotient
2934+
{
2935+
APInt divisor(32, -3, true);
2936+
APInt dividend(32, 2, true);
2937+
bool Overflow = false;
2938+
auto quotient = divisor.sfloordiv_ov(dividend, Overflow);
2939+
EXPECT_FALSE(Overflow);
2940+
EXPECT_EQ(-2, quotient.getSExtValue());
2941+
}
2942+
// test positive quotient
2943+
{
2944+
APInt divisor(32, 3, true);
2945+
APInt dividend(32, 2, true);
2946+
bool Overflow = false;
2947+
auto quotient = divisor.sfloordiv_ov(dividend, Overflow);
2948+
EXPECT_FALSE(Overflow);
2949+
EXPECT_EQ(1, quotient.getSExtValue());
2950+
}
2951+
// test overflow
2952+
{
2953+
auto check_overflow_one = [](auto arg) {
2954+
using IntTy = decltype(arg);
2955+
APInt divisor(8 * sizeof(arg), std::numeric_limits<IntTy>::lowest(),
2956+
true);
2957+
APInt dividend(8 * sizeof(arg), IntTy(-1), true);
2958+
bool Overflow = false;
2959+
[[maybe_unused]] auto quotient = divisor.sfloordiv_ov(dividend, Overflow);
2960+
EXPECT_TRUE(Overflow);
2961+
};
2962+
auto check_overflow_all = [&](auto... args) {
2963+
(void)std::initializer_list<int>{(check_overflow_one(args), 0)...};
2964+
};
2965+
std::apply(check_overflow_all, std::tuple<char, short, int, int64_t>());
2966+
}
2967+
}
2968+
29312969
TEST(APIntTest, SolveQuadraticEquationWrap) {
29322970
// Verify that "Solution" is the first non-negative integer that solves
29332971
// Ax^2 + Bx + C = "0 or overflow", i.e. that it is a correct solution

0 commit comments

Comments
 (0)