+
+;;; TODO:
+;;; - CAST chains;
+(defun ir1-optimize-cast (cast &optional do-not-optimize)
+ (declare (type cast cast))
+ (let ((value (cast-value cast))
+ (atype (cast-asserted-type cast)))
+ (when (not do-not-optimize)
+ (let ((lvar (node-lvar cast)))
+ (when (values-subtypep (lvar-derived-type value)
+ (cast-asserted-type cast))
+ (delete-filter cast lvar value)
+ (when lvar
+ (reoptimize-lvar lvar)
+ (when (lvar-single-value-p lvar)
+ (note-single-valuified-lvar lvar)))
+ (return-from ir1-optimize-cast t))
+
+ (when (and (listp (lvar-uses value))
+ lvar)
+ ;; Pathwise removing of CAST
+ (let ((ctran (node-next cast))
+ (dest (lvar-dest lvar))
+ next-block)
+ (collect ((merges))
+ (do-uses (use value)
+ (when (and (values-subtypep (node-derived-type use) atype)
+ (immediately-used-p value use))
+ (unless next-block
+ (when ctran (ensure-block-start ctran))
+ (setq next-block (first (block-succ (node-block cast))))
+ (ensure-block-start (node-prev cast))
+ (reoptimize-lvar lvar)
+ (setf (lvar-%derived-type value) nil))
+ (%delete-lvar-use use)
+ (add-lvar-use use lvar)
+ (unlink-blocks (node-block use) (node-block cast))
+ (link-blocks (node-block use) next-block)
+ (when (and (return-p dest)
+ (basic-combination-p use)
+ (eq (basic-combination-kind use) :local))
+ (merges use))))
+ (dolist (use (merges))
+ (merge-tail-sets use)))))))
+
+ (let* ((value-type (lvar-derived-type value))
+ (int (values-type-intersection value-type atype)))
+ (derive-node-type cast int)
+ (when (eq int *empty-type*)
+ (unless (eq value-type *empty-type*)
+
+ ;; FIXME: Do it in one step.
+ (filter-lvar
+ value
+ (if (cast-single-value-p cast)
+ `(list 'dummy)
+ `(multiple-value-call #'list 'dummy)))
+ (filter-lvar
+ (cast-value cast)
+ ;; FIXME: Derived type.
+ `(%compile-time-type-error 'dummy
+ ',(type-specifier atype)
+ ',(type-specifier value-type)))
+ ;; KLUDGE: FILTER-LVAR does not work for non-returning
+ ;; functions, so we declare the return type of
+ ;; %COMPILE-TIME-TYPE-ERROR to be * and derive the real type
+ ;; here.
+ (setq value (cast-value cast))
+ (derive-node-type (lvar-uses value) *empty-type*)
+ (maybe-terminate-block (lvar-uses value) nil)
+ ;; FIXME: Is it necessary?
+ (aver (null (block-pred (node-block cast))))
+ (delete-block-lazily (node-block cast))
+ (return-from ir1-optimize-cast)))
+ (when (eq (node-derived-type cast) *empty-type*)
+ (maybe-terminate-block cast nil))
+
+ (when (and (cast-%type-check cast)
+ (values-subtypep value-type
+ (cast-type-to-check cast)))
+ (setf (cast-%type-check cast) nil))))
+
+ (unless do-not-optimize
+ (setf (node-reoptimize cast) nil)))