Skip to content

Commit 5ff2774

Browse files
authored
[libc][stdfix] Implement idivfx functions in LLVM libc (llvm#133005)
This PR implements the following 8 functions along with the tests. ```c++ int idivr(fract, fract); long int idivlr(long fract, long fract); int idivk(accum, accum); long int idivlk(long accum, long accum); unsigned int idivur(unsigned fract, unsigned fract); unsigned long int idivulr(unsigned long fract, unsigned long fract); unsigned int idivuk(unsigned accum, unsigned accum); unsigned long int idivulk(unsigned long accum, unsigned long accum); ``` ref: https://www.iso.org/standard/51126.html Fixes llvm#129125 --------- Signed-off-by: krishna2803 <kpandey81930@gmail.com>
1 parent 2dc6e98 commit 5ff2774

36 files changed

+703
-1
lines changed

libc/config/baremetal/arm/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
820820
libc.src.stdfix.countlsuhk
821821
libc.src.stdfix.countlsuk
822822
libc.src.stdfix.countlsulk
823+
libc.src.stdfix.idivr
824+
libc.src.stdfix.idivlr
825+
libc.src.stdfix.idivk
826+
libc.src.stdfix.idivlk
827+
libc.src.stdfix.idivur
828+
libc.src.stdfix.idivulr
829+
libc.src.stdfix.idivuk
830+
libc.src.stdfix.idivulk
823831
)
824832
endif()
825833

libc/config/baremetal/riscv/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
820820
libc.src.stdfix.countlsuhk
821821
libc.src.stdfix.countlsuk
822822
libc.src.stdfix.countlsulk
823+
libc.src.stdfix.idivr
824+
libc.src.stdfix.idivlr
825+
libc.src.stdfix.idivk
826+
libc.src.stdfix.idivlk
827+
libc.src.stdfix.idivur
828+
libc.src.stdfix.idivulr
829+
libc.src.stdfix.idivuk
830+
libc.src.stdfix.idivulk
823831
)
824832
endif()
825833

libc/config/linux/riscv/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
775775
libc.src.stdfix.countlsuhk
776776
libc.src.stdfix.countlsuk
777777
libc.src.stdfix.countlsulk
778+
libc.src.stdfix.idivr
779+
libc.src.stdfix.idivlr
780+
libc.src.stdfix.idivk
781+
libc.src.stdfix.idivulk
782+
libc.src.stdfix.idivur
783+
libc.src.stdfix.idivulr
784+
libc.src.stdfix.idivuk
785+
libc.src.stdfix.idivulk
778786
)
779787
endif()
780788

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
920920
libc.src.stdfix.countlsuhk
921921
libc.src.stdfix.countlsuk
922922
libc.src.stdfix.countlsulk
923+
libc.src.stdfix.idivr
924+
libc.src.stdfix.idivlr
925+
libc.src.stdfix.idivk
926+
libc.src.stdfix.idivlk
927+
libc.src.stdfix.idivur
928+
libc.src.stdfix.idivulr
929+
libc.src.stdfix.idivuk
930+
libc.src.stdfix.idivulk
923931
)
924932
endif()
925933

libc/docs/headers/stdfix.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
7777
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
7878
| divi\* | | | | | | | | | | | | |
7979
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
80-
| idiv\* | | | | | | | | | | | | |
80+
| idiv\* | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
8181
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
8282
| muli | | | | | | | | | | | | |
8383
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+

libc/include/stdfix.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,70 @@ functions:
238238
arguments:
239239
- type: unsigned long accum
240240
guard: LIBC_COMPILER_HAS_FIXED_POINT
241+
- name: idivr
242+
standards:
243+
- stdc_ext
244+
return_type: int
245+
arguments:
246+
- type: fract
247+
- type: fract
248+
guard: LIBC_COMPILER_HAS_FIXED_POINT
249+
- name: idivlr
250+
standards:
251+
- stdc_ext
252+
return_type: long int
253+
arguments:
254+
- type: long fract
255+
- type: long fract
256+
guard: LIBC_COMPILER_HAS_FIXED_POINT
257+
- name: idivk
258+
standards:
259+
- stdc_ext
260+
return_type: int
261+
arguments:
262+
- type: accum
263+
- type: accum
264+
guard: LIBC_COMPILER_HAS_FIXED_POINT
265+
- name: idivlk
266+
standards:
267+
- stdc_ext
268+
return_type: long int
269+
arguments:
270+
- type: long accum
271+
- type: long accum
272+
guard: LIBC_COMPILER_HAS_FIXED_POINT
273+
- name: idivur
274+
standards:
275+
- stdc_ext
276+
return_type: unsigned int
277+
arguments:
278+
- type: unsigned fract
279+
- type: unsigned fract
280+
guard: LIBC_COMPILER_HAS_FIXED_POINT
281+
- name: idivulr
282+
standards:
283+
- stdc_ext
284+
return_type: unsigned long int
285+
arguments:
286+
- type: unsigned long fract
287+
- type: unsigned long fract
288+
guard: LIBC_COMPILER_HAS_FIXED_POINT
289+
- name: idivuk
290+
standards:
291+
- stdc_ext
292+
return_type: unsigned int
293+
arguments:
294+
- type: unsigned accum
295+
- type: unsigned accum
296+
guard: LIBC_COMPILER_HAS_FIXED_POINT
297+
- name: idivulk
298+
standards:
299+
- stdc_ext
300+
return_type: unsigned long int
301+
arguments:
302+
- type: unsigned long accum
303+
- type: unsigned long accum
304+
guard: LIBC_COMPILER_HAS_FIXED_POINT
241305
- name: roundhk
242306
standards:
243307
- stdc_ext

