[libunwind] r274744 - [libunwind][ARM] Improve unwinder stack usage - Make WMMX support optional

Asiri Rathnayake via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 7 03:55:40 PDT 2016


Author: asiri
Date: Thu Jul  7 05:55:39 2016
New Revision: 274744

URL: http://llvm.org/viewvc/llvm-project?rev=274744&view=rev
Log:
[libunwind][ARM] Improve unwinder stack usage - Make WMMX support optional

These registers are only available on a limited set of ARM targets (those
based on XScale). Other targets should not have to pay the cost of these.

This patch shaves off about ~300 bytes of stack usage and ~1KB of code-size.

Differential revision: http://reviews.llvm.org/D21991
Reviewers: bcraig, compnerd

Change-Id: I2d7a1911a193bd70b123e78747e1a7d1482463c7

Modified:
    libunwind/trunk/CMakeLists.txt
    libunwind/trunk/include/__libunwind_config.h
    libunwind/trunk/src/Registers.hpp
    libunwind/trunk/src/Unwind-EHABI.cpp
    libunwind/trunk/src/UnwindRegistersRestore.S
    libunwind/trunk/src/UnwindRegistersSave.S

Modified: libunwind/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/CMakeLists.txt?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/CMakeLists.txt (original)
+++ libunwind/trunk/CMakeLists.txt Thu Jul  7 05:55:39 2016
@@ -105,6 +105,7 @@ option(LIBUNWIND_ENABLE_PEDANTIC "Compil
 option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
 option(LIBUNWIND_ENABLE_SHARED "Build libunwind as a shared library." ON)
 option(LIBUNWIND_ENABLE_CROSS_UNWINDING "Enable cross-platform unwinding support." OFF)
+option(LIBUNWIND_ENABLE_ARM_WMMX "Enable unwinding support for ARM WMMX registers." OFF)
 
 set(LIBUNWIND_TARGET_TRIPLE "" CACHE STRING "Target triple for cross compiling.")
 set(LIBUNWIND_GCC_TOOLCHAIN "" CACHE PATH "GCC toolchain for cross compiling.")
@@ -237,6 +238,15 @@ if (NOT LIBUNWIND_ENABLE_CROSS_UNWINDING
   list(APPEND LIBUNWIND_COMPILE_FLAGS -D_LIBUNWIND_IS_NATIVE_ONLY)
 endif ()
 
+# ARM WMMX register support
+if (LIBUNWIND_ENABLE_ARM_WMMX)
+  # __ARM_WMMX is a compiler pre-define (as per the ACLE 2.0). Clang does not
+  # define this macro for any supported target at present. Therefore, here we
+  # provide the option to explicitly enable support for WMMX registers in the
+  # unwinder.
+  list(APPEND LIBUNWIND_COMPILE_FLAGS -D__ARM_WMMX)
+endif ()
+
 # This is the _ONLY_ place where add_definitions is called.
 if (MSVC)
   add_definitions(-D_CRT_SECURE_NO_WARNINGS)

Modified: libunwind/trunk/include/__libunwind_config.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/include/__libunwind_config.h?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/include/__libunwind_config.h (original)
+++ libunwind/trunk/include/__libunwind_config.h Thu Jul  7 05:55:39 2016
@@ -36,8 +36,13 @@
 #  define _LIBUNWIND_CURSOR_SIZE 78
 # elif defined(__arm__)
 #  define _LIBUNWIND_TARGET_ARM 1
-#  define _LIBUNWIND_CONTEXT_SIZE 60
-#  define _LIBUNWIND_CURSOR_SIZE 67
+#  if defined(__ARM_WMMX)
+#    define _LIBUNWIND_CONTEXT_SIZE 60
+#    define _LIBUNWIND_CURSOR_SIZE 67
+#  else
+#    define _LIBUNWIND_CONTEXT_SIZE 42
+#    define _LIBUNWIND_CURSOR_SIZE 49
+#  endif
 # elif defined(__or1k__)
 #  define _LIBUNWIND_TARGET_OR1K 1
 #  define _LIBUNWIND_CONTEXT_SIZE 16

Modified: libunwind/trunk/src/Registers.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/Registers.hpp?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/src/Registers.hpp (original)
+++ libunwind/trunk/src/Registers.hpp Thu Jul  7 05:55:39 2016
@@ -1343,10 +1343,12 @@ public:
     }
     if (_saved_vfp_d16_d31)
       restoreVFPv3(_vfp_d16_d31);
+#if defined(__ARM_WMMX)
     if (_saved_iwmmx)
       restoreiWMMX(_iwmmx);
     if (_saved_iwmmx_control)
       restoreiWMMXControl(_iwmmx_control);
+#endif
   }
 
 private:
