Skip to content

Commit 1650b4b

Browse files
Fix alignment prologue to actually align the pointer (+ some PEP 7 nits)
1 parent fe362fe commit 1650b4b

1 file changed

Lines changed: 16 additions & 8 deletions

File tree

‎Objects/stringlib/find_max_char.h‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
/* Mask to quickly check whether a C 'size_t' contains a
1414
non-ASCII, UTF8-encoded char. */
15-
1615
#if STRINGLIB_SIZEOF_CHAR == 1
1716
# if SIZEOF_SIZE_T == 8
1817
# define MASK_ASCII 0x8080808080808080ULL
@@ -53,6 +52,12 @@
5352
#error Invalid STRINGLIB_SIZEOF_CHAR (must be 1, 2 or 4)
5453
#endif
5554

55+
/* OR all characters into a single size_t accumulator and test the high bits
56+
at the end, instead of comparing each character. The accumulation loop has
57+
no branches, so compilers vectorize it, and the result does not depend on
58+
where each byte sits in the word, so unaligned ends can be read in smaller
59+
pieces. Every 32 words, check whether the widest kind is already known and
60+
exit early. */
5661
Py_LOCAL_INLINE(Py_UCS4)
5762
STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end)
5863
{
@@ -63,18 +68,18 @@ STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end)
6368

6469
if (!_Py_IS_ALIGNED(p, ALIGNOF_SIZE_T)) {
6570
#if STRINGLIB_SIZEOF_CHAR <= 1
66-
if (!_Py_IS_ALIGNED(p, 1) && p + 1 <= _end) {
71+
if (!_Py_IS_ALIGNED(p, sizeof(uint16_t)) && p + 1 <= _end) {
6772
value |= *p++;
6873
}
6974
#endif
7075
#if STRINGLIB_SIZEOF_CHAR <= 2
71-
if (!_Py_IS_ALIGNED(p, sizeof(uint16_t)) && p + sizeof(uint16_t) <= _end) {
76+
if (!_Py_IS_ALIGNED(p, sizeof(uint32_t)) && p + sizeof(uint16_t) <= _end) {
7277
value |= *(const uint16_t*)p;
7378
p += sizeof(uint16_t);
7479
}
7580
#endif
7681
#if SIZEOF_SIZE_T == 8
77-
if (!_Py_IS_ALIGNED(p, sizeof(uint32_t)) && p + sizeof(uint32_t) <= _end) {
82+
if (!_Py_IS_ALIGNED(p, SIZEOF_SIZE_T) && p + sizeof(uint32_t) <= _end) {
7883
value |= *(const uint32_t*)p;
7984
p += sizeof(uint32_t);
8085
}
@@ -83,7 +88,7 @@ STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end)
8388

8489
while (p + SIZEOF_SIZE_T * 32 <= _end) {
8590
const size_t *pp = (const size_t *)p;
86-
for(int i=0; i<32; i++) {
91+
for(int i = 0; i < 32; i++) {
8792
value |= pp[i];
8893
}
8994
if (value & MASK_MAX_CHAR) {
@@ -115,15 +120,18 @@ STRINGLIB(find_max_char)(const STRINGLIB_CHAR *begin, const STRINGLIB_CHAR *end)
115120
#endif
116121

117122
#ifdef MASK_UCS2
118-
if (value & MASK_UCS2)
123+
if (value & MASK_UCS2) {
119124
return MAX_CHAR_UCS4;
125+
}
120126
#endif
121127
#ifdef MASK_UCS1
122-
if (value & MASK_UCS1)
128+
if (value & MASK_UCS1) {
123129
return MAX_CHAR_UCS2;
130+
}
124131
#endif
125-
if (value & MASK_ASCII)
132+
if (value & MASK_ASCII) {
126133
return MAX_CHAR_UCS1;
134+
}
127135
return MAX_CHAR_ASCII;
128136
}
129137

0 commit comments

Comments
 (0)