1 /* 2 * Copyright (C) 2011, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #ifndef DenormalDisabler_h 26 #define DenormalDisabler_h 27 28 #include "wtf/CPU.h" 29 #include "wtf/MathExtras.h" 30 #include <float.h> 31 32 namespace WebCore { 33 34 // Deal with denormals. They can very seriously impact performance on x86. 35 36 // Define HAVE_DENORMAL if we support flushing denormals to zero. 37 #if OS(WIN) && COMPILER(MSVC) 38 #define HAVE_DENORMAL 1 39 #endif 40 41 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) 42 #define HAVE_DENORMAL 1 43 #endif 44 45 #if HAVE(DENORMAL) 46 class DenormalDisabler { 47 public: DenormalDisabler()48 DenormalDisabler() 49 : m_savedCSR(0) 50 { 51 #if OS(WIN) && COMPILER(MSVC) 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 int unused; 57 _controlfp_s(&unused, _DN_FLUSH, _MCW_DN); 58 #else 59 m_savedCSR = getCSR(); 60 setCSR(m_savedCSR | 0x8040); 61 #endif 62 } 63 ~DenormalDisabler()64 ~DenormalDisabler() 65 { 66 #if OS(WIN) && COMPILER(MSVC) 67 unsigned int unused; 68 _controlfp_s(&unused, m_savedCSR, _MCW_DN); 69 #else 70 setCSR(m_savedCSR); 71 #endif 72 } 73 74 // This is a nop if we can flush denormals to zero in hardware. flushDenormalFloatToZero(float f)75 static inline float flushDenormalFloatToZero(float f) 76 { 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; 84 #endif 85 } 86 private: 87 #if COMPILER(GCC) && (CPU(X86) || CPU(X86_64)) getCSR()88 inline int getCSR() 89 { 90 int result; 91 asm volatile("stmxcsr %0" : "=m" (result)); 92 return result; 93 } 94 setCSR(int a)95 inline void setCSR(int a) 96 { 97 int temp = a; 98 asm volatile("ldmxcsr %0" : : "m" (temp)); 99 } 100 101 #endif 102 103 unsigned int m_savedCSR; 104 }; 105 106 #else 107 // FIXME: add implementations for other architectures and compilers 108 class DenormalDisabler { 109 public: 110 DenormalDisabler() { } 111 112 // Assume the worst case that other architectures and compilers 113 // need to flush denormals to zero manually. 114 static inline float flushDenormalFloatToZero(float f) 115 { 116 return (fabs(f) < FLT_MIN) ? 0.0f : f; 117 } 118 }; 119 120 #endif 121 122 } // WebCore 123 124 #undef HAVE_DENORMAL 125 #endif // DenormalDisabler_h 126