Hi all, new to the list.

Attached is a very short patch which enables the use of fixed point
modes on x86 targets. I first created this a couple of years ago for
gcc 7 and have just updated it for current git master.

I have not sent this to the patches list as I do not expect it to be
anywhere near merge-ready. Rather, I was hoping to have a conversation
about what is missing and what else might need to be done for fixed
point modes to become officially supported on x86, or whether that's
even desirable.

My initial motivation for this was that we have a C codebase primarily
written for an embedded ARM target with no FPU, which makes extensive
use of the fract/accum types available on that target. To simplify
development we wanted to be able to build & test this code on
x86 systems. Performance (on x86) was not a concern for us.

Although I had no prior knowlede of gcc internals/development I started
looking at what might be needed to enable fixed point support on x86,
and it seems like very little is needed for it to work:

gcc/config/i386/i386.c:

- classify_argument() needs to classify the *Q and *A modes as per their
  corresponding integer modes.

- ix86_scalar_mode_supported_p needs to forward to
  default_fixed_point_supported_p for ALL_SCALAR_FIXED_POINT_MODE_P.

gcc/configure[.ac]:

- allow --enable-fixed-point for i?86* and x86_64*

With these changes, everything seems to "just work". The fixed point
helper functions in libgcc/fixed-bit.c are built automatically for all
the possible mode combinations, and get linked in as needed by the
resulting compiler. The tests in gcc/testsuite/gcc.dg/fixed-point pass.

Of course, everything is emulated - no special instruction sequences are
generated, and the resulting code is probably no faster than could be
achieved using libfixmath or similar libraries.

But even without a performance advantage this is useful - it allows
compatibility with fixed point code written for other platforms, and
enables fixed point code to be written more clearly on x86, by use of
special types rather than library functions.

I am guessing however that there is a lot more that needs to be thought
about before anything like this could be merged.

For starters, by doing this I have implicitly invented an ABI for fixed
point types on x86 (they get passed exactly like correspondingly-sized
integers, I suppose). This ABI would be unique to gcc.

I have also implicitly set the numbers of integral and fractional bits
for each mode to the gcc defaults (which are specified in the docs at
https://gcc.gnu.org/onlinedocs/gccint/Machine-Modes.html).

I don't know the x86 instruction set (and its many extensions) well, and
haven't thought about how fixed point operations could be implemented
most efficiently with it, and whether that would affect the choice of
format for each mode.

And yet, this works and is useful (to us at least).

What else have I missed? What else would be needed for this to be
supported? And does anyone see any value in adding this, or should I
just keep this to myself as an out of tree patch?

Regards,


Martin
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9a87413ee..aa8fb910c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2300,6 +2300,20 @@ classify_argument (machine_mode mode, const_tree type,
     case E_CSImode:
     case E_CHImode:
     case E_CQImode:
+    case E_QQmode:
+    case E_UQQmode:
+    case E_HQmode:
+    case E_UHQmode:
+    case E_SQmode:
+    case E_USQmode:
+    case E_DQmode:
+    case E_UDQmode:
+    case E_HAmode:
+    case E_UHAmode:
+    case E_SAmode:
+    case E_USAmode:
+    case E_DAmode:
+    case E_UDAmode:
       {
 	int size = bit_offset + (int) GET_MODE_BITSIZE (mode);
 
@@ -2332,6 +2346,10 @@ classify_argument (machine_mode mode, const_tree type,
       }
     case E_CDImode:
     case E_TImode:
+    case E_TQmode:
+    case E_UTQmode:
+    case E_TAmode:
+    case E_UTAmode:
       classes[0] = classes[1] = X86_64_INTEGER_CLASS;
       return 2;
     case E_COImode:
@@ -20618,6 +20636,8 @@ ix86_scalar_mode_supported_p (scalar_mode mode)
 {
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
+  else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
+    return default_fixed_point_supported_p ();
   else if (mode == TFmode)
     return true;
   else
diff --git a/gcc/configure b/gcc/configure
index 22cf194a8..1ac52cfbd 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7634,6 +7634,10 @@ else
     mips*-*-*)
       enable_fixed_point=yes
       ;;
+
+    i?86*-*-* | x86_64*-*-*)
+      enable_fixed_point=yes
+      ;;
     *)
       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fixed-point is not supported for this target, ignored" >&5
 $as_echo "$as_me: WARNING: fixed-point is not supported for this target, ignored" >&2;}
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5c60d0f8d..f12e87a01 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -868,6 +868,10 @@ AC_ARG_ENABLE(fixed-point,
     mips*-*-*)
       enable_fixed_point=yes
       ;;
+
+    i?86*-*-* | x86_64*-*-*)
+      enable_fixed_point=yes
+      ;;
     *)
       AC_MSG_WARN([fixed-point is not supported for this target, ignored])
       enable_fixed_point=no

Reply via email to