Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkCpu_DEFINED
      9 #define SkCpu_DEFINED
     10 
     11 #include "SkTypes.h"
     12 
     13 struct SkCpu {
     14     enum {
     15         SSE1       = 1 << 0,
     16         SSE2       = 1 << 1,
     17         SSE3       = 1 << 2,
     18         SSSE3      = 1 << 3,
     19         SSE41      = 1 << 4,
     20         SSE42      = 1 << 5,
     21         AVX        = 1 << 6,
     22         F16C       = 1 << 7,
     23         FMA        = 1 << 8,
     24         AVX2       = 1 << 9,
     25         BMI1       = 1 << 10,
     26         BMI2       = 1 << 11,
     27         // Handy alias for all the cool Haswell+ instructions.
     28         HSW = AVX2 | BMI1 | BMI2 | F16C | FMA,
     29 
     30         AVX512F    = 1 << 12,
     31         AVX512DQ   = 1 << 13,
     32         AVX512IFMA = 1 << 14,
     33         AVX512PF   = 1 << 15,
     34         AVX512ER   = 1 << 16,
     35         AVX512CD   = 1 << 17,
     36         AVX512BW   = 1 << 18,
     37         AVX512VL   = 1 << 19,
     38 
     39         // Handy alias for all the cool Skylake Xeon+ instructions.
     40         SKX = AVX512F  | AVX512DQ | AVX512CD | AVX512BW | AVX512VL,
     41     };
     42     enum {
     43         NEON     = 1 << 0,
     44         NEON_FMA = 1 << 1,
     45         VFP_FP16 = 1 << 2,
     46         CRC32    = 1 << 3,
     47     };
     48 
     49     static void CacheRuntimeFeatures();
     50     static bool Supports(uint32_t);
     51 private:
     52     static uint32_t gCachedFeatures;
     53 };
     54 
     55 inline bool SkCpu::Supports(uint32_t mask) {
     56     uint32_t features = gCachedFeatures;
     57 
     58     // If we mask in compile-time known lower limits, the compiler can
     59     // often compile away this entire function.
     60 #if SK_CPU_X86
     61     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
     62     features |= SSE1;
     63     #endif
     64     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
     65     features |= SSE2;
     66     #endif
     67     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3
     68     features |= SSE3;
     69     #endif
     70     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
     71     features |= SSSE3;
     72     #endif
     73     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
     74     features |= SSE41;
     75     #endif
     76     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE42
     77     features |= SSE42;
     78     #endif
     79     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX
     80     features |= AVX;
     81     #endif
     82     // F16C goes here if we add SK_CPU_SSE_LEVEL_F16C
     83     #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
     84     features |= AVX2;
     85     #endif
     86     // FMA doesn't fit neatly into this total ordering.
     87     // It's available on Haswell+ just like AVX2, but it's technically a different bit.
     88     // TODO: circle back on this if we find ourselves limited by lack of compile-time FMA
     89 
     90     #if defined(SK_CPU_LIMIT_SSE41)
     91     features &= (SkCpu::SSE1 | SkCpu::SSE2 | SkCpu::SSE3 | SkCpu::SSSE3 | SkCpu::SSE41);
     92     #elif defined(SK_CPU_LIMIT_SSE2)
     93     features &= (SkCpu::SSE1 | SkCpu::SSE2);
     94     #endif
     95 
     96 #else
     97     #if defined(SK_ARM_HAS_NEON)
     98     features |= NEON;
     99     #endif
    100 
    101     #if defined(SK_CPU_ARM64)
    102     features |= NEON|NEON_FMA|VFP_FP16;
    103     #endif
    104 
    105     #if defined(SK_ARM_HAS_CRC32)
    106     features |= CRC32;
    107     #endif
    108 
    109 #endif
    110     return (features & mask) == mask;
    111 }
    112 
    113 #endif//SkCpu_DEFINED
    114