diff --git a/miv.cabal b/miv.cabal
--- a/miv.cabal
+++ b/miv.cabal
@@ -1,5 +1,5 @@
 name:                   miv
-version:                0.4.5
+version:                0.4.6
 author:                 itchyny <https://github.com/itchyny>
 maintainer:             itchyny <https://github.com/itchyny>
 license:                MIT
diff --git a/src/VimScript.hs b/src/VimScript.hs
--- a/src/VimScript.hs
+++ b/src/VimScript.hs
@@ -6,7 +6,6 @@
 import Data.Hashable
 import qualified Data.HashMap.Lazy as HM
 import Data.List (foldl', groupBy, sort, sortBy, nub)
-import Data.Maybe (mapMaybe)
 import Data.Text (Text, singleton, unpack, unwords)
 import qualified Data.Text as T
 import GHC.Generics (Generic)
@@ -43,11 +42,6 @@
   show (Ftplugin s)  = "ftplugin/" <> s <> ".vim"
   show (Syntax s)    = "syntax/" <> s <> ".vim"
 
-autoloadSubdirName :: Place -> Maybe Text
-autoloadSubdirName (Autoload "") = Nothing
-autoloadSubdirName (Autoload s) = Just s
-autoloadSubdirName _ = Nothing
-
 vimScriptToList :: VimScript -> [(Place, [Text])]
 vimScriptToList (VimScript x) = HM.toList x
 
@@ -65,8 +59,7 @@
   mempty = VimScript HM.empty
 
 gatherScript :: S.Setting -> VimScript
-gatherScript setting = addAutoloadNames
-                     $ beforeScript setting
+gatherScript setting = beforeScript setting
                     <> gatherBeforeAfterScript plugins
                     <> gather' "dependon" P.dependon P.loadbefore plugins
                     <> gather' "dependedby" P.dependedby P.loadafter plugins
@@ -81,8 +74,8 @@
                     <> funcUndefinedLoader setting
                     <> cmdlineEnterLoader setting
                     <> insertEnterLoader setting
-                    <> filetypeScript (S.filetype setting)
-                    <> syntaxScript (S.syntax setting)
+                    <> filetypeScript setting
+                    <> syntaxScript setting
                     <> afterScript setting
   where plugins = S.plugins setting
 
@@ -103,18 +96,11 @@
         hchar | null (loadScript p) = maybe "_" singleton $ getHeadChar $ show p
               | otherwise = "_"
         funcname str = "miv#" <> hchar <> "#" <> str <> "_" <> name
-        au = Autoload hchar
-        vs' = VimScript $ HM.singleton au $ wrapFunction (funcname "before") (P.before p)
-                                         <> wrapFunction (funcname "after") (P.after p)
+        vs' = VimScript $ HM.singleton (Autoload hchar) $
+          wrapFunction (funcname "before") (P.before p) <>
+          wrapFunction (funcname "after") (P.after p)
     gatherScripts [] (vs, hm) = (vs, hm)
 
-addAutoloadNames :: VimScript -> VimScript
-addAutoloadNames h@(VimScript hm)
-  = VimScript (HM.singleton (Autoload "")
-      [ "let s:autoloads = { " <> T.intercalate ", " (((<>": 1") . singleQuote)
-                               <$> mapMaybe autoloadSubdirName (HM.keys hm)) <> " }"])
-   <> h
-
 gather :: Text -> (P.Plugin -> [Text]) -> [P.Plugin] -> VimScript
 gather name f plg
   = VimScript (HM.singleton (Autoload "") $
@@ -144,7 +130,7 @@
 pluginConfig :: P.Plugin -> VimScript
 pluginConfig plg
     = VimScript (HM.singleton Plugin $ wrapInfo $
-        wrapEnable plg $ mapleader <> gatherCommand plg <> gatherMapping plg <> P.script plg <> loadScript plg)
+        wrapEnable (P.enable plg) $ mapleader <> gatherCommand plg <> gatherMapping plg <> P.script plg <> loadScript plg)
   where
     wrapInfo [] = []
     wrapInfo str = ("\" " <> P.name plg) : str
@@ -194,59 +180,51 @@
 
 filetypeLoader :: S.Setting -> VimScript
 filetypeLoader setting
-  = HM.foldrWithKey f mempty (filetypeLoadPlugins (S.plugins setting) HM.empty)
+  = mconcat $ map (uncurry f) $
+      collectSndByFst [(ft, p) | p <- S.plugins setting, ft <- P.filetypes p]
   where
-    f ft plg val =
-      case getHeadChar ft of
-           Nothing -> val
-           Just c ->
-             let funcname = "miv#" <> singleton c <> "#load_" <> T.filter isAlphaNum (T.toLower ft)
-                 in val
-                  <> VimScript (HM.singleton (Autoload (singleton c))
-                       (("function! " <> funcname <> "() abort")
-                       : "  setlocal filetype="
-                       :  concat [wrapEnable b
-                       [ "  call miv#load(" <> singleQuote (show b) <> ")"] | b <- plg]
-                    <> [ "  autocmd! miv-file-type-" <> ft
-                       , "  augroup! miv-file-type-" <> ft
-                       , "  setlocal filetype=" <> ft
-                       , "  silent! doautocmd FileType " <> ft
-                       , "endfunction"
-                       ]))
-                  <> VimScript (HM.singleton Plugin
-                       [ "augroup miv-file-type-" <> ft
-                       , "  autocmd!"
-                       , "  autocmd FileType " <> ft <> " call " <> funcname <> "()"
-                       , "augroup END"
-                       ])
-
-filetypeLoadPlugins :: [P.Plugin] -> HM.HashMap Text [P.Plugin] -> HM.HashMap Text [P.Plugin]
-filetypeLoadPlugins (b:plugins) fts
-  | not (null (P.filetypes b))
-  = filetypeLoadPlugins plugins (foldr (flip (HM.insertWith (<>)) [b]) fts (P.filetypes b))
-  | otherwise = filetypeLoadPlugins plugins fts
-filetypeLoadPlugins [] fts = fts
+    f :: Text -> [P.Plugin] -> VimScript
+    f ft plugins = flip foldMap (getHeadChar ft) $
+      \c -> let funcname = "miv#" <> singleton c <> "#load_" <> T.filter isAlphaNum (T.toLower ft)
+                in VimScript (HM.singleton Plugin
+                     [ "augroup miv-file-type-" <> ft
+                     , "  autocmd!"
+                     , "  autocmd FileType " <> ft <> " call " <> funcname <> "()"
+                     , "augroup END" ]) <>
+                   VimScript (HM.singleton (Autoload (singleton c)) $
+                     ("function! " <> funcname <> "() abort")
+                     : "  setlocal filetype="
+                     : loadPlugins plugins
+                  <> [ "  autocmd! miv-file-type-" <> ft
+                     , "  augroup! miv-file-type-" <> ft
+                     , "  setlocal filetype=" <> ft
+                     , "  silent! doautocmd FileType " <> ft
+                     , "endfunction" ])
 
-wrapEnable :: P.Plugin -> [Text] -> [Text]
-wrapEnable plg str
+wrapEnable :: Text -> [Text] -> [Text]
+wrapEnable enable str
   | null str = []
-  | T.null (P.enable plg) = str
-  | P.enable plg == "0" = []
-  | otherwise = (indent <> "if " <> P.enable plg)
+  | T.null enable = str
+  | enable == "0" = []
+  | otherwise = (indent <> "if " <> enable)
                            : map ("  "<>) str
              <> [indent <> "endif"]
   where indent = T.takeWhile (==' ') (head str)
 
+loadPlugins :: [P.Plugin] -> [Text]
+loadPlugins plugins = concat
+  [wrapEnable enable
+    ["  call miv#load(" <> singleQuote (show p) <> ")" | p <- plugins']
+      | (enable, plugins') <- collectSndByFst [(P.enable p, p) | p <- plugins]]
+
 singleQuote :: Text -> Text
 singleQuote str = "'" <> str <> "'"
 
-filetypeScript :: HM.HashMap Text [Text] -> VimScript
-filetypeScript =
-  HM.foldrWithKey (\ft scr val -> val <> VimScript (HM.singleton (Ftplugin ft) scr)) mempty
+filetypeScript :: S.Setting -> VimScript
+filetypeScript = foldMap (\(ft, src) -> VimScript (HM.singleton (Ftplugin ft) src)) . HM.toList . S.filetype
 
-syntaxScript :: HM.HashMap Text [Text] -> VimScript
-syntaxScript =
-  HM.foldrWithKey (\ft scr val -> val <> VimScript (HM.singleton (Syntax ft) scr)) mempty
+syntaxScript :: S.Setting -> VimScript
+syntaxScript = foldMap (\(ft, src) -> VimScript (HM.singleton (Syntax ft) src)) . HM.toList . S.syntax
 
 wrapFunction :: Text -> [Text] -> [Text]
 wrapFunction funcname script =
@@ -271,8 +249,7 @@
   , "  endif"
   , "  call feedkeys((v:count ? v:count : '') . substitute(a:mapping, '<Plug>', \"\\<Plug>\", 'g'), 'm')"
   , "  return ''"
-  , "endfunction"
-  ])
+  , "endfunction" ])
 
 commandLoader :: VimScript
 commandLoader = VimScript (HM.singleton (Autoload "")
@@ -285,12 +262,11 @@
   , "  catch /^Vim\\%((\\a\\+)\\)\\=:E481:/"
   , "    exec a:command.a:bang a:args"
   , "  endtry"
-  , "endfunction"
-  ])
+  , "endfunction" ])
 
 funcUndefinedLoader :: S.Setting -> VimScript
