[GHC] #13614: Rewrite rules not applied exhaustively when simplifying from plugin

GHC ghc-devs at haskell.org
Tue Apr 25 16:19:58 UTC 2017


#13614: Rewrite rules not applied exhaustively when simplifying from plugin
-------------------------------------+-------------------------------------
           Reporter:  nomeata        |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  GHC API        |           Version:  8.1
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Consider this program:
 {{{
 {-# OPTIONS_GHC -O -fplugin TestPlugin #-}
 module Test where

 foo :: Int -> Int
 foo = id
 {-# INLINE [0] foo #-}

 {-# RULES
 "foo1" [1] foo 1 = foo 2
 "foo2" [1] foo 2 = foo 3
  #-}

 fun :: Int -> Int -> Int
 fun = (+)
 {-# NOINLINE fun #-}

 test = foo 1 `fun` foo 2
 }}}

 I would expect that one run of the simplifier in phase `1` will turn this
 into
 {{{
 test = foo 3 `fun` foo 3
 }}}

 I am using this plugin to test this:
 {{{
 module TestPlugin where

 import System.Exit
 import Control.Monad

 import GhcPlugins
 import Simplify
 import CoreStats
 import SimplMonad
 import FamInstEnv
 import SimplEnv

 -- Plugin boiler plate

 plugin :: Plugin
 plugin = defaultPlugin { installCoreToDos = install }

 install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
 install _ (simpl:xs) = return $ simpl : pass : xs
   where pass = CoreDoPluginPass "Test" testPass

 -- The plugin

 testPass :: ModGuts -> CoreM ModGuts
 testPass guts = do
     let [expr] = [ e | NonRec v e <- mg_binds guts
                      , occNameString (occName v) == "test" ]
     simplified_expression <- simplify guts expr

     putMsg $
         text "Test" $$
         nest 4 (hang (text "Before" <> colon) 4 (ppr expr)) $$
         nest 4 (hang (text "After" <> colon) 4 (ppr
 simplified_expression))

     liftIO $ exitFailure

 -- A simplifier

 simplify :: ModGuts -> CoreExpr -> CoreM CoreExpr
 simplify guts expr = do
     dflags <- getDynFlags

     let dflags' = dflags { ufVeryAggressive = True }
     us <- liftIO $ mkSplitUniqSupply 's'
     let sz = exprSize expr

     rule_base <- getRuleBase
     vis_orphs <- getVisibleOrphanMods
     let rule_base2 = extendRuleBaseList rule_base (mg_rules guts)
     let rule_env = RuleEnv rule_base2 vis_orphs

     (expr', _) <- liftIO $ initSmpl dflags' rule_env emptyFamInstEnvs us
 sz $
         simplExpr (simplEnv 1) >=> simplExpr (simplEnv 1) $
         expr
     return expr'

 simplEnv :: Int -> SimplEnv
 simplEnv p = mkSimplEnv $ SimplMode { sm_names = ["Test"]
                                     , sm_phase = Phase p
                                     , sm_rules = True
                                     , sm_inline = True
                                     , sm_eta_expand = True
                                     , sm_case_case = True }
 }}}

 But I get:

 {{{
 $ ghc-head -package ghc Test.hs
 [1 of 2] Compiling TestPlugin       ( TestPlugin.hs, TestPlugin.o )
 [2 of 2] Compiling Test             ( Test.hs, Test.o )
 Test
     Before: fun (foo (GHC.Types.I# 1#)) (foo (GHC.Types.I# 2#))
     After: fun (foo (GHC.Types.I# 2#)) (foo (GHC.Types.I# 3#))
 }}}

 If I however compile this without the plugin, and look at what’s happening
 with `-dverbose-core2core`, I observe this:

 {{{
 …
 test :: Int
 test = fun (foo (GHC.Types.I# 1#)) (foo (GHC.Types.I# 2#))
 …
 ==================== Simplifier ====================
   Max iterations = 4
   SimplMode {Phase = 1 [main],
              inline,
              rules,
              eta-expand,
              case-of-case}
 …
 test :: Int
 test = fun (foo (GHC.Types.I# 3#)) (foo (GHC.Types.I# 3#))
 …
 }}}

 So what am I doing wrong in my plugin? Any help is appreciated.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13614>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list