[commit: ghc] master: Case-of-empty-alts is trivial (Trac #11155) (1c9fd3f)

git at git.haskell.org git at git.haskell.org
Fri Dec 4 14:21:09 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/1c9fd3f1c5522372fcaf250c805b959e8090a62c/ghc

>---------------------------------------------------------------

commit 1c9fd3f1c5522372fcaf250c805b959e8090a62c
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Thu Dec 3 12:57:54 2015 +0000

    Case-of-empty-alts is trivial (Trac #11155)
    
    As you'll see from Trac #11155, the code generator was confused
    by a binding let x = y in ....   Why did that happen? Because of
    a (case y of {}) expression on the RHS.
    
    The right thing is just to expand what a "trivial" expression is.
    
    See Note [Empty case is trivial] in CoreUtils.


>---------------------------------------------------------------

1c9fd3f1c5522372fcaf250c805b959e8090a62c
 compiler/coreSyn/CorePrep.hs                       | 20 +++++++++++---------
 compiler/coreSyn/CoreUtils.hs                      | 20 +++++++++++++++++++-
 testsuite/tests/simplCore/should_compile/Makefile  |  6 ++++++
 testsuite/tests/simplCore/should_compile/T11155.hs | 11 +++++++++++
 testsuite/tests/simplCore/should_compile/all.T     |  5 ++++-
 5 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/compiler/coreSyn/CorePrep.hs b/compiler/coreSyn/CorePrep.hs
index fdf25d6..999ca54 100644
--- a/compiler/coreSyn/CorePrep.hs
+++ b/compiler/coreSyn/CorePrep.hs
@@ -847,15 +847,17 @@ of the scope of a `seq`, or dropped the `seq` altogether.
 
 cpe_ExprIsTrivial :: CoreExpr -> Bool
 -- Version that doesn't consider an scc annotation to be trivial.
-cpe_ExprIsTrivial (Var _)        = True
-cpe_ExprIsTrivial (Type _)       = True
-cpe_ExprIsTrivial (Coercion _)   = True
-cpe_ExprIsTrivial (Lit _)        = True
-cpe_ExprIsTrivial (App e arg)    = isTypeArg arg && cpe_ExprIsTrivial e
-cpe_ExprIsTrivial (Tick t e)     = not (tickishIsCode t) && cpe_ExprIsTrivial e
-cpe_ExprIsTrivial (Cast e _)     = cpe_ExprIsTrivial e
-cpe_ExprIsTrivial (Lam b body) | isTyVar b = cpe_ExprIsTrivial body
-cpe_ExprIsTrivial _              = False
+cpe_ExprIsTrivial (Var _)         = True
+cpe_ExprIsTrivial (Type _)        = True
+cpe_ExprIsTrivial (Coercion _)    = True
+cpe_ExprIsTrivial (Lit _)         = True
+cpe_ExprIsTrivial (App e arg)     = not (isRuntimeArg arg) && cpe_ExprIsTrivial e
+cpe_ExprIsTrivial (Lam b e)       = not (isRuntimeVar b) && cpe_ExprIsTrivial e
+cpe_ExprIsTrivial (Tick t e)      = not (tickishIsCode t) && cpe_ExprIsTrivial e
+cpe_ExprIsTrivial (Cast e _)      = cpe_ExprIsTrivial e
+cpe_ExprIsTrivial (Case e _ _ []) = cpe_ExprIsTrivial e
+                                    -- See Note [Empty case is trivial] in CoreUtils
+cpe_ExprIsTrivial _               = False
 
 {-
 -- -----------------------------------------------------------------------------
diff --git a/compiler/coreSyn/CoreUtils.hs b/compiler/coreSyn/CoreUtils.hs
index 889e239..5c1c986 100644
--- a/compiler/coreSyn/CoreUtils.hs
+++ b/compiler/coreSyn/CoreUtils.hs
@@ -733,11 +733,28 @@ saturating them.
 
 Note [Tick trivial]
 ~~~~~~~~~~~~~~~~~~~
-
 Ticks are only trivial if they are pure annotations. If we treat
 "tick<n> x" as trivial, it will be inlined inside lambdas and the
 entry count will be skewed, for example.  Furthermore "scc<n> x" will
 turn into just "x" in mkTick.
+
+Note [Empty case is trivial]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The expression (case (x::Int) Bool of {}) is just a type-changing
+case used when we are sure that 'x' will not return.  See
+Note [Empty case alternatives] in CoreSyn.
+
+If the scrutinee is trivial, then so is the whole expression; and the
+CoreToSTG pass in fact drops the case expression leaving only the
+scrutinee.
+
+Having more trivial expressions is good.  Moreover, if we don't treat
+it as trivial we may land up with let-bindings like
+   let v = case x of {} in ...
+and after CoreToSTG that gives
+   let v = x in ...
+and that confuses the code generator (Trac #11155). So best to kill
+it off at source.
 -}
 
 exprIsTrivial :: CoreExpr -> Bool
@@ -750,6 +767,7 @@ exprIsTrivial (Tick t e)       = not (tickishIsCode t) && exprIsTrivial e
                                  -- See Note [Tick trivial]
 exprIsTrivial (Cast e _)       = exprIsTrivial e
 exprIsTrivial (Lam b body)     = not (isRuntimeVar b) && exprIsTrivial body
+exprIsTrivial (Case e _ _ [])  = exprIsTrivial e  -- See Note [Empty case is trivial]
 exprIsTrivial _                = False
 
 {-
diff --git a/testsuite/tests/simplCore/should_compile/Makefile b/testsuite/tests/simplCore/should_compile/Makefile
index 8c6ec45..eb6d742 100644
--- a/testsuite/tests/simplCore/should_compile/Makefile
+++ b/testsuite/tests/simplCore/should_compile/Makefile
@@ -6,6 +6,12 @@ T8832:
 	$(RM) -f T8832.o T8832.hi
 	'$(TEST_HC)' $(TEST_HC_OPTS) $(T8832_WORDSIZE_OPTS) -O -c -ddump-simpl T8832.hs | grep '^[a-zA-Z0-9]\+ ='
 
+T11155:
+	$(RM) -f T11155.o T11155.hi
+	'$(TEST_HC)' $(TEST_HC_OPTS) -c T11155.hs
+	-nm T11155.o  | grep 'stg_ap_0_upd'
+	# Expecting no output from the grep
+
 T8274:
 	$(RM) -f T8274.o T8274.hi
 	'$(TEST_HC)' $(TEST_HC_OPTS) -O -c -ddump-simpl T8274.hs | grep '#'
diff --git a/testsuite/tests/simplCore/should_compile/T11155.hs b/testsuite/tests/simplCore/should_compile/T11155.hs
new file mode 100644
index 0000000..b57bbe9
--- /dev/null
+++ b/testsuite/tests/simplCore/should_compile/T11155.hs
@@ -0,0 +1,11 @@
+{-# OPTIONS_GHC -O -fno-full-laziness #-}
+module T11155 where
+
+foo :: Bool
+{-# NOINLINE foo #-}
+foo = error "rk"
+
+bar x = let t :: Char
+            t = case foo of { True -> 'v'; False -> 'y' }
+        in [t]
+
diff --git a/testsuite/tests/simplCore/should_compile/all.T b/testsuite/tests/simplCore/should_compile/all.T
index c99b8f2..f9388c9 100644
--- a/testsuite/tests/simplCore/should_compile/all.T
+++ b/testsuite/tests/simplCore/should_compile/all.T
@@ -224,4 +224,7 @@ test('T10083',
      run_command,
      ['$MAKE -s --no-print-directory T10083'])
 test('T10689', normal, compile, [''])
-test('T10689a', normal, compile, [''])
+test('T11155',
+     normal,
+     run_command,
+     ['$MAKE -s --no-print-directory T11155'])



More information about the ghc-commits mailing list