question about coercions between primitive types in STG level
Simon Peyton Jones
simonpj at microsoft.com
Thu Dec 17 12:52:48 UTC 2015
Omer
Honestly I'm out of my depth here, and so time-poor that I don't think I can realistically help much. I hope others can be more useful!
Simon
| -----Original Message-----
| From: Ömer Sinan Ağacan [mailto:omeragacan at gmail.com]
| Sent: 10 December 2015 02:46
| To: Simon Marlow <marlowsd at gmail.com>; Simon Peyton Jones
| <simonpj at microsoft.com>; ghc-devs <ghc-devs at haskell.org>; rwbarton at gmail.com
| Subject: Re: question about coercions between primitive types in STG level
|
| 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.
|
|
| 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 ->
| https://na01.safelinks.protection.outlook.com/?url=GHC.Types.IO&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=BnXCV6rCnP5ibif0LwHYctTd6BVA85horA1D
| 1Uketrk%3d () =
| \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
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#
| of
| (sat_s1Ia ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#)
| { __DEFAULT ->
| let {
| sat_s1Ib ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Types.Int&data=01%7c0
| 1%7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72
| f988bf86f141af91ab2d7cd011db47%7c1&sdata=SP%2fVPreBotFEHkZyK2Y1YSX30dEjkei6h
| PARLyK11Yw%3d =
| NO_CCS GHC.Types.I#! [(sat_s1Ia ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#)];
| } in
| System.IO.print
| :: forall a_aUq. GHC.Show.Show a_aUq => a_aUq ->
| https://na01.safelinks.protection.outlook.com/?url=GHC.Types.IO&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=BnXCV6rCnP5ibif0LwHYctTd6BVA85horA1D
| 1Uketrk%3d ()
| (GHC.Show.$fShowInt :: GHC.Show.Show
| https://na01.safelinks.protection.outlook.com/?url=GHC.Types.Int&data=01%7c0
| 1%7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72
| f988bf86f141af91ab2d7cd011db47%7c1&sdata=SP%2fVPreBotFEHkZyK2Y1YSX30dEjkei6h
| PARLyK11Yw%3d)
| (sat_s1Ib ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Types.Int&data=01%7c0
| 1%7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72
| f988bf86f141af91ab2d7cd011db47%7c1&sdata=SP%2fVPreBotFEHkZyK2Y1YSX30dEjkei6h
| PARLyK11Yw%3d);
| };
| };
|
| (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
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#
| of
| (co_g21m ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#)
| { __DEFAULT -> (#,#) [2## (co_g21m ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#)];
| } :: UbxTup 2
| of
| (sat_s21b :: (#
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#,
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d# #))
| { (#,#) (sat_g21R ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#) (sat_g21S ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#) ->
| Main.showEither2
| :: (#
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#,
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d# #) -> [GHC.Types.Char]
| (sat_g21R ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#) (sat_g21S ::
| https://na01.safelinks.protection.outlook.com/?url=GHC.Prim.Int&data=01%7c01
| %7csimonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7c72f
| 988bf86f141af91ab2d7cd011db47%7c1&sdata=GMVWFJOAJ4IZj2t9WZ2hX3h7xm7U7Dbn0OfU
| gjON958%3d#);
| };
|
| 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.
|
| 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%2fmai
| >> | l.h
| >> | askell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| >> |
| >> | devs&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7ced6a1fbfa625
| >> | 4e5
| >> |
| >> | 2a7d808d2fe6a9a63%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7j3f
| >> | Qs4 ox67SZbA4jv4uPVVdvp5X5yUUuMaqp4sh%2fpg%3d
| >> _______________________________________________
| >> ghc-devs mailing list
| >> ghc-devs at haskell.org
| >> https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.
| >> haskell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-devs&data=01%7c01%7c
| >> simonpj%40064d.mgd.microsoft.com%7c900655295d074c8b867b08d3010c2165%7
| >> c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=DYbGX1f9UBqSTEN9qDWBiqM9H
| >> ucMEitgBCnh4ZZjneg%3d
| >>
| >
More information about the ghc-devs
mailing list