tree data OPTIMIZE diff and lyd_insert_node()

Function lyd_insert_node() has new options that ignore the ordering of
data nodes. This is used in lyd_diff_add() because the diff as such
does not need to be sorted.
diff --git a/src/diff.c b/src/diff.c
index 14d3bb6..1e74704 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -366,7 +366,7 @@
 
         dup = diff_parent;
     } else {
-        diff_opts = LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS | LYD_DUP_WITH_FLAGS;
+        diff_opts = LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS | LYD_DUP_WITH_FLAGS | LYD_DUP_NO_LYDS;
         if ((op != LYD_DIFF_OP_REPLACE) || !lysc_is_userordered(node->schema) || (node->schema->flags & LYS_CONFIG_R)) {
             /* move applies only to the user-ordered list, no descendants */
             diff_opts |= LYD_DUP_RECURSIVE;
diff --git a/src/parser_json.c b/src/parser_json.c
index 6d22be7..95d689a 100644
--- a/src/parser_json.c
+++ b/src/parser_json.c
@@ -1073,7 +1073,8 @@
         /* continue with the next instance */
         LY_CHECK_GOTO(ret = lyjson_ctx_next(lydctx->jsonctx, status_inner_p), cleanup);
         assert(*node_p);
-        lydjson_maintain_children(parent, first_p, node_p, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0, NULL);
+        lydjson_maintain_children(parent, first_p, node_p,
+                lydctx->parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT, NULL);
 
         LOG_LOCBACK(0, 1);
 
@@ -1742,7 +1743,8 @@
                 }
                 LY_DPARSER_ERR_GOTO(r, rc = r, lydctx, cleanup);
 
-                lydjson_maintain_children(parent, first_p, &node, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0, ext);
+                lydjson_maintain_children(parent, first_p, &node,
+                        lydctx->parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT, ext);
 
                 /* move after the item(s) */
                 r = lyjson_ctx_next(lydctx->jsonctx, &status);
@@ -1780,7 +1782,8 @@
     }
 
     /* finally connect the parsed node, is zeroed */