-funcUndefinedLoader setting | all (null . P.functions) (S.plugins setting) = mempty
-funcUndefinedLoader _ = VimScript (HM.singleton Plugin
+funcUndefinedLoader setting = if null functions then mempty else
+  VimScript (HM.singleton Plugin
   [ "\" FuncUndefined"
   , "augroup miv-func-undefined"
   , "  autocmd!"
@@ -298,6 +274,9 @@
   , "augroup END" ])
   <> VimScript (HM.singleton (Autoload "")
   [ "function! miv#func_undefined(pattern) abort"
+  , "  if a:pattern !~# " <> singleQuote (T.intercalate "\\|" functions)
+  , "    return"
+  , "  endif"
   , "  if empty(s:functions)"
   , "    autocmd! miv-func-undefined"
   , "    augroup! miv-func-undefined"
@@ -311,47 +290,51 @@
   , "      endif"
   , "    endfor"
   , "  endfor"
-  , "endfunction"
-  ])
+  , "endfunction" ])
+  where functions = [ f | p <- S.plugins setting, f <- P.functions p ]
 
 cmdlineEnterLoader :: S.Setting -> VimScript
 cmdlineEnterLoader setting
-  = HM.foldrWithKey f mempty $
-      foldr (uncurry (HM.insertWith (<>))) HM.empty
-        [ (cmdline, [p]) | p <- S.plugins setting, cmdline <- P.cmdlines p ]
+  = mconcat $ map (uncurry f) $
+      collectSndByFst [(cmdline, p) | p <- S.plugins setting, cmdline <- P.cmdlines p]
   where
