[LLVMdev] Casting from float to unsigned char - incorrect output?
Jim Grosbach
grosbach at apple.com
Mon Aug 6 13:04:23 PDT 2012
On Aug 6, 2012, at 12:43 PM, ryan baird <ryanrbaird at gmail.com> wrote:
> 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));
> }
The prototype for trunc() here and it's definition above don't match. Dunno if that's related to the behavior you're seeing, but it's definitely a bug in the source code.
>
> 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?
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list