On 10/12/2015 02:45, Ömer Sinan Ağacan wrote:
Thanks for all the answers,

Simon, do you remember anything about the ticket about converting between
floating point types and integers? I spend quite a bit of time in Trac
searching for this but couldn't find it.

Sorry, I searched too but I couldn't find it. I did find an implementation of the conversion in GHC (ByteCodeAsm.mkLitD).

Before implementing a new primop, MachOp, and code generation functions for
that I tried this: Since type signature of this new primop will be same as
float2Int# I thought maybe I should first make current implementation working,
and then I can just change the primop to coerceFloat2Int# and it would work.

However I'm still this same problem(illegal assembly). What I changed is I
looked at the GHC-generated, working STG code that uses float2Int#, and tried
to generate a very similar code myself. The change I had to make for this was
to use a case expression instead of let expression to bind result of this
primop.

Here's an example. This STG is working fine:

     sat_s1Ic :: GHC.Types.Float -> GHC.Types.IO () =
         \r srt:SRT:[0B :-> System.IO.print,
                     rUB :-> GHC.Show.$fShowInt] [ds_s1I7]
             case
                 ds_s1I7 :: GHC.Types.Float :: Alg GHC.Types.Float
             of
             (wild_s1I8 :: GHC.Types.Float)
             { GHC.Types.F# (f_s1I9 :: GHC.Prim.Float#) ->
                   case
                       float2Int# [(f_s1I9 :: GHC.Prim.Float#)] :: Prim
GHC.Prim.Int#
                   of
                   (sat_s1Ia :: GHC.Prim.Int#)
                   { __DEFAULT ->
                         let {
                           sat_s1Ib :: GHC.Types.Int =
                               NO_CCS GHC.Types.I#! [(sat_s1Ia ::
GHC.Prim.Int#)];
                         } in
                           System.IO.print
                             :: forall a_aUq. GHC.Show.Show a_aUq =>
a_aUq -> GHC.Types.IO ()
                               (GHC.Show.$fShowInt :: GHC.Show.Show
GHC.Types.Int)
                               (sat_s1Ib :: GHC.Types.Int);
                   };
             };

(Sorry for extra noisy output, I changed Outputable instances to print some
extra info)

This code is generated by GHC for a program that uses the primop directly and
it's working. This is the code generated by my pass:

     Main.main2 :: [GHC.Types.Char] =
         \u srt:SRT:[r4 :-> Main.showEither2] []
             case
                 case
                     float2Int# [1.2#] :: Prim GHC.Prim.Int#
                 of
                 (co_g21m :: GHC.Prim.Int#)
                 { __DEFAULT -> (#,#) [2## (co_g21m :: GHC.Prim.Int#)];
                 } :: UbxTup 2
             of
             (sat_s21b :: (# GHC.Prim.Int#, GHC.Prim.Int# #))
             { (#,#) (sat_g21R :: GHC.Prim.Int#) (sat_g21S :: GHC.Prim.Int#) ->
                   Main.showEither2
                     :: (# GHC.Prim.Int#, GHC.Prim.Int# #) -> [GHC.Types.Char]
                       (sat_g21R :: GHC.Prim.Int#) (sat_g21S :: GHC.Prim.Int#);
             };

Types look correct, and I'm using a case expression to bind the result of the
primop. But generated assembly for this is still invalid! I'm wondering if
there are some invariants that I'm invalidating here, even although -dstg-lint
is passing. Does anyone know what I might be doing wrong here?

One thing that I'm not being very careful is the information about live
variables, but I don't see how it might be related with this illegal
instruction error.

I'm not sure what you did to get to this point, but let me elaborate on what I think is needed:

- Add primops for the conversions
- Add appropriate MachOps for the conversions (F32 -> I32, F64 -> I64)
- Make sure the primops get compiled into the appropriate MachOps (see StgCmmPrim) - Implement those MachOps in the native code generator (X86/CodeGen.hs). For this part you'll need to figure out what the appropriate x86/x86_64 instructions to generate are; it may be that you need to go via memory, which would be unfortunate.

Cheers,
Simon

Thanks again..

2015-12-07 13:57 GMT-05:00 Simon Marlow <marlo...@gmail.com>:
Simon's right, you need an explicit conversion, and unfortunately those
conversions don't currently exist.  You would have to add them to the MachOp
type, and implement them in each of the native code generators.

The good news is that if you did this, we could implement cheap conversions
between the IEEE floating point types and their representations as unboxed
integers, which is currently done by poking the values to memory and then
peeking them back at the desired type. There's a ticket for this around
somewhere....

Cheers
Simon


On 07/12/2015 12:23, Simon Peyton Jones wrote:

If memory serves, there are primops for converting between unboxed values
of different widths.

Certainly converting between a float and a non-float will require an
instruction on some architectures, since they use different register sets.

Re (2) I have no idea.  You'll need to get more information... pprTrace or
something.

Simon

|  -----Original Message-----
|  From: ghc-devs [mailto:ghc-devs-boun...@haskell.org] On Behalf Of Ömer
|  Sinan Agacan
|  Sent: 06 December 2015 18:25
|  To: ghc-devs <ghc-devs@haskell.org>
|  Subject: question about coercions between primitive types in STG level
|
|  Hi all,
|
|  In my compiler pass(D1559, see ElimUbxSums.hs) I'm doing some unsafe
|  coercions at the STG level. It works fine for lifted types, but for
|  unlifted ones I'm having some problems. What I'm trying to do is given
|  a number of primitive types I'm finding the one with biggest size, and
|  then generating a constructor that takes this biggest primitive type
|  as argument.
|
|  The problem is that this is not working very well - GHC is generating
|  illegal instructions that try to load a F32 value to a register
|  allocated for I64, using movss instruction.
|
|  CoreLint is catching this error and printing this:
|
|      Cmm lint error:
|        in basic block c1hF
|          in assignment:
|            _g16W::I64 = 4.5 :: W32;   // CmmAssign
|            Reg ty: I64
|            Rhs ty: F32
|
|  So I have two questions about this:
|
|  1. Is there a way to safely do this? What are my options here? What
|  I'm trying
|     to do is to use a single data constructor field for different
|  primitive
|     types.  The field is guaranteed to be as big as necessary.
|
|  2. In the Cmm code shown above, the type annotation is showing `W32`
|  but in the
|     error message it says `F32`. I'm confused about this, is this error
|  message
|     given because the sizes don't match? (64bits vs 32bits) Why the
|  type
|     annotation says W32 while the value has type F32?
|
|  Thanks..
|  _______________________________________________
|  ghc-devs mailing list
|  ghc-devs@haskell.org
|  https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.h
|  askell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
|  devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7ced6a1fbfa6254e5
|  2a7d808d2fe6a9a63%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7j3fQs4
|  ox67SZbA4jv4uPVVdvp5X5yUUuMaqp4sh%2fpg%3d
_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


_______________________________________________
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Reply via email to