diff --git a/StrictImplParams.hs b/StrictImplParams.hs
--- a/StrictImplParams.hs
+++ b/StrictImplParams.hs
@@ -1,27 +1,15 @@
 
-{-# language
-  LambdaCase,
-  Strict,
-  TemplateHaskell,
-  TupleSections,
-  ViewPatterns
-  #-}
-
-{-# options_ghc
-  -Wincomplete-patterns
-  -Wunused-imports
-  #-}
+{-# language LambdaCase, Strict, TupleSections, CPP #-}
+{-# options_ghc -Wincomplete-patterns -Wunused-imports #-}
 
 module StrictImplParams (plugin) where
 
-import System.Exit
 import Data.Foldable
-
-import GHC.Classes
+import Data.Maybe
+import GHC.Core.Predicate
 import GHC.Plugins
 
-import qualified Language.Haskell.TH as TH
-import qualified GHC.Core.TyCo.Rep   as GHC
+import qualified GHC.Core.TyCo.Rep as GHC
 
 plugin :: Plugin
 plugin = defaultPlugin {
@@ -29,51 +17,94 @@
   pluginRecompile  = purePlugin
   }
 
-fromTHName :: TH.Name -> CoreM Name
-fromTHName thn = thNameToGhcName thn >>= \case
-  Nothing -> do
-    errorMsg $ text "Could not resolve TH name" <+> text (show thn)
-    liftIO exitFailure
-  Just n -> pure n
+{-# inline ($$!) #-}
+($$!) :: (a -> b) -> a -> b
+f $$! x = f x
+infixl 8 $$!
 
+{-# inline ($$~) #-}
+($$~) :: (a -> b) -> a -> b
+f $$~ ~x = f x
+infixl 8 $$~
+
 map' :: (a -> b) -> [a] -> [b]
-map' f = foldr' (\a bs -> ((:) $! f a) $! bs) []
+map' f = foldr' (\a bs -> (:) $$! f a $$! bs) []
 {-# inline map' #-}
 
-forceVar :: Var -> CoreExpr -> Type -> CoreExpr
-forceVar x u uty = Case (Var x) x uty [Alt DEFAULT [] u]
+#if __GLASGOW_HASKELL__ <= 904
+manyType :: Mult
+manyType = Many
+#else
+manyType :: Mult
+manyType = ManyTy
+#endif
 
-setNoOccInfo :: Var -> Var
-setNoOccInfo x = case idInfo x of
-  i -> lazySetIdInfo x (i {occInfo = noOccInfo})
+#if __GLASGOW_HASKELL__ <= 906
+coreFullView :: Type -> Type
+coreFullView a = case coreView a of
+  Just a -> coreFullView a
+  _      -> a
 
-forceType :: Type -> Type
-forceType a = case coreView a of
-  Just a' -> forceType a'
-  _       -> a
+isImplicitParamTy :: Type -> Bool
+isImplicitParamTy ty = isJust $ isIPPred_maybe ty
+#else
+isImplicitParamTy :: Type -> Bool
+isImplicitParamTy ty = isJust $ do
+  (cls, tys) <- getClassPredTys_maybe ty
+  isIPPred_maybe cls tys
+#endif
 
+-- | Force var, continue with CoreExpr body that has Type type.
+forceVar :: Var -> CoreExpr -> Type -> CoreExpr
+forceVar x body bodyTy =
+  mkWildCase (Var x) (GHC.Scaled manyType (varType x)) bodyTy [Alt DEFAULT [] body]
+
 pass :: ModGuts -> CoreM ModGuts
 pass guts = do
   dflags <- getDynFlags
-  ipName <- fromTHName ''GHC.Classes.IP
 
-  let goDef :: [Var] -> CoreExpr -> Type -> CoreExpr
-      goDef xs t a = case t of
-        Lam x t -> case forceType a of
-          GHC.ForAllTy _ a  -> Lam x $! goDef xs t a
-          GHC.FunTy _ _ a b
-            | Just (getName -> con, _) <- splitTyConApp_maybe a, con == ipName ->
-                Lam x $! goDef (((:) $! setNoOccInfo x) xs) t b
-            | otherwise ->
-                Lam x $! goDef xs t b
-          a -> do
-            error $ "unexpected lam type: " ++ showSDoc dflags (ppr a)
-
-        t -> foldl' (\acc x -> forceVar x acc a) t xs
+  let dbg :: Outputable a => a -> String
+      dbg x = showSDoc dflags (ppr x)
 
   let goBind :: CoreBind -> CoreBind
-      goBind = \case
-        NonRec b t -> NonRec b $! goDef [] t (varType b)
-        Rec defs   -> Rec $! map' (\(b, t) -> (b,) $! goDef [] t (varType b)) defs
+      goBind b = let
 
-  pure $! guts {mg_binds = map' goBind (mg_binds guts)}
+        go :: [Var] -> CoreExpr -> Type -> CoreExpr
+        go vars t a = case t of
+          Lam x t -> case coreFullView a of
+            GHC.ForAllTy _ a  -> Lam x $! go vars t a
+            GHC.FunTy _ _ a b | isImplicitParamTy a -> Lam x $! go (x:vars) t b
+                              | otherwise           -> Lam x $! go vars t b
+            _ -> error $ "unexpected type for lambda expression: " ++ dbg a
+          t ->
+            foldl' (\acc x -> forceVar x acc a) (goExpr t) vars
+
+        in case b of
+          NonRec b t -> NonRec b $! go [] t (varType b)
+          Rec defs   -> Rec $! map' (\(b, t) -> (b,) $! go [] t (varType b)) defs
+
+      goExpr :: CoreExpr -> CoreExpr
+      goExpr t = case t of
+        Var{}                  -> t
+        Lit{}                  -> t
+        App t u                -> App $$! goExpr t $$! goExpr u
+        Case t scr bodyty alts -> Case $$! goExpr t $$! scr $$! bodyty $$! map' goAlt alts
+        Cast t coe             -> Cast $$! goExpr t $$~ coe
+        Tick tck t             -> Tick tck $$! goExpr t
+        Type{}                 -> t
+        Coercion{}             -> t
+
+        -- Note: the bound var of a free-standing lambda
+        -- does not get forced!
+        Lam x t -> Lam x $! goExpr t
+
+        -- Neither does an implicit let binder!
+        -- In both cases the issue is that we don't know the type
+        -- of the expr body and I don't like the idea of recomputing it!
+        Let b t -> Let $$! goBind b $$! goExpr t
+
+      goAlt :: Alt CoreBndr -> Alt CoreBndr
+      goAlt (Alt con bs body) = Alt con bs $! goExpr body
+
+  let mg_binds' = map' goBind (mg_binds guts)
+  pure $! guts {mg_binds = mg_binds'}
diff --git a/strict-impl-params.cabal b/strict-impl-params.cabal
--- a/strict-impl-params.cabal
+++ b/strict-impl-params.cabal
@@ -1,8 +1,8 @@
 name: strict-impl-params
 cabal-version: 1.12
 build-type: Simple
-version: 1.1.0
-synopsis: Plugin for making top-level implicit parameters strict
+version: 1.1.1
+synopsis: Plugin for making implicit parameters strict
 homepage: https://github.com/AndrasKovacs/ghc-strict-implicit-params
 bug-reports: https://github.com/AndrasKovacs/ghc-strict-implicit-params/issues
 copyright: 2022 András Kovács
@@ -15,7 +15,5 @@
   default-language: Haskell2010
   build-depends:
       base >=4.7 && <5
-    , ghc >= 9.2.3 && < 9.14
-    , ghc-prim < 0.14
-    , template-haskell < 2.24
+    , ghc >= 9.2.3 && < 9.16
   exposed-modules: StrictImplParams
