[Sbcl-help] Deleting unreachable code

13 views
Skip to first unread message

Steven Nunez via Sbcl-help

unread,
Jun 5, 2023, 8:23:43 AM6/5/23
to SBCL Help
I've got a case where I think the compiler is trying to be too clever:

          (if (< last (1- i))
              (progn
            (setf denom (- (aref x i) (aref x last)))
            (loop
              for j from last below i
              do (setf alpha (/ (- (aref x j) (aref x last))
                        denom)
                   (aref ys j) (+ (* alpha (aref ys i))
                          (* (1- alpha) (aref ys last)))))))
          (setf last i)

reporting that it's deleting 'unreachable' code.

It's doing that because, the first time through the outer loop (not shown here) last will not be less than i - 1.  I know that.  I expect that, and I set last to a different value so that the second time through the outer loop it will run and properly test last.

Any way to tell SBCL, "No, it looks to you like it's unreachable, but it is, really".

    Steve

Michał "phoe" Herda via Sbcl-help

unread,
Jun 5, 2023, 8:46:44 AM6/5/23
to sbcl...@lists.sourceforge.net

Can you paste the whole function? I don't know how to work with such a small snippet without larger context.

_______________________________________________
Sbcl-help mailing list
Sbcl...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-help

Steven Nunez via Sbcl-help

unread,
Jun 5, 2023, 9:08:44 AM6/5/23
to sbcl...@lists.sourceforge.net, Michał "phoe" Herda
This is a larger fragment of a statistical operation to fit a curve using loess.

   (loop for k from 1 to nsteps
      with nleft = 0 and nright = (1- ns)
      with i = 0            ;index of current point
      with last = -1        ;index of previously estimated point
      do (loop
           do (loop while (< nright (1- n))
            do (setf d1 (- (aref x i) (aref x nleft))
                     d2 (- (aref x (1+ nright)) (aref x i)))
               (if (<= d1 d2) (return)) ;If d1 <= d2 with x[nright+1] == x[nright], lowest fixes
               ;; Radius will not decrease by a move to the right
               (incf nleft)
               (incf nright))
          (setf (aref ys i) (lowest x y n i nleft nright res (if (> k 1) 1 0) rw)) ;Fitted value at x[i]


          (if (< last (1- i))
              (progn
            (setf denom (- (aref x i) (aref x last)))
            (loop
              for j from last below i
              do (setf alpha (/ (- (aref x j) (aref x last))
                        denom)
                   (aref ys j) (+ (* alpha (aref ys i))
                          (* (1- alpha) (aref ys last)))))))
          (setf last i)

           while (< last (1- n))
           )
      )


Michał "phoe" Herda via Sbcl-help

unread,
Jun 5, 2023, 9:19:45 AM6/5/23
to Steven Nunez, sbcl...@lists.sourceforge.net

I formatted this snippet so that it compiles with just the warning you describe:

(defun bar (ALPHA D1 D2 DENOM N NS NSTEPS RES RW X Y YS)
  (flet ((lowest (&rest args) (declare (ignore args))))
    (loop for k from 1 to nsteps
          with nleft = 0 and nright = (1- ns)
          with i = 0            ;index of current point
          with last = -1        ;index of previously estimated point
          do (loop
               do (loop while (< nright (1- n))
                        do (setf d1 (- (aref x i) (aref x nleft))
                                 d2 (- (aref x (1+ nright)) (aref x i)))
                           (if (<= d1 d2) (return))
                           ;; If d1 <= d2 with x[nright+1] == x[nright],
                           ;; lowest fixes
                           ;; Radius will not decrease by a move to the right
                           (incf nleft)
                           (incf nright))
                  (setf (aref ys i) (lowest x y n i nleft nright res
                                            (if (> k 1) 1 0) rw))
                  ;;Fitted value at x[i]

                  (if (< last (1- i))
                      (progn
                        (setf denom (- (aref x i) (aref x last)))
                        (loop
                          for j from last below i
                          do (print "a")
                             (setf alpha (/ (- (aref x j) (aref x last))
                                            denom)
                                   (aref ys j)
                                   (+ (* alpha (aref ys i))
                                      (* (1- alpha) (aref ys last)))))))
                  (setf last i)
               while (< last (1- n))))))

The way I read this code is: the variable I is initialized to 0 and never reassigned, so it's always 0. The variable LAST is initialized to -1 and then reassigned to the value of 0, so it's either -1 or 0. You have a block of code conditionalized by (IF (< LAST (1- I)) ...). If I is constant, then this is equivalent to (< LAST -1). LAST, being either -1 or 0, is never less than -1, so this code is unreachable.

BR
phoe

Steven Nunez via Sbcl-help

unread,
Jun 6, 2023, 1:17:31 AM6/6/23
to sbcl...@lists.sourceforge.net, Michał "phoe" Herda
Aaaargh.  You are correct.  I'm transcribing this code from some dense NIST C/FORTRAN, and I forgot  (setf i (max (1+ last) (1- i))) just before the while termination.  I know why there aren't many numerical libraries for common lisp.  Even porting code is a headache.

Thank you,
    Steve



Reply all
Reply to author
Forward
0 new messages