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