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>