
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
: 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-bounces@haskell.org] On Behalf Of Ömer | Sinan Agacan | Sent: 06 December 2015 18:25 | To: ghc-devs
| 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