0xAA55 发表于 2026-5-2 19:43:28

【图形学】不使用矩阵乘法实现生成四阶欧拉角旋转矩阵

# 不使用矩阵乘法实现生成四阶欧拉角旋转矩阵

## 欧拉角旋转矩阵
欧拉角旋转矩阵在图形学有很多的作用,配合平移矩阵,可以通过平移坐标 + 旋转,对一个需要渲染的物件的空间姿态进行控制。当给这个物件的所有顶点都经过矩阵变换后,就可以得到它在屏幕上的显示坐标。

欧拉角旋转矩阵是通过将单位矩阵先进行按 Z 轴的滚动旋转,然后再按 X 轴进行俯仰旋转,最后按 Y 轴进行朝向旋转。这样一来,就需要按 X、Y、Z 三个轴都旋转一下,需要生成三个矩阵,用矩阵乘法合并三个矩阵得到一个矩阵,让每个顶点都按这个矩阵进行旋转;或者不把三个矩阵合并,但是每个顶点需要分别乘以滚动、俯仰、朝向矩阵,才能变换到指定旋转后的位置。因此需要优化欧拉角旋转矩阵的生成方式,一次性生成一整个矩阵。

## 示例代码(未优化版:生成三个轴的旋转矩阵,再合并矩阵。)
```C
#include <math.h>

typedef struct Vector_s
{
        float x, y, z, w;
}Vector_t, *Vector_p;

typedef struct Matrix_s
{
        Vector_t x, y, z, w;
}Matrix_t, *Matrix_p;

static void MatrixItentity(Matrix_p out)
{
        *out = (Matrix_t){
                {1, 0, 0, 0},
                {0, 1, 0, 0},
                {0, 0, 1, 0},
                {0, 0, 0, 1},
        };
}

static void MatrixRotationX(Matrix_p out, float angle)
{
        float ca = (float)cos(angle);
        float sa = (float)sin(angle);
        *out = (Matrix_t){
                {1, 0, 0, 0},
                {0, ca, sa, 0},
                {0, -sa, ca, 0},
                {0, 0, 0, 1},
        };
}

static void MatrixRotationY(Matrix_p out, float angle)
{
        float ca = (float)cos(angle);
        float sa = (float)sin(angle);
        *out = (Matrix_t){
                {ca, 0, -sa, 0},
                {0, 1, 0, 0},
                {sa, 0, ca, 0},
                {0, 0, 0, 1},
        };
}

static void MatrixRotationZ(Matrix_p out, float angle)
{
        float ca = (float)cos(angle);
        float sa = (float)sin(angle);
        *out = (Matrix_t){
                {ca, sa, 0, 0},
                {-sa, ca, 0, 0},
                {0, 0, 1, 0},
                {0, 0, 0, 1},
        };
}

static void VectorMultMatrix(Vector_p out, Vector_p v, Matrix_p m)
{
        *out = (Vector_t){
                v->x * m->x.x + v->y * m->y.x + v->z * m->z.x + v->w * m->w.x,
                v->x * m->x.y + v->y * m->y.y + v->z * m->z.y + v->w * m->w.y,
                v->x * m->x.z + v->y * m->y.z + v->z * m->z.z + v->w * m->w.z,
                v->x * m->x.w + v->y * m->y.w + v->z * m->z.w + v->w * m->w.w
        };
}

static void MatrixMultMatrix(Matrix_p out, Matrix_p l, Matrix_p r)
{
        Vector_t ox, oy, oz, ow;
        VectorMultMatrix(&ox, &l->x, r);
        VectorMultMatrix(&oy, &l->y, r);
        VectorMultMatrix(&oz, &l->z, r);
        VectorMultMatrix(&ow, &l->w, r);
        *out = (Matrix_t){ox, oy, oz, ow};
}

void MatrixRotationEuler(Matrix_p out, float yaw, float pitch, float roll)
{
        Matrix_t ym, pm, rm, rpm;
        MatrixRotationZ(&rm, roll);
        MatrixRotationX(&pm, pitch);
        MatrixRotationY(&ym, yaw);
        MatrixMultMatrix(&rpm, &rm, &pm);
        MatrixMultMatrix(out, &ym, &rpm);
}
```

