[compiler-rt] r357035 - [builtins] Rounding mode support for addxf3/subxf3

Yi Kong via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 26 15:01:22 PDT 2019


Author: kongyi
Date: Tue Mar 26 15:01:22 2019
New Revision: 357035

URL: http://llvm.org/viewvc/llvm-project?rev=357035&view=rev
Log:
[builtins] Rounding mode support for addxf3/subxf3

Implement rounding mode support for addxf3/subxf3.

On architectures that implemented the support, this will access the
corresponding floating point environment register to apply the
correct rounding. For other architectures, it will keep the current
behaviour and use IEEE-754 default rounding mode (to nearest, ties
to even).

ARM32/AArch64 support implemented in this change. i386 and AMD64
will be added in a follow up change.

Differential Revision: https://reviews.llvm.org/D57143

Added:
    compiler-rt/trunk/lib/builtins/aarch64/fp_mode.c
    compiler-rt/trunk/lib/builtins/arm/fp_mode.c
    compiler-rt/trunk/lib/builtins/fp_mode.c
    compiler-rt/trunk/lib/builtins/fp_mode.h
Modified:
    compiler-rt/trunk/lib/builtins/CMakeLists.txt
    compiler-rt/trunk/lib/builtins/adddf3.c
    compiler-rt/trunk/lib/builtins/addsf3.c
    compiler-rt/trunk/lib/builtins/addtf3.c
    compiler-rt/trunk/lib/builtins/fp_add_impl.inc
    compiler-rt/trunk/lib/builtins/subdf3.c
    compiler-rt/trunk/lib/builtins/subsf3.c
    compiler-rt/trunk/lib/builtins/subtf3.c
    compiler-rt/trunk/test/builtins/Unit/addtf3_test.c
    compiler-rt/trunk/test/builtins/Unit/subtf3_test.c

