question about coercions between primitive types in STG level
Simon Marlow
marlowsd at gmail.com
Thu Dec 17 17:15:34 UTC 2015
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 <marlowsd at 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-bounces at haskell.org] On Behalf Of Ömer
>>> | Sinan Agacan
>>> | Sent: 06 December 2015 18:25
>>> | To: ghc-devs <ghc-devs at 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 at 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 at haskell.org
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>>>
>>
More information about the ghc-devs
mailing list