-    lydjson_maintain_children(parent, first_p, &node, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0, ext);
+    lydjson_maintain_children(parent, first_p, &node,
+            lydctx->parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT, ext);
 
     if (!parse_subtree) {
         /* move after the item(s) */
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index 119b6f4..3ef1c4b 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -931,7 +931,8 @@
     if (parent && (LYD_CTX(parent) != LYD_CTX(node))) {
         lyplg_ext_insert(parent, node);
     } else {
-        lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
+        lyd_insert_node(parent, first_p, node,
+                lybctx->parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT);
     }
     while (!parent && (*first_p)->prev->next) {
         *first_p = (*first_p)->prev;
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 02c6be6..0db10ca 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -1121,7 +1121,8 @@
         r = lyplg_ext_insert(parent, node);
         LY_CHECK_ERR_GOTO(r, rc = r; lyd_free_tree(node), cleanup);
     } else {
-        lyd_insert_node(parent, first_p, node, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
+        lyd_insert_node(parent, first_p, node,
+                lydctx->parse_opts & LYD_PARSE_ORDERED ? LYD_INSERT_NODE_LAST : LYD_INSERT_NODE_DEFAULT);
     }
     while (!parent && (*first_p)->prev->next) {
         *first_p = (*first_p)->prev;
@@ -1349,7 +1350,7 @@
     r = lydxml_envelope(xmlctx, "action", "urn:ietf:params:xml:ns:yang:1", 0, &child);
     if (r == LY_SUCCESS) {
         /* insert */
-        lyd_insert_node(*envp, NULL, child, 0);
+        lyd_insert_node(*envp, NULL, child, LYD_INSERT_NODE_DEFAULT);
 
         /* NETCONF action */
         *int_opts = LYD_INTOPT_NO_SIBLINGS | LYD_INTOPT_ACTION;
@@ -1438,7 +1439,7 @@
     }
 
     /* insert */
-    lyd_insert_node(parent, NULL, node, 1);
+    lyd_insert_node(parent, NULL, node, LYD_INSERT_NODE_LAST);
 
     /* update the value */
     opaq = (struct lyd_node_opaq *)node;
@@ -1572,7 +1573,7 @@
         LY_CHECK_GOTO(r = lyxml_ctx_next(xmlctx), error);
 
         /* insert */
-        lyd_insert_node(parent, NULL, child, 1);
+        lyd_insert_node(parent, NULL, child, LYD_INSERT_NODE_LAST);
     }
 
     return LY_SUCCESS;
@@ -1747,7 +1748,7 @@
         LY_CHECK_GOTO(r = lyxml_ctx_next(xmlctx), error);
 
         /* insert */
-        lyd_insert_node(parent, NULL, child, 1);
+        lyd_insert_node(parent, NULL, child, LYD_INSERT_NODE_LAST);
     }
 
     return LY_SUCCESS;
@@ -1791,7 +1792,7 @@
     r = lydxml_envelope(xmlctx, "ok", "urn:ietf:params:xml:ns:netconf:base:1.0", 0, &child);
     if (r == LY_SUCCESS) {
         /* insert */
-        lyd_insert_node(*envp, NULL, child, 1);
+        lyd_insert_node(*envp, NULL, child, LYD_INSERT_NODE_LAST);
 
         /* finish child parsing */
         if (xmlctx->status != LYXML_ELEM_CLOSE) {
@@ -1822,7 +1823,7 @@
         }
 
         /* insert */
-        lyd_insert_node(*envp, NULL, child, 1);
+        lyd_insert_node(*envp, NULL, child, LYD_INSERT_NODE_LAST);
 
         /* parse all children of "rpc-error" */
         LY_CHECK_GOTO(rc = lydxml_env_netconf_rpc_reply_error(xmlctx, child), cleanup);
diff --git a/src/tree_data.c b/src/tree_data.c
index 5ff1715..9d9f286 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -707,13 +707,6 @@
     assert(first_sibling && node);
 
     if (*first_sibling) {
-#ifndef NDEBUG
-        if (lyds_is_supported(node) && ((*first_sibling)->prev->schema == node->schema) &&
-                (lyds_compare_single((*first_sibling)->prev, node) > 0)) {
-            LOGWRN(LYD_CTX(node), "Data in \"%s\" are not sorted, inserted node should not be added to the end.",
-                    node->schema->name);
-        }
-#endif
         lyd_insert_after_node(first_sibling, (*first_sibling)->prev, node);
     } else if (parent) {
         lyd_insert_only_child(parent, node);
@@ -739,7 +732,7 @@
 }
 
 void
-lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node, ly_bool last)
+lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling_p, struct lyd_node *node, uint32_t order)
 {
     LY_ERR ret = LY_SUCCESS;
     struct lyd_node *first_sibling, *leader;
@@ -754,8 +747,10 @@
     }
     first_sibling = parent ? lyd_child(parent) : *first_sibling_p;
 