-    f :: Cmdline -> [P.Plugin] -> VimScript -> VimScript
-    f cmdline plugins val = val <> VimScript (HM.singleton Plugin
+    f :: Cmdline -> [P.Plugin] -> VimScript
+    f cmdline plugins = VimScript (HM.singleton Plugin
       [ "\" CmdlineEnter " <> (show cmdline)
-      , "augroup " <> group
-      , "  autocmd!"
-      , "  autocmd CmdlineEnter " <> (cmdlinePattern cmdline) <> " call miv#cmdline_enter_" <> c <> "()"
-      , "augroup END" ])
+      , "if exists('#CmdlineEnter')"
+      , "  augroup " <> group
+      , "    autocmd!"
+      , "    autocmd CmdlineEnter " <> (cmdlinePattern cmdline) <> " call miv#cmdline_enter_" <> c <> "()"
+      , "  augroup END"
+      , "else"
+      , "  call miv#cmdline_enter_" <> c <> "()"
+      , "endif" ])
       <> VimScript (HM.singleton (Autoload "") $
-       ("function! miv#cmdline_enter_" <> c <> "() abort") :
-      [ "  call miv#load(" <> singleQuote (show p) <> ")" | p <- plugins ]
-      <> [ "  autocmd! " <> group
-      , "  augroup! " <> group
-      , "endfunction"
-      ])
+       ("function! miv#cmdline_enter_" <> c <> "() abort")
+      : loadPlugins plugins
+      <> [ "  if exists('#CmdlineEnter')"
+      , "    autocmd! " <> group
+      , "    augroup! " <> group
+      , "  endif"
+      , "endfunction" ])
       where c = T.concat $ map (show . ord) (unpack (show cmdline))
             group = "miv-cmdline-enter-" <> c
 
 insertEnterLoader :: S.Setting -> VimScript
