diff --git a/py/compile.c b/py/compile.c
index ca3ee9d6d1622b5cc587812c5ee70fd42af88e75..4738c0ae554118d75d79ad63845efebdff252ef7 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -78,6 +78,19 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
     comp->had_error = true;
 }
 
+STATIC const mp_map_elem_t mp_constants_table[] = {
+    // Extra constants as defined by a port
+    MICROPY_EXTRA_CONSTANTS
+};
+
+STATIC const mp_map_t mp_constants_map = {
+    .all_keys_are_qstrs = 1,
+    .table_is_fixed_array = 1,
+    .used = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
+    .alloc = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
+    .table = (mp_map_elem_t*)mp_constants_table,
+};
+
 mp_parse_node_t fold_constants(mp_parse_node_t pn) {
     if (MP_PARSE_NODE_IS_STRUCT(pn)) {
         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@@ -168,10 +181,12 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
                 }
                 break;
 
-#if MICROPY_EMIT_CPYTHON
             case PN_power:
-                // can overflow; enabled only to compare with CPython
-                if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
+                if (0) {
+#if MICROPY_EMIT_CPYTHON
+                } else if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
+                    // int**x
+                    // can overflow; enabled only to compare with CPython
                     mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
                     if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
                         int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
@@ -184,9 +199,27 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
                             pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
                         }
                     }
+#endif
+                } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_trailer_period) && MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
+                    // id.id
+                    // look it up in constant table, see if it can be replaced with an integer
+                    mp_parse_node_struct_t* pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
+                    assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
+                    qstr q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
+                    qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
+                    mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);
+                    if (elem != NULL) {
+                        mp_obj_t dest[2];
+                        mp_load_method_maybe(elem->value, q_attr, dest);
+                        if (MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL) {
+                            machine_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
+                            if (MP_PARSE_FITS_SMALL_INT(val)) {
+                                pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
+                            }
+                        }
+                    }
                 }
                 break;
-#endif
         }
     }
 
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 1f2862ab0ebbb031c20264ffe76e6ec0e36591e4..b120c4bb4ac1d326fab897c95feab83368ad6348 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -150,6 +150,11 @@ typedef double mp_float_t;
 #define MICROPY_EXTRA_BUILTIN_MODULES
 #endif
 
+// Additional constant definitions for the compiler - see compile.c:mp_constants_table.
+#ifndef MICROPY_EXTRA_CONSTANTS
+#define MICROPY_EXTRA_CONSTANTS
+#endif
+
 /*****************************************************************************/
 /* Miscellaneous settings                                                    */