Skip to content

Commit 6d30223

Browse files
authored
[ADT][APInt] add sfloordiv_ov APInt's member function (#84720)
for mlir fold to avoid too many overflow state check
1 parent 328cb9b commit 6d30223

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

llvm/include/llvm/ADT/APInt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,12 @@ class [[nodiscard]] APInt {
997997
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
998998
APInt ushl_ov(unsigned Amt, bool &Overflow) const;
999999

1000+
/// Signed integer floor division operation.
1001+
///
1002+
/// Rounds towards negative infinity, i.e. 5 / -2 = -3. Iff minimum value
1003+
/// divided by -1 set Overflow to true.
1004+
APInt sfloordiv_ov(const APInt &RHS, bool &Overflow) const;
1005+
10001006
// Operations that saturate
10011007
APInt sadd_sat(const APInt &RHS) const;
10021008
APInt uadd_sat(const APInt &RHS) const;

llvm/lib/Support/APInt.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,6 +2022,13 @@ 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+
APInt quotient = sdiv_ov(RHS, Overflow);
2027+
if ((quotient * RHS != *this) && (isNegative() != RHS.isNegative()))
2028+
return quotient - 1;
2029+
return quotient;
2030+
}
2031+
20252032
APInt APInt::sadd_sat(const APInt &RHS) const {
20262033
bool Overflow;
20272034
APInt Res = sadd_ov(RHS, Overflow);

llvm/unittests/ADT/APIntTest.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "gtest/gtest.h"
1616
#include <array>
1717
#include <climits>
18+
#include <limits>
1819
#include <optional>
1920

2021
using namespace llvm;
@@ -3048,6 +3049,69 @@ TEST(APIntTest, smul_ov) {
30483049
}
30493050
}
30503051

3052+
TEST(APIntTest, sfloordiv_ov) {
3053+
// int16 test overflow
3054+
{
3055+
using IntTy = int16_t;
3056+
APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(),
3057+
true);
3058+
APInt dividend(8 * sizeof(IntTy), IntTy(-1), true);
3059+
bool Overflow = false;
3060+
(void)divisor.sfloordiv_ov(dividend, Overflow);
3061+
EXPECT_TRUE(Overflow);
3062+
}
3063+
// int32 test overflow
3064+
{
3065+
using IntTy = int32_t;
3066+
APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(),
3067+
true);
3068+
APInt dividend(8 * sizeof(IntTy), IntTy(-1), true);
3069+
bool Overflow = false;
3070+
(void)divisor.sfloordiv_ov(dividend, Overflow);
3071+
EXPECT_TRUE(Overflow);
3072+
}
3073+
// int64 test overflow
3074+
{
3075+
using IntTy = int64_t;
3076+
APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(),
3077+
true);
3078+
APInt dividend(8 * sizeof(IntTy), IntTy(-1), true);
3079+
bool Overflow = false;
3080+
(void)divisor.sfloordiv_ov(dividend, Overflow);
3081+
EXPECT_TRUE(Overflow);
3082+
}
3083+
// test all of int8
3084+
{
3085+
bool Overflow = false;
3086+
for (int i = -128; i < 128; ++i) {
3087+
for (int j = -128; j < 128; ++j) {
3088+
if (j == 0)
3089+
continue;
3090+
3091+
int8_t a = static_cast<int8_t>(i);
3092+
int8_t b = static_cast<int8_t>(j);
3093+
3094+
APInt divisor(8, a, true);
3095+
APInt dividend(8, b, true);
3096+
APInt quotient = divisor.sfloordiv_ov(dividend, Overflow);
3097+
3098+
if (i == -128 && j == -1) {
3099+
EXPECT_TRUE(Overflow);
3100+
continue;
3101+
}
3102+
3103+
if (((i >= 0 && j > 0) || (i <= 0 && j < 0)) ||
3104+
(i % j == 0)) // if quotient >= 0 and remain == 0 floordiv
3105+
// equivalent to div
3106+
EXPECT_EQ(quotient.getSExtValue(), a / b);
3107+
else
3108+
EXPECT_EQ(quotient.getSExtValue(), a / b - 1);
3109+
EXPECT_FALSE(Overflow);
3110+
}
3111+
}
3112+
}
3113+
}
3114+
30513115
TEST(APIntTest, SolveQuadraticEquationWrap) {
30523116
// Verify that "Solution" is the first non-negative integer that solves
30533117
// Ax^2 + Bx + C = "0 or overflow", i.e. that it is a correct solution

0 commit comments

Comments
 (0)