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
