aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkUtilsArm.cpp
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2016-04-14 09:03:35 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-14 09:03:35 -0700
commit872ea29357439f05b1f6995dd300fc054733e607 (patch)
tree66894036c118ebcf0c481ee0f281a55554d156b5 /src/core/SkUtilsArm.cpp
parent3dc6aac5da2dbeb56cda025f3699cad72e1a4b4e (diff)
Move CPU feature detection to its own file.
- Moves CPU feature detection to its own file. - Cleans up some redundant feature detection scattered around core/ and opts/. - Can now detect a few new CPU features: * F16C -> Intel f16<->f32 instructions, added between AVX and AVX2 * FMA -> Intel FMA instructions, added at the same time as AVX2 * VFP_FP16 -> ARM f16<->f32 instructions, quite common * NEON_FMA -> ARM FMA instructions, also quite common * SSE and SSE3... why not? This new internal API makes it very cheap to do fine-grained runtime CPU feature detection. Redundant calls to SkCpu::Supports() should be eliminated and it's hoistable out of loops. It compiles away entirely when we have the appropriate instructions available at compile time. This means we can call it to guard even a little snippet of 1 or 2 instructions right where needed and let inlining hoist the check (if any at all) up to somewhere that doesn't hurt performance. I've explained how I made this work in the private section of the new header. Once this lands and bakes a bit, I'll start following up with CLs to use it more and to add a bunch of those little 1-2 instruction snippets we've been wanting, e.g. cvtps2ph, cvtph2ps, ptest, pmulld, pmovzxbd, blendvps, pshufb, roundps (for floor) on x86, and vcvt.f32.f16, vcvt.f16.f32 on ARM. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1890483002 CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Review URL: https://codereview.chromium.org/1890483002
Diffstat (limited to 'src/core/SkUtilsArm.cpp')
-rw-r--r--src/core/SkUtilsArm.cpp139
1 files changed, 1 insertions, 138 deletions
diff --git a/src/core/SkUtilsArm.cpp b/src/core/SkUtilsArm.cpp
index bf98fed476..c29938fdfc 100644
--- a/src/core/SkUtilsArm.cpp
+++ b/src/core/SkUtilsArm.cpp
@@ -5,141 +5,4 @@
* found in the LICENSE file.
*/
-#include "SkUtilsArm.h"
-
-#if SK_ARM_NEON_IS_DYNAMIC
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <pthread.h>
-
-#if defined(SK_BUILD_FOR_ANDROID)
-# include <cpu-features.h>
-#endif
-
-// A function used to determine at runtime if the target CPU supports
-// the ARM NEON instruction set. This implementation is Linux-specific.
-static bool sk_cpu_arm_check_neon(void) {
- // If we fail any of the following, assume we don't have NEON instructions
- // This allows us to return immediately in case of error.
- bool result = false;
-
-// Use the Android NDK's cpu-features helper library to detect NEON at runtime.
-// See http://crbug.com/164154 to see why this is needed in Chromium for Android.
-#ifdef SK_BUILD_FOR_ANDROID
-
- result = (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
-
-#else // SK_BUILD_FOR_ANDROID
-
- // There is no user-accessible CPUID instruction on ARM that we can use.
- // Instead, we must parse /proc/cpuinfo and look for the 'neon' feature.
- // For example, here's a typical output (Nexus S running ICS 4.0.3):
- /*
- Processor : ARMv7 Processor rev 2 (v7l)
- BogoMIPS : 994.65
- Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3
- CPU implementer : 0x41
- CPU architecture: 7
- CPU variant : 0x2
- CPU part : 0xc08
- CPU revision : 2
-
- Hardware : herring
- Revision : 000b
- Serial : 3833c77d6dc000ec
- */
- char buffer[4096];
-
- do {
- // open /proc/cpuinfo
- int fd = TEMP_FAILURE_RETRY(open("/proc/cpuinfo", O_RDONLY));
- if (fd < 0) {
- SkDebugf("Could not open /proc/cpuinfo: %s\n", strerror(errno));
- break;
- }
-
- // Read the file. To simplify our search, we're going to place two
- // sentinel '\n' characters: one at the start of the buffer, and one at
- // the end. This means we reserve the first and last buffer bytes.
- buffer[0] = '\n';
- int size = TEMP_FAILURE_RETRY(read(fd, buffer+1, sizeof(buffer)-2));
- close(fd);
-
- if (size < 0) { // should not happen
- SkDebugf("Could not read /proc/cpuinfo: %s\n", strerror(errno));
- break;
- }
-
- SkDebugf("START /proc/cpuinfo:\n%.*s\nEND /proc/cpuinfo\n",
- size, buffer+1);
-
- // Compute buffer limit, and place final sentinel
- char* buffer_end = buffer + 1 + size;
- buffer_end[0] = '\n';
-
- // Now, find a line that starts with "Features", i.e. look for
- // '\nFeatures ' in our buffer.
- const char features[] = "\nFeatures\t";
- const size_t features_len = sizeof(features)-1;
-
- char* line = (char*) memmem(buffer, buffer_end - buffer,
- features, features_len);
- if (line == nullptr) { // Weird, no Features line, bad kernel?
- SkDebugf("Could not find a line starting with 'Features'"
- "in /proc/cpuinfo ?\n");
- break;
- }
-
- line += features_len; // Skip the "\nFeatures\t" prefix
-
- // Find the end of the current line
- char* line_end = (char*) memchr(line, '\n', buffer_end - line);
- if (line_end == nullptr)
- line_end = buffer_end;
-
- // Now find an instance of 'neon' in the flags list. We want to
- // ensure it's only 'neon' and not something fancy like 'noneon'
- // so check that it follows a space.
- const char neon[] = " neon";
- const size_t neon_len = sizeof(neon)-1;
- const char* flag = (const char*) memmem(line, line_end - line,
- neon, neon_len);
- if (flag == nullptr)
- break;
-
- // Ensure it is followed by a space or a newline.
- if (flag[neon_len] != ' ' && flag[neon_len] != '\n')
- break;
-
- // Fine, we support Arm NEON !
- result = true;
-
- } while (0);
-
-#endif // SK_BUILD_FOR_ANDROID
-
- if (result) {
- SkDEBUGF(("Device supports ARM NEON instructions!\n"));
- } else {
- SkDEBUGF(("Device does NOT support ARM NEON instructions!\n"));
- }
- return result;
-}
-
-static pthread_once_t sOnce;
-static bool sHasArmNeon;
-
-// called through pthread_once()
-void sk_cpu_arm_probe_features(void) {
- sHasArmNeon = sk_cpu_arm_check_neon();
-}
-
-bool sk_cpu_arm_has_neon(void) {
- pthread_once(&sOnce, sk_cpu_arm_probe_features);
- return sHasArmNeon;
-}
-
-#endif // SK_ARM_NEON_IS_DYNAMIC
+// This file no longer needs to exist, but it's still referenced by Chrome's GYP / GN builds.