@@ -586,74 +586,72 @@ namespace xsimd
586586 return m_leaf0;
587587 }
588588
589- inline x86_cpuid_leaf1 const & leaf1 () const
589+ inline x86_cpuid_leaf80000000 const & leaf80000000 () const
590590 {
591- if (!m_status.bit_is_set <status::leaf1_valid >())
591+ if (!m_status.bit_is_set <status::leaf80000000_valid >())
592592 {
593- // Check if safe to call CPUID with this value
594- if (leaf0 ().highest_leaf () >= x86_cpuid_leaf1::leaf)
595- {
596- m_leaf1 = x86_cpuid_leaf1::read ();
597- }
598- // Otherwise leave it filled with zeros and mark as valid
599- m_status.set_bit <status::leaf1_valid>();
593+ m_leaf80000000 = x86_cpuid_leaf80000000::read ();
594+ m_status.set_bit <status::leaf80000000_valid>();
600595 }
601- return m_leaf1 ;
596+ return m_leaf80000000 ;
602597 }
603598
604- inline x86_cpuid_leaf7 const & leaf7 () const
599+ template <status status_id, typename L>
600+ inline auto const & safe_get_leaf (L& leaf) const
605601 {
606- if (!m_status.bit_is_set <status::leaf7_valid>())
602+ // Check if already initialized
603+ if (m_status.bit_is_set <status_id>())
607604 {
608- // Check if safe to call CPUID with this value
609- if (leaf0 ().highest_leaf () >= x86_cpuid_leaf7::leaf)
605+ return leaf;
606+ }
607+
608+ // Limit where we need to check leaf0 or leaf 80000000.
609+ constexpr auto extended_threshold = x86_cpuid_leaf80000000::leaf;
610+
611+ // Check if safe to call CPUID with this value.
612+ // First we identify if the leaf is in the regular or extended range.
613+ // TODO(C++17): if constexpr
614+ if (L::leaf < extended_threshold)
615+ {
616+ // Check leaf0 in regular range
617+ if (L::leaf <= leaf0 ().highest_leaf ())
610618 {
611- m_leaf7 = x86_cpuid_leaf7 ::read ();
619+ leaf = L ::read ();
612620 }
613- // Otherwise leave it filled with zeros and mark as valid
614- m_status.set_bit <status::leaf7_valid>();
615621 }
616- return m_leaf7;
617- }
618-
619- inline x86_cpuid_leaf7sub1 const & leaf7sub1 () const
620- {
621- if (!m_status.bit_is_set <status::leaf7sub1_valid>())
622+ else
622623 {
623- // Check if safe to call CPUID with this value
624- if (leaf0 ().highest_leaf () >= x86_cpuid_leaf7::leaf )
624+ // Check leaf80000000 in extended range
625+ if (L::leaf <= leaf80000000 ().highest_leaf ())
625626 {
626- m_leaf7sub1 = x86_cpuid_leaf7sub1 ::read ();
627+ leaf = L ::read ();
627628 }
628- // Otherwise leave it filled with zeros and mark as valid
629- m_status.set_bit <status::leaf7sub1_valid>();
630629 }
631- return m_leaf7sub1;
630+
631+ // Mark as valid in all cases, including if it was not read.
632+ // In this case it will be filled with zeros (all false).
633+ m_status.set_bit <status_id>();
634+ return leaf;
632635 }
633636
634- inline x86_cpuid_leaf80000000 const & leaf80000000 () const
637+ inline x86_cpuid_leaf1 const & leaf1 () const
635638 {
636- if (!m_status.bit_is_set <status::leaf80000000_valid>())
637- {
638- m_leaf80000000 = x86_cpuid_leaf80000000::read ();
639- m_status.set_bit <status::leaf80000000_valid>();
640- }
641- return m_leaf80000000;
639+ return safe_get_leaf<status::leaf1_valid>(m_leaf1);
640+ }
641+
642+ inline x86_cpuid_leaf7 const & leaf7 () const
643+ {
644+ return safe_get_leaf<status::leaf7_valid>(m_leaf7);
645+ }
646+
647+ inline x86_cpuid_leaf7sub1 const & leaf7sub1 () const
648+ {
649+ return safe_get_leaf<status::leaf7sub1_valid>(m_leaf7sub1);
642650 }
643651
644652 inline x86_cpuid_leaf80000001 const & leaf80000001 () const
645653 {
646- if (!m_status.bit_is_set <status::leaf80000001_valid>())
647- {
648- // Check if safe to call CPUID with this value
649- if (leaf80000000 ().highest_leaf () >= x86_cpuid_leaf80000001::leaf)
650- {
651- m_leaf80000001 = x86_cpuid_leaf80000001::read ();
652- }
653- // Otherwise leave it filled with zeros and mark as valid
654- m_status.set_bit <status::leaf80000001_valid>();
655- }
656- return m_leaf80000001;
654+ return safe_get_leaf<status::leaf80000001_valid>(m_leaf80000001);
657655 }
658656 };
659657
0 commit comments