-    if (last) {
+    if (order == LYD_INSERT_NODE_LAST) {
         lyd_insert_node_last(parent, &first_sibling, node);
+    } else if (order == LYD_INSERT_NODE_LAST_BY_SCHEMA) {
+        lyd_insert_node_ordby_schema(parent, &first_sibling, node);
     } else if (lyds_is_supported(node) &&
             (lyd_find_sibling_schema(first_sibling, node->schema, &leader) == LY_SUCCESS)) {
         ret = lyds_insert(&first_sibling, &leader, node);
@@ -784,6 +779,14 @@
     if (first_sibling_p) {
         *first_sibling_p = first_sibling;
     }
+
+#ifndef NDEBUG
+    if ((order == LYD_INSERT_NODE_LAST) && lyds_is_supported(node) &&
+            (node->prev->schema == node->schema) && (lyds_compare_single(node->prev, node) > 0)) {
+        LOGWRN(LYD_CTX(node), "Data in \"%s\" are not sorted, inserted node should not be added to the end.",
+                node->schema->name);
+    }
+#endif
 }
 
 /**
@@ -1032,7 +1035,7 @@
 
     if (node->parent || node->prev->next || !node->next) {
         LY_CHECK_RET(lyd_unlink_tree(node));
-        lyd_insert_node(parent, NULL, node, 0);
+        lyd_insert_node(parent, NULL, node, LYD_INSERT_NODE_DEFAULT);
     } else {
         LY_CHECK_RET(lyd_move_nodes(parent, NULL, node));
     }
@@ -1056,7 +1059,7 @@
     while (first) {
         iter = first->next;
         lyd_unlink(first);
-        lyd_insert_node(parent, NULL, first, 1);
+        lyd_insert_node(parent, NULL, first, LYD_INSERT_NODE_LAST);
         first = iter;
     }
     return LY_SUCCESS;
@@ -1076,7 +1079,7 @@
     first_sibling = lyd_first_sibling(sibling);
     if (node->parent || node->prev->next || !node->next) {
         LY_CHECK_RET(lyd_unlink_tree(node));
-        lyd_insert_node(NULL, &first_sibling, node, 0);
+        lyd_insert_node(NULL, &first_sibling, node, LYD_INSERT_NODE_DEFAULT);
     } else {
         LY_CHECK_RET(lyd_move_nodes(NULL, &first_sibling, node));
     }
@@ -2001,15 +2004,14 @@
  * @param[in] node Node to duplicate.
  * @param[in] trg_ctx Target context for duplicated nodes.
  * @param[in] parent Parent to insert into, NULL for top-level sibling.
- * @param[in] insert_last Whether the duplicated node can be inserted as the last child of @p parent. Set for
- * recursive duplication as an optimization.
+ * @param[in] insert_order Options for inserting (sorting) duplicated node, @ref insertorder.
  * @param[in,out] first First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
  * @param[in] options Bitmask of options flags, see @ref dupoptions.
  * @param[out] dup_p Pointer where the created duplicated node is placed (besides connecting it to @p parent / @p first).
  * @return LY_ERR value.
  */
 static LY_ERR
-lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, ly_bool insert_last,
+lyd_dup_r(const struct lyd_node *node, const struct ly_ctx *trg_ctx, struct lyd_node *parent, uint32_t insert_order,
         struct lyd_node **first, uint32_t options, struct lyd_node **dup_p)
 {
     LY_ERR ret;
@@ -2103,7 +2105,7 @@
         if (options & LYD_DUP_RECURSIVE) {
             /* duplicate all the children */
             LY_LIST_FOR(orig->child, child) {
-                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
+                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
             }
         }
         LY_CHECK_GOTO(ret = lydict_insert(trg_ctx, orig->name.name, 0, &opaq->name.name), error);
@@ -2139,12 +2141,12 @@
         if (options & LYD_DUP_RECURSIVE) {
             /* duplicate all the children */
             LY_LIST_FOR(orig->child, child) {
-                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
+                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
             }
         } else if ((dup->schema->nodetype == LYS_LIST) && !(dup->schema->flags & LYS_KEYLESS)) {
             /* always duplicate keys of a list */
             for (child = orig->child; child && lysc_is_key(child->schema); child = child->next) {
-                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, 1, NULL, options, NULL), error);
+                LY_CHECK_GOTO(ret = lyd_dup_r(child, trg_ctx, dup, LYD_INSERT_NODE_LAST, NULL, options, NULL), error);
             }
         }
         lyd_hash(dup);
@@ -2155,7 +2157,7 @@
     }
 
     /* insert */
-    lyd_insert_node(parent, first, dup, insert_last);
+    lyd_insert_node(parent, first, dup, insert_order);
 
     if (dup_p) {
         *dup_p = dup;
@@ -2208,11 +2210,11 @@
             repeat = 0;
         } else {
             iter = NULL;
-            LY_CHECK_RET(lyd_dup_r(orig_parent, trg_ctx, NULL, 0, &iter, options, &iter));
+            LY_CHECK_RET(lyd_dup_r(orig_parent, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &iter, options, &iter));
 
             /* insert into the previous duplicated parent */
             if (*dup_parent) {
-                lyd_insert_node(iter, NULL, *dup_parent, 0);
+                lyd_insert_node(iter, NULL, *dup_parent, LYD_INSERT_NODE_DEFAULT);
             }
 
             /* update the last duplicated parent */
@@ -2238,7 +2240,7 @@
 
     if (*dup_parent && parent) {
         /* last insert into a prevously-existing parent */
-        lyd_insert_node(parent, NULL, *dup_parent, 0);
+        lyd_insert_node(parent, NULL, *dup_parent, LYD_INSERT_NODE_DEFAULT);
     }
     return LY_SUCCESS;
 }