## 尝试优化:减少不必要的计算步骤

由于按 X、Y、Z 旋转的俯仰、朝向、滚动的矩阵里面有很多成员的值都是零,其实会有很多无用的计算。此处我使用 TDM-GCC 通过设置 `-O3` 的优化将上述代码编译为 32 位、使用 FPU 进行计算的二进制,然后使用 IDA 进行逆向,看看它能不能帮我完成代数运算的项合并。如图所示,直接生啃 FPU 的指令实在是令人头大。不如按 F5,对生成的 C 代码进行一些标注,应该能得到更清晰的计算过程。### 目前的问题

可以看到它有非常多的局部变量,并且对这些变量进行赋值时,会有很多的乘零、加零的操作。 **恕我直言,这 gcc10 是有点逊啦!**### 对反编译的变量名进行标记

标记规则:
* 朝向角(yaw)的 cos 值名为 `cy`,yaw 的 sin 值为 `sy`;以此类推的话,俯仰角(pitch)的 cos 值名为 `cp`,sin 值为 `sp`;滚动角(roll)的 cos 和 sin 值分别为 `cr`、`sr`。
* 如果是负值,则添加 `n` 前缀(negative),比如负的 `cy` 起名为 `ncy`,以此类推。
* 乘到一起的项,则将名字合并。比如 `cp * sr` 得到的值存入的变量名为 `cpsr`
* 如果遇到不同的变量但是具有相同的值,则给这个变量名字后面加下划线,比如重复的 `cpsr` 变量,取名为 `cpsr_`,`cpsr__` 等,以此类推。
* 值为零的变量取名为 `zr`,并且根据变量的数量,后面加上十进制的数值后缀,比如 `zr0`、`zr1`,以此类推。