@@ -1360,13 +1362,15 @@ private:
   static void saveVFPWithFSTMD(unw_fpreg_t*);
   static void saveVFPWithFSTMX(unw_fpreg_t*);
   static void saveVFPv3(unw_fpreg_t*);
-  static void saveiWMMX(unw_fpreg_t*);
-  static void saveiWMMXControl(uint32_t*);
   static void restoreVFPWithFLDMD(unw_fpreg_t*);
   static void restoreVFPWithFLDMX(unw_fpreg_t*);
   static void restoreVFPv3(unw_fpreg_t*);
+#if defined(__ARM_WMMX)
+  static void saveiWMMX(unw_fpreg_t*);
+  static void saveiWMMXControl(uint32_t*);
   static void restoreiWMMX(unw_fpreg_t*);
   static void restoreiWMMXControl(uint32_t*);
+#endif
   void restoreCoreAndJumpTo();
 
   // ARM registers
@@ -1384,47 +1388,53 @@ private:
   bool _saved_vfp_d0_d15;
   // Whether VFPv3 D16-D31 are saved.
   bool _saved_vfp_d16_d31;
-  // Whether iWMMX data registers are saved.
-  bool _saved_iwmmx;
-  // Whether iWMMX control registers are saved.
-  bool _saved_iwmmx_control;
   // VFP registers D0-D15, + padding if saved using FSTMX
   unw_fpreg_t _vfp_d0_d15_pad[17];
   // VFPv3 registers D16-D31, always saved using FSTMD
   unw_fpreg_t _vfp_d16_d31[16];
+#if defined(__ARM_WMMX)
+  // Whether iWMMX data registers are saved.
+  bool _saved_iwmmx;
+  // Whether iWMMX control registers are saved.
+  bool _saved_iwmmx_control;
   // iWMMX registers
   unw_fpreg_t _iwmmx[16];
   // iWMMX control registers
   uint32_t _iwmmx_control[4];
+#endif
 };
 
 inline Registers_arm::Registers_arm(const void *registers)
   : _use_X_for_vfp_save(false),
     _saved_vfp_d0_d15(false),
-    _saved_vfp_d16_d31(false),
-    _saved_iwmmx(false),
-    _saved_iwmmx_control(false) {
+    _saved_vfp_d16_d31(false) {
   static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
                 "arm registers do not fit into unw_context_t");
   // See unw_getcontext() note about data.
   memcpy(&_registers, registers, sizeof(_registers));
   memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
   memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
+#if defined(__ARM_WMMX)
+  _saved_iwmmx = false;
+  _saved_iwmmx_control = false;
   memset(&_iwmmx, 0, sizeof(_iwmmx));
   memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
+#endif
 }
 
 inline Registers_arm::Registers_arm()
   : _use_X_for_vfp_save(false),
     _saved_vfp_d0_d15(false),
-    _saved_vfp_d16_d31(false),
-    _saved_iwmmx(false),
-    _saved_iwmmx_control(false) {
+    _saved_vfp_d16_d31(false) {
   memset(&_registers, 0, sizeof(_registers));
   memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
   memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
+#if defined(__ARM_WMMX)
+  _saved_iwmmx = false;
+  _saved_iwmmx_control = false;  
   memset(&_iwmmx, 0, sizeof(_iwmmx));
   memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
+#endif
 }
 
 inline bool Registers_arm::validRegister(int regNum) const {
@@ -1436,8 +1446,10 @@ inline bool Registers_arm::validRegister
     return true;
   if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
     return true;
+#if defined(__ARM_WMMX)
   if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
     return true;
+#endif
   return false;
 }
 
@@ -1450,6 +1462,7 @@ inline uint32_t Registers_arm::getRegist
     return _registers.__pc;
   if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
     return _registers.__r[regNum];
+#if defined(__ARM_WMMX)
   if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
     if (!_saved_iwmmx_control) {
       _saved_iwmmx_control = true;
@@ -1457,6 +1470,7 @@ inline uint32_t Registers_arm::getRegist
     }
     return _iwmmx_control[regNum - UNW_ARM_WC0];
   }
