Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: Source/platform/audio/DenormalDisabler.h

Issue 402803003: Flush denormals to zero on arm and arm64. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011, Google Inc. All rights reserved. 2 * Copyright (C) 2011, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 16 matching lines...) Expand all
27 27
28 #include "wtf/CPU.h" 28 #include "wtf/CPU.h"
29 #include "wtf/MathExtras.h" 29 #include "wtf/MathExtras.h"
30 #include <float.h> 30 #include <float.h>
31 31
32 namespace WebCore { 32 namespace WebCore {
33 33
34 // Deal with denormals. They can very seriously impact performance on x86. 34 // Deal with denormals. They can very seriously impact performance on x86.
35 35
36 // Define HAVE_DENORMAL if we support flushing denormals to zero. 36 // Define HAVE_DENORMAL if we support flushing denormals to zero.
37
37 #if OS(WIN) && COMPILER(MSVC) 38 #if OS(WIN) && COMPILER(MSVC)
39 // Windows compiled using MSVC with SSE2
38 #define HAVE_DENORMAL 1 40 #define HAVE_DENORMAL 1
39 #endif 41 #endif
40 42
41 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) 43 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64))
44 // X86 chips can flush denormals
42 #define HAVE_DENORMAL 1 45 #define HAVE_DENORMAL 1
43 #endif 46 #endif
44 47
48 #if CPU(ARM) || CPU(ARM64)
49 #define HAVE_DENORMAL 1
50 #endif
51
45 #if HAVE(DENORMAL) 52 #if HAVE(DENORMAL)
46 class DenormalDisabler { 53 class DenormalDisabler {
47 public: 54 public:
48 DenormalDisabler() 55 DenormalDisabler()
49 : m_savedCSR(0) 56 : m_savedCSR(0)
50 { 57 {
51 #if OS(WIN) && COMPILER(MSVC) 58 disableDenormals();
52 // Save the current state, and set mode to flush denormals.
53 //
54 // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s -may-not-restore-control-word-correctly
55 _controlfp_s(&m_savedCSR, 0, 0);
56 unsigned unused;
57 _controlfp_s(&unused, _DN_FLUSH, _MCW_DN);
58 #else
59 m_savedCSR = getCSR();
60 setCSR(m_savedCSR | 0x8040);
61 #endif
62 } 59 }
63 60
64 ~DenormalDisabler() 61 ~DenormalDisabler()
65 { 62 {
66 #if OS(WIN) && COMPILER(MSVC) 63 restoreState();
67 unsigned unused;
68 _controlfp_s(&unused, m_savedCSR, _MCW_DN);
69 #else
70 setCSR(m_savedCSR);
71 #endif
72 } 64 }
73 65
74 // This is a nop if we can flush denormals to zero in hardware. 66 // This is a nop if we can flush denormals to zero in hardware.
75 static inline float flushDenormalFloatToZero(float f) 67 static inline float flushDenormalFloatToZero(float f)
76 { 68 {
77 #if OS(WIN) && COMPILER(MSVC) && (!_M_IX86_FP)
78 // For systems using x87 instead of sse, there's no hardware support
79 // to flush denormals automatically. Hence, we need to flush
80 // denormals to zero manually.
81 return (fabs(f) < FLT_MIN) ? 0.0f : f;
82 #else
83 return f; 69 return f;
84 #endif
85 } 70 }
86 private: 71 private:
72 unsigned m_savedCSR;
73
87 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) 74 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64))
75 inline void disableDenormals()
76 {
77 m_savedCSR = getCSR();
78 setCSR(m_savedCSR | 0x8040);
79 }
80
81 inline void restoreState()
82 {
83 setCSR(m_savedCSR);
84 }
85
88 inline int getCSR() 86 inline int getCSR()
89 { 87 {
90 int result; 88 int result;
91 asm volatile("stmxcsr %0" : "=m" (result)); 89 asm volatile("stmxcsr %0" : "=m" (result));
92 return result; 90 return result;
93 } 91 }
94 92
95 inline void setCSR(int a) 93 inline void setCSR(int a)
96 { 94 {
97 int temp = a; 95 int temp = a;
98 asm volatile("ldmxcsr %0" : : "m" (temp)); 96 asm volatile("ldmxcsr %0" : : "m" (temp));
99 } 97 }
100 98
99 #elif OS(WIN) && COMPILER(MSVC)
100 inline void disableDenormals()
101 {
102 // Save the current state, and set mode to flush denormals.
103 //
104 // http://stackoverflow.com/questions/637175/possible-bug-in-controlfp-s -may-not-restore-control-word-correctly
105 _controlfp_s(&m_savedCSR, 0, 0);
106 unsigned unused;
107 _controlfp_s(&unused, _DN_FLUSH, _MCW_DN);
108 }
109
110 inline void restoreState()
111 {
112 unsigned unused;
113 _controlfp_s(&unused, m_savedCSR, _MCW_DN);
114 }
115 #elif CPU(ARM) || CPU(ARM64)
116 inline void disableDenormals()
117 {
118 m_savedCSR = getStatusWord();
119 // Bit 24 is the flush-to-zero mode control bit. Setting it to 1 flushes denormals to 0.
120 setStatusWord(m_savedCSR | (1 << 24));
121 }
122
123 inline void restoreState()
124 {
125 setStatusWord(m_savedCSR);
126 }
127
128 inline int getStatusWord()
129 {
130 int result;
131 #if CPU(ARM64)
132 asm volatile("mrs %[result], FPCR" : [result] "=r" (result));
133 #else
134 asm volatile("vmrs %[result], FPSCR" : [result] "=r" (result));
135 #endif
136 return result;
137 }
138
139 inline void setStatusWord(int a)
140 {
141 #if CPU(ARM64)
142 asm volatile("msr FPCR, %[src]" : : [src] "r" (a));
143 #else
144 asm volatile("vmsr FPSCR, %[src]" : : [src] "r" (a));
145 #endif
146 }
147
101 #endif 148 #endif
102 149
103 unsigned m_savedCSR;
104 }; 150 };
105 151
106 #else 152 #else
107 // FIXME: add implementations for other architectures and compilers 153 // FIXME: add implementations for other architectures and compilers
108 class DenormalDisabler { 154 class DenormalDisabler {
109 public: 155 public:
110 DenormalDisabler() { } 156 DenormalDisabler() { }
111 157
112 // Assume the worst case that other architectures and compilers 158 // Assume the worst case that other architectures and compilers
113 // need to flush denormals to zero manually. 159 // need to flush denormals to zero manually.
114 static inline float flushDenormalFloatToZero(float f) 160 static inline float flushDenormalFloatToZero(float f)
115 { 161 {
116 return (fabs(f) < FLT_MIN) ? 0.0f : f; 162 return (fabs(f) < FLT_MIN) ? 0.0f : f;
117 } 163 }
118 }; 164 };
119 165
120 #endif 166 #endif
121 167
122 } // WebCore 168 } // WebCore
123 169
124 #undef HAVE_DENORMAL 170 #undef HAVE_DENORMAL
125 #endif // DenormalDisabler_h 171 #endif // DenormalDisabler_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698