如何让ARM Clang编译器生成带#fbits参数的SCVTF指令?
如何让ARM Clang编译器生成带#fbits参数的SCVTF指令?
在嵌入式开发场景中,我们常会遇到把S1.31格式的有符号小数转换成单精度浮点数的需求,比如下面这个C实现:
#include <stdint.h> float Fixed_to_FP(int32_t x) { return ((float) (x) / (1U << 31)); }
目前用ARM编译器编译这段代码时,它会生成两条指令:
; s0 = x ; s2 = 1 / (1 << 31) VCVT.F32.S32 s1, s0 ; s1 = float(x) VMUL.F32 s1, s1, s2 ; s1 = float(x) * 1/(1<<31)
但其实ARM架构里的SCVTF指令可以一步完成固定点到浮点的转换——带#fbits参数的话,它会直接根据指定的小数位位数完成转换,不需要额外的乘法操作,效率更高。要让ARM Clang生成这条指令,可以试试下面这些方法:
- 指定支持SCVTF的目标架构:SCVTF是ARMv7-A/R及更高版本架构支持的指令,编译时要明确指定架构参数,比如
-march=armv7-a或者-march=armv8-a,确保编译器知道目标硬件支持这条指令。 - 开启足够的优化等级:低优化等级下编译器不会做指令融合这类优化,至少要开启
-O2或者-O3,让编译器有机会把除法/乘法组合转换成更高效的SCVTF指令。 - 明确代码的固定点转换意图:
- 可以利用Clang支持的固定点类型属性,让编译器直接识别这是固定点到浮点的转换:
typedef int32_t s1_31_t __attribute__((fixed_point(1, 31))); float Fixed_to_FP(s1_31_t x) { return (float)x; } - 也可以直接使用ARM内置函数(需要确认Clang版本支持):
#include <stdint.h> float Fixed_to_FP(int32_t x) { return __builtin_arm_scvtf(x, 31); }
- 可以利用Clang支持的固定点类型属性,让编译器直接识别这是固定点到浮点的转换:
通过这些调整,编译器就能识别出我们需要的是固定点转浮点的操作,进而生成带#31参数的SCVTF.F32指令,一步完成转换。
备注:内容来源于stack exchange,提问作者ysap
相关产品推荐
相关产品推荐