@@ -2271,12 +2273,14 @@
             } else {
                 assert(!(options & LYD_DUP_WITH_PARENTS));
                 /* duplicating a single key, okay, I suppose... */
-                rc = lyd_dup_r(orig, trg_ctx, NULL, 0, &first, options, first ? NULL : &first);
+                rc = lyd_dup_r(orig, trg_ctx, NULL, LYD_INSERT_NODE_DEFAULT, &first, options, first ? NULL : &first);
                 LY_CHECK_GOTO(rc, error);
             }
         } else {
             /* if there is no local parent, it will be inserted into first */
-            rc = lyd_dup_r(orig, trg_ctx, local_parent, 0, &first, options, first ? NULL : &first);
+            rc = lyd_dup_r(orig, trg_ctx, local_parent,
+                    options & LYD_DUP_NO_LYDS ? LYD_INSERT_NODE_LAST_BY_SCHEMA : LYD_INSERT_NODE_DEFAULT,
+                    &first, options, first ? NULL : &first);
             LY_CHECK_GOTO(rc, error);
         }
         if (nosiblings) {
@@ -2568,7 +2572,7 @@
             lyds_insert2(parent_trg, first_trg, leader_p, dup_src, lyds);
         } else {
             /* generic insert node */
-            lyd_insert_node(parent_trg, first_trg, dup_src, 0);
+            lyd_insert_node(parent_trg, first_trg, dup_src, LYD_INSERT_NODE_DEFAULT);
         }
 
         if (first_inst) {
diff --git a/src/tree_data.h b/src/tree_data.h
index 2319655..a7ce4bf 100644
--- a/src/tree_data.h
+++ b/src/tree_data.h
@@ -2039,6 +2039,10 @@
 #define LYD_DUP_NO_EXT       0x10  /**< Do not duplicate nodes with the ::LYD_EXT flag (nested extension instance data). */
 #define LYD_DUP_WITH_PRIV    0x20  /**< Also copy data node private pointer. Only the pointer is copied, it still points
                                         to the same data. */
+#define LYD_DUP_NO_LYDS      0x40  /**< The order of nodes is used the same as for copied nodes and a 'lyds_tree' is not
+                                        created, so the flag is suitable for optimization. If a new node is inserted into
+                                        such a (leaf-)list by default, the 'lyds_tree' will be created additionally and
+                                        the sorting will work. */
 
 /** @} dupoptions */
 
diff --git a/src/tree_data_internal.h b/src/tree_data_internal.h
index 19fb859..57ec2c4 100644
--- a/src/tree_data_internal.h
+++ b/src/tree_data_internal.h
@@ -391,15 +391,34 @@
 void lyd_insert_before_node(struct lyd_node *sibling, struct lyd_node *node);
 
 /**
+ * @defgroup insertorder Data insert order.
+ *
+ * Various options for optimal node insertion.
+ * Flags that cause the order of nodes not to be checked are adapted to fast insertion but can cause
+ * nodes for (leaf-)lists with LYS_ORDBY_SYSTEM flag set to be out of order, which is an undesirable state,
+ * so these flags must be set carefully. In such exceptional cases, (leaf-)list instances may remain unsorted,
+ * in which case inserting a new node causes sorting to be invoked.
+ * @{
+ */
+
+#define LYD_INSERT_NODE_DEFAULT         0x00 /**< Default behavior. Node is inserted to preserve order. */
+#define LYD_INSERT_NODE_LAST            0x01 /**< Node inserted as last sibling. Node ordering is checked only
+                                                  in Debug build, to detect misuse of the LYD_PARSE_ORDERED flag. */
+#define LYD_INSERT_NODE_LAST_BY_SCHEMA  0x02 /**< The node is inserted according to the schema as a last instance.
+                                                  Node order not checked. */
+
+/** @} insertorder */
+
+/**
  * @brief Insert a node into parent/siblings. Order and hashes are fully handled.
  *
  * @param[in] parent Parent to insert into, NULL for top-level sibling.
  * @param[in,out] first_sibling First sibling, NULL if no top-level sibling exist yet. Can be also NULL if @p parent is set.
  * @param[in] node Individual node (without siblings) to insert.
- * @param[in] last If set, do not search for the correct anchor but always insert at the end. Setting the flag can
- * break the ordering of nodes for (leaf-)lists that have the LYS_ORDBY_SYSTEM flag set.
+ * @param[in] order Options for inserting (sorting) the node (@ref insertorder).
  */
-void lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node, ly_bool last);
+void lyd_insert_node(struct lyd_node *parent, struct lyd_node **first_sibling, struct lyd_node *node,
+        uint32_t order);
 
 /**
  * @brief Insert a node into parent/siblings, either before the 'anchor' or as the last sibling.
diff --git a/src/tree_data_new.c b/src/tree_data_new.c
index 289d2da..bbe59f2 100644
--- a/src/tree_data_new.c
+++ b/src/tree_data_new.c
@@ -179,7 +179,7 @@
             memset(&val, 0, sizeof val);
         }
         LY_CHECK_GOTO(ret, cleanup);
-        lyd_insert_node(list, NULL, key, 0);
+        lyd_insert_node(list, NULL, key, LYD_INSERT_NODE_DEFAULT);
     }
 
     /* hash having all the keys */