+#endif
   _LIBUNWIND_ABORT("unsupported arm register");
 }
 
@@ -1469,13 +1483,16 @@ inline void Registers_arm::setRegister(i
     _registers.__pc = value;
   else if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
     _registers.__r[regNum] = value;
+#if defined(__ARM_WMMX)
   else if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
     if (!_saved_iwmmx_control) {
       _saved_iwmmx_control = true;
       saveiWMMXControl(_iwmmx_control);
     }
     _iwmmx_control[regNum - UNW_ARM_WC0] = value;
-  } else
+  }
+#endif
+  else
     _LIBUNWIND_ABORT("unsupported arm register");
 }
 
@@ -1652,7 +1669,10 @@ inline bool Registers_arm::validFloatReg
   // NOTE: Consider the intel MMX registers floating points so the
   // unw_get_fpreg can be used to transmit the 64-bit data back.
   return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
-      || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15));
+#if defined(__ARM_WMMX)
+      || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
+#endif
+      ;
 }
 
 inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
@@ -1671,15 +1691,18 @@ inline unw_fpreg_t Registers_arm::getFlo
       saveVFPv3(_vfp_d16_d31);
     }
     return _vfp_d16_d31[regNum - UNW_ARM_D16];
-  } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
+  }
+#if defined(__ARM_WMMX)
+  else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
     if (!_saved_iwmmx) {
       _saved_iwmmx = true;
       saveiWMMX(_iwmmx);
     }
     return _iwmmx[regNum - UNW_ARM_WR0];
-  } else {
-    _LIBUNWIND_ABORT("Unknown ARM float register");
   }
+#endif
+  else
+    _LIBUNWIND_ABORT("Unknown ARM float register");
 }
 
 inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
@@ -1698,15 +1721,18 @@ inline void Registers_arm::setFloatRegis
       saveVFPv3(_vfp_d16_d31);
     }
     _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
-  } else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
+  }
+#if defined(__ARM_WMMX)
+  else if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
     if (!_saved_iwmmx) {
       _saved_iwmmx = true;
       saveiWMMX(_iwmmx);
     }
     _iwmmx[regNum - UNW_ARM_WR0] = value;
-  } else {
-    _LIBUNWIND_ABORT("Unknown ARM float register");
   }
+#endif
+  else
+    _LIBUNWIND_ABORT("Unknown ARM float register");
 }
 
 inline bool Registers_arm::validVectorRegister(int) const {

Modified: libunwind/trunk/src/Unwind-EHABI.cpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/Unwind-EHABI.cpp?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/src/Unwind-EHABI.cpp (original)
+++ libunwind/trunk/src/Unwind-EHABI.cpp Thu Jul  7 05:55:39 2016
@@ -351,6 +351,7 @@ _Unwind_Reason_Code _Unwind_VRS_Interpre
         }
         case 0xc0: {
           switch (byte) {
+#if defined(__ARM_WMMX)
             case 0xc0:
             case 0xc1:
             case 0xc2:
@@ -378,6 +379,7 @@ _Unwind_Reason_Code _Unwind_VRS_Interpre
               _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);
               break;
             }
