[libc] Add sub_with_borrow to builtin_wrapper.h
Add sub_with_borrow to builtin_wrapper.h to be used in UInt. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D138182
This commit is contained in:
parent
420d0d3aa6
commit
e205fc1836
|
@ -6,11 +6,18 @@ add_header_library(
|
||||||
blockstore.h
|
blockstore.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_header_library(
|
||||||
|
named_pair
|
||||||
|
HDRS
|
||||||
|
named_pair.h
|
||||||
|
)
|
||||||
|
|
||||||
add_header_library(
|
add_header_library(
|
||||||
builtin_wrappers
|
builtin_wrappers
|
||||||
HDRS
|
HDRS
|
||||||
builtin_wrappers.h
|
builtin_wrappers.h
|
||||||
DEPENDS
|
DEPENDS
|
||||||
|
.named_pair
|
||||||
libc.src.__support.CPP.type_traits
|
libc.src.__support.CPP.type_traits
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -111,6 +118,7 @@ add_header_library(
|
||||||
HDRS
|
HDRS
|
||||||
number_pair.h
|
number_pair.h
|
||||||
DEPENDS
|
DEPENDS
|
||||||
|
.named_pair
|
||||||
libc.src.__support.CPP.type_traits
|
libc.src.__support.CPP.type_traits
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -101,22 +101,20 @@ template <size_t Bits> struct UInt {
|
||||||
// property of unsigned integers:
|
// property of unsigned integers:
|
||||||
// x + (~x) = 2^(sizeof(x)) - 1.
|
// x + (~x) = 2^(sizeof(x)) - 1.
|
||||||
constexpr uint64_t add(const UInt<Bits> &x) {
|
constexpr uint64_t add(const UInt<Bits> &x) {
|
||||||
uint64_t carry_in = 0;
|
SumCarry<uint64_t> s{0, 0};
|
||||||
uint64_t carry_out = 0;
|
|
||||||
for (size_t i = 0; i < WordCount; ++i) {
|
for (size_t i = 0; i < WordCount; ++i) {
|
||||||
val[i] = add_with_carry(val[i], x.val[i], carry_in, carry_out);
|
s = add_with_carry(val[i], x.val[i], s.carry);
|
||||||
carry_in = carry_out;
|
val[i] = s.sum;
|
||||||
}
|
}
|
||||||
return carry_out;
|
return s.carry;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr UInt<Bits> operator+(const UInt<Bits> &other) const {
|
constexpr UInt<Bits> operator+(const UInt<Bits> &other) const {
|
||||||
UInt<Bits> result;
|
UInt<Bits> result;
|
||||||
uint64_t carry_in = 0;
|
SumCarry<uint64_t> s{0, 0};
|
||||||
uint64_t carry_out = 0;
|
|
||||||
for (size_t i = 0; i < WordCount; ++i) {
|
for (size_t i = 0; i < WordCount; ++i) {
|
||||||
result.val[i] = add_with_carry(val[i], other.val[i], carry_in, carry_out);
|
s = add_with_carry(val[i], other.val[i], s.carry);
|
||||||
carry_in = carry_out;
|
result.val[i] = s.sum;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
#ifndef LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
||||||
#define LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
#define LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
||||||
|
|
||||||
|
#include "named_pair.h"
|
||||||
#include "src/__support/CPP/type_traits.h"
|
#include "src/__support/CPP/type_traits.h"
|
||||||
|
|
||||||
namespace __llvm_libc {
|
namespace __llvm_libc {
|
||||||
|
@ -67,59 +68,131 @@ template <typename T> static inline int unsafe_clz(T val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add with carry
|
// Add with carry
|
||||||
|
DEFINE_NAMED_PAIR_TEMPLATE(SumCarry, sum, carry);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr cpp::enable_if_t<
|
inline constexpr cpp::enable_if_t<
|
||||||
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, T>
|
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, SumCarry<T>>
|
||||||
add_with_carry(T a, T b, T carry_in, T &carry_out) {
|
add_with_carry(T a, T b, T carry_in) {
|
||||||
T tmp = a + carry_in;
|
T tmp = a + carry_in;
|
||||||
T sum = b + tmp;
|
T sum = b + tmp;
|
||||||
carry_out = (sum < b) || (tmp < a);
|
T carry_out = (sum < b) || (tmp < a);
|
||||||
return sum;
|
return {sum, carry_out};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __has_builtin(__builtin_addc)
|
#if __has_builtin(__builtin_addc)
|
||||||
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
|
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline unsigned char add_with_carry<unsigned char>(unsigned char a,
|
inline SumCarry<unsigned char>
|
||||||
unsigned char b,
|
add_with_carry<unsigned char>(unsigned char a, unsigned char b,
|
||||||
unsigned char carry_in,
|
unsigned char carry_in) {
|
||||||
unsigned char &carry_out) {
|
SumCarry<unsigned char> result{0, 0};
|
||||||
return __builtin_addcb(a, b, carry_in, &carry_out);
|
result.sum = __builtin_addcb(a, b, carry_in, &result.carry);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline unsigned short
|
inline SumCarry<unsigned short>
|
||||||
add_with_carry<unsigned short>(unsigned short a, unsigned short b,
|
add_with_carry<unsigned short>(unsigned short a, unsigned short b,
|
||||||
unsigned short carry_in,
|
unsigned short carry_in) {
|
||||||
unsigned short &carry_out) {
|
SumCarry<unsigned short> result{0, 0};
|
||||||
return __builtin_addcs(a, b, carry_in, &carry_out);
|
result.sum = __builtin_addcs(a, b, carry_in, &result.carry);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline unsigned int add_with_carry<unsigned int>(unsigned int a, unsigned int b,
|
inline SumCarry<unsigned int>
|
||||||
unsigned int carry_in,
|
add_with_carry<unsigned int>(unsigned int a, unsigned int b,
|
||||||
unsigned int &carry_out) {
|
unsigned int carry_in) {
|
||||||
return __builtin_addc(a, b, carry_in, &carry_out);
|
SumCarry<unsigned int> result{0, 0};
|
||||||
|
result.sum = __builtin_addc(a, b, carry_in, &result.carry);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline unsigned long add_with_carry<unsigned long>(unsigned long a,
|
inline SumCarry<unsigned long>
|
||||||
unsigned long b,
|
add_with_carry<unsigned long>(unsigned long a, unsigned long b,
|
||||||
unsigned long carry_in,
|
unsigned long carry_in) {
|
||||||
unsigned long &carry_out) {
|
SumCarry<unsigned long> result{0, 0};
|
||||||
return __builtin_addcl(a, b, carry_in, &carry_out);
|
result.sum = __builtin_addcl(a, b, carry_in, &result.carry);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline unsigned long long
|
inline SumCarry<unsigned long long>
|
||||||
add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
|
add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b,
|
||||||
unsigned long long carry_in,
|
unsigned long long carry_in) {
|
||||||
unsigned long long &carry_out) {
|
SumCarry<unsigned long long> result{0, 0};
|
||||||
return __builtin_addcll(a, b, carry_in, &carry_out);
|
result.sum = __builtin_addcll(a, b, carry_in, &result.carry);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __has_builtin(__builtin_addc)
|
#endif // __has_builtin(__builtin_addc)
|
||||||
|
|
||||||
|
// Subtract with borrow
|
||||||
|
DEFINE_NAMED_PAIR_TEMPLATE(DiffBorrow, diff, borrow);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr cpp::enable_if_t<
|
||||||
|
cpp::is_integral_v<T> && cpp::is_unsigned_v<T>, DiffBorrow<T>>
|
||||||
|
sub_with_borrow(T a, T b, T borrow_in) {
|
||||||
|
T tmp = a - b;
|
||||||
|
T diff = tmp - borrow_in;
|
||||||
|
T borrow_out = (diff > tmp) || (tmp > a);
|
||||||
|
return {diff, borrow_out};
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_subc)
|
||||||
|
// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline DiffBorrow<unsigned char>
|
||||||
|
sub_with_borrow<unsigned char>(unsigned char a, unsigned char b,
|
||||||
|
unsigned char borrow_in) {
|
||||||
|
DiffBorrow<unsigned char> result{0, 0};
|
||||||
|
result.diff = __builtin_subcb(a, b, borrow_in, &result.borrow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline DiffBorrow<unsigned short>
|
||||||
|
sub_with_borrow<unsigned short>(unsigned short a, unsigned short b,
|
||||||
|
unsigned short borrow_in) {
|
||||||
|
DiffBorrow<unsigned short> result{0, 0};
|
||||||
|
result.diff = __builtin_subcs(a, b, borrow_in, &result.borrow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline DiffBorrow<unsigned int>
|
||||||
|
sub_with_borrow<unsigned int>(unsigned int a, unsigned int b,
|
||||||
|
unsigned int borrow_in) {
|
||||||
|
DiffBorrow<unsigned int> result{0, 0};
|
||||||
|
result.diff = __builtin_subc(a, b, borrow_in, &result.borrow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline DiffBorrow<unsigned long>
|
||||||
|
sub_with_borrow<unsigned long>(unsigned long a, unsigned long b,
|
||||||
|
unsigned long borrow_in) {
|
||||||
|
DiffBorrow<unsigned long> result{0, 0};
|
||||||
|
result.diff = __builtin_subcl(a, b, borrow_in, &result.borrow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline DiffBorrow<unsigned long long>
|
||||||
|
sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b,
|
||||||
|
unsigned long long borrow_in) {
|
||||||
|
DiffBorrow<unsigned long long> result{0, 0};
|
||||||
|
result.diff = __builtin_subcll(a, b, borrow_in, &result.borrow);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __has_builtin(__builtin_subc)
|
||||||
|
|
||||||
} // namespace __llvm_libc
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
#endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
#endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H
|
||||||
|
|
|
@ -46,13 +46,13 @@ inline NumberPair<uint64_t> full_mul<uint64_t>(uint64_t a, uint64_t b) {
|
||||||
NumberPair<uint64_t> lo_hi = split(pa.lo * pb.hi); // exact
|
NumberPair<uint64_t> lo_hi = split(pa.lo * pb.hi); // exact
|
||||||
NumberPair<uint64_t> hi_lo = split(pa.hi * pb.lo); // exact
|
NumberPair<uint64_t> hi_lo = split(pa.hi * pb.lo); // exact
|
||||||
|
|
||||||
uint64_t carry_in = 0;
|
auto r1 = add_with_carry(prod.lo, lo_hi.lo << 32, uint64_t(0));
|
||||||
uint64_t carry_out = 0;
|
prod.lo = r1.sum;
|
||||||
uint64_t carry_unused = 0;
|
prod.hi = add_with_carry(prod.hi, lo_hi.hi, r1.carry).sum;
|
||||||
prod.lo = add_with_carry(prod.lo, lo_hi.lo << 32, carry_in, carry_out);
|
|
||||||
prod.hi = add_with_carry(prod.hi, lo_hi.hi, carry_out, carry_unused);
|
auto r2 = add_with_carry(prod.lo, hi_lo.lo << 32, uint64_t(0));
|
||||||
prod.lo = add_with_carry(prod.lo, hi_lo.lo << 32, carry_in, carry_out);
|
prod.lo = r2.sum;
|
||||||
prod.hi = add_with_carry(prod.hi, hi_lo.hi, carry_out, carry_unused);
|
prod.hi = add_with_carry(prod.hi, hi_lo.hi, r2.carry).sum;
|
||||||
|
|
||||||
return prod;
|
return prod;
|
||||||
#endif // __SIZEOF_INT128__
|
#endif // __SIZEOF_INT128__
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
//===-- Utilities for pairs of numbers. -------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H
|
||||||
|
#define LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H
|
||||||
|
|
||||||
|
#define DEFINE_NAMED_PAIR_TEMPLATE(Name, FirstField, SecondField) \
|
||||||
|
template <typename T1, typename T2 = T1> struct Name { \
|
||||||
|
T1 FirstField; \
|
||||||
|
T2 SecondField; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LLVM_LIBC_SRC_SUPPORT_NAMED_PAIR_H
|
|
@ -10,15 +10,13 @@
|
||||||
#define LLVM_LIBC_SRC_SUPPORT_NUMBER_PAIR_H
|
#define LLVM_LIBC_SRC_SUPPORT_NUMBER_PAIR_H
|
||||||
|
|
||||||
#include "CPP/type_traits.h"
|
#include "CPP/type_traits.h"
|
||||||
|
#include "named_pair.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
namespace __llvm_libc {
|
namespace __llvm_libc {
|
||||||
|
|
||||||
template <typename T> struct NumberPair {
|
DEFINE_NAMED_PAIR_TEMPLATE(NumberPair, lo, hi);
|
||||||
T lo;
|
|
||||||
T hi;
|
|
||||||
};
|
|
||||||
|
|
||||||
using DoubleDouble = NumberPair<double>;
|
using DoubleDouble = NumberPair<double>;
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,7 @@ cc_library(
|
||||||
hdrs = ["src/__support/number_pair.h"],
|
hdrs = ["src/__support/number_pair.h"],
|
||||||
deps = [
|
deps = [
|
||||||
"__support_cpp_type_traits",
|
"__support_cpp_type_traits",
|
||||||
|
"__support_named_pair",
|
||||||
":libc_root",
|
":libc_root",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -230,11 +231,18 @@ cc_library(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "__support_named_pair",
|
||||||
|
hdrs = ["src/__support/named_pair.h"],
|
||||||
|
deps = [":libc_root"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "__support_builtin_wrappers",
|
name = "__support_builtin_wrappers",
|
||||||
hdrs = ["src/__support/builtin_wrappers.h"],
|
hdrs = ["src/__support/builtin_wrappers.h"],
|
||||||
deps = [
|
deps = [
|
||||||
":__support_cpp_type_traits",
|
":__support_cpp_type_traits",
|
||||||
|
":__support_named_pair",
|
||||||
":libc_root",
|
":libc_root",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue