<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/55755>55755</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Issues with ARM hardware floating point support
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          itaig1
      </td>
    </tr>
</table>

<pre>
    First a bit of background information, I'm developing a RTOS system for the ARM Cortex M series cores and will also be working on the Cortex R cores at a later date. Anyway to cut a long story short, I came across several issues when dealing with floating point support which appears to differ from GCC and the ARM ABI standards so I looked into this deeper and came up with the following:

This actually could be considered several bugs but are all connected. I have checked these issues on versions 11.0.0, 12.0.0, 13.0.0, 14.0.0 and 15.0.0 with option -target arm-none-eabi -O3 -std=gnu++20 -x c++ also tested with the following options:

For CPU
-mcpu=cortex-m3
-mcpu=cortex-m4
-mcpu=cortex-m4+nofp
-mcpu=cortex-m4 -mfpu=none
-mcpu=cortex-m7
-mcpu=cortex-m7+nofp
-mcpu=cortex-m7+nofp.dp
-mcpu=cortex-m7 -mfpu=none

In addition to the above setting I have also tried with either one or none of the following:
-mfloat-abi=soft
-mfloat-abi=softfp
-mfloat-abi=hard

For comparison the version GCC compiler used was 10.3.1 arm-none-eabi with exactly the same options minus the -target arm-none-eabi

Each if the tests was done with simple functions using floating point so code validity could be checked and also using performing a check using -dM to dump the predefined macros.

1. When compiling with the command line option -mfloat-abi=hard the predefined macro __ARM_PCS_VFP to 1 is always defined even on devices without hardware floating point or the options like -mfpu=none are used. Although the compiler doesn't emit floating point instructions in this case the macro __ARM_PCS_VFP indicates that we are using hardware FP registers for passing parameters even when they don't exist. As a side note, GCC will generate an error if you use -mfloat-abi=hard in these cases. I have not checked what effect this has on the created object files. Currently I resolve this using:

#ifndef __ARM_FP
#ifdef __ARM_PCS_VFP
#undef __ARM_PCS_VFP
#warning Unexpected __ARM_PCS_VFP is defined, undefining __ARM_PCS_VFP
#endif
#endif

2. Not sure, it could be because GCC defaults to -mfloat-abi=soft and Clang defaults to -mfloat-abi=softfp however on GCC __SOFTFP__ and __ARM_FP will have one and only one of these defined, Clang will not define __SOFTFP__ unless the option -mfloat-abi=soft is used. GCC will also define __SOFTFP__ even if the option -mfloat-abi=softfp is used on a device without an FPU. While this can be resoved by checking if __ARM_FP is undefined instead of checking if __SOFTFP__ is defined, this may cause some compatibility issues with GCC. This also had other issues on versions of Clang prior to 12.0.0

3. There is a difference to how GCC and Clang define __ARM_FP, ACLE specifies that bit 2 indicates double precision FPU however on a Cortex M4 which only supports single precision arithmetic has bit 2 set on Clang and it is clear on GCC, the same is true for a Cortex M7 when a single precision FPU is specified instead of the double precision one. The generated code from the compiler appears correct just the define value in __ARM_FP appears different. The single precision FPUs do have "double" registers but they are only 2 single precision registers so the only valid instructions are to move double registers which allows the moving of 2 single precision registers with one instruction. I do not think this constitutes double capable FPU. This makes it hard to conditionally compile on whether doubles are supported or not by the FPU, this can be a real problem for assembly routines. Not sure if the Clang or the GCC method of reporting is correct according to ACLE however the GCC way does seem more logical and useful.

I did find other issues but they seemed to have been resolved since version 12.0.0 onwards so will not mention them here and those can be resolved by checking the Clang version or at least report a conflict.

I have been able to work around most of it except for item 3 when there are different FPU variations for the core such as the Cortex M7 and probably really since Clang 12.0.0 would probably only be a real issue if dealing with assembly language as the compiler does appear to generate the correct code for C/C++.

Regards,

itaig1


</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJx9WF1v4roW_TX0xQJBaA_TBx46zHBV6c6daj7OeaycxAGfOnZkO6X993ft7SQECiNVaUjs_bn22tvJXfm-3mofopAi11G4SuSyeNl519pSaFs5X8uonZ1kG_E4yVa1KNWrMq7Rdoc9P359_ynCe4iqFlgr4l6Jhx_fxMb5qN7ENxGU1yqIwnlcJWQetDFCmuBErsTB-RcS5Czv7Hb96JeTVUZG5UWJ60w82PeDfBfRiaLldw57Q3T-XYQ99rKRopC1ErLwLgSof1VeGqFDaCHxsFcWDkhDSg867kVlHPzDr8ZpG0VomwaCsFAXeyGbRkkfSGGpqwp2VN7V4j-bDbvSO_vw-RFW4In0JVQ62GCce1EUQGyNex2gVDXYT9vYvrZJ-klG5YxxBxgxWT5M5l8m8-76izbKIrbSmHfEpDUlBa1wNuhSecjv3cvbXcAFMfFwHQHGGquKqMoZjNnLV-zaq4JMgsKg-ngg7hAQkN8gFovZfDanEC6y4W453N3SHdu_uONbNt81BA4xjdLvFKmvp9ZZNVUy12L6fSmmIZaT5ZedbSfZZ_xlczF9E0X6kXAQFeBTXghHJz2chWULnG2efqcf07poWigoGDrTenn58e21x9ln66rmylsxrSt-Qj5dXrO69vhPgvu3s_Laggua0_XRClmWmqPO2EK-c4f8BhUZx126U2RRe11gFS7AH6QJhM_y_-oK-qCbqmKKHMKC4Kp47fnRwfGbPergPGGFqxvpdegqvUMdlxK90gbGtYGslYDifLacLc7QlNx4Qz2gGEhGoDrqICJqbdvAjy9icWzOV4nS1sl5wl5gnSWFhHUEXTcGcWltkWS3gQJ7zhQgIVfCE5AJ8jGuz67SqFY4DWk_yp_YNPEmr-leTMtvzDBt3bBNDSpbVdpCRM00Nhtbv5iJf4jFUtQGHqONeFSTUjxVQ2V-yMxFHeL5GUz2_LT5-fz39onMWQgiHwO-JfJKS8E2ljgDLUAXRKfQ7MA6JPZA1HMWo64h9Dky-kWdAJvpirIOajckajc4khBROhXQelZRqBrd6Uy8tiH6tkuStoloCwl6IyGX_NK21AVaCSEF3eXQW0AyByewzqudBimB-qmpNTKkDEoPyPFjjgR3E6h6J_AkK9-wDc4gcoI4GoUWFdEn4Zw7305ZMHaEYiuU95AOJL67lsJwKVnsFjE2-RUGNofcAWcHckWhPRUxhWAvQ99RC68kkavL_6XXFaIKIZvWe2Wpjh7hanDmVaWdHIkzup1kS11ZQKCL5fZp9Pz4uAvx8K61198hzJYC-tuqt4bb1HmeBsxR8FiU5h2X5Smktbr4i6_ZTPzPUW_3nAsAaajVXBWSIk_5gRLZmsjt_iPVcTlvjIQRf15YNWLvDtSYRUdwz88_v29_bZ-en1lIH8YECE4n1wJeOYucHLkZho3CkJTzJkp_ejMW3lpkN4xK7pIbnGWquAGSzFEfpTHEO5q8Kg7OdgLJWdkxw0AMAPn26TcxFoDX16elwBPsXrErf084puTqI8RYqu15hwpdyZKicrp4MPYUMKyoxqSYkhtcnTgF5JGDM0HW_TxI1IlAzESatSgSe1LEzfLCkAQLUhoar4ndXD8sjeC2JGkYz5hAu8FRWUQFq4GMYXwcwJQC39UWzH_Y_PerCCgMXemeqmg4z0b8Vbo2N8zjheZOijiPcSeHEfy2G2YZW918iykVMTzZj-Yc92A3XTB_JH0YKkhYspRs1gygwmAs7tCd4t11Y7wDIytmzaMFq8SU8qNSMhp7el9PMk1CP3iJ2uDoDjxapi7Mc_lJ6-hnd4xUnqjv3zbEJDMFHH0bhoJeB8j1O_qMxaTpktEU_1S5kyxLRuJm1DZoFufOQA2FI599FHRcHtIkxwt5oDjtbSQE4KlpzutCctzbHVVoiEu1j2U8PFd_1pnmd6vGqqi_wDOiF9SQfelKFjZEHdsR7grZSPrP1f0rldsLXus0DPARzdk0p3anF84LgQZg4PJKopJ3HS6JRjyrz9OMB_lDQXfMIeEDjjyNd9idTp3oz6rOoQXHVswH1OJ6wu8ZLEG4G0ioAgH1vWOgeUWqmVOOcJEF7kp6CFe4IPvi6gXQSZTmExQJzKhxYsWpb4fyNFwpIJ6qNSejG2KLzAJ9ZwQzgIUkKQ4eYytXyvb9uaRUFsfBOdEOwnnoD51DY6gBXZ36fy2YiNJh1fEUMbCvOaffY5h6JRTaKFDsKJ0UJRpdna2MLuKZa0eLGRjwgQ73SC5_Sahd4I8LmmakQjWR86bps8FymKN8GseG-mN6eAUxyVQG_QcG-jqA5BLqw_i7AYiGPCVkSEaDYuilwCXPurAduP8PC7nujtDitBBwTr4UDCAjQa3cqV77ybTasQj5P4x6nc2Mq8RWdIKdZNtNOgafRPKH2lFGgfrxUx2l3i3GT27K9bK8X97LG5SmUevHUUejjxLXZvKu0m5ab9b7GBs-XWdb_O2wtc1ncAc_jHnt_00RJ5oe8TMBFjd3d6u7u5v9ulrkcr6St_lidXv7af7X7SdVfsrzXFb3i6zI_roxMlcmrCd3cDSz6pCCi_vJ3Zcbvc7mWTa_y-7ny8V8OZ9JWX6S5f1KLotVcV8uJrdzVUttZmTHzPndjV-zSfTBAy8NuCwcX9KcvrNKsTrIly1Q79cpeDesec2W_x-fw464">