diff --git a/py/builtinimport.c b/py/builtinimport.c
index 0e4dce64308b6cfe6cdc2d6e343663d516329dec..5cff163f3ba17c56b6598b39ffc2718d103e1655 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -60,22 +60,32 @@ bool mp_obj_is_package(mp_obj_t module) {
     return dest[0] != MP_OBJ_NULL;
 }
 
+// Stat either frozen or normal module by a given path
+// (whatever is available, if at all).
+STATIC mp_import_stat_t mp_import_stat_any(const char *path) {
+    mp_import_stat_t st = mp_frozen_stat(path);
+    if (st != MP_IMPORT_STAT_NO_EXIST) {
+        return st;
+    }
+    return mp_import_stat(path);
+}
+
 STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
-    mp_import_stat_t stat = mp_import_stat(vstr_null_terminated_str(path));
+    mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));
     DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
     if (stat == MP_IMPORT_STAT_DIR) {
         return stat;
     }
 
     vstr_add_str(path, ".py");
-    stat = mp_import_stat(vstr_null_terminated_str(path));
+    stat = mp_import_stat_any(vstr_null_terminated_str(path));
     if (stat == MP_IMPORT_STAT_FILE) {
         return stat;
     }
 
     #if MICROPY_PERSISTENT_CODE_LOAD
     vstr_ins_byte(path, path->len - 2, 'm');
-    stat = mp_import_stat(vstr_null_terminated_str(path));
+    stat = mp_import_stat_any(vstr_null_terminated_str(path));
     if (stat == MP_IMPORT_STAT_FILE) {
         return stat;
     }
@@ -196,8 +206,18 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
 
     #if MICROPY_ENABLE_COMPILER
     {
-        mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
-        do_load_from_lexer(module_obj, lex, file_str);
+        void *modref;
+        int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);
+        #if MICROPY_PERSISTENT_CODE_LOAD
+        if (frozen_type == MP_FROZEN_MPY) {
+            do_execute_raw_code(module_obj, modref);
+            return;
+        }
+        #endif
+        if (frozen_type == MP_FROZEN_NONE) {
+            modref = mp_lexer_new_from_file(file_str);
+        }
+        do_load_from_lexer(module_obj, modref, file_str);
     }
     #else
     nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
@@ -340,33 +360,6 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
     }
     DEBUG_printf("Module not yet loaded\n");
 
-    #if MICROPY_MODULE_FROZEN
-    void *frozen_data;
-    int frozen_type = mp_find_frozen_module(mod_str, mod_len, &frozen_data);
-    if (frozen_type != MP_FROZEN_NONE) {
-        module_obj = mp_obj_new_module(module_name_qstr);
-        // if args[3] (fromtuple) has magic value False, set up
-        // this module for command-line "-m" option (set module's
-        // name to __main__ instead of real name).
-        // TODO: Duplicated below too.
-        if (fromtuple == mp_const_false) {
-            mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
-            mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
-        }
-        #if MICROPY_MODULE_FROZEN_STR
-        if (frozen_type == MP_FROZEN_STR) {
-            do_load_from_lexer(module_obj, frozen_data, mod_str);
-        }
-        #endif
-        #if MICROPY_MODULE_FROZEN_MPY
-        if (frozen_type == MP_FROZEN_MPY) {
-            do_execute_raw_code(module_obj, frozen_data);
-        }
-        #endif
-        return module_obj;
-    }
-    #endif
-
     uint last = 0;
     VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
     module_obj = MP_OBJ_NULL;
@@ -445,7 +438,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
                     mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
                     vstr_add_char(&path, PATH_SEP_CHAR);
                     vstr_add_str(&path, "__init__.py");
-                    if (mp_import_stat(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
+                    if (mp_import_stat_any(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
                         vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
                         mp_warning("%s is imported as namespace package", vstr_str(&path));
                     } else {
diff --git a/py/frozenmod.c b/py/frozenmod.c
index 18beb0f8e4d0ab24c25b7a2f213444c2ef2ff65e..0fabb06a98ec254e03b0a466f3758627c0795c6c 100644
--- a/py/frozenmod.c
+++ b/py/frozenmod.c
@@ -43,6 +43,24 @@ extern const char mp_frozen_str_names[];
 extern const uint32_t mp_frozen_str_sizes[];
 extern const char mp_frozen_str_content[];
 
+mp_import_stat_t mp_frozen_stat(const char *str) {
+    size_t len = strlen(str);
+    const char *name = mp_frozen_str_names;
+
+    for (int i = 0; *name != 0; i++) {
+        size_t l = strlen(name);
+        if (l >= len && !memcmp(str, name, len)) {
+            if (name[len] == 0) {
+                return MP_IMPORT_STAT_FILE;
+            } else if (name[len] == '/') {
+                return MP_IMPORT_STAT_DIR;
+            }
+        }
+        name += l + 1;
+    }
+    return MP_IMPORT_STAT_NO_EXIST;
+}
+
 STATIC mp_lexer_t *mp_find_frozen_str(const char *str, size_t len) {
     const char *name = mp_frozen_str_names;
 
diff --git a/py/frozenmod.h b/py/frozenmod.h
index a1638d2293dc86339958050647611e8caa091b92..f08cb5e3219f99385549aea8163fdbd0232ea47a 100644
--- a/py/frozenmod.h
+++ b/py/frozenmod.h
@@ -31,3 +31,4 @@ enum {
 };
 
 int mp_find_frozen_module(const char *str, size_t len, void **data);
+mp_import_stat_t mp_frozen_stat(const char *str);