Relax an implicit restriction on the number of code constants on SPARC
authorDavid Lichteblau <david@lichteblau.com>
Wed, 6 Jun 2012 14:24:00 +0000 (16:24 +0200)
committerDavid Lichteblau <david@lichteblau.com>
Fri, 8 Jun 2012 12:24:13 +0000 (14:24 +0200)
Previously, LOAD-CONSTANT was restricted by SPARC's particularly small
13 bit immediate field, allowing fewer constants than on other platforms.

Fixes lp#1008996.

src/compiler/sparc/move.lisp
src/compiler/sparc/vm.lisp
tests/compiler.impure.lisp

index 72080a2..fb3c9de 100644 (file)
 
 (define-move-fun (load-constant 5) (vop x y)
   ((constant) (descriptor-reg))
-  (loadw y code-tn (tn-offset x) other-pointer-lowtag))
+  ;; Does the (positive) offset fit into our signed 13 bit immediate?
+  ;; Else go through a temporary register.  Note that PPC (for example)
+  ;; does not try to support arbitrarily large constant offsets, but PPC
+  ;; supports 16 bit immediates, so the restriction is not as severe
+  ;; there.
+  (let ((nbits 12))
+    (cond
+      ((<= (- (ash (tn-offset x) word-shift) other-pointer-lowtag)
+           (1- (ash 1 nbits)))
+       (loadw y code-tn (tn-offset x) other-pointer-lowtag))
+      (t
+       ;; Use LIP as a temporary.  This should be OK, because LIP is only
+       ;; used within VOPs, whereas we get called to supply the VOP's
+       ;; parameters much earlier.  And LIP-TN is relative to CODE-TN, so
+       ;; the GC should be fine with this.
+       (move lip-tn code-tn)
+       ;; When ADDing the offset, we need multiple steps, because ADD's
+       ;; immediate has the same size restriction as LOADW's.  Take care
+       ;; to add in word-sized steps, so that the LIP remains valid.
+       (let ((stepsize (logandc2 (1- (ash 1 nbits)) (1- (ash 1 word-shift)))))
+         (multiple-value-bind (q r)
+             (truncate (ash (tn-offset x) word-shift) stepsize)
+           (dotimes (x q) (inst add lip-tn stepsize))
+           (when (plusp r) (inst add lip-tn r))))
+       (loadw y lip-tn 0 other-pointer-lowtag)))))
 
 (define-move-fun (load-stack 5) (vop x y)
   ((control-stack) (any-reg descriptor-reg))
index 95d29f2..c282c6a 100644 (file)
   (defregtn zero any-reg)
   (defregtn null descriptor-reg)
   (defregtn code descriptor-reg)
+  (defregtn lip descriptor-reg)
   (defregtn alloc any-reg)
 
   (defregtn nargs any-reg)
index a6df1ea..263aef1 100644 (file)
       (assert (= quo -1))
       (assert (= rem (float -228645653448151381))))))
 
+(defmacro def-many-code-constants ()
+  `(defun many-code-constants ()
+     ,@(loop for i from 0 below 1000
+          collect `(print ,(format nil "hi-~d" i)))))
+
+(test-util:with-test (:name :many-code-constants)
+  (def-many-code-constants)
+  (assert (search "hi-999"
+                  (with-output-to-string (*standard-output*)
+                    (many-code-constants)))))
+
 ;;; success