Jan

I'm conscious that we have not closed the loop on this thread, below.  (I think 
the attached email is also relevant.) 

If it's not sorted out, can you open a ticket, put in the relevant info (so we 
don't need to look at the email trail), and we can tackle it when you get here.

Simon

-----Original Message-----
From: [email protected] [mailto:[email protected]] On 
Behalf Of Jan Stolarek
Sent: 20 May 2013 12:35
To: Ian Lynagh
Cc: [email protected]
Subject: Re: Integer constant folding in the presence of new primops

> If you remove everything but the quotInteger test from 
> integerConstantFolding and compile with -ddump-rule-rewrites then 
> you'll see that the eqInteger rule fires before quotInteger. This is 
> presumably comparing against 0, as the definition of quot for Integer 
> (in GHC.Real) is
>     _ `quot` 0 = divZeroError
>     n `quot` d = n `quotInteger` d
Yes, I noticed these two rules firing together - perhaps that's the explanation 
why. I created a small program for testing:

main = print quotInt
quotInt :: Integer
quotInt = 100063 `quot` 156

I noticed that when I define eqInteger wrapper to be NOINLINE, the call to quot 
is translated to Core as:

Main.quotInt =
  GHC.Real.$fIntegralInteger_$cquot
    (__integer 100063) (__integer 156)

but when I change the wrapper to INLINE I get:

Main.quotInt =
  GHC.Real.$fNumRatio_$cquot             <-------- NumRatio instead of 
IntegralInteger
    (__integer 100063) (__integer 156)

All rule firing happens later (I used -ddump-simpl-iterations 
-ddump-rule-firings), except that for $fNumRatio_$cquot the quot rules don't 
fire.

> Do you also still have eqInteger wired in? It sounds like you might 
> have given them both the same unique?
No, they didn't have the same unique. I modified the existing rules to work on 
the new primops and ignore their wrappers. At the moment I reverted these 
changes so that I can make progress and leave this problem for later.

Janek

_______________________________________________
ghc-devs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/ghc-devs
--- Begin Message ---
> All the same issues arise for Int# too, right?
I guess you're right :) I removed the rules for wrappers (eqInteger) and 
created rules
for "primOps" (eqIntegerPrim, which I think I'll rename to eqInteger#)

> Why?  Because eqInteger is now inlined, so the rule doesn't get a chance to
> fire?
There's something very subtle going on with inlining and I can't grasp what it 
is. At the moment I
have this in prelude/PrelNames.lhs:

eqIntegerPrimIdKey      = mkPreludeMiscIdUnique 70
eqIntegerPrimName     = varQual gHC_INTEGER_TYPE (fsLit "eqIntegerPrim")     
eqIntegerPrimIdKey

and in prelude/PrelRules.lhs I have this:

builtinIntegerRules = [
  ...
   rule_binop_Prim     "eqIntegerPrim"       eqIntegerPrimName       (==),
  ...]
    where
          rule_binop_Prim str name op
           = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
                           ru_try = match_Integer_binop_Prim op }

match_Integer_binop_Prim binop dflags _ id_unf [xl, yl]
  | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
  , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
  = Just (if x `binop` y then trueValInt dflags else falseValInt dflags)
match_Integer_binop_Prim _ _ _ _ _ = Nothing

My understanding is that this rule will fire if it finds a function 
"eqIntegerPrim" with two
Integer literals as parameters. Given my definitions in integer-gmp library:

{-# NOINLINE eqIntegerPrim #-}
eqIntegerPrim :: Integer -> Integer -> Int#
eqIntegerPrim ... -- same as before, but uses new primops

{-# INLINE eqInteger #-}
eqInteger :: Integer -> Integer -> Bool
eqInteger  a b = tagToEnum# (a `eqIntegerPrim`  b)

my understanding is that in expression:

    eqIntegerE = (100012 :: Integer) == 100012

the (==) gets inlined to eqInteger:

    eqIntegerE = (100012 :: Integer) `eqInteger` 100012

which in turn gets inlined to eqIntegerPrim:

    eqIntegerE = tagToEnum# ((100012 :: Integer) `eqIntegerPrim` 100012)

At this point inling stops (because of NOINLINE) and my rule fires giving:

    eqIntegerE = tagToEnum# 1#

which in turns allows the rule for tagToEnum# to fire, giving:

    eqIntegerE = GHC.Prim.True

Now here's the tricky part. I'm testing this with test 
lib/integer/integerConstantFolding in the
testsuite and the test fails because rules for quotRemInteger, divModInteger, 
quotInteger and
remInteger don't fire, leaving the constants unfolded. I noticed that if I mark 
eqInteger with
NOINLINE, then these rules fire, but then obviously comparisons like (100012 :: 
Integer) ==
100012 don't get folded and the test fails anyway. I'm analyzing how the 
function quotInteger and
others use eqInteger, but I don't see anything that would be obvious.

Janek

--- End Message ---
_______________________________________________
ghc-devs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/ghc-devs

Reply via email to