Skip to content

Commit 0cabe3e

Browse files
GH-48151: [C++][Parquet] Fix arrow-acero-asof-join-node-test failures on s390x
1 parent 55587ef commit 0cabe3e

File tree

1 file changed

+44
-9
lines changed

1 file changed

+44
-9
lines changed

cpp/src/arrow/compute/util.cc

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,40 @@ namespace util {
3030
namespace bit_util {
3131

3232
inline uint64_t SafeLoadUpTo8Bytes(const uint8_t* bytes, int num_bytes) {
33-
// This will not be correct on big-endian architectures.
34-
#if !ARROW_LITTLE_ENDIAN
35-
ARROW_DCHECK(false);
36-
#endif
3733
ARROW_DCHECK(num_bytes >= 0 && num_bytes <= 8);
3834
if (num_bytes == 8) {
3935
return util::SafeLoad(reinterpret_cast<const uint64_t*>(bytes));
4036
} else {
4137
uint64_t word = 0;
38+
#if ARROW_LITTLE_ENDIAN
4239
for (int i = 0; i < num_bytes; ++i) {
4340
word |= static_cast<uint64_t>(bytes[i]) << (8 * i);
4441
}
42+
#else
43+
// Big-endian: most significant byte first
44+
for (int i = 0; i < num_bytes; ++i) {
45+
word |= static_cast<uint64_t>(bytes[i]) << (8 * (num_bytes - 1 - i));
46+
}
47+
#endif
4548
return word;
4649
}
4750
}
4851

4952
inline void SafeStoreUpTo8Bytes(uint8_t* bytes, int num_bytes, uint64_t value) {
50-
// This will not be correct on big-endian architectures.
51-
#if !ARROW_LITTLE_ENDIAN
52-
ARROW_DCHECK(false);
53-
#endif
5453
ARROW_DCHECK(num_bytes >= 0 && num_bytes <= 8);
5554
if (num_bytes == 8) {
5655
util::SafeStore(reinterpret_cast<uint64_t*>(bytes), value);
5756
} else {
57+
#if ARROW_LITTLE_ENDIAN
5858
for (int i = 0; i < num_bytes; ++i) {
5959
bytes[i] = static_cast<uint8_t>(value >> (8 * i));
6060
}
61+
#else
62+
// Big-endian: most significant byte first
63+
for (int i = 0; i < num_bytes; ++i) {
64+
bytes[i] = static_cast<uint8_t>(value >> (8 * (num_bytes - 1 - i)));
65+
}
66+
#endif
6167
}
6268
}
6369

@@ -118,7 +124,22 @@ void bits_to_indexes_internal(int64_t hardware_flags, const int num_bits,
118124
// Optionally process the last partial word with masking out bits outside range
119125
if (tail) {
120126
const uint8_t* bits_tail = bits + (num_bits - tail) / 8;
127+
#if ARROW_LITTLE_ENDIAN
121128
uint64_t word = SafeLoadUpTo8Bytes(bits_tail, (tail + 7) / 8);
129+
#else
130+
int tail_bytes = (tail + 7) / 8;
131+
uint64_t word;
132+
if (tail_bytes == 8) {
133+
word = util::SafeLoad(reinterpret_cast<const uint64_t*>(bits_tail));
134+
} else {
135+
// For bit manipulation, always load into least significant bits
136+
// to ensure compatibility with CountTrailingZeros on Big-endian systems
137+
word = 0;
138+
for (int i = 0; i < tail_bytes; ++i) {
139+
word |= static_cast<uint64_t>(bits_tail[i]) << (8 * i);
140+
}
141+
}
142+
#endif
122143
if (bit_to_search == 0) {
123144
word = ~word;
124145
}
@@ -299,7 +320,21 @@ void bytes_to_bits(int64_t hardware_flags, const int num_bits, const uint8_t* by
299320
}
300321
int tail = num_bits % unroll;
301322
if (tail) {
302-
uint64_t bytes_next = SafeLoadUpTo8Bytes(bytes + num_bits - tail, tail);
323+
uint64_t bytes_next;
324+
#if ARROW_LITTLE_ENDIAN
325+
bytes_next = SafeLoadUpTo8Bytes(bytes + num_bits - tail, tail);
326+
#else
327+
if (tail == 8) {
328+
bytes_next = util::SafeLoad(reinterpret_cast<const uint64_t*>(bytes + num_bits - tail));
329+
} else {
330+
// On Big-endian systems, for bytes_to_bits, load all tail bytes in little-endian order
331+
// to ensure compatibility with subsequent bit operations
332+
bytes_next = 0;
333+
for (int i = 0; i < tail; ++i) {
334+
bytes_next |= static_cast<uint64_t>((bytes + num_bits - tail)[i]) << (8 * i);
335+
}
336+
}
337+
#endif
303338
bytes_next &= 0x0101010101010101ULL;
304339
bytes_next |= (bytes_next >> 7); // Pairs of adjacent output bits in individual bytes
305340
bytes_next |= (bytes_next >> 14); // 4 adjacent output bits in individual bytes

0 commit comments

Comments
 (0)