相交Ray Sphere x86 fpu asm例程 - 如何优化

时间:2012-08-20 13:38:16

标签: optimization assembly x86 fpu

Hullo,我有一些c程序:

    inline float intersectRaySphere(float3* rayO, float3* rayV, float3* sO, float sR)
    {
    static float3 Q;

    Q = sub(sO,rayO);

    float cc = dot(&Q,&Q);
    float v = dot(&Q,rayV);
    float d = sR*sR - (cc - v*v);

    // If there was no intersection, return -1
    if (d < 0.0) return (-1.0f);
    // Return the distance to the [first] intersecting point
    return (v - sqrt(d));
    }

我试图在x86 fpu asm中重写它并创建这样一个

    _asm_intersectRaySphere:; Function begin
    push    ebp                                     ; 0000 _ 55
    mov     ebp, esp                                ; 0001 _ 89. E5
    add     esp, -20                                ; 0003 _ 83. C4, EC
    mov     eax, dword [ebp+8H]                     ; 0006 _ 8B. 45, 08
    mov     ecx, dword [ebp+0CH]                    ; 0009 _ 8B. 4D, 0C
    mov     edx, dword [ebp+10H]                    ; 000C _ 8B. 55, 10
    fld     dword [edx]                             ; 000F _ D9. 02
    fsub    dword [eax]                             ; 0011 _ D8. 20
    fld     dword [edx+4H]                          ; 0013 _ D9. 42, 04
    fsub    dword [eax+4H]                          ; 0016 _ D8. 60, 04
    fld     dword [edx+8H]                          ; 0019 _ D9. 42, 08
    fsub    dword [eax+8H]                          ; 001C _ D8. 60, 08
    fld     st2                                     ; 001F _ D9. C2
    fmul    st0, st(0)                              ; 0021 _ DC. C8
    fld     st2                                     ; 0023 _ D9. C2
    fmul    st0, st(0)                              ; 0025 _ DC. C8
    fld     st2                                     ; 0027 _ D9. C2
    fmul    st0, st(0)                              ; 0029 _ DC. C8
    faddp   st1, st(0)                              ; 002B _ DE. C1
    faddp   st1, st(0)                              ; 002D _ DE. C1
    fld     dword [ecx]                             ; 002F _ D9. 01
    fmul    st(0), st4                              ; 0031 _ D8. CC
    fld     dword [ecx+4H]                          ; 0033 _ D9. 41, 04
    fmul    st(0), st4                              ; 0036 _ D8. CC
    fld     dword [ecx+8H]                          ; 0038 _ D9. 41, 08
    fmul    st(0), st4                              ; 003B _ D8. CC
    faddp   st1, st(0)                              ; 003D _ DE. C1
    faddp   st1, st(0)                              ; 003F _ DE. C1
    fst     dword [ebp-4H]                          ; 0041 _ D9. 55, FC
    fmul    st0, st(0)                              ; 0044 _ DC. C8
    fld     dword [ebp+14H]                         ; 0046 _ D9. 45, 14
    fmul    st0, st(0)                              ; 0049 _ DC. C8
    faddp   st1, st(0)                              ; 004B _ DE. C1
    fsubrp  st1, st(0)                              ; 004D _ DE. E1
    fxch    st3                                     ; 004F _ D9. CB
    fstp    st0                                     ; 0051 _ DD. D8
    fstp    st0                                     ; 0053 _ DD. D8
    fstp    st0                                     ; 0055 _ DD. D8
    ftst                                            ; 0057 _ D9. E4
    fwait                                           ; 0059 _ 9B
    fnstsw  ax                                      ; 005A _ DF. E0
    fwait                                           ; 005C _ 9B
    sahf                                            ; 005D _ 9E
    jc      ?_001                                   ; 005E _ 72, 07
    fsqrt                                           ; 0060 _ D9. FA
    fsubr   dword [ebp-4H]                          ; 0062 _ D8. 6D, FC
    jmp     ?_002                                   ; 0065 _ EB, 06

     ?_001:  
    fstp    st0                                     ; 0067 _ DD. D8
    fld1                                            ; 0069 _ D9. E8
    fchs                                            ; 006B _ D9. E0
     ?_002:  
    mov     esp, ebp                                ; 006D _ 89. EC
    pop     ebp                                     ; 006F _ 5D
    ret                                             ; 0070 _ C3
    ; _asm_intersectRaySphere End of function

测试,它工作正常,c例程需要大约150个周期(在我的6或 7岁的奔腾4),我的asm例程需要大约66个周期(*) - 所以它是 好的改进,但也许它还可以改善一点?

TNX

(*)我对随机输入数据进行了不太谨慎的测试 可能这是一个'非交叉'的原因 - 没有涉及sqrt

1 个答案:

答案 0 :(得分:1)

我会替换它:

fstp st0
fstp st0
fstp st0
ftst
fwait
fnstsw  ax
fwait
sahf
jc ?__001

由此:

fcompp
fstp st0
fldz
fcomip st0, st1
ja ?__001

fnstsw并不快,sahf也不是很好,特别是在P4上没有。如果您无法使用fcomi(即,如果必须使用P1或PMMX),您仍然可以通过直接在sahf中测试一下来跳过ax