Merge pull request #122 from zeek:topic/awelzel/fix-guest-without-osxsave

PiperOrigin-RevId: 612828573
diff --git a/highwayhash/instruction_sets.cc b/highwayhash/instruction_sets.cc
index a02e1f8..ab6775b 100644
--- a/highwayhash/instruction_sets.cc
+++ b/highwayhash/instruction_sets.cc
@@ -92,6 +92,7 @@
   flags |= IsBitSet(abcd[2], 20) ? kBitSSE42 : 0;
   flags |= IsBitSet(abcd[2], 12) ? kBitFMA : 0;
   flags |= IsBitSet(abcd[2], 28) ? kBitAVX : 0;
+  const bool has_xsave = IsBitSet(abcd[2], 26);
   const bool has_osxsave = IsBitSet(abcd[2], 27);
 
   // Extended feature flags
@@ -108,17 +109,19 @@
 
   // Verify OS support for XSAVE, without which XMM/YMM registers are not
   // preserved across context switches and are not safe to use.
-  if (has_osxsave) {
+  if (has_xsave && has_osxsave) {
     const uint32_t xcr0 = ReadXCR0();
-    // XMM
-    if ((xcr0 & 2) == 0) {
-      flags &= ~(kBitSSE | kBitSSE2 | kBitSSE3 | kBitSSSE3 | kBitSSE41 |
-                 kBitSSE42 | kBitAVX | kBitAVX2 | kBitFMA);
-    }
-    // YMM
-    if ((xcr0 & 4) == 0) {
+    // XMM/YMM
+    if ((xcr0 & 2) == 0 || (xcr0 & 4) == 0) {
       flags &= ~(kBitAVX | kBitAVX2);
     }
+  } else {
+    // Clear the AVX/AVX2 bits if the CPU or OS does not support XSAVE.
+    //
+    // The lower 128 bits of XMM0-XMM15 are guaranteed to be preserved across
+    // context switches on x86_64 and any modern 32-bit system, so only AVX2
+    // needs to be disabled.
+    flags &= ~(kBitAVX | kBitAVX2);
   }
 
   // Also indicates "supported" has been initialized.