-insertEnterLoader setting = if null plugins then mempty else VimScript (HM.singleton Plugin
+insertEnterLoader setting = if null plugins then mempty else
+  VimScript (HM.singleton Plugin
   [ "\" InsertEnter"
   , "augroup miv-insert-enter"
   , "  autocmd!"
   , "  autocmd InsertEnter * call miv#insert_enter()"
   , "augroup END" ])
   <> VimScript (HM.singleton (Autoload "")
-  $ "function! miv#insert_enter() abort" :
-  [ "  call miv#load(" <> singleQuote (show p) <> ")" | p <- plugins ]
+  $ "function! miv#insert_enter() abort"
+  : loadPlugins plugins
   <> [ "  autocmd! miv-insert-enter"
   , "  augroup! miv-insert-enter"
   , "  silent! doautocmd InsertEnter"
-  , "endfunction"
-  ])
+  , "endfunction" ])
   where plugins = filter P.insert (S.plugins setting)
 
 pluginLoader :: VimScript
@@ -359,6 +342,7 @@
   [ "let s:loaded = {}"
   , "let s:path = expand('<sfile>:p:h:h')"
   , "let s:mivpath = expand('<sfile>:p:h:h:h') . '/'"
+  , "let s:rtpidx = 0"
   , "function! miv#load(name) abort"
   , "  if has_key(s:loaded, a:name)"
   , "    return"
@@ -376,25 +360,21 @@
   , "    endfor"
   , "  endfor"
   , "  let name = substitute(tolower(a:name), '[^a-z0-9]', '', 'g')"
-  , "  let au = has_key(s:autoload, name) && get(s:autoloads, s:autoload[name])"
+  , "  let au = has_key(s:autoload, name)"
   , "  if au"
   , "    call miv#{s:autoload[name]}#before_{name}()"
   , "  endif"
-  , "  let newrtp = s:mivpath . a:name . '/'"
+  , "  let newrtp = s:mivpath . a:name"
   , "  if !isdirectory(newrtp)"
   , "    return"
   , "  endif"
   , "  let rtps = split(&rtp, ',')"
-  , "  let i = index(map(deepcopy(rtps), 'resolve(v:val)'), s:path)"
-  , "  if i < 0"
-  , "    let mivpath = get(filter(deepcopy(rtps), 'v:val =~# \"miv.\\\\?$\"'), 0, '')"
-  , "    let i = max([0, index(deepcopy(rtps), mivpath)])"
-  , "  endif"
-  , "  let &rtp = join(insert(rtps, newrtp, i), ',')"
-  , "  if isdirectory(newrtp . 'after/')"
-  , "    exec 'set rtp+=' . newrtp . 'after/'"
+  , "  let s:rtpidx = max([index(rtps, s:path, s:rtpidx), 0])"
+  , "  let &rtp = join(insert(rtps, newrtp, s:rtpidx), ',')"
+  , "  if isdirectory(newrtp . '/after')"
+  , "    exec 'set rtp+=' . newrtp . '/after'"
   , "  endif"
-  , "  for dir in filter(['plugin', 'after/plugin'], 'isdirectory(newrtp . v:val)')"
+  , "  for dir in filter(['/plugin', '/after/plugin'], 'isdirectory(newrtp . v:val)')"
   , "    for file in split(glob(newrtp . dir . '/**/*.vim'), '\\n')"
   , "      silent! source `=file`"
   , "    endfor"
@@ -405,5 +385,4 @@
   , "  for n in get(s:dependedby, a:name, [])"
   , "    call miv#load(n)"
   , "  endfor"
-  , "endfunction"
-  ])
+  , "endfunction" ])
