Index: libcfa/src/collections/list2.hfa
===================================================================
--- libcfa/src/collections/list2.hfa	(revision 1b4e5a84173be2ec1a815d98741f2ac6fb809dd5)
+++ libcfa/src/collections/list2.hfa	(revision 8f448e01c658ade79b98aeba42994dc8576e0e5a)
@@ -239,4 +239,34 @@
 }
 
+forall( tE & ) {
+#ifdef __EXPERIMENTAL_DISABLE_OTAG__ // Perf experimention alt mode
+    static inline size_t origin_tag_query_arith$( tE & raw ) {
+        return 0;
+    }
+    static inline tE & nullif$( tE & val, size_t arith_ctrl ) {
+        verify( arith_ctrl == 0 );  (void) arith_ctrl;
+        return val;
+    }
+#else // Normal
+    // like ORIGIN_TAG_QUERY, but return is arithmetic number 0 or 1 (rather than 0 or non-0)
+    static inline size_t origin_tag_query_arith$( tE & raw ) {
+        size_t ret = (((size_t) & raw) >> ORIGIN_TAG_BITNO) & 1;
+        verify( ORIGIN_TAG_QUERY( (size_t) & raw ) ? ret == 1 : ret == 0 );
+        return ret;
+    }
+    // Requires arith_ctrl being 0 or 1.
+    // When 0, passes val through; when 1, returns null reference.
+    // Importantly, implemented without jumps or tests.
+    static inline tE & nullif$( tE & val, size_t arith_ctrl ) {
+        verify( ! ORIGIN_TAG_QUERY( (size_t) & val ) );
+        verify( arith_ctrl == 0 || arith_ctrl == 1 );
+        size_t mask_ctrl = ~ - arith_ctrl;
+        verify( arith_ctrl == 0 && mask_ctrl == -1 || arith_ctrl == 1 && mask_ctrl ==0 );
+        tE & ret = * (tE*) ( ((size_t) & val) & mask_ctrl);
+        verify( arith_ctrl == 0 && &ret == &val || arith_ctrl == 1 && &ret == 0p );
+        return ret;
+    }
+#endif
+}
 
 forall( tE &, tLinks & | embedded( tE, tLinks, dlink(tE) ) ) {
@@ -496,11 +526,13 @@
 		verify (&lst != 0p);
         dlink(tE) & list_links = lst;
-        verify (! ORIGIN_TAG_QUERY( (size_t) (list_links.next) ) );
-
-        dlink(tE) & fst_links = * list_links.next;
+        verify (! ORIGIN_TAG_QUERY( (size_t) (& list_links) ) );
+        // call is valid on empty list; when so, list_links.next and after_links.prev have otags set
+
+        dlink(tE) & fst_raw = * list_links.next;
+        dlink(tE) & fst_links = * (dlink(tE) *) ORIGIN_TAG_CLEAR( (size_t) & fst_raw );
+        size_t fst_tagval = origin_tag_query_arith$( fst_raw );
 
         dlink(tE) & after_raw = * fst_links.next;
         dlink(tE) & after_links = * (dlink(tE) *) ORIGIN_TAG_CLEAR( (size_t) & after_raw );
-        verify( ! ORIGIN_TAG_QUERY( (size_t) (after_links.prev) ) );
 
         size_t before_links_next_rslt = ((size_t) & after_raw);
@@ -515,6 +547,6 @@
         asm( "" : : : "memory" );
 
-        tytagref( tLinks, dlink(tE) ) lpLnkTagged = {fst_links};
-        return downcast$( lpLnkTagged );
+        tytagref( tLinks, dlink(tE) ) retExt = { fst_links };
+        return nullif$( downcast$( retExt ), fst_tagval );
     }
 
@@ -522,11 +554,12 @@
 		verify (&lst != 0p);
         dlink(tE) & list_links = lst;
-        verify (! ORIGIN_TAG_QUERY( (size_t) (list_links.prev) ) );
-
-        dlink(tE) & last_links = * list_links.prev;
+        // call is valid on empty list; when so, list_links.prev and before_links.next have otags set
+
+        dlink(tE) & last_raw = * list_links.prev;
+        dlink(tE) & last_links = * (dlink(tE) *) ORIGIN_TAG_CLEAR( (size_t) & last_raw );
+        size_t last_tagval = origin_tag_query_arith$( last_raw );
 
         dlink(tE) & before_raw = * last_links.prev;
         dlink(tE) & before_links = * (dlink(tE) *) ORIGIN_TAG_CLEAR( (size_t) & before_raw );
-        verify( ! ORIGIN_TAG_QUERY( (size_t) (before_links.next) ) );
 
         size_t after_links_prev_rslt = ((size_t) & before_raw);
@@ -541,6 +574,6 @@
         asm( "" : : : "memory" );
 
-        tytagref( tLinks, dlink(tE) ) lpLnkTagged = {last_links};
-        return downcast$( lpLnkTagged );
+        tytagref( tLinks, dlink(tE) ) lpLnkTagged = { last_links };
+        return nullif$( downcast$( lpLnkTagged ), last_tagval );
     }
 
