HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.03k stars 648 forks source link

Hashlink HL/C CArray code generation has unnecessary cast for known types. #11611

Closed onehundredfeet closed 3 months ago

onehundredfeet commented 3 months ago

I've been looking at the HL/C code generation for iterating over arrays. I've found native arrays to be the best. I was hoping CArrays would be better, but it seems there's an extra cast even though the type is known.

class Obj {
    public function new(v : Int) {
        value = v;
    }
    public var value : Int;
}
class Arrays {
    static function doNativeObjRead(tmp : hl.NativeArray<Obj>) {
        var accum = 0;
        for (i in 0...100) {
            accum += tmp[i].value;
        }
    }
    static function doCObjectObjRead(tmp : hl.CArray<Obj>) {
        var accum = 0;
        for (i in 0...100) {
            accum += tmp[i].value;
        }
    }
}

Results in the following two outputs.

void Arrays_doNativeObjRead(varray* r0) {
    perf__Obj r7;
    int r1, r3, r4, r5, r6;
    r1 = 0;
    r3 = 0;
    label$cfc120a_5_2:
    r5 = 100;
    if( r3 >= r5 ) goto label$cfc120a_5_13;
    r4 = r3;
    ++r3;
    r7 = ((perf__Obj*)(r0 + 1))[r4];
    r6 = r7->value;
    r5 = r1 + r6;
    r1 = r5;
    goto label$cfc120a_5_2;
    label$cfc120a_5_13:
    return;
}

void Arrays_doCObjectObjRead(hl_carray* r0) {
    perf__Obj r8;
    vdynamic *r7;
    int r1, r3, r4, r5, r6;
    r1 = 0;
    r3 = 0;
    label$cfc120a_6_2:
    r5 = 100;
    if( r3 >= r5 ) goto label$cfc120a_6_14;
    r4 = r3;
    ++r3;
    r7 = hl_carray_get(r0,r4);
    r8 = (perf__Obj)hl_dyn_castp(&r7,&t$_dyn,&t$perf_Obj);
    r6 = r8->value;
    r5 = r1 + r6;
    r1 = r5;
    goto label$cfc120a_6_2;
    label$cfc120a_6_14:
    return;
}

The native array can cast directly to the pointer type, while the CArray has to go through the hl_dyn_castp. it would be awesome if it could avoid the hl_carray_get and the hl_dyn_castp and index the CArray directly as the type is known at compile time.

yuxiaomao commented 3 months ago

Hi ! Could you please check with git latest version of Haxe ? It gives me the following

void Main_doCObjectObjRead(hl_carray* r0) {
    Obj r7;
    int r1, r3, r4, r5, r6;
    r1 = 0;
    r3 = 0;
    label$36888b6_2_2:
    r5 = 100;
    if( r3 >= r5 ) goto label$36888b6_2_12;
    r4 = r3;
    ++r3;
    r7 = ((Obj)r0) + r4;
    r6 = r7->value;
    r5 = r1 + r6;
    r1 = r5;
    goto label$36888b6_2_2;
    label$36888b6_2_12:
    return;
}
yuxiaomao commented 3 months ago

CArray implementation has changed recently (you'll need both Haxe and Hashlink to the git version), before it carry the length value, and now it's more like a true C Array (designed for passing value to DX12 afaik)

onehundredfeet commented 3 months ago

nice.