(end1 (or end1 len1))
(end2 (or end2 len2))
(replace-len (min (- end1 start1) (- end2 start2))))
- ,(unless (policy node (= safety 0))
+ ,(unless (policy node (= insert-array-bounds-checks 0))
`(progn
(unless (<= 0 start1 end1 len1)
(sequence-bounding-indices-bad-error seq1 start1 end1))
;;; Only handle the simple result type cases. If somebody does (CONCATENATE
;;; '(STRING 6) ...) their code won't be optimized, but nobody does that in
;;; practice.
+;;;
+;;; Limit full open coding based on length of constant sequences. Default
+;;; value is chosen so that other parts of to compiler (constraint propagation
+;;; mainly) won't go nonlinear too badly. It's not an exact number -- but
+;;; in the right ballpark.
+(defvar *concatenate-open-code-limit* 129)
+
(deftransform concatenate ((result-type &rest lvars)
((constant-arg
(member string simple-string base-string simple-base-string))
`(apply
(lambda ,vars
(declare (ignorable ,@vars))
+ (declare (optimize (insert-array-bounds-checks 0)))
(let* ((.length. (+ ,@lengths))
(.pos. 0)
(.string. (make-string .length. :element-type ',element-type)))
(muffle-conditions compiler-note))
,@(loop for value in lvar-values
for var in vars
- collect (if (stringp value)
+ collect (if (and (stringp value)
+ (< (length value) *concatenate-open-code-limit*))
;; Fold the array reads for constant arguments
`(progn
,@(loop for c across value
- collect `(setf (aref .string.
- .pos.) ,c)
- collect `(incf .pos.)))
+ for i from 0
+ collect
+ ;; Without truly-the we get massive numbers
+ ;; of pointless error traps.
+ `(setf (aref .string.
+ (truly-the index (+ .pos. ,i)))
+ ,c))
+ (incf .pos. ,(length value)))
`(sb!impl::string-dispatch
(#!+sb-unicode
(simple-array character (*))
(if from-end
(setf find element
position index)
- (unless find
- (setf find element
- position index)))))))))))))
+ (return (values element index)))))))))))))
(def %find-position-if when)
(def %find-position-if-not unless))