LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkCpu.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 31 39 79.5 %
Date: 2017-07-14 16:53:18 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "SkCpu.h"
       9             : #include "SkOnce.h"
      10             : 
      11             : #if !defined(__has_include)
      12             :     #define __has_include(x) 0
      13             : #endif
      14             : 
      15             : #if defined(SK_CPU_X86)
      16             :     #if defined(SK_BUILD_FOR_WIN32)
      17             :         #include <intrin.h>
      18             :         static void cpuid (uint32_t abcd[4]) { __cpuid  ((int*)abcd, 1);    }
      19             :         static void cpuid7(uint32_t abcd[4]) { __cpuidex((int*)abcd, 7, 0); }
      20             :         static uint64_t xgetbv(uint32_t xcr) { return _xgetbv(xcr); }
      21             :     #else
      22             :         #include <cpuid.h>
      23             :         #if !defined(__cpuid_count)  // Old Mac Clang doesn't have this defined.
      24             :             #define  __cpuid_count(eax, ecx, a, b, c, d) \
      25             :                 __asm__("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eax), "2"(ecx))
      26             :         #endif
      27           3 :         static void cpuid (uint32_t abcd[4]) { __get_cpuid(1, abcd+0, abcd+1, abcd+2, abcd+3); }
      28           3 :         static void cpuid7(uint32_t abcd[4]) {
      29           3 :             __cpuid_count(7, 0, abcd[0], abcd[1], abcd[2], abcd[3]);
      30           3 :         }
      31           6 :         static uint64_t xgetbv(uint32_t xcr) {
      32             :             uint32_t eax, edx;
      33           6 :             __asm__ __volatile__ ( "xgetbv" : "=a"(eax), "=d"(edx) : "c"(xcr));
      34           6 :             return (uint64_t)(edx) << 32 | eax;
      35             :         }
      36             :     #endif
      37             : 
      38           3 :     static uint32_t read_cpu_features() {
      39           3 :         uint32_t features = 0;
      40           3 :         uint32_t abcd[4] = {0,0,0,0};
      41             : 
      42             :         // You might want to refer to http://www.sandpile.org/x86/cpuid.htm
      43             : 
      44           3 :         cpuid(abcd);
      45           3 :         if (abcd[3] & (1<<25)) { features |= SkCpu:: SSE1; }
      46           3 :         if (abcd[3] & (1<<26)) { features |= SkCpu:: SSE2; }
      47           3 :         if (abcd[2] & (1<< 0)) { features |= SkCpu:: SSE3; }
      48           3 :         if (abcd[2] & (1<< 9)) { features |= SkCpu::SSSE3; }
      49           3 :         if (abcd[2] & (1<<19)) { features |= SkCpu::SSE41; }
      50           3 :         if (abcd[2] & (1<<20)) { features |= SkCpu::SSE42; }
      51             : 
      52           6 :         if ((abcd[2] & (3<<26)) == (3<<26)         // XSAVE + OSXSAVE
      53           3 :              && (xgetbv(0) & (3<<1)) == (3<<1)) {  // XMM and YMM state enabled.
      54           3 :             if (abcd[2] & (1<<28)) { features |= SkCpu:: AVX; }
      55           3 :             if (abcd[2] & (1<<29)) { features |= SkCpu::F16C; }
      56           3 :             if (abcd[2] & (1<<12)) { features |= SkCpu:: FMA; }
      57             : 
      58           3 :             cpuid7(abcd);
      59           3 :             if (abcd[1] & (1<<5)) { features |= SkCpu::AVX2; }
      60           3 :             if (abcd[1] & (1<<3)) { features |= SkCpu::BMI1; }
      61           3 :             if (abcd[1] & (1<<8)) { features |= SkCpu::BMI2; }
      62             : 
      63           3 :             if ((xgetbv(0) & (7<<5)) == (7<<5)) {  // All ZMM state bits enabled too.
      64           0 :                 if (abcd[1] & (1<<16)) { features |= SkCpu::AVX512F; }
      65           0 :                 if (abcd[1] & (1<<17)) { features |= SkCpu::AVX512DQ; }
      66           0 :                 if (abcd[1] & (1<<21)) { features |= SkCpu::AVX512IFMA; }
      67           0 :                 if (abcd[1] & (1<<26)) { features |= SkCpu::AVX512PF; }
      68           0 :                 if (abcd[1] & (1<<27)) { features |= SkCpu::AVX512ER; }
      69           0 :                 if (abcd[1] & (1<<28)) { features |= SkCpu::AVX512CD; }
      70           0 :                 if (abcd[1] & (1<<30)) { features |= SkCpu::AVX512BW; }
      71           0 :                 if (abcd[1] & (1<<31)) { features |= SkCpu::AVX512VL; }
      72             :             }
      73             :         }
      74           3 :         return features;
      75             :     }
      76             : 
      77             : #elif defined(SK_CPU_ARM64) && __has_include(<asm/hwcap.h>) && __has_include(<sys/auxv.h>)
      78             :     #include <asm/hwcap.h>
      79             :     #include <sys/auxv.h>
      80             : 
      81             :     static uint32_t read_cpu_features() {
      82             :         uint32_t features = 0;
      83             :         uint32_t hwcaps = getauxval(AT_HWCAP);
      84             :         if (hwcaps & HWCAP_CRC32) { features |= SkCpu::CRC32; }
      85             :         return features;
      86             :     }
      87             : 
      88             : #elif defined(SK_CPU_ARM32) && __has_include(<asm/hwcap.h>) && __has_include(<sys/auxv.h>)
      89             :     // asm/hwcap.h and sys/auxv.h won't be present on NDK builds before API v21.
      90             :     #include <asm/hwcap.h>
      91             :     #include <sys/auxv.h>
      92             : 
      93             :     static uint32_t read_cpu_features() {
      94             :         uint32_t features = 0;
      95             :         uint32_t hwcaps = getauxval(AT_HWCAP);
      96             :         if (hwcaps & HWCAP_VFPv4) { features |= SkCpu::NEON|SkCpu::NEON_FMA|SkCpu::VFP_FP16; }
      97             :         return features;
      98             :     }
      99             : 
     100             : #elif defined(SK_CPU_ARM32) && __has_include(<cpu-features.h>)
     101             :     #include <cpu-features.h>
     102             : 
     103             :     static uint32_t read_cpu_features() {
     104             :         uint32_t features = 0;
     105             :         uint64_t cpu_features = android_getCpuFeatures();
     106             :         if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON)     { features |= SkCpu::NEON; }
     107             :         if (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON_FMA) { features |= SkCpu::NEON_FMA; }
     108             :         if (cpu_features & ANDROID_CPU_ARM_FEATURE_VFP_FP16) { features |= SkCpu::VFP_FP16; }
     109             :         return features;
     110             :     }
     111             : 
     112             : #else
     113             :     static uint32_t read_cpu_features() {
     114             :         return 0;
     115             :     }
     116             : 
     117             : #endif
     118             : 
     119             : uint32_t SkCpu::gCachedFeatures = 0;
     120             : 
     121           3 : void SkCpu::CacheRuntimeFeatures() {
     122             :     static SkOnce once;
     123           6 :     once([] { gCachedFeatures = read_cpu_features(); });
     124           3 : }

Generated by: LCOV version 1.13