+#endif
             case 0xc8:
             case 0xc9: {
               uint8_t v = getByte(data, offset++);
@@ -771,13 +773,6 @@ _Unwind_VRS_Set(_Unwind_Context *context
                          *(unw_word_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
-    case _UVRSC_WMMXC:
-      if (representation != _UVRSD_UINT32 || regno > 3)
-        return _UVRSR_FAILED;
-      return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
-                         *(unw_word_t *)valuep) == UNW_ESUCCESS
-                 ? _UVRSR_OK
-                 : _UVRSR_FAILED;
     case _UVRSC_VFP:
       if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
         return _UVRSR_FAILED;
@@ -794,6 +789,14 @@ _Unwind_VRS_Set(_Unwind_Context *context
                            *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
+#if defined(__ARM_WMMX)
+    case _UVRSC_WMMXC:
+      if (representation != _UVRSD_UINT32 || regno > 3)
+        return _UVRSR_FAILED;
+      return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
+                         *(unw_word_t *)valuep) == UNW_ESUCCESS
+                 ? _UVRSR_OK
+                 : _UVRSR_FAILED;
     case _UVRSC_WMMXD:
       if (representation != _UVRSD_DOUBLE || regno > 31)
         return _UVRSR_FAILED;
@@ -801,6 +804,7 @@ _Unwind_VRS_Set(_Unwind_Context *context
                            *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
+#endif
   }
   _LIBUNWIND_ABORT("unsupported register class");
 }
@@ -819,13 +823,6 @@ _Unwind_VRS_Get_Internal(_Unwind_Context
                          (unw_word_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
-    case _UVRSC_WMMXC:
-      if (representation != _UVRSD_UINT32 || regno > 3)
-        return _UVRSR_FAILED;
-      return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
-                         (unw_word_t *)valuep) == UNW_ESUCCESS
-                 ? _UVRSR_OK
-                 : _UVRSR_FAILED;
     case _UVRSC_VFP:
       if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
         return _UVRSR_FAILED;
@@ -842,6 +839,14 @@ _Unwind_VRS_Get_Internal(_Unwind_Context
                            (unw_fpreg_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
+#if defined(__ARM_WMMX)
+    case _UVRSC_WMMXC:
+      if (representation != _UVRSD_UINT32 || regno > 3)
+        return _UVRSR_FAILED;
+      return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
+                         (unw_word_t *)valuep) == UNW_ESUCCESS
+                 ? _UVRSR_OK
+                 : _UVRSR_FAILED;
     case _UVRSC_WMMXD:
       if (representation != _UVRSD_DOUBLE || regno > 31)
         return _UVRSR_FAILED;
@@ -849,6 +854,7 @@ _Unwind_VRS_Get_Internal(_Unwind_Context
                            (unw_fpreg_t *)valuep) == UNW_ESUCCESS
                  ? _UVRSR_OK
                  : _UVRSR_FAILED;
+#endif
   }
   _LIBUNWIND_ABORT("unsupported register class");
 }

Modified: libunwind/trunk/src/UnwindRegistersRestore.S
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindRegistersRestore.S?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindRegistersRestore.S (original)
+++ libunwind/trunk/src/UnwindRegistersRestore.S Thu Jul  7 05:55:39 2016
@@ -383,6 +383,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
   vldmia r0, {d16-d31}
   JMP(lr)
 
+#if defined(__ARM_WMMX)
+
 @
 @ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
 @
@@ -391,7 +393,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 @
   .p2align 2
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
   ldcl p1, cr0, [r0], #8  @ wldrd wR0, [r0], #8
   ldcl p1, cr1, [r0], #8  @ wldrd wR1, [r0], #8
   ldcl p1, cr2, [r0], #8  @ wldrd wR2, [r0], #8
@@ -408,7 +409,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
   ldcl p1, cr13, [r0], #8  @ wldrd wR13, [r0], #8
   ldcl p1, cr14, [r0], #8  @ wldrd wR14, [r0], #8
   ldcl p1, cr15, [r0], #8  @ wldrd wR15, [r0], #8
-#endif
   JMP(lr)
 
 @
@@ -419,14 +419,14 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 @
   .p2align 2
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
   ldc2 p1, cr8, [r0], #4  @ wldrw wCGR0, [r0], #4
   ldc2 p1, cr9, [r0], #4  @ wldrw wCGR1, [r0], #4
   ldc2 p1, cr10, [r0], #4  @ wldrw wCGR2, [r0], #4
   ldc2 p1, cr11, [r0], #4  @ wldrw wCGR3, [r0], #4
-#endif
   JMP(lr)
 
+#endif
+
 #elif defined(__or1k__)
 
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)

Modified: libunwind/trunk/src/UnwindRegistersSave.S
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindRegistersSave.S?rev=274744&r1=274743&r2=274744&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindRegistersSave.S (original)
+++ libunwind/trunk/src/UnwindRegistersSave.S Thu Jul  7 05:55:39 2016
@@ -378,6 +378,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
   vstmia r0, {d16-d31}
   JMP(lr)
 
+#if defined(_LIBUNWIND_ARM_WMMX)
+
 @
 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
 @
@@ -386,7 +388,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 @
   .p2align 2
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
@@ -403,7 +404,6 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
-#endif
   JMP(lr)
 
 @
@@ -414,14 +414,14 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
 @
   .p2align 2
 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
-#if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
-#endif
   JMP(lr)
 
+#endif
+
 #elif defined(__or1k__)
 
 #




More information about the cfe-commits mailing list