@@ -503,7 +503,7 @@
         ret->flags |= LYD_EXT;
     }
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
     if (node) {
@@ -626,11 +626,11 @@
 
         rc = lyd_create_term(key_s, key_val, key_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
         LY_CHECK_GOTO(rc, cleanup);
-        lyd_insert_node(ret, NULL, key, 1);
+        lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
     }
 
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
 cleanup:
@@ -722,7 +722,7 @@
         rc = lyd_create_term(key_s, key_val, key_val ? strlen(key_val) : 0, 0, NULL, LY_VALUE_JSON, NULL, LYD_HINT_DATA,
                 NULL, &key);
         LY_CHECK_GOTO(rc, cleanup);
-        lyd_insert_node(ret, NULL, key, 1);
+        lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
     }
 
 cleanup:
@@ -775,7 +775,7 @@
         ret->flags |= LYD_EXT;
     }
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
     if (node) {
@@ -829,11 +829,11 @@
 
         rc = lyd_create_term(key_s, key_val, key_len, 0, NULL, format, NULL, LYD_HINT_DATA, NULL, &key);
         LY_CHECK_GOTO(rc, cleanup);
-        lyd_insert_node(ret, NULL, key, 1);
+        lyd_insert_node(ret, NULL, key, LYD_INSERT_NODE_LAST);
     }
 
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
 cleanup:
