As things stand
(defun test (x)
(expt x 2))
doesn't get optimized to (* x x) as NOT-MORE-CONTAGIOUS fails. Adding a
second leg to the final IF (see below the KLUDGE comment) there fixes this:
(defun not-more-contagious (x y)
(declare (type lvar x y))
(flet ((simple-numeric-type (num)
(and (numeric-type-p num)
;; Return non-NIL if NUM is integer, rational, or a float
;; of some type (but not FLOAT)
(case (numeric-type-class num)
(let ((x (lvar-type x))
(y (lvar-type y)))
(if (and (simple-numeric-type x)
(values (type= (numeric-contagion x y)
(numeric-contagion y y)))
;; KLUDGE: Include special case of X as an integer. Should
;; be more thoroughly fixed/rethought as per comment above.
(eq 'integer (numeric-type-class x))))))
(However, after this there is a redundant type-check in the generated code
for TEST, which disappears if X is declared a NUMBER -- but that seems a
totally different issue.)
Am I missing an edge-case here? Integers are the least contagious type as
far as I can tell, so this seems safe... but I'm not quite sure.
-- Nikodemus Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs."