Work around LLVM #108722.
https://github.com/llvm/llvm-project/issues/108722
diff --git a/src/aarch32/instructions-aarch32.cc b/src/aarch32/instructions-aarch32.cc
index fe5458f..f3ed0e0 100644
--- a/src/aarch32/instructions-aarch32.cc
+++ b/src/aarch32/instructions-aarch32.cc
@@ -636,20 +636,15 @@
}
-static inline uint32_t ror(uint32_t x, int i) {
- VIXL_ASSERT((0 < i) && (i < 32));
- return (x >> i) | (x << (32 - i));
-}
-
-
bool ImmediateT32::IsImmediateT32(uint32_t imm) {
/* abcdefgh abcdefgh abcdefgh abcdefgh */
- if ((imm ^ ror(imm, 8)) == 0) return true;
+ if (AllBytesMatch(imm)) return true;
/* 00000000 abcdefgh 00000000 abcdefgh */
/* abcdefgh 00000000 abcdefgh 00000000 */
- if ((imm ^ ror(imm, 16)) == 0 &&
- (((imm & 0xff00) == 0) || ((imm & 0xff) == 0)))
+ if (AllHalfwordsMatch(imm) &&
+ (((imm & 0xff00) == 0) || ((imm & 0xff) == 0))) {
return true;
+ }
/* isolate least-significant set bit */
uint32_t lsb = imm & UnsignedNegate(imm);
/* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
@@ -697,7 +692,7 @@
if (imm < 256) return true;
/* avoid getting confused by wrapped-around bytes (this transform has no
* effect on pass/fail results) */
- if (imm & 0xff000000) imm = ror(imm, 16);
+ if (imm & 0xff000000) imm = static_cast<uint32_t>(RotateRight(imm, 16, 32));
/* copy odd-numbered set bits into even-numbered bits immediately below, so
* that the least-significant set bit is always an even bit */
imm = imm | ((imm >> 1) & 0x55555555);
diff --git a/src/aarch64/disasm-aarch64.cc b/src/aarch64/disasm-aarch64.cc
index ebfc2c7..59dcef6 100644
--- a/src/aarch64/disasm-aarch64.cc
+++ b/src/aarch64/disasm-aarch64.cc
@@ -4020,8 +4020,7 @@
}
// Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00.
- uint64_t rotvalue = RotateRight(value, 32, 64);
- if (value == rotvalue) {
+ if (AllWordsMatch(value)) {
generic_value &= 0xffffffff;
if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) {
return false;
@@ -4029,8 +4028,7 @@
}
// Check 0xpq00pq00_pq00pq00.
- rotvalue = RotateRight(value, 16, 64);
- if (value == rotvalue) {
+ if (AllHalfwordsMatch(value)) {
return false;
}
} else {
@@ -4044,8 +4042,7 @@
}
// Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq.
- uint64_t rotvalue = RotateRight(value, 32, 64);
- if (value == rotvalue) {
+ if (AllWordsMatch(value)) {
generic_value &= 0xffffffff;
if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) {
return false;
@@ -4053,8 +4050,7 @@
}
// Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq.
- rotvalue = RotateRight(value, 16, 64);
- if (value == rotvalue) {
+ if (AllHalfwordsMatch(value)) {
generic_value &= 0xffff;
if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) {
return false;
@@ -4062,8 +4058,7 @@
}
// Check 0xpqpqpqpq_pqpqpqpq.
- rotvalue = RotateRight(value, 8, 64);
- if (value == rotvalue) {
+ if (AllBytesMatch(value)) {
return false;
}
}
diff --git a/src/utils-vixl.h b/src/utils-vixl.h
index 86de68a..d4b8a35 100644
--- a/src/utils-vixl.h
+++ b/src/utils-vixl.h
@@ -623,6 +623,39 @@
return IsAligned<4>(pointer);
}
+template <unsigned BITS, typename T>
+bool IsRepeatingPattern(T value) {
+ VIXL_STATIC_ASSERT(std::is_unsigned<T>::value);
+ VIXL_ASSERT(IsMultiple(sizeof(value) * kBitsPerByte, BITS));
+ VIXL_ASSERT(IsMultiple(BITS, 2));
+ VIXL_STATIC_ASSERT(BITS >= 2);
+#if (defined(__x86_64__) || defined(__i386)) && \
+ __clang_major__ >= 17 && __clang_major__ <= 19
+ // Workaround for https://github.com/llvm/llvm-project/issues/108722
+ unsigned hbits = BITS / 2;
+ T midmask = (~static_cast<T>(0) >> BITS) << hbits;
+ // E.g. for bytes in a word (0xb3b2b1b0): .b3b2b1. == .b2b1b0.
+ return (((value >> hbits) & midmask) == ((value << hbits) & midmask));
+#else
+ return value == RotateRight(value, BITS, sizeof(value) * kBitsPerByte);
+#endif
+}
+
+template <typename T>
+bool AllBytesMatch(T value) {
+ return IsRepeatingPattern<kBitsPerByte>(value);
+}
+
+template <typename T>
+bool AllHalfwordsMatch(T value) {
+ return IsRepeatingPattern<kBitsPerByte * 2>(value);
+}
+
+template <typename T>
+bool AllWordsMatch(T value) {
+ return IsRepeatingPattern<kBitsPerByte * 4>(value);
+}
+
// Increment a pointer until it has the specified alignment. The alignment must
// be a power of two.
template <class T>