@@ -911,7 +911,7 @@
         ret->flags |= LYD_EXT;
     }
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
     if (node) {
@@ -1001,7 +1001,7 @@
         ret->flags |= LYD_EXT;
     }
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 0);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_DEFAULT);
     }
 
     if (node) {
@@ -1140,7 +1140,7 @@
     LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), prefix, prefix ? strlen(prefix) : 0, module_name,
             strlen(module_name), value, strlen(value), NULL, LY_VALUE_JSON, NULL, 0, &ret));
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 1);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST);
     }
 
     if (node) {
@@ -1168,7 +1168,7 @@
     LY_CHECK_RET(lyd_create_opaq(ctx, name, strlen(name), prefix, prefix ? strlen(prefix) : 0, module_ns,
             strlen(module_ns), value, strlen(value), NULL, LY_VALUE_XML, NULL, 0, &ret));
     if (parent) {
-        lyd_insert_node(parent, NULL, ret, 1);
+        lyd_insert_node(parent, NULL, ret, LYD_INSERT_NODE_LAST);
     }
 
     if (node) {
@@ -1309,7 +1309,7 @@
         term->value.realtype->plugin->free(LYD_CTX(term), &term->value);
         term->value = *val;
         /* reinserting */
-        lyd_insert_node(NULL, &first, target, 0);
+        lyd_insert_node(NULL, &first, target, LYD_INSERT_NODE_DEFAULT);
     } else {
         /* unlink hash */
         lyd_unlink_hash(target);
@@ -1835,10 +1835,10 @@
         }
         if (cur_parent) {
             /* connect to the parent */
-            lyd_insert_node(cur_parent, NULL, node, 0);
+            lyd_insert_node(cur_parent, NULL, node, LYD_INSERT_NODE_DEFAULT);
         } else if (parent) {
             /* connect to top-level siblings */
-            lyd_insert_node(NULL, &parent, node, 0);
+            lyd_insert_node(NULL, &parent, node, LYD_INSERT_NODE_DEFAULT);
         }
 
 next_iter:
@@ -1956,7 +1956,7 @@
                 /* create default NP container */
                 LY_CHECK_RET(lyd_create_inner(iter, &node));
                 node->flags = LYD_DEFAULT | (lysc_has_when(iter) ? LYD_WHEN_TRUE : 0);
-                lyd_insert_node(parent, first, node, 0);
+                lyd_insert_node(parent, first, node, LYD_INSERT_NODE_DEFAULT);
 
                 if (lysc_has_when(iter) && node_when) {
                     /* remember to resolve when */
@@ -1990,7 +1990,7 @@
                     return ret;
                 }
                 node->flags = LYD_DEFAULT | (lysc_has_when(iter) ? LYD_WHEN_TRUE : 0);
-                lyd_insert_node(parent, first, node, 0);
+                lyd_insert_node(parent, first, node, LYD_INSERT_NODE_DEFAULT);
 
                 if (lysc_has_when(iter) && node_when) {
                     /* remember to resolve when */
@@ -2022,7 +2022,7 @@
                         return ret;
                     }
                     node->flags = LYD_DEFAULT | (lysc_has_when(iter) ? LYD_WHEN_TRUE : 0);
-                    lyd_insert_node(parent, first, node, 0);
+                    lyd_insert_node(parent, first, node, LYD_INSERT_NODE_DEFAULT);
 
                     if (lysc_has_when(iter) && node_when) {
                         /* remember to resolve when */
diff --git a/src/tree_data_sorted.c b/src/tree_data_sorted.c
index cce9f9c..54ad2ff 100644
--- a/src/tree_data_sorted.c
+++ b/src/tree_data_sorted.c
@@ -968,7 +968,11 @@
 
     /* find @p node in the Red-black tree. */
     rbn = rb_find(*rbt, node);
-    assert(rbn && (RBN_DNODE(rbn) == node));
+    if (!rbn) {
+        /* node was not inserted to the lyds tree due to optimization */
+        return;
+    }
+    assert(RBN_DNODE(rbn) == node);
 
     /* remove node */
     rbn = rb_remove(rbt, rbn);
@@ -1725,7 +1729,9 @@
 {
     assert(node1 && node2 && (node1->schema == node2->schema) && lyds_is_supported(node1));
 
-    if (node1->schema->nodetype == LYS_LEAFLIST) {
+    if (node1 == node2) {
+        return 0;
+    } else if (node1->schema->nodetype == LYS_LEAFLIST) {
         return rb_compare_leaflists(node1, node2);
     } else {
         return rb_compare_lists(node1, node2);
diff --git a/src/validation.c b/src/validation.c
index 1faf3f1..ecba13d 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -2047,7 +2047,7 @@
     op_parent = lyd_parent(op_subtree);
 
     lyd_unlink(op_subtree);
-    lyd_insert_node(tree_parent, &tree_sibling, op_subtree, 0);
+    lyd_insert_node(tree_parent, &tree_sibling, op_subtree, LYD_INSERT_NODE_DEFAULT);
     if (!dep_tree) {
         dep_tree = tree_sibling;
     }
@@ -2096,7 +2096,7 @@
         lyd_insert_before_node(op_sibling_after, op_subtree);
         lyd_insert_hash(op_subtree);
     } else if (op_parent) {
-        lyd_insert_node(op_parent, NULL, op_subtree, 0);
+        lyd_insert_node(op_parent, NULL, op_subtree, LYD_INSERT_NODE_DEFAULT);
     }
 
     ly_set_erase(&node_when, NULL);
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index 3c313c4..c121bc1 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -594,13 +594,13 @@
             "</df>\n";
     const char *xml3 = "<df xmlns=\"urn:libyang:tests:defaults\">\n"
             "  <list>\n"
-            "    <name>a</name>\n"
-            "    <value>2</value>\n"
-            "  </list>\n"
-            "  <list>\n"
             "    <name>b</name>\n"
             "    <value>-2</value>\n"
             "  </list>\n"
+            "  <list>\n"
+            "    <name>a</name>\n"
+            "    <value>2</value>\n"
+            "  </list>\n"
             "</df>\n";
 
     const char *out_diff_1 =
@@ -620,14 +620,14 @@
             "</df>\n";
     const char *out_diff_2 =
             "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
-            "  <list yang:operation=\"create\">\n"
-            "    <name>a</name>\n"
-            "    <value>2</value>\n"
-            "  </list>\n"
             "  <list yang:operation=\"delete\">\n"
             "    <name>c</name>\n"
             "    <value>3</value>\n"
             "  </list>\n"
+            "  <list yang:operation=\"create\">\n"
+            "    <name>a</name>\n"
+            "    <value>2</value>\n"
+            "  </list>\n"
             "</df>\n";
     const char *out_merge =
             "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"