#@mod with floating point values get compiled as a call to a function on x64 ?

1 messages · Page 1 of 1 (latest)

restive plume
#

I was browsing the assembly output of my program (In ReleaseFast) when I noticed a peculiar call to a fmod function
I reproduced the result in godbolt and we can see that the mod operation gets converted to I assume is a function that actually performs the operation https://zig.godbolt.org/z/P51e81a6T
As the code using the mod operator is in a very tight loop, I would rather prefer this call be inlined, but as the @mod is an intrinsic call, I can't do that. Is this normal or should I report the issue on github ?

devout hedge
#

i believe thats because theres no cpu instruction for that operation so it falls back to compiler_rt

restive plume
#

wow I wouldn't have guessed the actual implementation of fmod to be that big

devout hedge
restive plume
#

I'll guess I'll workaround my code to not rely on fmod then (also i'm surprised that of all the instructions that exists on x64 there is no opcode for that)

devout hedge
unreal bluff
#

There's an x87 instruction which does this (or, well, it does rem - you can adjust it to mod by branching on the sign afterwards if you need), but I'm not sure if it'll be faster than a function call (x87 is known for being pretty slow). But you can try it with inline asm - here's a rem function which uses that instruction on x86_64, and falls back to @rem otherwise:

const builtin = @import("builtin");
fn floatRem(a: f32, b: f32) f32 {
    if (builtin.cpu.arch == .x86_64) {
        return asm (
            "FPREM"
            : [ret] "={ST(0)}" (-> f32),
            : [a] "{ST(0)}" (a),
              [b] "{ST(1)}" (b),
        );
    }
    // Fallback
    return @rem(a, b);
}
south crag
#

@unreal bluff that's only partial remainder

#

so not only is it slow but you have to run the instruction many times

unreal bluff
#

oh, that's on me for not reading the docs. x87 is.....weird

#

okay yeah so final advice: don't do that, just accept that x86[_64] is bad at this

south crag
#

also you didn't preserve fp tags, so arbitrary other code in the program will break

#

actually maybe it just underflows which is technically fine

#

unless it isn't, haven't tried that yet

#

I mean, you don't really want an instruction because there are multiple algorithms with different tradeoffs

restive plume
#

wow I get a 2x speedup if I replace the @mod call with a if(my_value > 1.0) my_value -= 1.0 because I know my_value can't increase by more than 1.0 each iteration

south crag
#

yeah if you only need one reduction, you won't get much faster than just doing it directly