libc/src/__support/fixed_point/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_header_library(
1616
.fx_rep
1717
libc.include.llvm-libc-macros.stdfix_macros
1818
libc.src.__support.macros.attributes
19+
libc.src.__support.macros.null_check
1920
libc.src.__support.macros.optimization
2021
libc.src.__support.CPP.type_traits
2122
libc.src.__support.CPP.bit

libc/src/__support/fixed_point/fx_bits.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "src/__support/CPP/type_traits.h"
1616
#include "src/__support/macros/attributes.h" // LIBC_INLINE
1717
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
18+
#include "src/__support/macros/null_check.h" // LIBC_CRASH_ON_VALUE
1819
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
1920
#include "src/__support/math_extras.h"
2021

@@ -201,6 +202,28 @@ bitsfx(T f) {
201202
return cpp::bit_cast<XType, T>(f);
202203
}
203204

205+
// divide the two fixed-point types and return an integer result
206+
template <typename T, typename XType>
207+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, XType>
208+
idiv(T x, T y) {
209+
using FXBits = FXBits<T>;
210+
using FXRep = FXRep<T>;
211+
using CompType = typename FXRep::CompType;
212+
213+
// If the value of the second operand of the / operator is zero, the
214+
// behavior is undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
215+
LIBC_CRASH_ON_VALUE(y, FXRep::ZERO());
216+
217+
CompType x_comp = static_cast<CompType>(FXBits(x).get_bits());
218+
CompType y_comp = static_cast<CompType>(FXBits(y).get_bits());
219+
220+
// If an integer result of one of these functions overflows, the behavior is
221+
// undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
222+
CompType result = x_comp / y_comp;
223+
224+
return static_cast<XType>(result);
225+
}
226+
204227
} // namespace fixed_point
205228
} // namespace LIBC_NAMESPACE_DECL
206229

libc/src/__support/macros/null_check.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,19 @@
1919
if (LIBC_UNLIKELY((ptr) == nullptr)) \
2020
__builtin_trap(); \
2121
} while (0)
22+
#define LIBC_CRASH_ON_VALUE(var, value) \
23+
do { \
24+
if (LIBC_UNLIKELY((var) == (value))) \
25+
__builtin_trap(); \
26+
} while (0)
27+
2228
#else
2329
#define LIBC_CRASH_ON_NULLPTR(ptr) \
2430
do { \
2531
} while (0)
32+
#define LIBC_CRASH_ON_VALUE(var, value) \
33+
do { \
34+
} while (0)
2635
#endif
2736

2837
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H

libc/src/stdfix/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
7575
)
7676
endforeach()
7777

78+
foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
79+
add_entrypoint_object(
80+
idiv${suffix}
81+
HDRS
82+
idiv${suffix}.h
83+
SRCS
84+
idiv${suffix}.cpp
85+
COMPILE_OPTIONS
86+
${libc_opt_high_flag}
87+
DEPENDS
88+
libc.src.__support.fixed_point.fx_bits
89+
)
90+
endforeach()
91+
7892
add_entrypoint_object(
7993
uhksqrtus
8094
HDRS

libc/src/stdfix/idivk.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation of idivk function ---------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "idivk.h"
10+
#include "include/llvm-libc-macros/stdfix-macros.h" // accum
11+
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
12+
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
LLVM_LIBC_FUNCTION(int, idivk, (accum x, accum y)) {
18+
return fixed_point::idiv<accum, int>(x, y);
19+
}
20+
21+
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdfix/idivk.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for idivk ------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDFIX_IDIVK_H
10+
#define LLVM_LIBC_SRC_STDFIX_IDIVK_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h" // accum
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
int idivk(accum x, accum y);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_STDFIX_IDIVK_H

libc/src/stdfix/idivlk.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation of idivlk function --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "idivlk.h"
10+
#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
11+
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
12+
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
LLVM_LIBC_FUNCTION(long int, idivlk, (long accum x, long accum y)) {
18+
return fixed_point::idiv<long accum, long int>(x, y);
19+
}
20+
21+
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdfix/idivlk.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for idivlk -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDFIX_IDIVLK_H
10+
#define LLVM_LIBC_SRC_STDFIX_IDIVLK_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
long int idivlk(long accum x, long accum y);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_STDFIX_IDIVLK_H

libc/src/stdfix/idivlr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation of idivlr function --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "idivlr.h"
10+
#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
11+
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
12+
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
LLVM_LIBC_FUNCTION(long int, idivlr, (long fract x, long fract y)) {
18+
return fixed_point::idiv<long fract, long int>(x, y);
19+
}
20+
21+
} // namespace LIBC_NAMESPACE_DECL

libc/src/stdfix/idivlr.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation header for idivlr -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_STDFIX_IDIVLR_H
10+
#define LLVM_LIBC_SRC_STDFIX_IDIVLR_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
long int idivlr(long fract x, long fract y);
18+
19+
} // namespace LIBC_NAMESPACE_DECL
20+
21+
#endif // LLVM_LIBC_SRC_STDFIX_IDIVLR_H

libc/src/stdfix/idivr.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//===-- Implementation of idivr function ---------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "idivr.h"
10+
#include "include/llvm-libc-macros/stdfix-macros.h" // fract
11+
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
12+
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
13+
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
LLVM_LIBC_FUNCTION(int, idivr, (fract x, fract y)) {
18+
return fixed_point::idiv<fract, int>(x, y);
19+
}
20+
21+
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)