A slight reduction of the above. Call it with (PREPARE #(3)) (defun prepare (context) (declare (optimize (debug 1) (safety 0))) (let ((npcs (the fixnum (svref context 0))) (outer-index 3)) (tagbody outer-loop (let ((payload (svref #(#((a . b) (c . d) (e . f)) (g . h) (o . p) #((i . j) (k . l) (m . n))) outer-index))) (loop for jj fixnum from 0 below (if (listp payload) 1 npcs) do (print jj) (when (eq payload nil) ; always false ;; the mere presence of this unwind-protect borks things (unwind-protect t)))) (unless (minusp (decf outer-index)) (go outer-loop))))) You can see the problem from this fragment of the trace file. lvar 30 holds the [incorrect] result of (IF (LISTP PAYLOAD) 1 NPCS). But lvar 30 has only a single WRITE into it. The write for the ELSE branch of the IF is missing, and the ELSE code jumps directly to the top of the loop. Also note that the lambda-let for (loop for jj ...) elides the binding of #:loop-limit-0 and reads directly from lvar 30, which would have been OK if lvar 30 were correct. IR1 block 5 start c52 start stack: 52> entry NIL 53> 54: SB-C::CLAMBDA (LET ((JJ 0) (#:LOOP-LIMIT-0 (IF (LISTP PAYLOAD) 1 NPCS)))) 55> 56: '0 57> 58: LISTP {GLOBAL-FUNCTION} 59> 60: PAYLOAD 61> 62: known combination v58 v60 63> if v62 c64 c65 end stack: successors c65 c64 IR1 block 19 start c64 start stack: 64> 30: '1 end stack: successors c65 IR1 block 6 start c65 start stack: 65> local combination v54 v56 66> bind SB-C::CLAMBDA (LET ((JJ 0) (#:LOOP-LIMIT-0 (IF (LISTP PAYLOAD) 1 NPCS))) ) :KIND :LET end stack: successors c67 IR1 block 7 start c67 start stack: 67> entry NIL end stack: successors c68 IR1 block 8 start c68 start stack: 68> 69: JJ 70> 71: < {GLOBAL-FUNCTION} 72> 73: known combination v71 v69 v30 ; <<< BUG. v30 was only written by one branch of the IF. 74> if v73 c75 c76 end stack: successors c76 c75 --- For comparison's sake, here is the code when you artificially inhibit single-use lvar elimination with (DEBUG 2) or whatever. Lvar 66 holds the result of (IF (LISTP PAYLOAD) 1 NPCS). It is written from both successor blocks of the IF, as expected. The comparison of JJ is against the lambda var #:LOOP-LIMIT-0. Though I think it would have been legal to elide the lambda var and read from lvar 66 which was correctly computed. IR1 block 5 start c52 start stack: 52> entry NIL 53> 54: SB-C::CLAMBDA (LET ((JJ 0) (#:LOOP-LIMIT-0 (IF (LISTP PAYLOAD) 1 NPCS)))) 55> 56: '0 57> 58: LISTP {GLOBAL-FUNCTION} 59> 60: PAYLOAD 61> 62: known combination v58 v60 63> if v62 c64 c65 end stack: successors c65 c64 IR1 block 20 start c64 start stack: 64> 66: '1 end stack: successors c67 IR1 block 6 start c65 start stack: 65> 66: NPCS end stack: successors c67 IR1 block 7 start c67 start stack: 67> local combination v54 v56 v66 68> bind SB-C::CLAMBDA (LET ((JJ 0) (#:LOOP-LIMIT-0 (IF (LISTP PAYLOAD) 1 NPCS))) ) :KIND :LET end stack: successors c69 IR1 block 8 start c69 start stack: 69> entry NIL end stack: successors c70 IR1 block 9 start c70 start stack: 70> 71: JJ 72> 73: < {GLOBAL-FUNCTION} 74> 75: #:LOOP-LIMIT-0 76> 77: known combination v73 v71 v75 78> if v77 c79 c80 end stack: