diff --git a/compiler/GHC/Stg/CSE.hs b/compiler/GHC/Stg/CSE.hs
index eb52d6f8d215e469b30ebaaf2ba1e29a4e37fa24..9f5f196e2808c719aef8f4fffdf86ab7e5f1f3ab 100644
--- a/compiler/GHC/Stg/CSE.hs
+++ b/compiler/GHC/Stg/CSE.hs
@@ -71,6 +71,11 @@ and nothing stops us from transforming that to
                           , Right [x] -> b}
 
 
+Note that this can revive dead case binders (e.g. "b" above), hence we zap
+occurrence information on all case binders during STG CSE.
+See Note [Dead-binder optimisation] in GHC.StgToCmm.Expr.
+
+
 Note [StgCse after unarisation]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -344,16 +349,20 @@ stgCseExpr env (StgTick tick body)
     = let body' = stgCseExpr env body
       in StgTick tick body'
 stgCseExpr env (StgCase scrut bndr ty alts)
-    = mkStgCase scrut' bndr' ty alts'
+    = mkStgCase scrut' bndr'' ty alts'
   where
     scrut' = stgCseExpr env scrut
     (env1, bndr') = substBndr env bndr
+    -- we must zap occurrence information on the case binder
+    -- because CSE might revive it.
+    -- See Note [Dead-binder optimisation] in GHC.StgToCmm.Expr
+    bndr'' = zapIdOccInfo bndr'
     env2 | StgApp trivial_scrut [] <- scrut'
          = addTrivCaseBndr bndr trivial_scrut env1
                  -- See Note [Trivial case scrutinee]
          | otherwise
          = env1
-    alts' = map (stgCseAlt env2 ty bndr') alts
+    alts' = map (stgCseAlt env2 ty bndr'') alts
 
 
 -- A constructor application.
diff --git a/compiler/GHC/StgToCmm/Expr.hs b/compiler/GHC/StgToCmm/Expr.hs
index e86e5a76ae0a04d34ba0cc5de28b141ec471f109..4887857296eee1f1b685c3517df300d0444410fd 100644
--- a/compiler/GHC/StgToCmm/Expr.hs
+++ b/compiler/GHC/StgToCmm/Expr.hs
@@ -446,21 +446,49 @@ calls to nonVoidIds in various places.  So we must not look up
 
 Note [Dead-binder optimisation]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A case-binder, or data-constructor argument, may be marked as dead,
-because we preserve occurrence-info on binders in GHC.Core.Tidy (see
+Consider:
+
+   case x of (y, z<dead>) -> rhs
+
+where `z` is unused in `rhs`.  When we return form the eval of `x`,
+GHC.StgToCmm.DataCon.bindConArgs will generate some loads, assuming the the
+value of `x` is returned in R1:
+   y := R1[1]
+   z := R1[2]
+
+If `z` is never used, the load `z := R1[2]` is a waste of a memory operation.
+CmmSink (which sinks loads to their usage sites, if any) will eliminate the dead
+load; but
+  1. CmmSink only runs with -O
+  2. It would save CmmSink work if we simply did not generate the load in the
+  first place.
+
+Hence STG uses dead-binder information, in `bindConArgs` to drop dead loads.
+That's why we preserve occurrence-info on binders in GHC.Core.Tidy (see
 GHC.Core.Tidy.tidyIdBndr).
 
-If the binder is dead, we can sometimes eliminate a load.  While
-CmmSink will eliminate that load, it's very easy to kill it at source
-(giving CmmSink less work to do), and in any case CmmSink only runs
-with -O. Since the majority of case binders are dead, this
-optimisation probably still has a great benefit-cost ratio and we want
-to keep it for -O0. See also Phab:D5358.
-
-This probably also was the reason for occurrence hack in Phab:D5339 to
-exist, perhaps because the occurrence information preserved by
-'GHC.Core.Tidy.tidyIdBndr' was insufficient.  But now that CmmSink does the
-job we deleted the hacks.
+So it's important that deadness is accurate.  But StgCse can invalidate it
+(#14895 #24233).  Here is an example:
+
+  map_either :: (a -> b) -> Either String a -> Either String b
+  map_either = \f e -> case e of b<dead> {
+    Right x -> Right (f x)
+    Left  x -> Left x
+  }
+
+  The case-binder "b" is dead (not used in the rhss of the alternatives).
+  StgCse notices that `Left x` doesn't need to be allocated as we can reuse `b`,
+  and we get:
+
+  map_either :: (a -> b) -> Either String a -> Either String b
+  map_either = \f e -> case e of b { -- b no longer dead!
+    Right x -> Right (f x)
+    Left  x -> b
+  }
+
+For now StgCse simply zaps occurrence information on case binders. A more
+accurate update would complexify the implementation and doesn't seem worth it.
+
 -}
 
 cgCase (StgApp v []) _ (PrimAlt _) alts
diff --git a/testsuite/tests/core-to-stg/T14895.hs b/testsuite/tests/core-to-stg/T14895.hs
new file mode 100644
index 0000000000000000000000000000000000000000..ef1458ecbbeeade69ef0159de9ef67350c4a85cc
--- /dev/null
+++ b/testsuite/tests/core-to-stg/T14895.hs
@@ -0,0 +1,5 @@
+module T14895 where
+
+go :: (a -> b) -> Either String a -> Either String b
+go f (Right a) = Right (f a)
+go _ (Left e)  = Left e
diff --git a/testsuite/tests/core-to-stg/T14895.stderr b/testsuite/tests/core-to-stg/T14895.stderr
new file mode 100644
index 0000000000000000000000000000000000000000..bf951646e5fc0585081855068657b9e662821b1e
--- /dev/null
+++ b/testsuite/tests/core-to-stg/T14895.stderr
@@ -0,0 +1,20 @@
+
+==================== Final STG: ====================
+T14895.go
+  :: forall a b.
+     (a -> b)
+     -> Data.Either.Either GHC.Base.String a
+     -> Data.Either.Either GHC.Base.String b
+[GblId, Arity=2, Str=<MC(1,L)><1L>, Unf=OtherCon []] =
+    {} \r [f ds]
+        case ds of wild {
+          Data.Either.Left e [Occ=Once1] -> wild<TagProper>;
+          Data.Either.Right a1 [Occ=Once1] ->
+              let {
+                sat [Occ=Once1] :: b
+                [LclId] =
+                    {a1, f} \u [] f a1;
+              } in  Data.Either.Right [sat];
+        };
+
+
diff --git a/testsuite/tests/core-to-stg/all.T b/testsuite/tests/core-to-stg/all.T
index e353cb8f7d7c33b7ac20d12996a072c3ba027727..ed2231bfbb9cfec7f6803815c8caf6dbdd169fcd 100644
--- a/testsuite/tests/core-to-stg/all.T
+++ b/testsuite/tests/core-to-stg/all.T
@@ -3,3 +3,4 @@
 test('T19700', normal, compile, ['-O'])
 test('T23270', [grep_errmsg(r'patError')], compile, ['-O0 -dsuppress-uniques -ddump-prep'])
 test('T23914', normal, compile, ['-O'])
+test('T14895', normal, compile, ['-O -ddump-stg-final -dno-typeable-binds -dsuppress-uniques'])
diff --git a/testsuite/tests/simplCore/should_compile/T22309.stderr b/testsuite/tests/simplCore/should_compile/T22309.stderr
index ac0c768688aca60abfed35bdb8fe852ecb709992..65185b546d62bf91605d9a3a613cbccd10686104 100644
--- a/testsuite/tests/simplCore/should_compile/T22309.stderr
+++ b/testsuite/tests/simplCore/should_compile/T22309.stderr
@@ -9,45 +9,46 @@ $WMkW_NA :: NU_A %1 -> WNU_A =
         case conrep of conrep1 { __DEFAULT -> MkW_NA [conrep1]; };
 
 $WMkW_F :: UF %1 -> WU_F =
-    \r [conrep] case conrep of { Mk_F us -> MkW_F [us]; };
+    \r [conrep] case conrep of conrep1 { Mk_F us -> MkW_F [us]; };
 
 $WMkW_E :: UE %1 -> WU_E =
-    \r [conrep] case conrep of { Mk_E us -> MkW_E [us]; };
+    \r [conrep] case conrep of conrep1 { Mk_E us -> MkW_E [us]; };
 
 $WMkW_D :: UD %1 -> WU_D =
     \r [conrep]
-        case conrep of { Mk_D unbx unbx1 -> MkW_D [unbx unbx1]; };
+        case conrep of conrep1 { Mk_D unbx unbx1 -> MkW_D [unbx unbx1]; };
 
 $WMkW_C :: UC %1 -> WU_C =
-    \r [conrep] case conrep of { Mk_C unbx -> MkW_C [unbx]; };
+    \r [conrep] case conrep of conrep1 { Mk_C unbx -> MkW_C [unbx]; };
 
 $WMkW_B :: UB %1 -> WU_B =
-    \r [conrep] case conrep of { Mk_B unbx -> MkW_B [unbx]; };
+    \r [conrep] case conrep of conrep1 { Mk_B unbx -> MkW_B [unbx]; };
 
 $WMkW_A :: UA %1 -> WU_A =
-    \r [conrep] case conrep of { Mk_A unbx -> MkW_A [unbx]; };
+    \r [conrep] case conrep of conrep1 { Mk_A unbx -> MkW_A [unbx]; };
 
 $WNU_MkB :: Int64 %1 -> Int64 %1 -> NU_B =
     \r [conrep conrep1]
-        case conrep of {
+        case conrep of conrep2 {
         I64# unbx ->
-        case conrep1 of { I64# unbx1 -> NU_MkB [unbx unbx1]; };
+        case conrep1 of conrep3 { I64# unbx1 -> NU_MkB [unbx unbx1]; };
         };
 
 $WMk_D :: Int32 %1 -> Int32 %1 -> UD =
     \r [conrep conrep1]
-        case conrep of {
-        I32# unbx -> case conrep1 of { I32# unbx1 -> Mk_D [unbx unbx1]; };
+        case conrep of conrep2 {
+        I32# unbx ->
+        case conrep1 of conrep3 { I32# unbx1 -> Mk_D [unbx unbx1]; };
         };
 
 $WMk_C :: Int32 %1 -> UC =
-    \r [conrep] case conrep of { I32# unbx -> Mk_C [unbx]; };
+    \r [conrep] case conrep of conrep1 { I32# unbx -> Mk_C [unbx]; };
 
 $WMk_B :: Int64 %1 -> UB =
-    \r [conrep] case conrep of { I64# unbx -> Mk_B [unbx]; };
+    \r [conrep] case conrep of conrep1 { I64# unbx -> Mk_B [unbx]; };
 
 $WMk_A :: Int %1 -> UA =
-    \r [conrep] case conrep of { I# unbx -> Mk_A [unbx]; };
+    \r [conrep] case conrep of conrep1 { I# unbx -> Mk_A [unbx]; };
 
 MkW_NB :: NU_B %1 -> WNU_B =
     \r [eta] case eta of eta { __DEFAULT -> MkW_NB [eta]; };
@@ -71,7 +72,8 @@ MkW_A :: Int# %1 -> WU_A = \r [eta] MkW_A [eta];
 NU_MkB :: Int64# %1 -> Int64# %1 -> NU_B =
     \r [eta eta] NU_MkB [eta eta];
 
-NU_MkA :: (# Int, Int #) %1 -> NU_A = \r [us us] NU_MkA [us us];
+NU_MkA :: (# Int64, Int64 #) %1 -> NU_A =
+    \r [us us] NU_MkA [us us];
 
 Mk_F :: (# Double #) %1 -> UF = \r [us] Mk_F [us];
 
diff --git a/testsuite/tests/simplStg/should_compile/T15226b.stderr b/testsuite/tests/simplStg/should_compile/T15226b.stderr
index ed92963c0eff248fb33ce9fc3a7a938620273e2c..416b9321be2af4aa8e7ebe9c8f7d682d753efeaf 100644
--- a/testsuite/tests/simplStg/should_compile/T15226b.stderr
+++ b/testsuite/tests/simplStg/should_compile/T15226b.stderr
@@ -4,9 +4,9 @@ T15226b.$WMkStrictPair [InlPrag=INLINE[final] CONLIKE]
   :: forall a b. a %1 -> b %1 -> T15226b.StrictPair a b
 [GblId[DataConWrapper], Arity=2, Str=<SL><SL>, Unf=OtherCon []] =
     {} \r [conrep conrep1]
-        case conrep of conrep2 [Occ=Once1] {
+        case conrep of conrep2 {
         __DEFAULT ->
-        case conrep1 of conrep3 [Occ=Once1] {
+        case conrep1 of conrep3 {
         __DEFAULT -> T15226b.MkStrictPair [conrep2 conrep3];
         };
         };
@@ -19,13 +19,13 @@ T15226b.testFun1
      -> (# GHC.Prim.State# GHC.Prim.RealWorld, T15226b.StrictPair a b #)
 [GblId, Arity=3, Str=<L><ML><L>, Unf=OtherCon []] =
     {} \r [x y void]
-        case seq# [x GHC.Prim.void#] of {
+        case seq# [x GHC.Prim.void#] of ds1 {
         Solo# ipv1 [Occ=Once1] ->
         let {
           sat [Occ=Once1] :: T15226b.StrictPair a b
           [LclId] =
               {ipv1, y} \u []
-                  case y of conrep [Occ=Once1] {
+                  case y of conrep {
                   __DEFAULT -> T15226b.MkStrictPair [ipv1 conrep];
                   };
         } in  seq# [sat GHC.Prim.void#];