Project

General

Profile

Behaviour of conv

Added by Rochus Keller about 1 year ago

What is the officially expected behaviour when converting a float to an int value?

From the description in the 0.0.41 manual, I can't say if it would truncate or round.

When I compile and run the attached program with 0.0.40, the literal to int assignments in float_convert1 are truncated, but the float to int register conversions in float_convert2 and double_convert) are apparently rounded.

When I compile and run the probram with 0.0.41, all conversions seem to truncate (what I would expect).

convert.c (636 Bytes) convert.c

Replies (11)

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

It should truncate.

RE: Behaviour of conv - Added by Rochus Keller about 1 year ago

Ok, I see.

I should mention that I used the x86 version of 0.0.40 and the arm64 version of 0.0.41.

Since I assumed that this again is an issue which was fixed from 0.0.40 to 0.0.41, I now updated all used ECS files of my branch to version 0.0.41.

But I still get rounded instead of truncated values (i.e. both a and b in float_convert2 and double_convert become 3)!

I already attached the source in the above comment; here also the generated cod file.

Is this possibly a machine code generator issue, or am I doing something wrong?

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

Are you using the legacy FPU or media-float instructions?

RE: Behaviour of conv - Added by Rochus Keller about 1 year ago

I'm using media-float, i.e. in compiler.cpp I set:

#elif defined AMD32BACKEND

    #include "amd64.hpp" 
    #include "amd64generator.hpp" 

    #define NAMESUFFIX "amd32" 
    static AMD64::Generator generator {diagnostics, stringPool, charset, AMD64::ProtectedMode, true, true};

didn't try yet with the legacy FPU yet; shall I try it?

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

It should work with the legacy FPU which is why I wasn't able to reproduce the problem. Appearently, the media-float instructions require initialisation of the rounding modes as well. The attached patch fixes this oversight for the 64-bit mode. You might have to adapt the code for your specialised 32-bit case. Thanks for reporting.

fpu.patch (625 Bytes) fpu.patch

RE: Behaviour of conv - Added by Rochus Keller about 1 year ago

Thanks for the patch. I applied it to my version of runtime.c and repeated the test with convert.c, but the result is the same (2.7 "truncates" to 3).

Meanwhile I also tried with

AMD64::Generator generator {diagnostics, stringPool, charset, AMD64::ProtectedMode, false, true};

which indeed works correctly, but as we found out it's about factor 10 slower, so I would prefer the "media-float" version.

You might have to adapt the code for your specialised 32-bit case.

What do you mean by that? I have very little experience with i386 nor "media-float".

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

Replace the inline assembler for the 32-bit case with this code:

.initdata _init_fpu
    .required
    push    dword 00'0111'1111'1000'0000b
    ldmxcsr    dword [esp]
    pop    eax

RE: Behaviour of conv - Added by Rochus Keller about 1 year ago

That's the solution, great, thank you very much!

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

Please note that the generated floating-point conversion to and from unsigned integers don't behave properly in 32-bit mode.

RE: Behaviour of conv - Added by Rochus Keller about 1 year ago

In what respect? I didn's see an issue with unsigned ints for the positive cases in convert.c.

RE: Behaviour of conv - Added by Florian Negele about 1 year ago

Unsigned integer values are basically treated as signed integers during floating-point conversions. There is no problem as long as their representations match.

    (1-11/11)