[LLVMdev] Casting from float to unsigned char - incorrect output?

ryan baird ryanrbaird at gmail.com
Mon Aug 6 12:43:12 PDT 2012


I am compiling the following code for the MIPS architecture:

unsigned char trunc(float f) {
        return (unsigned char) f;
}

and it produces the following assembly (directives removed for convenience:
trunc:
    trunc.w.s    $f0, $f12
    mfc1    $2, $f0
    jr    $ra
    nop

However, this does not seem to produce the correct output for negative
numbers. When I run the following code, I get -1 instead of 255 (which is
produced by compiling natively with gcc).
int trunc(float c);
int main() {
  printf("%d\n", trunc(-1.0));
}

I am running the mips code on a PISA simulator (SimpleScalar's  Simple-Sim
3.0) instead of a MIPS IV simulator, so there is a little bit of
translation occurring before I can simulate it; here is the revised code:
trunc:
    cvt.w.s    $f0, $f12
    mfc1    $2, $f0
    jr    $ra
    nop
the cvt.w.s function in PISA MIPS is rounding towards zero, so it should
meet the specification for trunc.w.s in MIPS IV.

Here are the commands I used to compile test.c (with the trunc function in
it):
clang -emit-llvm -mfloat-abi=hard -ccc-host-triple mipsel-unknown-linux
-ccc-clang-archs mipsel -O3 -S -o test_unopt.ll test.c
opt -std-compile-opts test_unopt.ll -o test.ll
llc -march=mipsel -mcpu=mips32 -float-abi=hard -relocation-model=static
test.ll -o test.s

Here is the llvm intermediate representation:
; ModuleID = 'test_unopt.ll'
target datalayout =
"e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32"
target triple = "mipsel-unknown-linux"

define zeroext i8 @trunc(float %f) nounwind readnone {
entry:
  %conv = fptoui float %f to i8
  ret i8 %conv
}

This is the assembly produced by another compiler; it is more complex, but
it produces the expected output, matching with GCC: (directives removed for
convenience)
trunc:
        mov.s   $f4,$f12
        la      $2,L6
        l.s     $f6,($2)
        c.lt.s  $f12,$f6
        bc1t    .L3
        sub.s   $f0,$f12,$f6
        cvt.w.s $f0,$f0
        mfc1    $2,$f0
        lui     $3,32768
        addu    $3,$2,$3
        j       .L4
.L3:
         cvt.w.s $f4,$f4
         mfc1    $3,$f4
.L4:
        sll     $2,$3,24
        srl     $2,$2,24
        sll     $2,$2,24
        srl     $2,$2,24
        j       $31
.data
.align 4
L6:
.word 1325400064

Am I correct in my analysis that LLVM's assembly output is wrong?  Is there
a way for me to get the correct output?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120806/50365ec6/attachment.html>


More information about the llvm-dev mailing list