标记后的代码:
```C
void __cdecl MatrixRotationEuler(float *out, float yaw, float pitch, float roll)
{
        long double sr__; // fst6
        long double zr0; // fst5
        long double zr1; // fst4
        long double zr2; // fst3
        long double cp_; // fst2
        long double zr3; // fst1
        long double zr4; // rt0
        long double zr5; // fst1
        long double zr6; // fst5
        long double cp__; // rt1
        long double zr8; // fst2
        long double zr9; // fst1
        long double crsp; // fst4
        long double zr11; // fst2
        long double nsp; // fst1
        long double zr12; // rt0
        long double cp___; // rt1
        long double nsp_; // fst6
        long double zr15; // fst2
        long double crsp_; // fst0
        long double zr16; // fst4
        long double zr18; // fst1
        long double zr19; // fst3
        long double cpsr_; // fst5
        float sr; //
        float cy; //
        float sp; //
        float zr14; //
        float cr; //
        float zr17; //
        float sy; //
        float nsy; //
        float sr_; //
        float cr_; //
        float cp; //
        float spsr; //
        float zr7; //
        float zr21; //
        float zr13; //
        float cpsr; //
        float cp____; //
        float nsr; //
        float crcp; //
        float zr10; //
        float zr23; //
        float zr24; //
        float zr25; //
        float zr26; //
        float zr27; //
        float zr28; //
        float zr22; //
        float zr20; //
        float crsp__; //
        float zr29; //

        cr = cos(roll);
        sr = sin(roll);
        sr_ = sr;
        cp = cos(pitch);
        sp = sin(pitch);
        cy = cos(yaw);
        sy = sin(yaw);
        nsy = -sy;
        sr__ = sr_;
        zr0 = sr_ * 0.0;
        cr_ = cr + zr0 + 0.0;
        zr1 = cr * 0.0;
        zr2 = -sp * 0.0;
        cp_ = cp;
        cpsr = cp * sr__ + zr1 + zr2 + 0.0;
        zr3 = cp * 0.0;
        spsr = sp * sr__ + zr1 + zr3 + 0.0;
        zr4 = zr3;
        zr5 = zr0;
        zr6 = zr4;
        zr7 = zr5 + zr1 + 0.0;
        nsr = zr1 - sr__ + 0.0;
        cp__ = cp_;
        zr8 = -sr__ * 0.0;
        crcp = cr * cp__ + zr8 + zr2 + 0.0;
        zr9 = zr1;
        crsp = cr * sp + zr8 + zr4 + 0.0;
        zr10 = zr8 + zr9 + 0.0;
        zr11 = zr4 + 0.0;
        nsp = zr4 + 0.0 - sp + 0.0;
        zr12 = sp * 0.0 + 0.0;
        cp___ = cp__ + zr12 + 0.0;
        zr13 = zr11 + zr2 + 0.0;
        nsp_ = nsp;
        zr14 = nsr * 0.0;
        zr15 = nsy * 0.0;
        crsp_ = crsp;
        zr16 = zr13 * 0.0;
        crsp__ = crsp_;
        zr17 = crsp_ * 0.0;
        zr18 = zr6 + zr12 + 0.0;
        zr19 = crcp * 0.0;
        zr20 = zr18;
        zr21 = zr18 * 0.0;
        zr22 = zr10 * 0.0;
        zr23 = cr_ * 0.0;
        zr24 = cpsr * 0.0;
        zr25 = nsp_ * 0.0;
        zr26 = spsr * 0.0;
        cpsr_ = cpsr;
        cp____ = cp___;
        zr27 = cp___ * 0.0;
        zr28 = zr7 * 0.0;
        zr29 = cy * 0.0;
        out = cy * cr_ + zr14 + zr15 + 0.0;
        out = cy * cpsr_ + zr19 + nsy * nsp_ + zr16;
        out = cy * spsr + zr17 + nsy * cp____ + zr21;
        out = zr15 + zr7 * cy + zr22 + 0.0;
        out = nsr + zr23 + 0.0;
        out = crcp + zr24 + zr25 + zr16;
        out = crsp__ + zr26 + zr27 + zr21;
        out = zr10 + zr28 + 0.0;
        out = cr_ * sy + zr14 + zr29 + 0.0;
        out = zr16 + cpsr_ * sy + zr19 + nsp_ * cy;
        out = spsr * sy + zr17 + cy * cp____ + zr21;
        out = zr29 + sy * zr7 + zr22 + 0.0;
        out = zr23 + zr14 + 0.0;
        out = zr19 + zr24 + zr25 + zr13;
        out = zr26 + zr17 + zr27 + zr20;
        out = zr22 + zr28 + 0.0 + 1.0;
}
```

可以看到,有大量的变量值为零,并且有非常多的重复的值的变量。

### 剔除无用变量,手动简化代码

```C
#include <math.h>

typedef struct Vector_s
{
        float x, y, z, w;
}Vector_t, *Vector_p;

typedef struct Matrix_s
{
        Vector_t x, y, z, w;
}Matrix_t, *Matrix_p;

void MatrixRotationEuler(Matrix_p out, float yaw, float pitch, float roll)
{
        float cy = (float)cos(yaw);
        float sy = (float)sin(yaw);
        float cp = (float)cos(pitch);
        float sp = (float)sin(pitch);
        float cr = (float)cos(roll);
        float sr = (float)sin(roll);
        float cpsr = cp * sr;
        float spsr = sp * sr;
        *out = (Matrix_t){
                {
                        cy * cr,
                        cy * cpsr + sy * sp,
                        cy * spsr - sy * cp,
                        0.0f
                },
                {
                        -sr,
                        cr * cp,
                        cr * sp,
                        0.0f
                },
                {
                        cr * sy,
                        cpsr * sy - sp * cy,
                        spsr * sy + cp * cy,
                        0.0f
                },
                {
                        0.0f,
                        0.0f,
                        0.0f,
                        1.0f
                },
        };
}
```

## 既然 GCC 那么菜,那么 clang 的表现如何呢?

### 人肉编译优化过的 C 源码
如果是我手写汇编(我 = 人肉编译器),得到的指令是像下面这样的(已根据流水线优化的需求,对代码进行排序)

