@@ -94,9 +94,13 @@ namespace xsimd
9494 constexpr x86_cpuid_regs () noexcept = default;
9595
9696 using eax_bitset::all_bits_set;
97+ using eax_bitset::get_range;
9798 using ebx_bitset::all_bits_set;
99+ using ebx_bitset::get_range;
98100 using ecx_bitset::all_bits_set;
101+ using ecx_bitset::get_range;
99102 using edx_bitset::all_bits_set;
103+ using edx_bitset::get_range;
100104 };
101105
102106 template <typename T>
@@ -239,6 +243,10 @@ namespace xsimd
239243
240244 enum class eax
241245 {
246+ /* Start bit for the encoding of the highest subleaf available. */
247+ highest_subleaf_start = 0 ,
248+ /* End bit for the encoding of the highest subleaf available. */
249+ highest_subleaf_end = 32 ,
242250 };
243251 enum class ebx
244252 {
@@ -645,7 +653,25 @@ namespace xsimd
645653
646654 inline x86_cpuid_leaf7sub1 const & leaf7sub1 () const
647655 {
648- return safe_get_leaf<status::leaf7sub1_valid>(m_leaf7sub1);
656+ // Check if already initialized
657+ if (m_status.bit_is_set <status::leaf7sub1_valid>())
658+ {
659+ return m_leaf7sub1;
660+ }
661+
662+ // Check if safe to call CPUID with this value as subleaf.
663+ constexpr auto start = x86_cpuid_leaf7::eax::highest_subleaf_start;
664+ constexpr auto end = x86_cpuid_leaf7::eax::highest_subleaf_end;
665+ const auto highest_subleaf7 = leaf7 ().get_range <start, end>();
666+ if (x86_cpuid_leaf7sub1::subleaf <= highest_subleaf7)
667+ {
668+ m_leaf7sub1 = x86_cpuid_leaf7sub1::read ();
669+ }
670+
671+ // Mark as valid in all cases, including if it was not read.
672+ // In this case it will be filled with zeros (all false).
673+ m_status.set_bit <status::leaf7sub1_valid>();
674+ return m_leaf7sub1;
649675 }
650676
651677 inline x86_cpuid_leaf80000001 const & leaf80000001 () const
0 commit comments