[flang-commits] [flang] [Flang] Shift the data from lower to higher order bits in the big endian environment (PR #73670)
via flang-commits
flang-commits at lists.llvm.org
Thu Dec 28 09:50:23 PST 2023
https://github.com/madanial0 updated https://github.com/llvm/llvm-project/pull/73670
>From 14b202a1c6c499bfb52ce6f33aa0ff28ff674e60 Mon Sep 17 00:00:00 2001
From: Mark Danial <madanial at dixon.rtp.raleigh.ibm.com>
Date: Mon, 27 Nov 2023 21:11:52 -0500
Subject: [PATCH 1/4] [Flang] Shift the data from lower to higher order bits in
the big endian environment
---
flang/runtime/edit-input.cpp | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 2b809749067772..9ebb9965bf9ead 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -244,7 +244,15 @@ bool EditIntegerInput(
value = -value;
}
if (any || !io.GetConnectionState().IsAtEOF()) {
- std::memcpy(n, &value, kind); // a blank field means zero
+ // For integer kind <= 4, the value is stored in the lower order bits on
+ // the big endian platform. When memcpy the value, shift the value, shift
+ // the value to the higher order bit.
+ if (!isHostLittleEndian && kind <= 4) {
+ auto l{value.low() << (8 * (sizeof(value.low()) - kind))};
+ std::memcpy(n, &l, kind);
+ } else {
+ std::memcpy(n, &value, kind); // a blank field means zero
+ }
}
return any;
}
>From cd46ecd08aac149e818b3d17305fa85b71eb4434 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Tue, 12 Dec 2023 15:56:33 -0500
Subject: [PATCH 2/4] swap two halves in Int128 in big endian
---
flang/include/flang/Common/uint128.h | 30 ++++++++++++++++++++--------
flang/runtime/edit-input.cpp | 10 +++++-----
2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/flang/include/flang/Common/uint128.h b/flang/include/flang/Common/uint128.h
index bfd2eef01f6f08..c66dc4f303a734 100644
--- a/flang/include/flang/Common/uint128.h
+++ b/flang/include/flang/Common/uint128.h
@@ -23,6 +23,16 @@
#include <cstdint>
#include <type_traits>
+#if FLANG_LITTLE_ENDIAN
+#define SWAP(a, i, b, j) \
+ a{i}, b { j }
+#elif FLANG_BIG_ENDIAN
+#define SWAP(a, i, b, j) \
+ b{j}, a { i }
+#else
+#error host endianness is not known
+#endif
+
namespace Fortran::common {
template <bool IS_SIGNED = false> class Int128 {
@@ -34,14 +44,14 @@ template <bool IS_SIGNED = false> class Int128 {
constexpr Int128(unsigned long n) : low_{n} {}
constexpr Int128(unsigned long long n) : low_{n} {}
constexpr Int128(int n)
- : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
- n < 0)} {}
+ : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+ -static_cast<std::uint64_t>(n < 0)) {}
constexpr Int128(long n)
- : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
- n < 0)} {}
+ : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+ -static_cast<std::uint64_t>(n < 0)) {}
constexpr Int128(long long n)
- : low_{static_cast<std::uint64_t>(n)}, high_{-static_cast<std::uint64_t>(
- n < 0)} {}
+ : SWAP(low_, static_cast<std::uint64_t>(n), high_,
+ -static_cast<std::uint64_t>(n < 0)) {}
constexpr Int128(const Int128 &) = default;
constexpr Int128(Int128 &&) = default;
constexpr Int128 &operator=(const Int128 &) = default;
@@ -246,7 +256,8 @@ template <bool IS_SIGNED = false> class Int128 {
}
private:
- constexpr Int128(std::uint64_t hi, std::uint64_t lo) : low_{lo}, high_{hi} {}
+ constexpr Int128(std::uint64_t hi, std::uint64_t lo)
+ : SWAP(low_, lo, high_, hi) {}
constexpr int LeadingZeroes() const {
if (high_ == 0) {
return 64 + LeadingZeroBitCount(low_);
@@ -255,7 +266,7 @@ template <bool IS_SIGNED = false> class Int128 {
}
}
static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
- std::uint64_t low_{0}, high_{0};
+ std::uint64_t SWAP(low_, 0, high_, 0);
};
using UnsignedInt128 = Int128<false>;
@@ -288,4 +299,7 @@ template <int BITS>
using HostSignedIntType = typename HostSignedIntTypeHelper<BITS>::type;
} // namespace Fortran::common
+
+#undef SWAP
+
#endif
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 9ebb9965bf9ead..1e831e11794ac7 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -244,11 +244,11 @@ bool EditIntegerInput(
value = -value;
}
if (any || !io.GetConnectionState().IsAtEOF()) {
- // For integer kind <= 4, the value is stored in the lower order bits on
- // the big endian platform. When memcpy the value, shift the value, shift
- // the value to the higher order bit.
- if (!isHostLittleEndian && kind <= 4) {
- auto l{value.low() << (8 * (sizeof(value.low()) - kind))};
+ // The value is stored in the lower order bits on big endian platform.
+ // When memcpy, shift the value to the higher order bit.
+ auto shft{static_cast<int>(sizeof(value.low())) - kind};
+ if (!isHostLittleEndian && shft >= 0) {
+ auto l{value.low() << (8 * shft)};
std::memcpy(n, &l, kind);
} else {
std::memcpy(n, &value, kind); // a blank field means zero
>From 61ac864a92ee2f5060bade348432cf08905e6e6f Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 18 Dec 2023 20:54:17 -0500
Subject: [PATCH 3/4] address review comments
---
flang/include/flang/Common/uint128.h | 48 +++++++++++++---------------
1 file changed, 23 insertions(+), 25 deletions(-)
diff --git a/flang/include/flang/Common/uint128.h b/flang/include/flang/Common/uint128.h
index c66dc4f303a734..03e44eb6997d5b 100644
--- a/flang/include/flang/Common/uint128.h
+++ b/flang/include/flang/Common/uint128.h
@@ -23,16 +23,6 @@
#include <cstdint>
#include <type_traits>
-#if FLANG_LITTLE_ENDIAN
-#define SWAP(a, i, b, j) \
- a{i}, b { j }
-#elif FLANG_BIG_ENDIAN
-#define SWAP(a, i, b, j) \
- b{j}, a { i }
-#else
-#error host endianness is not known
-#endif
-
namespace Fortran::common {
template <bool IS_SIGNED = false> class Int128 {
@@ -43,15 +33,18 @@ template <bool IS_SIGNED = false> class Int128 {
constexpr Int128(unsigned n) : low_{n} {}
constexpr Int128(unsigned long n) : low_{n} {}
constexpr Int128(unsigned long long n) : low_{n} {}
- constexpr Int128(int n)
- : SWAP(low_, static_cast<std::uint64_t>(n), high_,
- -static_cast<std::uint64_t>(n < 0)) {}
- constexpr Int128(long n)
- : SWAP(low_, static_cast<std::uint64_t>(n), high_,
- -static_cast<std::uint64_t>(n < 0)) {}
- constexpr Int128(long long n)
- : SWAP(low_, static_cast<std::uint64_t>(n), high_,
- -static_cast<std::uint64_t>(n < 0)) {}
+ constexpr Int128(int n) {
+ low_ = static_cast<std::uint64_t>(n);
+ high_ = -static_cast<std::uint64_t>(n < 0);
+ }
+ constexpr Int128(long n) {
+ low_ = static_cast<std::uint64_t>(n);
+ high_ = -static_cast<std::uint64_t>(n < 0);
+ }
+ constexpr Int128(long long n) {
+ low_ = static_cast<std::uint64_t>(n);
+ high_ = -static_cast<std::uint64_t>(n < 0);
+ }
constexpr Int128(const Int128 &) = default;
constexpr Int128(Int128 &&) = default;
constexpr Int128 &operator=(const Int128 &) = default;
@@ -256,8 +249,10 @@ template <bool IS_SIGNED = false> class Int128 {
}
private:
- constexpr Int128(std::uint64_t hi, std::uint64_t lo)
- : SWAP(low_, lo, high_, hi) {}
+ constexpr Int128(std::uint64_t hi, std::uint64_t lo) {
+ low_ = lo;
+ high_ = hi;
+ }
constexpr int LeadingZeroes() const {
if (high_ == 0) {
return 64 + LeadingZeroBitCount(low_);
@@ -266,7 +261,13 @@ template <bool IS_SIGNED = false> class Int128 {
}
}
static constexpr std::uint64_t topBit{std::uint64_t{1} << 63};
- std::uint64_t SWAP(low_, 0, high_, 0);
+#if FLANG_LITTLE_ENDIAN
+ std::uint64_t low_{0}, high_{0};
+#elif FLANG_BIG_ENDIAN
+ std::uint64_t high_{0}, low_{0};
+#else
+#error host endianness is not known
+#endif
};
using UnsignedInt128 = Int128<false>;
@@ -299,7 +300,4 @@ template <int BITS>
using HostSignedIntType = typename HostSignedIntTypeHelper<BITS>::type;
} // namespace Fortran::common
-
-#undef SWAP
-
#endif
>From 89a44e1184904338b6d7d40dba5698c276d83a31 Mon Sep 17 00:00:00 2001
From: Kelvin Li <kli at ca.ibm.com>
Date: Mon, 18 Dec 2023 22:15:44 -0500
Subject: [PATCH 4/4] add comment to explain the logic
---
flang/runtime/edit-input.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 1e831e11794ac7..c4fa186e289db2 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -247,6 +247,7 @@ bool EditIntegerInput(
// The value is stored in the lower order bits on big endian platform.
// When memcpy, shift the value to the higher order bit.
auto shft{static_cast<int>(sizeof(value.low())) - kind};
+ // For kind==8 (i.e. shft==0), the value is stored in low_ in big endian.
if (!isHostLittleEndian && shft >= 0) {
auto l{value.low() << (8 * shft)};
std::memcpy(n, &l, kind);
More information about the flang-commits
mailing list