```
segment .bss
alignb 16
global _ZeroVector
_ZeroVector resd 4

segment .text
; void MatrixRotationEuler(Matrix_p out, float yaw, float pitch, float roll)
global _MatrixRotationEuler
_MatrixRotationEuler:
        sub esp, 32
        %define _CY
        %define _SY
        %define _CP
        %define _SP
        %define _CR
        %define _SR
        %define _CPSR
        %define _SPSR
        %define _OUT
        %define _YAW
        %define _PITCH
        %define _ROLL

        fld dword _YAW
        fsincos
        fstp _CY
        fstp _SY
        fld dword _PITCH
        fsincos
        fstp _CP
        fstp _SP
        fld dword _ROLL
        fsincos
        fstp _CR
        fstp _SR

        mov eax, _OUT
        movaps xmm0,
        movaps , xmm0
        movaps , xmm0
        movaps , xmm0
        movaps , xmm0

        movss xmm0, _CP
        movss xmm1, _SP
        movss xmm2, _CR
        movss xmm3, _CY
        movss xmm4, _CY
        movss xmm5, _SY
        movss xmm6, _CY
        movss xmm7, _SY
        mulss xmm0, _SR
        mulss xmm1, _SR
        mulss xmm2, _CP
        mulss xmm3, _CR
        mulss xmm4, xmm0
        mulss xmm5, _SP
        mulss xmm6, xmm1
        mulss xmm7, _CP
        addss xmm4, xmm5
        subss xmm6, xmm7
        movss _CPSR, xmm0
        movss _SPSR, xmm1
        movss , xmm3
        movss , xmm4
        movss , xmm6
        movss , xmm2

        movss xmm0,
        movss xmm1, _CR
        movss xmm2, _CR
        movss xmm3, _CPSR
        movss xmm4, _SP
        movss xmm5, _SPSR
        movss xmm6, _CY
        subss xmm0, _SR
        mulss xmm1, _SP
        mulss xmm2, _SY
        mulss xmm3, _SY
        mulss xmm4, _CY
        mulss xmm5, _SY
        mulss xmm6, _CP
        subss xmm3, xmm4
        addss xmm5, xmm6
        movss , xmm0
        movss , xmm1
        movss , xmm2
        movss , xmm3
        movss , xmm5
        mov dword, 0x3F800000

        add esp, 32
        ret
        %undef _CY
        %undef _SY
        %undef _CP
        %undef _SP
        %undef _CR
        %undef _SR
        %undef _CPSR
        %undef _SPSR
        %undef _OUT
        %undef _YAW
        %undef _PITCH
        %undef _ROLL
```
### 使用 clang 开 -O3 编译原始源码(编译为 x86-64 平台机器,生成汇编文件)

