[Git][ghc/ghc][master] Allow disabling builtin rules (#20298)
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 5ae89054 by Sylvain Henry at 2025-09-24T17:07:00-04:00 Allow disabling builtin rules (#20298) Add a way to disable built-in rules programmatically and with a debug flag. I also took the opportunity to add a debug flag to disable bignum rules, which was only possible programmatically (e.g. in a plugin). - - - - - 14 changed files: - compiler/GHC/Core/Opt/ConstantFold.hs - compiler/GHC/Core/Rules.hs - compiler/GHC/Core/Rules/Config.hs - compiler/GHC/Driver/Config/Core/Rules.hs - compiler/GHC/Driver/Flags.hs - compiler/GHC/Driver/Session.hs - docs/users_guide/debugging.rst - + testsuite/tests/codeGen/should_compile/T20298a.hs - + testsuite/tests/codeGen/should_compile/T20298a.stderr - + testsuite/tests/codeGen/should_compile/T20298b.hs - + testsuite/tests/codeGen/should_compile/T20298b.stderr - + testsuite/tests/codeGen/should_compile/T20298c.hs - + testsuite/tests/codeGen/should_compile/T20298c.stderr - testsuite/tests/codeGen/should_compile/all.T Changes: ===================================== compiler/GHC/Core/Opt/ConstantFold.hs ===================================== @@ -2173,6 +2173,43 @@ builtinRules -- there is no benefit to inlining these yet, despite this, GHC produces -- unfoldings for this regardless since the floated list entries look small. + + +{- Note [Built-in bignum rules] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We have some built-in rules for operations on bignum types (Integer, Natural, +BigNat). These rules implement the same kind of constant folding as we have for +Int#/Word#/etc. primops. See builtinBignumRules. + +These rules are built-in because they can't be expressed as regular rules for +now. The reason is that due to the let-can-float invariant (see Note [Core +let-can-float invariant] in GHC.Core), GHC is too conservative with some bignum +operations and they don't match rules. For example: + + case integerAdd 1 x of r { _ -> integerAdd 1 r } + +doesn't constant-fold into `integerAdd 2 x` with a regular rule. That's because +GHC never floats in `integerAdd 1 x` to form `integerAdd 1 (integerAdd 1 x)` +because of the let-can-float invariant (it doesn't know if `integerAdd` +terminates). + +In the built-in rule for `integerAdd` we can access the unfolding of `r` and we +can perform the appropriate substitution. + +To support constant-folding, Bignum operations are not allowed to inline. As a +consequence, some codes that would benefit from inlining of bignum operations +don't. An idea to fix this was to only have built-in rules for BigNat# +operations and to allow Integer and Natural operations to inline. However these +operations are often too big to inline and we end up with broken +constant-folding and still no inlining. This issue is tracked in #20361 + +Bignum built-in rules can be disabled independently of other built-in rules by +passing the -dno-bignum-rules flag or programmatically with the `roBignumRules` field of +RuleOpts. + +-} + +-- | Built-in bignum rules (see Note [Built-in bignum rules]) builtinBignumRules :: [CoreRule] builtinBignumRules = [ -- conversions ===================================== compiler/GHC/Core/Rules.hs ===================================== @@ -65,6 +65,7 @@ import GHC.Core.Map.Expr ( eqCoreExpr ) import GHC.Core.Opt.Arity( etaExpandToJoinPointRule ) import GHC.Core.Make ( mkCoreLams ) import GHC.Core.Opt.OccurAnal( occurAnalyseExpr ) +import GHC.Core.Rules.Config (roBuiltinRules) import GHC.Tc.Utils.TcType ( tcSplitTyConApp_maybe ) import GHC.Builtin.Types ( anyTypeOfKind ) @@ -708,10 +709,8 @@ matchRule :: HasDebugCallStack matchRule opts rule_env _is_active fn args _rough_args (BuiltinRule { ru_try = match_fn }) --- Built-in rules can't be switched off, it seems - = case match_fn opts rule_env fn args of - Nothing -> Nothing - Just expr -> Just expr + | not (roBuiltinRules opts) = Nothing + | otherwise = match_fn opts rule_env fn args matchRule _ rule_env is_active _ args rough_args (Rule { ru_name = rule_name, ru_act = act, ru_rough = tpl_tops ===================================== compiler/GHC/Core/Rules/Config.hs ===================================== @@ -14,6 +14,10 @@ data RuleOpts = RuleOpts , roExcessRationalPrecision :: !Bool -- ^ Cut down precision of Rational values to that of Float/Double if disabled , roBignumRules :: !Bool - -- ^ Enable rules for bignums + -- ^ Enable built-in bignum rules (requires roBuiltinRules to be True too) + -- + -- See Note [Built-in bignum rules] in GHC.Core.Opt.ConstantFold + , roBuiltinRules :: !Bool + -- ^ Enable or disable all builtin rules (including bignum rules) } ===================================== compiler/GHC/Driver/Config/Core/Rules.hs ===================================== @@ -15,5 +15,6 @@ initRuleOpts dflags = RuleOpts { roPlatform = targetPlatform dflags , roNumConstantFolding = gopt Opt_NumConstantFolding dflags , roExcessRationalPrecision = gopt Opt_ExcessPrecision dflags - , roBignumRules = True + , roBignumRules = not (gopt Opt_NoBignumRules dflags) + , roBuiltinRules = not (gopt Opt_NoBuiltinRules dflags) } ===================================== compiler/GHC/Driver/Flags.hs ===================================== @@ -592,6 +592,8 @@ data GeneralFlag | Opt_NoLlvmMangler -- hidden flag | Opt_FastLlvm -- hidden flag | Opt_NoTypeableBinds + | Opt_NoBuiltinRules + | Opt_NoBignumRules | Opt_DistinctConstructorTables | Opt_InfoTableMap @@ -973,6 +975,8 @@ codeGenFlags = EnumSet.fromList , Opt_ExposeAllUnfoldings , Opt_ExposeOverloadedUnfoldings , Opt_NoTypeableBinds + , Opt_NoBuiltinRules + , Opt_NoBignumRules , Opt_ObjectDeterminism , Opt_Haddock ===================================== compiler/GHC/Driver/Session.hs ===================================== @@ -1660,6 +1660,10 @@ dynamic_flags_deps = [ (NoArg (setGeneralFlag Opt_NoLlvmMangler)) -- hidden flag , make_ord_flag defGhcFlag "dno-typeable-binds" (NoArg (setGeneralFlag Opt_NoTypeableBinds)) + , make_ord_flag defGhcFlag "dno-builtin-rules" + (NoArg (setGeneralFlag Opt_NoBuiltinRules)) + , make_ord_flag defGhcFlag "dno-bignum-rules" + (NoArg (setGeneralFlag Opt_NoBignumRules)) , make_ord_flag defGhcFlag "ddump-debug" (setDumpFlag Opt_D_dump_debug) , make_dep_flag defGhcFlag "ddump-json" ===================================== docs/users_guide/debugging.rst ===================================== @@ -1225,6 +1225,18 @@ Other compiler will panic if you try to use Typeable instances of things that you built with this flag. +.. ghc-flag:: -dno-builtin-rules + :shortdesc: Disable all built-in rewrite rules + :type: dynamic + + This disables all the built-in rewrite rules. Mostly useful for debugging. + +.. ghc-flag:: -dno-bignum-rules + :shortdesc: Disable bignum built-in rewrite rules + :type: dynamic + + This disables bignum built-in rewrite rules. Mostly useful for debugging. + .. ghc-flag:: -dtag-inference-checks :shortdesc: Affirm tag inference results are correct at runtime. :type: dynamic ===================================== testsuite/tests/codeGen/should_compile/T20298a.hs ===================================== @@ -0,0 +1,4 @@ +module T20298a where + +foo :: Integer +foo = 10 + 20 ===================================== testsuite/tests/codeGen/should_compile/T20298a.stderr ===================================== @@ -0,0 +1,9 @@ + +==================== Tidy Core ==================== +Result size of Tidy Core + = {terms: 3, types: 1, coercions: 0, joins: 0/0} + +foo = IS 30# + + + ===================================== testsuite/tests/codeGen/should_compile/T20298b.hs ===================================== @@ -0,0 +1,4 @@ +module T20298b where + +foo :: Integer +foo = 10 + 20 ===================================== testsuite/tests/codeGen/should_compile/T20298b.stderr ===================================== @@ -0,0 +1,13 @@ + +==================== Tidy Core ==================== +Result size of Tidy Core + = {terms: 10, types: 3, coercions: 0, joins: 0/0} + +foo2 = IS 10# + +foo1 = IS 20# + +foo = integerAdd foo2 foo1 + + + ===================================== testsuite/tests/codeGen/should_compile/T20298c.hs ===================================== @@ -0,0 +1,4 @@ +module T20298c where + +foo :: Integer +foo = 10 + 20 ===================================== testsuite/tests/codeGen/should_compile/T20298c.stderr ===================================== @@ -0,0 +1,13 @@ + +==================== Tidy Core ==================== +Result size of Tidy Core + = {terms: 11, types: 4, coercions: 0, joins: 0/0} + +foo2 = IS 10# + +foo1 = IS 20# + +foo = + $fNumInteger foo2 foo1 + + + ===================================== testsuite/tests/codeGen/should_compile/all.T ===================================== @@ -145,3 +145,7 @@ test('T25166', [req_cmm], makefile_test, []) test('T25177', normal, compile, ['-O2 -dno-typeable-binds -ddump-simpl -dsuppress-all -dsuppress-uniques -v0']) test('T16351', normal, compile, ['-O2 -ddump-simpl -dno-typeable-binds -dsuppress-all -dsuppress-uniques']) + +test('T20298a', normal, compile, ['-O2 -ddump-simpl -dno-typeable-binds -dsuppress-all -dsuppress-uniques']) +test('T20298b', normal, compile, ['-O2 -dno-bignum-rules -ddump-simpl -dno-typeable-binds -dsuppress-all -dsuppress-uniques']) +test('T20298c', normal, compile, ['-O2 -dno-builtin-rules -ddump-simpl -dno-typeable-binds -dsuppress-all -dsuppress-uniques']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5ae89054d14c5dfd42ab5bc4fff8e50b... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5ae89054d14c5dfd42ab5bc4fff8e50b... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)