Modified: compiler-rt/trunk/lib/builtins/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/CMakeLists.txt?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/builtins/CMakeLists.txt Tue Mar 26 15:01:22 2019
@@ -94,6 +94,7 @@ set(GENERIC_SOURCES
   floatunsisf.c
   floatuntidf.c
   floatuntisf.c
+  fp_mode.c
   int_util.c
   lshrdi3.c
   lshrti3.c
@@ -290,6 +291,7 @@ set(i386_SOURCES ${i386_SOURCES} ${x86_A
 set(i686_SOURCES ${i686_SOURCES} ${x86_ARCH_SOURCES})
 
 set(arm_SOURCES
+  arm/fp_mode.c
   arm/bswapdi2.S
   arm/bswapsi2.S
   arm/clzdi2.S
@@ -441,7 +443,8 @@ endif()
 
 set(aarch64_SOURCES
   ${GENERIC_TF_SOURCES}
-  ${GENERIC_SOURCES})
+  ${GENERIC_SOURCES}
+  aarch64/fp_mode.c)
 
 if (MINGW)
   set(aarch64_SOURCES

Added: compiler-rt/trunk/lib/builtins/aarch64/fp_mode.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/aarch64/fp_mode.c?rev=357035&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/aarch64/fp_mode.c (added)
+++ compiler-rt/trunk/lib/builtins/aarch64/fp_mode.c Tue Mar 26 15:01:22 2019
@@ -0,0 +1,59 @@
+//===----- lib/aarch64/fp_mode.c - Floaing-point mode utilities ---*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+
+#include "../fp_mode.h"
+
+#define AARCH64_TONEAREST  0x0
+#define AARCH64_UPWARD     0x1
+#define AARCH64_DOWNWARD   0x2
+#define AARCH64_TOWARDZERO 0x3
+#define AARCH64_RMODE_MASK (AARCH64_TONEAREST | AARCH64_UPWARD | \
+                            AARCH64_DOWNWARD | AARCH64_TOWARDZERO)
+#define AARCH64_RMODE_SHIFT 22
+
+#define AARCH64_INEXACT     0x10
+
+#ifndef __ARM_FP
+// For soft float targets, allow changing rounding mode by overriding the weak
+// __aarch64_fe_default_rmode symbol.
+FE_ROUND_MODE __attribute__((weak)) __aarch64_fe_default_rmode = FE_TONEAREST;
+#endif
+
+FE_ROUND_MODE __fe_getround() {
+#ifdef __ARM_FP
+  uint64_t fpcr;
+  __asm__ __volatile__("mrs  %0, fpcr" : "=r" (fpcr));
+  fpcr = fpcr >> AARCH64_RMODE_SHIFT & AARCH64_RMODE_MASK;
+  switch (fpcr) {
+    case AARCH64_UPWARD:
+      return FE_UPWARD;
+    case AARCH64_DOWNWARD:
+      return FE_DOWNWARD;
+    case AARCH64_TOWARDZERO:
+      return FE_TOWARDZERO;
+    case AARCH64_TONEAREST:
+    default:
+      return FE_TONEAREST;
+  }
+#else
+  return __aarch64_fe_default_rmode;
+#endif
+}
+
+int __fe_raise_inexact() {
+#ifdef __ARM_FP
+  uint64_t fpsr;
+  __asm__ __volatile__("mrs  %0, fpsr" : "=r" (fpsr));
+  __asm__ __volatile__("msr  fpsr, %0" : : "ri" (fpsr | AARCH64_INEXACT));
+  return 0;
+#else
+  return 0;
+#endif
+}

Modified: compiler-rt/trunk/lib/builtins/adddf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/adddf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/adddf3.c (original)
+++ compiler-rt/trunk/lib/builtins/adddf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements double-precision soft-float addition with the IEEE-754
-// default rounding (to nearest, ties to even).
+// This file implements double-precision soft-float addition.
 //
 //===----------------------------------------------------------------------===//
 

Modified: compiler-rt/trunk/lib/builtins/addsf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/addsf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/addsf3.c (original)
+++ compiler-rt/trunk/lib/builtins/addsf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements single-precision soft-float addition with the IEEE-754
-// default rounding (to nearest, ties to even).
+// This file implements single-precision soft-float addition.
 //
 //===----------------------------------------------------------------------===//
 

Modified: compiler-rt/trunk/lib/builtins/addtf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/addtf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/addtf3.c (original)
+++ compiler-rt/trunk/lib/builtins/addtf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements quad-precision soft-float addition with the IEEE-754
-// default rounding (to nearest, ties to even).
+// This file implements quad-precision soft-float addition.
 //
 //===----------------------------------------------------------------------===//
 

Added: compiler-rt/trunk/lib/builtins/arm/fp_mode.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/arm/fp_mode.c?rev=357035&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/arm/fp_mode.c (added)
+++ compiler-rt/trunk/lib/builtins/arm/fp_mode.c Tue Mar 26 15:01:22 2019
@@ -0,0 +1,59 @@
+//===----- lib/arm/fp_mode.c - Floaing-point mode utilities -------*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdint.h>
+
+#include "../fp_mode.h"
+
+#define ARM_TONEAREST  0x0
+#define ARM_UPWARD     0x1
+#define ARM_DOWNWARD   0x2
+#define ARM_TOWARDZERO 0x3
+#define ARM_RMODE_MASK (ARM_TONEAREST | ARM_UPWARD | \
+                        ARM_DOWNWARD | ARM_TOWARDZERO)
+#define ARM_RMODE_SHIFT 22
+
+#define ARM_INEXACT     0x1000
+
+#ifndef __ARM_FP
+// For soft float targets, allow changing rounding mode by overriding the weak
+// __arm_fe_default_rmode symbol.
+FE_ROUND_MODE __attribute__((weak)) __arm_fe_default_rmode = FE_TONEAREST;
+#endif
+
+FE_ROUND_MODE __fe_getround() {
+#ifdef __ARM_FP
+  uint32_t fpscr;
+  __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
+  fpscr = fpscr >> ARM_RMODE_SHIFT & ARM_RMODE_MASK;
+  switch (fpscr) {
+    case ARM_UPWARD:
+      return FE_UPWARD;
+    case ARM_DOWNWARD:
+      return FE_DOWNWARD;
+    case ARM_TOWARDZERO:
+      return FE_TOWARDZERO;
+    case ARM_TONEAREST:
+    default:
+      return FE_TONEAREST;
+  }
+#else
+  return __arm_fe_default_rmode;
+#endif
+}
+
+int __fe_raise_inexact() {
+#ifdef __ARM_FP
+  uint32_t fpscr;
+  __asm__ __volatile__("vmrs  %0, fpscr" : "=r" (fpscr));
+  __asm__ __volatile__("vmsr  fpscr, %0" : : "ri" (fpscr | ARM_INEXACT));
+  return 0;
+#else
+  return 0;
+#endif
+}

Modified: compiler-rt/trunk/lib/builtins/fp_add_impl.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/fp_add_impl.inc?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/fp_add_impl.inc (original)
+++ compiler-rt/trunk/lib/builtins/fp_add_impl.inc Tue Mar 26 15:01:22 2019
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "fp_lib.h"
+#include "fp_mode.h"
 
 static __inline fp_t __addXf3__(fp_t a, fp_t b) {
     rep_t aRep = toRep(a);
@@ -137,7 +138,21 @@ static __inline fp_t __addXf3__(fp_t a,
 
     // Final rounding.  The result may overflow to infinity, but that is the
     // correct result in that case.
-    if (roundGuardSticky > 0x4) result++;
-    if (roundGuardSticky == 0x4) result += result & 1;
+    switch (__fe_getround()){
+    case FE_TONEAREST:
+      if (roundGuardSticky > 0x4) result++;
+      if (roundGuardSticky == 0x4) result += result & 1;
+      break;
+    case FE_DOWNWARD:
+      if (resultSign && roundGuardSticky) result++;
+      break;
+    case FE_UPWARD:
+      if (!resultSign && roundGuardSticky) result++;
+      break;
+    case FE_TOWARDZERO:
+      break;
+    }
+    if (roundGuardSticky)
+      __fe_raise_inexact();
     return fromRep(result);
 }

Added: compiler-rt/trunk/lib/builtins/fp_mode.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/fp_mode.c?rev=357035&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/fp_mode.c (added)
+++ compiler-rt/trunk/lib/builtins/fp_mode.c Tue Mar 26 15:01:22 2019
@@ -0,0 +1,24 @@
+//===----- lib/fp_mode.c - Floaing-point environment mode utilities --C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a default implementation of fp_mode.h for architectures
+// that does not support or does not have an implementation of floating point
+// environment mode.
+//
+//===----------------------------------------------------------------------===//
+
+#include "fp_mode.h"
+
+// IEEE-754 default rounding (to nearest, ties to even).
+FE_ROUND_MODE __fe_getround() {
+  return FE_TONEAREST;
+}
+
+int __fe_raise_inexact() {
+  return 0;
+}

Added: compiler-rt/trunk/lib/builtins/fp_mode.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/fp_mode.h?rev=357035&view=auto
==============================================================================
--- compiler-rt/trunk/lib/builtins/fp_mode.h (added)
+++ compiler-rt/trunk/lib/builtins/fp_mode.h Tue Mar 26 15:01:22 2019
@@ -0,0 +1,29 @@
+//===----- lib/fp_mode.h - Floaing-point environment mode utilities --C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is not part of the interface of this library.
+//
+// This file defines an interface for accessing hardware floating point
+// environment mode.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FP_MODE
+#define FP_MODE
+
+typedef enum {
+  FE_TONEAREST,
+  FE_DOWNWARD,
+  FE_UPWARD,
+  FE_TOWARDZERO
+} FE_ROUND_MODE;
+
+FE_ROUND_MODE __fe_getround();
+int __fe_raise_inexact();
+
+#endif // FP_MODE_H

Modified: compiler-rt/trunk/lib/builtins/subdf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/subdf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/subdf3.c (original)
+++ compiler-rt/trunk/lib/builtins/subdf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements double-precision soft-float subtraction with the
-// IEEE-754 default rounding (to nearest, ties to even).
+// This file implements double-precision soft-float subtraction.
 //
 //===----------------------------------------------------------------------===//
 

Modified: compiler-rt/trunk/lib/builtins/subsf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/subsf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/subsf3.c (original)
+++ compiler-rt/trunk/lib/builtins/subsf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements single-precision soft-float subtraction with the
-// IEEE-754 default rounding (to nearest, ties to even).
+// This file implements single-precision soft-float subtraction.
 //
 //===----------------------------------------------------------------------===//
 

Modified: compiler-rt/trunk/lib/builtins/subtf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/subtf3.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/subtf3.c (original)
+++ compiler-rt/trunk/lib/builtins/subtf3.c Tue Mar 26 15:01:22 2019
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements quad-precision soft-float subtraction with the
-// IEEE-754 default rounding (to nearest, ties to even).
+// This file implements quad-precision soft-float subtraction.
 //
 //===----------------------------------------------------------------------===//
 

Modified: compiler-rt/trunk/test/builtins/Unit/addtf3_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/addtf3_test.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/addtf3_test.c (original)
+++ compiler-rt/trunk/test/builtins/Unit/addtf3_test.c Tue Mar 26 15:01:22 2019
@@ -11,11 +11,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "int_lib.h"
+#include <fenv.h>
 #include <stdio.h>
 
 #if __LDBL_MANT_DIG__ == 113
 
+#include "int_lib.h"
 #include "fp_test.h"
 
 // Returns: a + b
@@ -74,6 +75,26 @@ int main()
                      UINT64_C(0x61e58dd6c51eb77c)))
         return 1;
 
+#if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP)
+    // Rounding mode tests on supported architectures
+    long double m = 1234.0L, n = 0.01L;
+    fesetround(FE_UPWARD);
+    if (__addtf3(m, n) != 1235.0L)
+        return 1;
+
+    fesetround(FE_DOWNWARD);
+    if (__addtf3(m, n) != 1234.0L)
+        return 1;
+
+    fesetround(FE_TOWARDZERO);
+    if (__addtf3(m, n) != 1234.0L)
+        return 1;
+
+    fesetround(FE_TONEAREST);
+    if (__addtf3(m, n) != 1234.0L)
+        return 1;
+#endif
+
 #else
     printf("skipped\n");
 

Modified: compiler-rt/trunk/test/builtins/Unit/subtf3_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/subtf3_test.c?rev=357035&r1=357034&r2=357035&view=diff
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/subtf3_test.c (original)
+++ compiler-rt/trunk/test/builtins/Unit/subtf3_test.c Tue Mar 26 15:01:22 2019
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <fenv.h>
 #include <stdio.h>
 
 #if __LDBL_MANT_DIG__ == 113
@@ -67,6 +68,26 @@ int main()
                      UINT64_C(0xa44a7bca780a166c)))
         return 1;
 
+#if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP)
+    // Rounding mode tests on supported architectures
+    long double m = 1234.0L, n = 0.01L;
+    fesetround(FE_UPWARD);
+    if (__subtf3(m, n) != 1234.0L)
+        return 1;
+
+    fesetround(FE_DOWNWARD);
+    if (__subtf3(m, n) != 1233.0L)
+        return 1;
+
+    fesetround(FE_TOWARDZERO);
+    if (__subtf3(m, n) != 1233.0L)
+        return 1;
+
+    fesetround(FE_TONEAREST);
+    if (__subtf3(m, n) != 1234.0L)
+        return 1;
+#endif
+
 #else
     printf("skipped\n");
 




More information about the llvm-commits mailing list