请看汇编:
```
        .def        @feat.00;
        .scl        3;
        .type        0;
        .endef
        .globl        @feat.00
@feat.00 = 0
        .intel_syntax noprefix
        .file        "matrot.c"
        .def        MatrixRotationEuler;
        .scl        2;
        .type        32;
        .endef
        .globl        __xmm@80000000800000008000000080000000 # -- Begin function MatrixRotationEuler
        .section        .rdata,"dr",discard,__xmm@80000000800000008000000080000000
        .p2align        4, 0x0
__xmm@80000000800000008000000080000000:
        .long        0x80000000                      # float -0
        .long        0x80000000                      # float -0
        .long        0x80000000                      # float -0
        .long        0x80000000                      # float -0
        .globl        __real@80000000
        .section        .rdata,"dr",discard,__real@80000000
        .p2align        2, 0x0
__real@80000000:
        .long        0x80000000                      # float -0
        .globl        __xmm@00000000000000008000000080000000
        .section        .rdata,"dr",discard,__xmm@00000000000000008000000080000000
        .p2align        4, 0x0
__xmm@00000000000000008000000080000000:
        .long        0x80000000                      # float -0
        .long        0x80000000                      # float -0
        .long        0x00000000                      # float 0
        .long        0x00000000                      # float 0
        .globl        __xmm@00000000000000003f80000000000000
        .section        .rdata,"dr",discard,__xmm@00000000000000003f80000000000000
        .p2align        4, 0x0
__xmm@00000000000000003f80000000000000:
        .long        0x00000000                      # float 0
        .long        0x3f800000                      # float 1
        .zero        4
        .zero        4
        .text
        .globl        MatrixRotationEuler
        .p2align        4
MatrixRotationEuler:                  # @MatrixRotationEuler
.seh_proc MatrixRotationEuler
# %bb.0:
        push        rsi
        .seh_pushreg rsi
        sub        rsp, 368
        .seh_stackalloc 368
        movaps        xmmword ptr , xmm15# 16-byte Spill
        .seh_savexmm xmm15, 352
        movaps        xmmword ptr , xmm14# 16-byte Spill
        .seh_savexmm xmm14, 336
        movaps        xmmword ptr , xmm13# 16-byte Spill
        .seh_savexmm xmm13, 320
        movaps        xmmword ptr , xmm12# 16-byte Spill
        .seh_savexmm xmm12, 304
        movaps        xmmword ptr , xmm11# 16-byte Spill
        .seh_savexmm xmm11, 288
        movaps        xmmword ptr , xmm10# 16-byte Spill
        .seh_savexmm xmm10, 272
        movaps        xmmword ptr , xmm9   # 16-byte Spill
        .seh_savexmm xmm9, 256
        movaps        xmmword ptr , xmm8   # 16-byte Spill
        .seh_savexmm xmm8, 240
        movaps        xmmword ptr , xmm7   # 16-byte Spill
        .seh_savexmm xmm7, 224
        movaps        xmmword ptr , xmm6   # 16-byte Spill
        .seh_savexmm xmm6, 208
        .seh_endprologue
        movaps        xmm6, xmm2
        movaps        xmm7, xmm1
        mov        rsi, rcx
        xorps        xmm8, xmm8
        cvtss2sd        xmm8, xmm3
        movaps        xmm0, xmm8
        call        cos
        xorps        xmm11, xmm11
        cvtsd2ss        xmm11, xmm0
        movaps        xmm0, xmm8
        call        sin
        xorps        xmm9, xmm9
        cvtsd2ss        xmm9, xmm0
        movaps        xmm0, xmmword ptr # xmm0 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
        xorps        xmm0, xmm9
        movaps        xmmword ptr , xmm0   # 16-byte Spill
        cvtss2sd        xmm6, xmm6
        movaps        xmm0, xmm6
        call        cos
        xorps        xmm8, xmm8
        cvtsd2ss        xmm8, xmm0
        movaps        xmm0, xmm6
        call        sin
        cvtsd2ss        xmm0, xmm0
        movaps        xmmword ptr , xmm0    # 16-byte Spill
        xorps        xmm6, xmm6
        cvtss2sd        xmm6, xmm7
        movaps        xmm0, xmm6
        call        cos
        cvtsd2ss        xmm0, xmm0
        movaps        xmmword ptr , xmm0    # 16-byte Spill
        movaps        xmm0, xmm6
        call        sin
        xorps        xmm7, xmm7
        cvtsd2ss        xmm7, xmm0
        xorps        xmm4, xmm4
        movaps        xmm13, xmm9
        mulss        xmm13, xmm4
        movaps        xmm14, xmm13
        addss        xmm14, xmm11
        addss        xmm14, xmm4
        movaps        xmm10, xmm9
        mulss        xmm10, xmm8
        movaps        xmm12, xmm11
        movaps        xmm6, xmm11
        mulss        xmm12, xmm4
        addss        xmm10, xmm12
        movss        xmm11, dword ptr # xmm11 = [-0.0E+0,0.0E+0,0.0E+0,0.0E+0]
        movaps        xmm1, xmm9
        movaps        xmm5, xmm12
        movaps        xmmword ptr , xmm12   # 16-byte Spill
        subss        xmm5, xmm9
        movaps        xmm15, xmm6
        mulss        xmm15, xmm8
        movaps        xmmword ptr , xmm8   # 16-byte Spill
        mulss        xmm9, xmm11
        addss        xmm15, xmm9
        movaps        xmm3, xmmword ptr     # 16-byte Reload
        mulss        xmm6, xmm3
        addss        xmm6, xmm9
        movaps        xmmword ptr , xmm6   # 16-byte Spill
        movaps        xmm2, xmm3
        mulss        xmm2, xmm11
        addss        xmm10, xmm2
        movaps        xmm9, xmm2
        addss        xmm10, xmm4
        movaps        xmm6, xmm10
        mulss        xmm6, xmm4
        movaps        xmm2, xmm14
        movaps        xmm0, xmm7
        movaps        xmmword ptr , xmm7    # 16-byte Spill
        mulss        xmm2, xmm7
        movaps        xmm7, xmm6
        subss        xmm7, xmm2
        mulss        xmm1, xmm3
        movaps        xmm11, xmm3
        addss        xmm1, xmm12
        movaps        xmm12, xmm8
        mulss        xmm12, xmm4
        addss        xmm1, xmm12
        movaps        xmmword ptr , xmm12# 16-byte Spill
        addss        xmm1, xmm4
        movaps        xmm8, xmm1
        movaps        xmm2, xmmword ptr     # 16-byte Reload
        mulss        xmm8, xmm2
        addss        xmm8, xmm7
        movaps        xmm7, xmm14
        mulss        xmm7, xmm4
        addss        xmm7, xmm6
        movaps        xmm3, xmm1
        mulss        xmm3, xmm4
        addss        xmm3, xmm7
        addss        xmm15, xmm9
        movaps        xmmword ptr , xmm15# 16-byte Spill
        movaps        xmm15, xmm12
        addss        xmm15, xmm4
        addss        xmm9, xmm15
        movaps        xmmword ptr , xmm9    # 16-byte Spill
        subss        xmm15, xmm11
        movaps        xmm9, xmm15
        mulss        xmm9, xmm4
        mulss        xmm2, xmm4
        movaps        xmm12, xmm2
        addss        xmm12, xmm9
        movss        xmm7, dword ptr # xmm7 = [-0.0E+0,0.0E+0,0.0E+0,0.0E+0]
        mulss        xmm7, xmm0
        movaps        xmm11, xmm7
        addss        xmm11, xmm9
        addss        xmm9, xmm4
        unpcklps        xmm11, xmm9                     # xmm11 = xmm11,xmm9,xmm11,xmm9
        movaps        xmm9, xmmword ptr     # 16-byte Reload
        addss        xmm9, xmm4
        movaps        xmmword ptr , xmm9    # 16-byte Spill
        mulss        xmm9, xmm4
        addss        xmm2, xmm9
        movaps        xmmword ptr , xmm2   # 16-byte Spill
        addss        xmm7, xmm9
        addss        xmm9, xmm4
        unpcklps        xmm7, xmm9                      # xmm7 = xmm7,xmm9,xmm7,xmm9
        unpcklps        xmm6, xmm10                     # xmm6 = xmm6,xmm10,xmm6,xmm10
        xorps        xmm0, xmm0
        movaps        xmm2, xmmword ptr     # 16-byte Reload
        movss        xmm0, xmm2                      # xmm0 = xmm2,xmm0
        unpcklps        xmm14, xmm14                  # xmm14 = xmm14
        mulps        xmm14, xmm0
        addps        xmm14, xmm6
        unpcklps        xmm1, xmm1                      # xmm1 = xmm1
        xorps        xmm2, xmm2
        movaps        xmm9, xmmword ptr     # 16-byte Reload
        movss        xmm2, xmm9                      # xmm2 = xmm9,xmm2
        movaps        xmmword ptr , xmm2    # 16-byte Spill
        mulps        xmm1, xmm2
        addps        xmm1, xmm14
        movaps        xmm2, xmmword ptr     # 16-byte Reload
        addss        xmm13, xmm2
        addss        xmm13, xmm4
        addss        xmm3, xmm13
        mulss        xmm13, xmm4
        addss        xmm8, xmm13
        unpcklps        xmm13, xmm13                  # xmm13 = xmm13
        addps        xmm13, xmm1
        movlps        qword ptr , xmm13
        movss        dword ptr , xmm8
        movss        dword ptr , xmm3
        unpcklps        xmm2, xmmword ptr    # 16-byte Folded Reload
                                        # xmm2 = xmm2,mem,xmm2,mem
        movaps        xmm6, xmm2
        movaps        xmm2, xmmword ptr    # 16-byte Reload
        movaps        xmm3, xmmword ptr    # 16-byte Reload
        unpcklps        xmm2, xmm3                      # xmm2 = xmm2,xmm3,xmm2,xmm3
        xorps        xmm1, xmm1
        mulps        xmm2, xmm1
        addps        xmm2, xmm6
        movaps        xmm6, xmmword ptr     # 16-byte Reload
        mulss        xmm6, xmm4
        movaps        xmm10, xmm2
        shufps        xmm10, xmm6, 4                  # xmm10 = xmm10,xmm6
        shufps        xmm5, xmm2, 212               # xmm5 = xmm5,xmm2
        shufps        xmm5, xmm2, 82                  # xmm5 = xmm5,xmm2
        xorps        xmm8, xmm8
        shufps        xmm8, xmm3, 4                   # xmm8 = xmm8,xmm3
        addps        xmm10, xmmword ptr
        movaps        xmm2, xmmword ptr    # 16-byte Reload
        addss        xmm2, xmm4
        addps        xmm8, xmm10
        movhlps        xmm10, xmm10                  # xmm10 = xmm10
        addss        xmm10, dword ptr     # 16-byte Folded Reload
        movaps        xmm3, xmm2
        movaps        xmm14, xmm2
        mulss        xmm3, xmm4
        addps        xmm5, xmm1
        movaps        xmm2, xmm5
        shufps        xmm2, xmm5, 85                  # xmm2 = xmm2,xmm5
        movaps        xmm6, xmm2
        movaps        xmm13, xmm9
        mulss        xmm6, xmm9
        movaps        xmm9, xmm3
        subss        xmm9, xmm6
        unpcklps        xmm9, xmm3                      # xmm9 = xmm9,xmm3,xmm9,xmm3
        mulps        xmm5, xmm0
        addps        xmm5, xmm9
        unpcklps        xmm12, xmm15                  # xmm12 = xmm12,xmm15,xmm12,xmm15
        movlhps        xmm5, xmm12                     # xmm5 = xmm5,xmm12
        movq        xmm6, xmm13                     # xmm6 = xmm13,zero
        xorps        xmm9, xmm9
        shufps        xmm9, xmm6, 132               # xmm9 = xmm9,xmm6
        mulps        xmm9, xmm8
        addps        xmm9, xmm5
        movss        xmm5, dword ptr # xmm5 = [-0.0E+0,0.0E+0,0.0E+0,0.0E+0]
        movaps        xmm6, xmm8
        movlhps        xmm6, xmm5                      # xmm6 = xmm6,xmm5
        shufps        xmm6, xmm5, 226               # xmm6 = xmm6,xmm5
        addps        xmm6, xmm9
        unpcklps        xmm3, xmm14                     # xmm3 = xmm3,xmm14,xmm3,xmm14
        mulps        xmm2, xmm0
        addps        xmm2, xmm3
        movaps        xmm3, xmm8
        shufps        xmm3, xmm8, 85                  # xmm3 = xmm3,xmm8
        movaps        xmm5, xmmword ptr     # 16-byte Reload
        mulps        xmm3, xmm5
        addps        xmm3, xmm2
        addss        xmm10, xmm4
        mulss        xmm4, xmm8
        unpcklps        xmm4, xmm4                      # xmm4 = xmm4
        addps        xmm4, xmm3
        movlps        qword ptr , xmm4
        movups        xmmword ptr , xmm6
        shufps        xmm8, xmm10, 10               # xmm8 = xmm8,xmm10
        unpcklps        xmm10, xmm10                  # xmm10 = xmm10
        mulps        xmm10, xmm0
        movaps        xmm4, xmm0
        movlhps        xmm4, xmm5                      # xmm4 = xmm4,xmm5
        mulps        xmm4, xmm8
        movaps        xmm0, xmmword ptr    # 16-byte Reload
        unpcklps        xmm0, xmmword ptr     # 16-byte Folded Reload
                                        # xmm0 = xmm0,mem,xmm0,mem
        movlhps        xmm11, xmm0                     # xmm11 = xmm11,xmm0
        addps        xmm11, xmm4
        addps        xmm11, xmm1
        movups        xmmword ptr , xmm11
        addps        xmm10, xmm7
        addps        xmm10, xmmword ptr
        movlps        qword ptr , xmm10
        movaps        xmm6, xmmword ptr    # 16-byte Reload
        movaps        xmm7, xmmword ptr    # 16-byte Reload
        movaps        xmm8, xmmword ptr    # 16-byte Reload
        movaps        xmm9, xmmword ptr    # 16-byte Reload
        movaps        xmm10, xmmword ptr # 16-byte Reload
        movaps        xmm11, xmmword ptr # 16-byte Reload
        movaps        xmm12, xmmword ptr # 16-byte Reload
        movaps        xmm13, xmmword ptr # 16-byte Reload
        movaps        xmm14, xmmword ptr # 16-byte Reload
        movaps        xmm15, xmmword ptr # 16-byte Reload
        .seh_startepilogue
        add        rsp, 368
        pop        rsi
        .seh_endepilogue
        ret
        .seh_endproc
                                        # -- End function
        .section        .debug$S,"dr"
        .p2align        2, 0x0
        .long        4                               # Debug section magic
        .long        241
        .long        .Ltmp1-.Ltmp0                   # Subsection size
.Ltmp0:
        .short        .Ltmp3-.Ltmp2                   # Record length
.Ltmp2:
        .short        4353                            # Record kind: S_OBJNAME
        .long        0                               # Signature
        .byte        0                               # Object name
        .p2align        2, 0x0
.Ltmp3:
        .short        .Ltmp5-.Ltmp4                   # Record length
.Ltmp4:
        .short        4412                            # Record kind: S_COMPILE3
        .long        0                               # Flags and language
        .short        208                           # CPUType
        .short        22                              # Frontend version
        .short        1
        .short        1
        .short        0
        .short        22011                           # Backend version
        .short        0
        .short        0
        .short        0
        .asciz        "clang version 22.1.1 (https://github.com/llvm/llvm-project fef02d48c08db859ef83f84232ed78bd9d1c323a)" # Null-terminated compiler version string
        .p2align        2, 0x0
.Ltmp5:
.Ltmp1:
        .p2align        2, 0x0
        .addrsig
        .globl        _fltused
```

### 结论:显然 clang 生成的指令明显更多,计算复杂度也更大,使用的常量也更多,而且栈用的也更大。

这也表示编译器似乎没有做到浮点数的乘零步骤的优化过程。
古法编程之:人肉编译器战胜了 gcc、clang
我虽然不能用针扎 CD、磁针扎硬盘、软盘、口算 MD5 等方式工作,但是我充当个编译器是可以的

AyalaRs 发表于 2026-5-3 15:41:14

浮点数算数计算优化用单独的编译参数。

0xAA55 发表于 2026-5-3 19:32:57

AyalaRs 发表于 2026-5-3 15:41
浮点数算数计算优化用单独的编译参数。

确实有效。这个优化选项竟然不是默认开启的。优化后的效果和我自己手动优化的一致。

AyalaRs 发表于 2026-5-3 19:56:45

0xAA55 发表于 2026-5-3 19:32
确实有效。这个优化选项竟然不是默认开启的。优化后的效果和我自己手动优化的一致。

...

浮点数优化容易损失精度,编译器默认甚至都不会改变前后指令顺序。

YY菌 发表于 2026-5-14 09:04:56

AyalaRs 发表于 2026-5-3 19:56
浮点数优化容易损失精度,编译器默认甚至都不会改变前后指令顺序。

看需求嘛,对于像游戏这种以速度为主的实时渲染来说,不在乎那点精度。
页: [1]
查看完整版本: 【图形学】不使用矩阵乘法实现生成四阶欧拉角旋转矩阵