;;; cp0.ms
;;; Copyright 1984-2017 Cisco Systems, Inc.
;;; 
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;; 
;;; http://www.apache.org/licenses/LICENSE-2.0
;;; 
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

(define-syntax cp0-mat
  (syntax-rules ()
    [(_ name form ...)
     (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
       (mat name form ...))]))

(cp0-mat cp0-regression
 ; test to keep cp0 honest about letrec's implicit assignment
  #;(letrec ((x (call/cc (lambda (k) k)))) ; invalid in r6rs
    (let ((y x))
      (y (lambda (z) (not (eq? x y))))))
 ; make sure compiler doesn't loop...
  (begin
    (define omega
      (lambda ()
        ((lambda (x) (x x)) (lambda (x) (x x)))))
    (procedure? omega))
 ; make sure cp0 doesn't assume read returns #t
  (not (read (open-input-string "#f")))
 ; test proper visiting of assigned variables
  (letrec ((x (lambda () x)) (y (lambda () x)))
    (set! y (y))
    (eq? y (y)))
 ; test proper quote propagation from seq w/side effect
  (equal?
    (let ((x 0))
      (let ((y (begin (set! x (+ x 1)) 0)))
        (let ((z (+ y 1)))
          (list x z))))
    '(1 1))
 ; test that we reset integrated? flags for outer calls when we bug out of
 ; an inner call in cases where operator of call is itself a call
  (begin
    (define whack! (lambda () (set! whack! 'okay)))
    (define ignore list)
    (letrec ([g
              (lambda x
                  ((lambda (x)
                     (ignore)
                     (when (null? x) (g #f))
                     (lambda (y) (ignore x y y y)))
                   (ignore (ignore ignore))))])
      ((g) (whack!)))
    (eq? whack! 'okay))
 ; make sure cp0 does not go to lala land
  (error? (letrec ((x x)) x))
 ; make sure residual assignments to unref'd vars don's blow
  (eq? (let ((x (void)))
         (set! x 0)
         (letrec ((f (lambda () (set! x (+ x 1)) x)) (g (lambda (x) x)))
           (g 3)))
       3)
  (eq? (let ()
         (define kons-proc
           (lambda (a) (lambda (b) (lambda (g) ((g a) b)))))
         (define-syntax kons
           (syntax-rules () [(_ x y) ((kons-proc x) y)]))
         (define kar (lambda (pr) (pr (lambda (a) (lambda (b) a)))))
         (define kdr (lambda (pr) (pr (lambda (a) (lambda (b) b)))))
         ((kar (kons (lambda (x y) (kar (kons x y)))
                 (kons (lambda (x y) (kdr (kons x y)))
                       (lambda (x y) (kdr (kar (kons (kons x y) 'nil)))))))
          3 4))
       3)
 ; test for various bugs fixed in 5.9i, all relating to resetting an
 ; outer context when we abort from an inner one
  (begin
    (define **a 1)
    (define-syntax **huge
      (identifier-syntax
        (set! **output
          (cons
            (list (list **a **a **a **a **a **a **a **a **a **a)
                  (list **a **a **a **a **a **a **a **a **a **a)
                  (list **a **a **a **a **a **a **a **a **a **a)
                  (list **a **a **a **a **a **a **a **a **a **a)
                  (list **a **a **a **a **a **a **a **a **a **a))
            **output))))
    (define **test-output
      (case-lambda
        [(th) (**test-output 1 th)]
        [(n th)
         (set! **output '())
         (and (th)
           (equal? **output
             (make-list n
               '((1 1 1 1 1 1 1 1 1 1)
                 (1 1 1 1 1 1 1 1 1 1)
                 (1 1 1 1 1 1 1 1 1 1)
                 (1 1 1 1 1 1 1 1 1 1)
                 (1 1 1 1 1 1 1 1 1 1)))))]))
    (**test-output (lambda () **huge #t)))
  (**test-output
    (lambda ()
      (equal?
        (let ((f (lambda ()
                   (let ((x **huge))
                     (let ((g (lambda () x)))
                       (g) memq)))))
          ((f) (+ 1 2) '(1 2 3 4 5)))
        '(3 4 5))))
  (**test-output
    (lambda ()
      (equal?
        (let ((f (lambda ()
                   (let ((x **huge))
                     (let ((g (begin 0 (lambda () x)))) (g) memq)))))
          ((f) (+ 1 2) '(1 2 3 4 5)))
        '(3 4 5))))
  (**test-output
    (lambda ()
      (equal?
        (let ((f (lambda ()
                   (let ((x **huge))
                     (let ((g (lambda () x))) (g) (g) memq)))))
          ((f) (+ 1 2) '(1 2 3 4 5)))
        '(3 4 5))))
  (**test-output
    (lambda ()
      (eq?
        (let ((f (lambda () (let ((x **huge)) (lambda (y z) (or (= y 3) x))))))
          ((f) (+ 1 2) 4))
        #t)))
  (**test-output 2
    (lambda ()
      (eq? (let ((f (lambda ()
                      (let ((x **huge)) (lambda (y z) (or (= y 3) x))))))
            ((f) (+ 1 2) 4)
            ((f) (+ 1 2) 4))
        #t)))
  (**test-output 2
    (lambda ()
      (eq?
        (let ((f (lambda ()
                   (let ((x **huge)) (lambda (y z) (if (y z) 'ok x))))))
          ((f) + 3)
          ((f) + 3))
        'ok)))
  (eq?
    (let ((f (lambda () (let ((x 0)) (lambda (y z) (if (y z) 'ok x))))))
      ((f) + 3))
    'ok)
  (not (let ((f (lambda (x)
             (eq? (begin (set! x 4) x)
                  (begin (set! x 5) x)))))
         (f 'a)))
  (not (let ((f #f) (g #f))
         (let ((x 0))
           (set! g (lambda () (eq? (begin (f) x) (begin (f) x))))
           (set! f (lambda () (set! x (+ x 1))))
           (g))))
  (eq? (let ([g% (lambda (cp)
                   (let ([t1 0])
                     (set! t1 (car cp))
                     (let ([t2 t1]) 4)))])
         g%
         (g% '(0)))
       4)
  (error? (let ((f (lambda (x) x))) (let ((g f)) (g))))
  (begin
    (define $foo$
      (letrec ((func1
                (lambda (cont0)
                  (cont0 'x)))) ; incorrect # args to cont0 (func3)
         (lambda ()
           (letrec ((func3
                     (lambda (cont2 x)
                       (cont2 x))))
              (lambda ()
                (func1 func3))))))
    #t)
  (error? (($foo$)))
  (begin
    (define $foo$
      (letrec ((func1
                (lambda (cont0)
                  (cont0 list 'x)))) ; correct # args to cont0 (func3)
         (lambda ()
           (letrec ((func3
                     (lambda (cont2 x)
                       (cont2 x))))
              (lambda ()
                (func1 func3))))))
    #t)
  (equal? (($foo$)) '(x))
 ; make sure cpletrec doesn't toss bindings for assigned variables
  (equal?
    (let ()
      (define *root* '())
      (define (init-traverse) (set! *root* 0))
      (define (run-traverse) (traverse *root*))
      (init-traverse))
    (void))
 ; make sure nested cp0 doesn't assimilate letrec bindings when
 ; body is simple but not pure
  ((lambda (x ls) (and (member x ls) #t))
    (let ([x 0])
      (letrec ([a (letrec ([b (set! x 1)]) x)]
               [c (letrec ([d (set! x 2)]) x)])
        (list a c)))
    '((1 2) (2 1)))
  ((lambda (x ls) (and (member x ls) #t))
    (let ([x 0])
      (letrec ([a (letrec ([b x]) (set! x 1) b)]
               [c (letrec ([d x]) (set! x 2) d)])
        (list a c x)))
    '((2 0 1) (0 1 2)))
 ; make sure (r6rs:fx+ x 0) isn't folded to (r6rs:fx+ x), since
 ; r6rs:fx+ doesn't accept just one argument.
  (begin
    (define $cp0-f (let ([z 0]) (lambda (x) (r6rs:fx+ x z))))
    (define $cp0-g (let ([z 0]) (lambda (x) (r6rs:fx* x 1))))
    #t)
  (eqv? ($cp0-f 17) 17)
  (eqv? ($cp0-g 17) 17)
  (error? ($cp0-f 'a))
  (error? ($cp0-g 'a))
 ; make sure cp0 isn't overeager about moving discardable but
 ; not pure primitive calls
  (and
    (member
      (let ([p (cons 1 2)])
        (list
          (let ([x (car p)]) (set-car! p 3) x)
          (let ([x (car p)]) (set-car! p 4) x)))
      '((4 1) (1 3)))
    #t)
  ; make sure cp0 doesn't screw up on an "almost" or pattern
  (error? ; #f is not a number
    (if (let ([x (eqv? (random 2) 2)]) (if x x (+ x 1))) 4 5))
   (begin
     (define f
       (lambda (x)
         (letrec ([foo (lambda (ls)
                         (let loop ([ls ls] [rls '()])
                           (if (null? ls)
                               rls
                               (loop (cdr ls) (cons (car ls) rls)))))])
           (apply foo (list x)))))
     #t)
   (equal?
     (f (list 1 2))
     '(2 1))
   (begin
     (define f
       (lambda (x)
         (letrec ([foo (lambda (x ls)
                         (let loop ([ls ls] [rls '()])
                           (if (null? ls)
                               (cons x rls)
                               (loop (cdr ls) (cons (car ls) rls)))))])
           (apply (begin (write 'a) foo) (begin (write 'b) 'bar) (begin (write 'c) (list x))))))
     #t)
   (equal?
     (f (list 1 2))
     '(bar 2 1))
   ((lambda (x ls) (and (member x ls) #t))
    (with-output-to-string (lambda () (f (list 1 2))))
    '("abc" "acb" "bac" "bca" "cab" "cba"))
   (begin
     (define $x 17)
     #t)
   ((lambda (x ls) (and (member x ls) #t))
    (with-output-to-string
      (lambda ()
        (apply
          (begin (write 'a) member)
          (begin (write 'b) $x)
          (begin (write 'c) (list (begin (write 'd) '()))))))
    '("abcd" "acdb" "bacd" "bcda" "cdab" "cdba"))
   ((lambda (x ls) (and (member x ls) #t))
    (with-output-to-string
      (lambda ()
        (apply
          (begin (write 'a) ash)
          (begin (write 'b) $x)
          (begin (write 'c) (list (begin (write 'd) 0))))))
    '("abcd" "acdb" "bacd" "bcda" "cdab" "cdba"))
   ; check to see if this turns up a missing referenced flag due to an extra
   ; binding for p.  (missing referenced flags are presently detected only when
   ; cpletrec is compiled with d=k, k > 0.)
   (equal?
     (apply (let ([p (box 0)]) (lambda () p)) '())
     '#&0)
   ; check for some corrected flags
   (not (and (record-type-parent #!base-rtd) #t))
   (error? ; invalid report specifier
     (begin
       (null-environment #f)
       #t))
   (error? ; not a source object
     (begin
       (source-object-bfp #f)
       #t))
   (error? ; not a source object
     (begin
       (source-object-efp #f)
       #t))
   (error? ; not a source object
     (begin
       (source-object-sfd #f)
       #t))
   (error? ; not a condition
     (begin
       (condition #f)
       #t))
   ; nested if optimization
   (begin
     (define $cp0-f
       (lambda (x y a b c)
         (if (if (if (if (#3%zero? (a)) #f #t) (begin (b) #t) #f)
                 (c)
                 #f)
             (x)
             (y))))
     #t)
   (equal?
     (with-output-to-string
       (lambda ()
         ($cp0-f
           (lambda () (printf "x\n"))
           (lambda () (printf "y\n"))
           (lambda () (printf "a\n") 0)
           (lambda () (printf "b\n"))
           (lambda () (printf "c\n") #t))))
     "a\ny\n")
   (equivalent-expansion?
     (expand/optimize
       '(lambda (x y a b c)
          (if (if (if (if (#3%zero? (a)) #f #t) (begin (b) #t) #f)
                  (c)
                  #f)
              (x)
              (y))))
     '(lambda (x y a b c)
        (if (if (#3%zero? (a))
                #f
                (begin (b) (c)))
            (x)
            (y))))
   (equivalent-expansion?
     (expand/optimize
       '(lambda (x y a b c)
          (if (if (if (not (#3%zero? (a))) (begin (b) #t) #f)
                  (c)
                  #f)
              (x)
              (y))))
     '(lambda (x y a b c)
        (if (if (#3%zero? (a))
                #f
                (begin (b) (c)))
            (x)
            (y))))
   (error? (apply zero? 0))
   (error? (if (apply eof-object 1 2) 3 4))
  ; test for folding of multiple-value primitives
   (equivalent-expansion?
     (expand/optimize '(lambda () (div-and-mod 7 3)))
     '(lambda () (#3%values 2 1)))
   (equivalent-expansion?
     (expand/optimize '(lambda () (exact-integer-sqrt 19)))
     '(lambda () (#3%values 4 3)))
   (equivalent-expansion?
     (expand/optimize
       '(call-with-values
          (lambda () (div-and-mod 7 3))
          (lambda (x y) (#2%cons (* x 10) (/ y 10)))))
     '(#2%cons 20 1/10))

  (equivalent-expansion?
   (expand/optimize '(lambda (t) (#3%$value (if t 1 (values 3 3 3))) #t))
   (if (eqv? (optimize-level) 3)
       '(lambda (x) #t)
       '(lambda (x)
          (#3%$value (if x 1 (#2%values 3 3 3)))
          #t)))

  (not
   (equivalent-expansion?
    (expand/optimize
     '(lambda (g x y)
        (call-with-values (lambda ()
                            (values
                             (values x y)))
          (case-lambda
           [(x y) (g x y)]))))
    '(lambda (g x y) (g x y))))

)

(cp0-mat cp0-mrvs
  (eqv? (call-with-values (lambda () (values 1 2 3)) +) 6)
  (begin
    (define **cwv-test
      (lambda (out p)
        (define x '())
        (define pp (lambda (a) (set! x (cons a x))))
        (and (p pp)
             (if (procedure? out)
                 (out (reverse x))
                 (equal? (reverse x) out)))))
    (**cwv-test '(1 2 2 3)
      (lambda (pretty-print)
        (pretty-print 1)
        (pretty-print 2)
        (pretty-print 2)
        (pretty-print 3)
        #t)))
  (**cwv-test '(1 1 2 3)
    (lambda (pretty-print)
      (equal?
        (call-with-values
          (begin
            (pretty-print 1)
            (lambda () (pretty-print 2) (+ 1 2 3)))
          (begin
            (pretty-print 1)
            (lambda (n) (pretty-print 3) (list n n n))))
        '(6 6 6))))
  (**cwv-test '(1 1 2 3)
    (lambda (pretty-print)
      (eqv?
        (call-with-values
          (begin
            (pretty-print '1)
            (lambda () (pretty-print '2) (values 1 2 3)))
          (begin
            (pretty-print '1)
            (lambda (a b c) (pretty-print '3) (+ c b a))))
        6)))
  (**cwv-test '(1 1 2 3 4)
    (lambda (pretty-print)
      (eqv?
        (call-with-values
          (begin
            (pretty-print '1)
            (lambda ()
              (pretty-print '2)
              (values 1 (begin (pretty-print '3) 2) 3)))
          (begin
            (pretty-print '1)
            (lambda (a b c) (pretty-print '4) (+ c b a))))
        6)))
  (begin
    (define **foo (lambda () (values 'a 'b 'c)))
    (define **bar vector)
    (equal? (call-with-values **foo **bar) '#(a b c)))
  (equal?
    (call-with-values
      (lambda () (values 1 2 3))
      (case-lambda [(x) (list x x x)] [(a b c) (list c b a)]))
    '(3 2 1))
  (equal? (call-with-values (lambda () (values 1 2 3)) **bar) '#(1 2 3))
  (**cwv-test '(1 2)
    (lambda (pretty-print)
      (equal?
        (call-with-values
          (lambda () (pretty-print '2) (values 1 2 3))
          (begin (pretty-print '1) **bar))
        '#(1 2 3))))
  (**cwv-test '(1 1 2)
    (lambda (pretty-print)
      (equal?
        (call-with-values
          (begin
            (pretty-print '1)
            (lambda () (pretty-print '2) (values 1 2 3)))
          (begin (pretty-print '1) **bar))
        '#(1 2 3))))
  (equal? (call-with-values **foo (lambda (a b c) (list c b a))) '(c b a))
  (equal? (let ((f (lambda (a b c) (list c b a))))
            (call-with-values **foo f))
    '(c b a))
  (**cwv-test '(1)
    (lambda (pretty-print)
      (equal? (call-with-values
                **foo
                (begin
                  (pretty-print '1)
                  (lambda (a b c) (vector c b a))))
        '#(c b a))))
  (**cwv-test (lambda (x) (or (equal? x '(1 2 3)) (equal? x '(2 3 4))))
    (lambda (pretty-print)
      (define n 1)
      (define boof
        (lambda ()
          (pretty-print 3)
          (lambda (a b c) (list c b a))))
      (equal?
        (call-with-values
          (begin (pretty-print n) **foo)
          (begin (set! n 4) (pretty-print 2) (boof)))
        '(c b a))))
  (**cwv-test '(1 2 3)
    (lambda (pretty-print)
      (define n 1)
      (define boof
        (lambda ()
          (pretty-print 3)
          (lambda (a b c) (list c b a))))
      (equal?
        (let* ((prod (begin (pretty-print n) **foo))
               (csmr (begin (set! n 4) (pretty-print 2) (boof))))
          (call-with-values prod csmr))
        '(c b a))))
  (**cwv-test '(2 3 4)
    (lambda (pretty-print)
      (define n 1)
      (define boof
        (lambda ()
          (pretty-print 3)
          (lambda (a b c) (list c b a))))
      (equal?
        (let* ((csmr (begin (set! n 4) (pretty-print 2) (boof)))
               (prod (begin (pretty-print n) **foo)))
          (call-with-values prod csmr))
        '(c b a))))
  (**cwv-test '(1 1)
    (lambda (pretty-print)
      (equal?
        (call-with-values
          (begin
            (pretty-print '1)
            **foo)
          (begin
            (pretty-print '1)
            (lambda (a b c) (list c b a))))
        '(c b a))))
  (begin
    (set! **a #t)
    (equal?
      (call-with-values
        (lambda () (if **a (values 1) (values 1 2 3)))
        (case-lambda [(x) (list x x x)] [(a b c) (list c b a)]))
      '(1 1 1)))
  (begin
    (set! **a #f)
    (equal?
      (call-with-values
        (lambda () (if **a (values 1) (values 1 2 3)))
        (case-lambda [(x) (list x x x)] [(a b c) (list c b a)]))
      '(3 2 1)))
  (begin
    (set! **a #t)
    (equal?
      (let ((f (lambda (a) (if **a (values 1) (values 1 2 3)))))
        (call-with-values
          (lambda () (f #t))
          (case-lambda [(x) (list x x x)] [(a b c) (list c b a)])))
      '(1 1 1)))
  (begin
    (set! **a #f)
    (equal?
      (let ((f (lambda (a) (if **a (values 1) (values 1 2 3)))))
        (call-with-values
          (lambda () (f #t))
          (case-lambda [(x) (list x x x)] [(a b c) (list c b a)])))
      '(3 2 1)))
  (equal?
    (call-with-values
      (lambda ()
        (define foo
          (lambda (x)
            (if (zero? x)
                (values 1 2 3)
                (call-with-values
                  (lambda () (foo (- x 1)))
                  (lambda (a b c)
                    (values (+ a 1) (+ b a) (+ c 2)))))))
        (call-with-values
          (lambda () (foo 0))
          (lambda (a b c)
            (foo (+ a b c)))))
      list)
    '(7 23 15))
  (equal?
    (let ((f (lambda ()
               (let loop ((n 10))
                 (if (zero? n)
                     call-with-values
                     (loop (fx- n 1)))))))
      ((f) (lambda () (values 1 2)) cons))
    '(1 . 2))
  (equal?
    (let ()
      (define (go n)
        (let ((f (lambda ()
                   (let loop ((n n))
                     (if (zero? n)
                         call-with-values
                         (loop (fx- n 1)))))))
          ((f) (lambda () (values 1 2)) cons)))
      (go 1000))
    '(1 . 2))
  (begin
    (define **bozo
      (lambda (pretty-print)
        (pretty-print '3)
        (lambda x
          (pretty-print 6)
          x)))
    (define **clown (lambda () (values 1 2 3)))
    (**cwv-test '(3 6)
      (lambda (pretty-print)
        (equal?
          (call-with-values **clown (**bozo pretty-print))
          '(1 2 3)))))
  (**cwv-test '(1 2)
    (lambda (pretty-print)
      (equal?
        (let ((f (lambda () (pretty-print '2) (values 1 2 3))))
          (call-with-values
            (begin (pretty-print '1) f)
            (lambda x x)))
        '(1 2 3))))
  (**cwv-test '(1 2)
    (lambda (pretty-print)
      (equal?
        (let ((f (lambda () (pretty-print '2) (**foo))))
          (call-with-values
            (begin (pretty-print '1) f)
            (lambda x x)))
        '(a b c))))
  (**cwv-test '(1 2 3 4)
    (lambda (pretty-print)
      (equal?
        (let ([f
               (lambda ()
                 (pretty-print '2)
                 (lambda () (pretty-print '3) (**foo)))])
          (call-with-values
            (begin (pretty-print '1) (f))
            (lambda x (pretty-print 4) x)))
        '(a b c))))
  (**cwv-test '(1)
    (lambda (pretty-print)
      (equal?
        (call-with-values
          (begin (pretty-print '1) (lambda () (**foo)))
          (lambda (x y z) (list y z x)))
        '(b c a))))
  (procedure?
    (lambda ()
      (define test1 (lambda () void))
      (define test2
        (lambda ()
          (call-with-values test1 (lambda (tester) (tester)))))
      (test2)))
  (eqv?
    (let ()
      (define test1 (lambda (x) (values (lambda () (+ x 1)))))
      (define test2
        (lambda (x)
          (let-values ([(tester) (test1 x)])
            (tester))))
      (test2 10))
    11)
  (test-cp0-expansion
    '(lambda (x)
       (call-with-values (lambda () (unbox x)) display))
    (if (eqv? (optimize-level) 3)
        '(lambda (x) (#3%display (#3%unbox x)))
        '(lambda (x) (#2%display (#2%unbox x)))))
  (test-cp0-expansion
    '(lambda (x)
       (call-with-values (lambda () (if x 1 2)) display))
    (if (eqv? (optimize-level) 3)
        '(lambda (x) (#3%display (if x 1 2)))
        '(lambda (x) (#2%display (if x 1 2)))))
  ; verify optimization of begin0 pattern
  (test-cp0-expansion
    '(lambda (x)
       (call-with-values (lambda ()
                           (call-with-values (lambda () (unbox x))
                             (case-lambda
                               [(x) (values x #f)]
                               [args (values args #t)])))
         (lambda (l apply?)
           (newline)
           (if apply?
               (apply values l)
               l))))
    (if (eqv? (optimize-level) 3)
        '(lambda (x)
           (let ([temp (#3%unbox x)])
             (#3%newline)
             temp))
        '(lambda (x)
           (let ([temp (#2%unbox x)])
             (#2%newline)
             temp))))
)

(cp0-mat apply-partial-folding
  (test-cp0-expansion
    '(apply fx+ '(1 2 3 4 5))
    15)
  (test-cp0-expansion
    '(apply fx+ 3 x 4 '(5 7 9))
    (if (eqv? (optimize-level) 3)
        '(#3%fx+ 28 x)
        '(#2%fx+ 28 x)))
  (test-cp0-expansion
    '(apply fx+ 3 x 4 (begin (write 'hi) '(5 7 9)))
    (if (eqv? (optimize-level) 3)
        '(let ([g x]) (#3%write 'hi) (#3%fx+ 28 g))
        '(let ([g x]) (#2%write 'hi) (#2%fx+ 28 g))))
  (test-cp0-expansion
    '(apply fx+ 3 x 4 '(5 7 9.0))
    (if (eqv? (optimize-level) 3)
        '(#3%fx+ 19 x 9.0)
        '(#2%fx+ 19 x 9.0)))
  (test-cp0-expansion
    `(apply apply '(,list 2 3 (4 5 6)))
    `(',list 2 3 4 5 6))
  (test-cp0-expansion
    `(#3%apply #3%apply #3%+ '(1 (2 3 4)))
    10)
  (test-cp0-expansion
    `(apply apply apply + 1 '(2 3 (4 5 (6 7))))
    28)
  (test-cp0-expansion
    `(let ([f apply]) (f f f * 1 '(2 3 (4 5 (6)))))
    720)
  (test-cp0-expansion
   `(lambda (x) (apply (lambda (prim ls) (apply prim ls)) zero? (list x)))
   (if (eqv? (optimize-level) 3)
       '(lambda (x) (#3%apply #3%zero? x))
       '(lambda (x) (#2%apply #2%zero? x))))
  (test-cp0-expansion
   `(apply (lambda (prim ls) (apply prim ls)) zero? (list (cons 0 '())))
   #t)
  (test-cp0-expansion
   `(apply (lambda (prim ls) (apply prim ls)) zero? (cons 0 '()))
   (if (eqv? (optimize-level) 3)
       '(#3%apply #3%zero? 0)
       '(#2%apply #2%zero? 0)))
)

(mat expand/optimize
  (error? (expand/optimize))
  (error? (expand/optimize 'a 'b))
  (error? (expand/optimize 'a 'b 'c))
  (eqv? (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))])
          (expand/optimize 3))
        3)
  (equal? (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))])
            (expand/optimize '(#2%cdr '(3 4))))
          ''(4))
  (eqv? (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2])
          (expand/optimize ; from cp0 talk
            '(let ([n (expt 2 10)])
               (define even?
                 (lambda (x) (or (zero? x) (not (odd? x)))))
               (define odd?
                 (lambda (x) (not (even? (- x 1)))))
               (define f
                 (lambda (x)
                   (lambda (y)
                     (lambda (z)
                       (if (= z 0) (omega) (+ x y z))))))
               (define omega
                 (lambda ()
                   ((lambda (x) (x x)) (lambda (x) (x x)))))
               (let ([g (f 1)] [m (f n)])
                 (let ([h
                        (if (> ((g 2) 3) 5)
                            (lambda (x) (+ x 1))
                            odd?)])
                   (h n))))))
        1025)
  (let ([x (parameterize ([#%$suppress-primitive-inlining #f]
                          [run-cp0 (lambda (cp0 x) (cp0 x))]
                          [optimize-level 3])
             (expand/optimize ; from mwbor talk
               '(let ()
                  (import scheme)
                  (define opcode-pos 27)
                  (define src1-pos 22)
                  (define src2-pos 0)
                  (define dst-pos 17)
                  (define imm-bit (ash 1 16))
                  (define regops '((ld . 22) (add . 28)))
                  (define immops '((addi . 28)))
                  (define regcodes
                    '((r0 . 0) (r1 . 1) (r2 . 2) (r3 . 3)))
                  (define-syntax reg
                    (syntax-rules ()
                      [(_ r) (cdr (assq 'r regcodes))]))
                  (define imm
                    (lambda (n)
                      (unless (< -32768 n 32767)
                        (errorf 'imm "invalid immediate ~s" n))
                      n))
                  (define $emit!
                    (lambda (op a1 a2 a3)
                      (emit-word!
                        (+ (cond
                             [(assq op regops) =>
                              (lambda (a)
                                (ash (cdr a) opcode-pos))]
                             [(assq op immops) =>
                              (lambda (a)
                                (+ (ash (cdr a) opcode-pos)
                                   imm-bit))]
                             [else
                              (errorf 'emit
                                "unrecognized operator ~s"
                                op)])
                           (ash a1 src1-pos)
                           (ash a2 src2-pos)
                           (ash a3 dst-pos)))))
                  (define-syntax emit
                    (syntax-rules ()
                      [(_ op a1 a2 a3) ($emit! 'op a1 a2 a3)]))
                  (set! test
                    (lambda (r)
                      (emit ld (reg r0) (reg r1) (reg r2))
                      (emit addi (reg r2) 320 (reg r2))
                      (emit add (reg r2) r (reg r2)))))))])
    (and
      (equivalent-expansion? x
        '(set! test
           (lambda (r)
             (emit-word! 2953052161)
             (emit-word! 3766812992)
             (emit-word! (#3%+ 3766747136 r)))))
      (syntax-case x ()
        [(set! test
           (lambda (r1)
             (ew1! 2953052161)
             (ew2! 3766812992)
             (ew3! (#3%+ 3766747136 r2))))
         (eq? #'r1 #'r2)])))
  (let ([x (parameterize ([#%$suppress-primitive-inlining #f]
                          [run-cp0 (lambda (cp0 x) (cp0 x))]
                          [optimize-level 2])
             (expand/optimize ; from mwbor talk
               '(let ()
                  (import scheme)
                  (define opcode-pos 27)
                  (define src1-pos 22)
                  (define src2-pos 0)
                  (define dst-pos 17)
                  (define imm-bit (ash 1 16))
                  (define regops '((ld . 22) (add . 28)))
                  (define immops '((addi . 28)))
                  (define regcodes
                    '((r0 . 0) (r1 . 1) (r2 . 2) (r3 . 3)))
                  (define-syntax reg
                    (syntax-rules ()
                      [(_ r) (cdr (assq 'r regcodes))]))
                  (define imm
                    (lambda (n)
                      (unless (< -32768 n 32767)
                        (errorf 'imm "invalid immediate ~s" n))
                      n))
                  (define $emit!
                    (lambda (op a1 a2 a3)
                      (emit-word!
                        (+ (cond
                             [(assq op regops) =>
                              (lambda (a)
                                (ash (cdr a) opcode-pos))]
                             [(assq op immops) =>
                              (lambda (a)
                                (+ (ash (cdr a) opcode-pos)
                                   imm-bit))]
                             [else
                              (errorf 'emit
                                "unrecognized operator ~s"
                                op)])
                           (ash a1 src1-pos)
                           (ash a2 src2-pos)
                           (ash a3 dst-pos)))))
                  (define-syntax emit
                    (syntax-rules ()
                      [(_ op a1 a2 a3) ($emit! 'op a1 a2 a3)]))
                  (set! test
                    (lambda (r)
                      (emit ld (reg r0) (reg r1) (reg r2))
                      (emit addi (reg r2) 320 (reg r2))
                      (emit add (reg r2) r (reg r2)))))))])
    (and
      (equivalent-expansion? x
        '(set! test
           (lambda (r)
             (emit-word! 2953052161)
             (emit-word! 3766812992)
             (emit-word! (#3%+ 3766747136 (#2%ash r 0))))))
      (syntax-case x ($primitive)
        [(set! test
           (lambda (r1)
             (ew1! 2953052161)
             (ew2! 3766812992)
             (ew3! (#3%+ 3766747136 (#2%ash r2 0)))))
         (eq? #'r1 #'r2)])))
 ; verify optimization of (if e s s) => (begin e s)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x) (if e x x))))
    '(lambda (x) e x))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (y x) (if y x x))))
    '(lambda (y x) x))
 ; verify optimization of (if s s #f) => s
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x) (if x x #f))))
    '(lambda (x) x))
 ; verify optimization of (if (eq? x y) x y)  => (begin x y) => y
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x y) (if (eq? x y) x y))))
    '(lambda (x y) y))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x y) (if (eq? y x) x y))))
    '(lambda (x y) y))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (y) (if (eq? 'x y) 'x y))))
    '(lambda (y) y))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (y) (if (eq? y 'x) 'x y))))
    '(lambda (y) y))
 ; verify optimization of or pattern
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(let ()
           (define-syntax broken-or
             (syntax-rules ()
               [(_) #f]
               [(_ x y ...)
                (let ([t x])
                  (if t t (broken-or y ...)))]))
           (broken-or a))))
    'a)
 ; verify optimization of or pattern
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x y) (if (not (or (fx< x y) (fx> y x))) x y))))
    '(lambda (x.0 y.1)
       (if (if (#2%fx< x.0 y.1) #t (#3%fx> y.1 x.0))
           y.1
           x.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(lambda (x y) (if (or (fx< x y) (fx> y x)) x y))))
    '(lambda (x y) (if (if (#2%fx< x y) #t (#3%fx> y x)) x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(let ([q #f])
           (lambda (x y) (if (or q (fx> x y)) x y)))))
    '(lambda (x y) (if (#2%fx> x y) x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(let ([q #t])
           (lambda (x y) (if (or q (fx> x y)) x y)))))
    '(lambda (x y) x))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(begin 3 4)))
    4)
  ; verify expansion of not pattern
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(not #t)))
    #f)
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(not #f)))
    #t)
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(not '(a b c))))
    #f)
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(let ([x 2] [y 3])
           (not (begin (set! x (* x y)) (set! y (* x y)) 10)))))
    `(let ([x 2] [y 3])
       (set! x (#2%* x y))
       (set! y (#2%* x y))
       #f))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(not (let ([x 2] [y 3]) (set! x (* x y)) (set! y (* x y)) 10))))
    `(let ([x 2])
       (let ([y 3])
         (set! x (#2%* x y))
         (set! y (#2%* x y))
         #f)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(if (not (or #t (futz))) 17 32)))
    32)
  ; verify expansion of (eq? _ #f) pattern
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(lambda (x) (eq? x #f))))
    `(lambda (x) (if x #f #t)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        `(lambda (x) (if (eq? x #f) 1 2))))
    `(lambda (x) (if x 2 1)))
)

(mat expand-output
  (error? ; not a textual output port or #f
    (expand-output #t))
  (error?  ; not a textual output port or #f
    (let-values ([(bop get) (open-bytevector-output-port)])
      (expand-output bop)))
  (begin
    (define $eospam 17)
    #t)
  (equal?
    (with-output-to-string
      (lambda ()
        (parameterize ([expand-output (current-output-port)] [#%$suppress-primitive-inlining #f])
          (pretty-print (compile '(let () (import (chezscheme)) (+ 3 4 $eospam)))))))
    (if (eqv? (optimize-level) 3)
        "(#3%+ 3 4 $eospam)\n24\n"
        "(#2%+ 3 4 $eospam)\n24\n"))
  (equal?
    (with-output-to-string
      (lambda ()
        (parameterize ([expand-output (current-output-port)] [#%$suppress-primitive-inlining #f])
          (pretty-print (interpret '(let () (import (chezscheme)) (+ 3 4 $eospam)))))))
    (if (eqv? (optimize-level) 3)
        "(#3%+ 3 4 $eospam)\n24\n"
        "(#2%+ 3 4 $eospam)\n24\n"))
  (begin
    (with-output-to-file "testfile.ss"
      (lambda ()
        (pretty-print '(eval-when (visit revisit) (define $eo-q (* 2 2))))
        (pretty-print '(define $eo-x 3))
        (pretty-print '(define-syntax $eo-a (identifier-syntax 5)))
        (pretty-print '(pretty-print (vector $eo-x $eo-q (+ $eo-a 1)))))
      'replace)
    #t)
  (begin
    (define $eo-sop
      (let ()
        (define syntax-record-writer
          (case-lambda
            [() (record-writer (record-rtd #'a))]
            [(x) (record-writer (record-rtd #'a) x)]))
        (open-input-string
          (with-output-to-string
            (lambda ()
              (parameterize ([expand-output (current-output-port)]
                             [print-gensym #t]
                             [optimize-level 2]
                             [compile-file-message #f]
                             [enable-cp0 #t]
                             [#%$suppress-primitive-inlining #f]
                             [syntax-record-writer (lambda (x p wr) (display "syntax-object" p))])
                (compile-file "testfile")))))))
    #t)
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (begin
         (set! $eo-q (#2%* 2 2))
         (#3%$sc-put-cte
           'syntax-object
           '(global . ,gensym?)
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (revisit)
         (set! $eo-x 3))
       (eval-when (visit)
         (#3%$sc-put-cte
           'syntax-object
           '(global . ,gensym?)
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (visit)
         (#3%$sc-put-cte
           'syntax-object
           ,list?
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (revisit)
         (#2%pretty-print (#2%vector $eo-x $eo-q (#2%+ 5 1))))))
  (begin (set! $eo-sop #f) #t)
)

(mat expand/optimize-output
  (error? ; not a textual output port or #f
    (expand/optimize-output #t))
  (error?  ; not a textual output port or #f
    (let-values ([(bop get) (open-bytevector-output-port)])
      (expand/optimize-output bop)))
  (equal?
    (with-output-to-string
      (lambda ()
        (parameterize ([expand/optimize-output (current-output-port)]
                       [enable-cp0 #t]
                       [#%$suppress-primitive-inlining #f])
          (pretty-print (compile '(let () (import (chezscheme)) (+ 3 4 $eospam)))))))
    (if (eqv? (optimize-level) 3)
        "(#3%+ 7 $eospam)\n24\n"
        "(#2%+ 7 $eospam)\n24\n"))
  (equal?
    (with-output-to-string
      (lambda ()
        (parameterize ([expand/optimize-output (current-output-port)]
                       [enable-cp0 #t]
                       [#%$suppress-primitive-inlining #f])
          (pretty-print (interpret '(let () (import (chezscheme)) (+ 3 4 $eospam)))))))
    (if (eqv? (optimize-level) 3)
        "(#3%+ 7 $eospam)\n24\n"
        "(#2%+ 7 $eospam)\n24\n"))
  (begin
    (with-output-to-file "testfile.ss"
      (lambda ()
        (pretty-print '(eval-when (visit revisit) (define $eo-q (* 2 2))))
        (pretty-print '(define $eo-x 3))
        (pretty-print '(define-syntax $eo-a (identifier-syntax 5)))
        (pretty-print '(pretty-print (vector $eo-x $eo-q (+ $eo-a 1)))))
      'replace)
    #t)
  (begin
    (define $eo-sop
      (let ()
        (define syntax-record-writer
          (case-lambda
            [() (record-writer (record-rtd #'a))]
            [(x) (record-writer (record-rtd #'a) x)]))
        (open-input-string
          (with-output-to-string
            (lambda ()
              (parameterize ([expand/optimize-output (current-output-port)]
                             [print-gensym #t]
                             [optimize-level 2]
                             [compile-file-message #f]
                             [enable-cp0 #t]
                             [#%$suppress-primitive-inlining #f]
                             [syntax-record-writer (lambda (x p wr) (display "syntax-object" p))])
                (compile-file "testfile")))))))
    #t)
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (begin
         (set! $eo-q 4)
         (#3%$sc-put-cte
           'syntax-object
           '(global . ,gensym?)
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (revisit)
         (set! $eo-x 3))
       (eval-when (visit)
         (#3%$sc-put-cte
           'syntax-object
           '(global . ,gensym?)
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (visit)
         (#3%$sc-put-cte
           'syntax-object
           ,list?
           '*top*))))
  (equivalent-expansion?
    (read $eo-sop)
    `(begin
       (recompile-requirements () ())
       (eval-when (revisit)
         (#2%pretty-print (#2%vector $eo-x $eo-q 6)))))
  (begin (set! $eo-sop #f) #t)
)

(mat cp0-partial-folding
 ; check partial folding of +, fx+, fl+, and cfl+
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] 
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (+) (+ 3) (+ 3 4) (+ x) (+ x 0) (+ 0 x) (+ x 3)
           (+ x 3 4) (+ 3 x 4) (+ 3 x -3) (+ 3 x 4 y 5)
           (+ +nan.0 x 4 y 5))))
    '(#2%list 0 3 7 (#2%+ x) (#2%+ x) (#2%+ x) (#2%+ 3 x)
       (#2%+ 7 x) (#2%+ 7 x) (#2%+ x) (#2%+ 12 x y)
       (begin (#2%+ x y) +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (+) (+ 3) (+ 3 4) (+ x) (+ x 0) (+ 0 x) (+ x 3)
           (+ x 3 4) (+ 3 x 4) (+ 3 x -3) (+ 3 x 4 y 5)
           (+ +nan.0 x 4 y 5))))
    '(#3%list 0 3 7 x x x (#3%+ 3 x)
       (#3%+ 7 x) (#3%+ 7 x) x (#3%+ 12 x y)
       +nan.0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx+) (fx+ 3) (fx+ 3 4) (fx+ x) (fx+ x 0) (fx+ 0 x) (fx+ x 3)
           (fx+ x 3 4) (fx+ 3 x 4) (fx+ 3 x -3) (fx+ 3 x 4 y 5))))
    '(#2%list 0 3 7 (#2%fx+ x) (#2%fx+ x) (#2%fx+ x) (#2%fx+ 3 x)
       (#2%fx+ 7 x) (#2%fx+ 7 x) (#2%fx+ x) (#2%fx+ 12 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx+) (fx+ 3) (fx+ 3 4) (fx+ x) (fx+ x 0) (fx+ 0 x) (fx+ x 3)
           (fx+ x 3 4) (fx+ 3 x 4) (fx+ 3 x -3) (fx+ 3 x 4 y 5))))
    '(#3%list 0 3 7 x x x (#3%fx+ 3 x)
       (#3%fx+ 7 x) (#3%fx+ 7 x) x (#3%fx+ 12 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl+) (fl+ 3.0) (fl+ 3.0 4.0) (fl+ x) (fl+ x 0.0) (fl+ x -0.0) (fl+ 0.0 x) (fl+ -0.0 x) (fl+ x 3.0)
           (fl+ x 3.0 4.0) (fl+ 3.0 x 4.0) (fl+ 3.0 x -3.0) (fl+ (truncate -.5) x (/ -inf.0)) (fl+ 3.0 x 4.0 y 5.0)
           (fl+ 3.0 x +nan.0 y 5.0))))
    '(#2%list 0.0 3.0 7.0 (#2%fl+ x) (#2%fl+ 0.0 x) (#2%fl+ x) (#2%fl+ 0.0 x) (#2%fl+ x) (#2%fl+ 3.0 x)
       (#2%fl+ 7.0 x) (#2%fl+ 7.0 x) (#2%fl+ 0.0 x) (#2%fl+ x) (#2%fl+ 12.0 x y)
       (begin (#2%fl+ x y) +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl+) (fl+ 3.0) (fl+ 3.0 4.0) (fl+ x) (fl+ x 0.0) (fl+ x -0.0) (fl+ 0.0 x) (fl+ -0.0 x) (fl+ x 3.0)
           (fl+ x 3.0 4.0) (fl+ 3.0 x 4.0) (fl+ 3.0 x -3.0) (fl+ (truncate -.5) x (/ -inf.0)) (fl+ 3.0 x 4.0 y 5.0)
           (fl+ 3.0 x +nan.0 y 5.0))))
    '(#3%list 0.0 3.0 7.0 (#3%fl+ x) (#3%fl+ 0.0 x) (#3%fl+ x) (#3%fl+ 0.0 x) (#3%fl+ x) (#3%fl+ 3.0 x)
       (#3%fl+ 7.0 x) (#3%fl+ 7.0 x) (#3%fl+ 0.0 x) (#3%fl+ x) (#3%fl+ 12.0 x y)
       +nan.0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl+) (cfl+ 3.0) (cfl+ 3.0 4.0) (cfl+ x) (cfl+ x 0.0) (cfl+ x -0.0) (cfl+ 0.0 x) (cfl+ -0.0 x) (cfl+ x 3.0)
           (cfl+ x 3.0 4.0) (cfl+ 3.0 x 4.0) (cfl+ 3.0 x -3.0) (cfl+ (truncate -.5) x (/ -inf.0)) (cfl+ 3.0 x 4.0 y 5.0)
           (cfl+ 3.0 x +nan.0+nan.0i y 5.0))))
    '(#2%list 0.0 3.0 7.0 (#2%cfl+ x) (#2%cfl+ 0.0 x) (#2%cfl+ x) (#2%cfl+ 0.0 x) (#2%cfl+ x) (#2%cfl+ 3.0 x)
       (#2%cfl+ 7.0 x) (#2%cfl+ 7.0 x) (#2%cfl+ 0.0 x) (#2%cfl+ x) (#2%cfl+ 12.0 x y)
       (begin (#2%cfl+ x y) +nan.0+nan.0i)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl+) (cfl+ 3.0) (cfl+ 3.0 4.0) (cfl+ x) (cfl+ x 0.0) (cfl+ x -0.0) (cfl+ 0.0 x) (cfl+ -0.0 x) (cfl+ x 3.0)
           (cfl+ x 3.0 4.0) (cfl+ 3.0 x 4.0) (cfl+ 3.0 x -3.0) (cfl+ (truncate -.5) x (/ -inf.0)) (cfl+ 3.0 x 4.0 y 5.0)
           (cfl+ 3.0 x +nan.0+nan.0i y 5.0))))
    '(#3%list 0.0 3.0 7.0 x (#3%cfl+ 0.0 x) x (#3%cfl+ 0.0 x) x (#3%cfl+ 3.0 x)
       (#3%cfl+ 7.0 x) (#3%cfl+ 7.0 x) (#3%cfl+ 0.0 x) x (#3%cfl+ 12.0 x y)
       +nan.0+nan.0i))

 ; check partial folding of *, fx*, fl*, and cfl*
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (*) (* 3) (* 3 4) (* x) (* x 1) (* 1 x) (* x 3)
           (* x 3 4) (* 3 x 4) (* 3 x 1/3) (* 3 x 4 y 5)
           (* 3 x 0 y 5))))
    '(#2%list 1 3 12 (#2%* x) (#2%* x) (#2%* x) (#2%* 3 x)
       (#2%* 12 x) (#2%* 12 x) (#2%* x) (#2%* 60 x y)
       (begin (#2%* x y) 0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (*) (* 3) (* 3 4) (* x) (* x 1) (* 1 x) (* x 3)
           (* x 3 4) (* 3 x 4) (* 3 x 1/3) (* 3 x 4 y 5)
           (* 3 x 0 y 5))))
    '(#3%list 1 3 12 x x x (#3%* 3 x)
       (#3%* 12 x) (#3%* 12 x) x (#3%* 60 x y)
       0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx*) (fx* 3) (fx* 3 4) (fx* x) (fx* x 1) (fx* 1 x) (fx* x 3)
           (fx* x 3 4) (fx* 3 x 4) (fx* 1 x 1) (fx* 3 x 4 y 5)
           (fx* 3 x 0 y 5))))
    '(#2%list 1 3 12 (#2%fx* x) (#2%fx* x) (#2%fx* x) (#2%fx* 3 x)
       (#2%fx* 12 x) (#2%fx* 12 x) (#2%fx* x) (#2%fx* 60 x y)
       (begin (#2%fx* x y) 0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx*) (fx* 3) (fx* 3 4) (fx* x) (fx* x 1) (fx* 1 x) (fx* x 3)
           (fx* x 3 4) (fx* 3 x 4) (fx* 1 x 1) (fx* 3 x 4 y 5)
           (fx* 3 x 0 y 5))))
    '(#3%list 1 3 12 x x x (#3%fx* 3 x)
       (#3%fx* 12 x) (#3%fx* 12 x) x (#3%fx* 60 x y)
       0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl*) (fl* 3.0) (fl* 3.0 4.0) (fl* x) (fl* x 1.0) (fl* 1.0 x) (fl* x 3.0)
           (fl* x 3.0 4.0) (fl* 3.0 x 4.0) (fl* 3.0 x #i1/3) (fl* 3.0 x 4.0 y 5.0)
           (fl* 3.0 x 4.0 y +nan.0))))
    '(#2%list 1.0 3.0 12.0 (#2%fl* x) (#2%fl* x) (#2%fl* x) (#2%fl* 3.0 x)
       (#2%fl* 12.0 x) (#2%fl* 12.0 x) (#2%fl* x) (#2%fl* 60.0 x y)
       (begin (#2%fl* x y) +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl*) (fl* 3.0) (fl* 3.0 4.0) (fl* x) (fl* x 1.0) (fl* 1.0 x) (fl* x 3.0)
           (fl* x 3.0 4.0) (fl* 3.0 x 4.0) (fl* 3.0 x #i1/3) (fl* 3.0 x 4.0 y 5.0)
           (fl* 3.0 x 4.0 y +nan.0))))
    '(#3%list 1.0 3.0 12.0 (#3%fl* x) (#3%fl* x) (#3%fl* x) (#3%fl* 3.0 x)
       (#3%fl* 12.0 x) (#3%fl* 12.0 x) (#3%fl* x) (#3%fl* 60.0 x y)
       +nan.0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl*) (cfl* 3.0) (cfl* 3.0 4.0) (cfl* x) (cfl* x 1.0) (cfl* 1.0 x) (cfl* x 3.0)
           (cfl* x 3.0 4.0) (cfl* 3.0 x 4.0) (cfl* 3.0 x #i1/3) (cfl* 3.0 x 4.0 y 5.0)
           (cfl* 3.0 x 4.0 y +nan.0+nan.0i))))
    '(#2%list 1.0 3.0 12.0 (#2%cfl* x) (#2%cfl* x) (#2%cfl* x) (#2%cfl* 3.0 x)
       (#2%cfl* 12.0 x) (#2%cfl* 12.0 x) (#2%cfl* x) (#2%cfl* 60.0 x y)
       (begin (#2%cfl* x y) +nan.0+nan.0i)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl*) (cfl* 3.0) (cfl* 3.0 4.0) (cfl* x) (cfl* x 1.0) (cfl* 1.0 x) (cfl* x 3.0)
           (cfl* x 3.0 4.0) (cfl* 3.0 x 4.0) (cfl* 3.0 x #i1/3) (cfl* 3.0 x 4.0 y 5.0)
           (cfl* 3.0 x 4.0 y +nan.0+nan.0i))))
    '(#3%list 1.0 3.0 12.0 x x x (#3%cfl* 3.0 x)
       (#3%cfl* 12.0 x) (#3%cfl* 12.0 x) x (#3%cfl* 60.0 x y)
       +nan.0+nan.0i))

 ; check partial folding of -, fx-, fl-, and cfl-
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (- 3) (- 3 4) (- x) (- x 0) (- 0 x) (- x 3) (- x 3 4)
           (- 3 x 4) (- 3 x 3) (- x 3 -3) (- 4 x 3 -3) (- 3 x 4 y 5))))
    '(#2%list -3 -1 (#2%- x) (#2%- x 0) (#2%- x) (#2%- x 3) (#2%- x 3 4) (#2%- 3 x 4)
       (#2%- 3 x 3) (#2%- x 3 -3) (#2%- 4 x 3 -3) (#2%- 3 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (- 3) (- 3 4) (- x) (- x 0) (- 0 x) (- x 3) (- x 3 4)
           (- 3 x 4) (- 3 x 3) (- x 3 -3) (- 4 x 3 -3) (- 3 x 4 y 5))))
    '(#3%list -3 -1 (#3%- x) (#3%- x 0) (#3%- x) (#3%- x 3) (#3%- x 3 4) (#3%- 3 x 4)
       (#3%- 3 x 3) (#3%- x 3 -3) (#3%- 4 x 3 -3) (#3%- 3 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx- 3) (fx- 3 4) (fx- x) (fx- x 0) (fx- 0 x) (fx- x 3) (fx- x 3 4)
           (fx- 3 x 4) (fx- 3 x 3) (fx- x 3 -3) (fx- 4 x 3 -3) (fx- 3 x 4 y 5))))
    '(#2%list -3 -1 (#2%fx- x) (#2%fx- x 0) (#2%fx- x) (#2%fx- x 3) (#2%fx- x 3 4) (#2%fx- 3 x 4)
       (#2%fx- 3 x 3) (#2%fx- x 3 -3) (#2%fx- 4 x 3 -3) (#2%fx- 3 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx- 3) (fx- 3 4) (fx- x) (fx- x 0) (fx- 0 x) (fx- x 3) (fx- x 3 4)
           (fx- 3 x 4) (fx- 3 x 3) (fx- x 3 -3) (fx- 4 x 3 -3) (fx- 3 x 4 y 5))))
    '(#3%list -3 -1 (#3%fx- x) (#3%fx- x 0) (#3%fx- x) (#3%fx- x 3) (#3%fx- x 3 4) (#3%fx- 3 x 4)
       (#3%fx- 3 x 3) (#3%fx- x 3 -3) (#3%fx- 4 x 3 -3) (#3%fx- 3 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl- 3.0) (fl- 3.0 4.0) (fl- x) (fl- x 0.0) (fl- x -0.0) (fl- 0.0 x) (fl- -0.0 x) (fl- x 3.0) (fl- x 3.0 4.0)
           (fl- 3.0 x 4.0) (fl- 3.0 x 3.0) (fl- -0.0 x 0.0) (fl- x 3.0 -3.0) (fl- x 0.0 y) (fl- x -0.0 3.0) (fl- 4.0 x 3.0 -3.0)
           (fl- 3.0 x 4.0 y 5.0))))
    '(#2%list -3.0 -1.0 (#2%fl- x) (#2%fl- x 0.0) (#2%fl- x -0.0) (#2%fl- 0.0 x) (#2%fl- x) (#2%fl- x 3.0)
       (#2%fl- x 3.0 4.0) (#2%fl- 3.0 x 4.0) (#2%fl- 3.0 x 3.0) (#2%fl- -0.0 x 0.0) (#2%fl- x 3.0 -3.0)
       (#2%fl- x 0.0 y) (#2%fl- x -0.0 3.0) (#2%fl- 4.0 x 3.0 -3.0) (#2%fl- 3.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl- 3.0) (fl- 3.0 4.0) (fl- x) (fl- x 0.0) (fl- x -0.0) (fl- 0.0 x) (fl- -0.0 x) (fl- x 3.0) (fl- x 3.0 4.0)
           (fl- 3.0 x 4.0) (fl- 3.0 x 3.0) (fl- -0.0 x 0.0) (fl- x 3.0 -3.0) (fl- x 0.0 y) (fl- x -0.0 3.0) (fl- 4.0 x 3.0 -3.0)
           (fl- 3.0 x 4.0 y 5.0))))
    '(#3%list -3.0 -1.0 (#3%fl- x) (#3%fl- x 0.0) (#3%fl- x -0.0) (#3%fl- 0.0 x) (#3%fl- x) (#3%fl- x 3.0)
       (#3%fl- x 3.0 4.0) (#3%fl- 3.0 x 4.0) (#3%fl- 3.0 x 3.0) (#3%fl- -0.0 x 0.0) (#3%fl- x 3.0 -3.0)
       (#3%fl- x 0.0 y) (#3%fl- x -0.0 3.0) (#3%fl- 4.0 x 3.0 -3.0) (#3%fl- 3.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl- 3.0) (cfl- 3.0 4.0) (cfl- x) (cfl- x 0.0) (cfl- x -0.0) (cfl- 0.0 x) (cfl- -0.0 x) (cfl- x 3.0) (cfl- x 3.0 4.0)
           (cfl- 3.0 x 4.0) (cfl- 3.0 x 3.0) (cfl- -0.0 x 0.0) (cfl- x 3.0 -3.0) (cfl- x 0.0 y) (cfl- x -0.0 3.0) (cfl- 4.0 x 3.0 -3.0)
           (cfl- 3.0 x 4.0 y 5.0))))
    '(#2%list
       -3.0 -1.0 (#2%cfl- x) (#2%cfl- x 0.0) (#2%cfl- x -0.0) (#2%cfl- 0.0 x) (#2%cfl- x) (#2%cfl- x 3.0) (#2%cfl- x 3.0 4.0)
       (#2%cfl- 3.0 x 4.0) (#2%cfl- 3.0 x 3.0) (#2%cfl- -0.0 x 0.0) (#2%cfl- x 3.0 -3.0) (#2%cfl- x 0.0 y) (#2%cfl- x -0.0 3.0) (#2%cfl- 4.0 x 3.0 -3.0)
       (#2%cfl- 3.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl- 3.0) (cfl- 3.0 4.0) (cfl- x) (cfl- x 0.0) (cfl- x -0.0) (cfl- 0.0 x) (cfl- -0.0 x) (cfl- x 3.0) (cfl- x 3.0 4.0)
           (cfl- 3.0 x 4.0) (cfl- 3.0 x 3.0) (cfl- -0.0 x 0.0) (cfl- x 3.0 -3.0) (cfl- x 0.0 y) (cfl- x -0.0 3.0) (cfl- 4.0 x 3.0 -3.0)
           (cfl- 3.0 x 4.0 y 5.0))))
    '(#3%list
       -3.0 -1.0 (#3%cfl- x) (#3%cfl- x 0.0) (#3%cfl- x -0.0) (#3%cfl- 0.0 x) (#3%cfl- x) (#3%cfl- x 3.0) (#3%cfl- x 3.0 4.0)
       (#3%cfl- 3.0 x 4.0) (#3%cfl- 3.0 x 3.0) (#3%cfl- -0.0 x 0.0) (#3%cfl- x 3.0 -3.0) (#3%cfl- x 0.0 y) (#3%cfl- x -0.0 3.0) (#3%cfl- 4.0 x 3.0 -3.0)
       (#3%cfl- 3.0 x 4.0 y 5.0)))

 ; check partial folding of /, fx/, fl/, and cfl/
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (/ 3) (/ 9 4) (/ x) (/ x 1) (/ 1 x) (/ x 3) (/ x 3 4)
           (/ 9 x 4) (/ 3 x 3) (/ x 3 1/3) (/ 4 x 3 1/3) (/ 50 x 4 y 5))))
    '(#2%list
       1/3 9/4 (#2%/ x) (#2%/ x 1) (#2%/ x) (#2%/ x 3) (#2%/ x 3 4)
       (#2%/ 9 x 4) (#2%/ 3 x 3) (#2%/ x 3 1/3) (#2%/ 4 x 3 1/3) (#2%/ 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (/ 3) (/ 9 4) (/ x) (/ x 1) (/ 1 x) (/ x 3) (/ x 3 4)
           (/ 9 x 4) (/ 3 x 3) (/ x 3 1/3) (/ 4 x 3 1/3) (/ 50 x 4 y 5))))
    '(#3%list
       1/3 9/4 (#3%/ x) (#3%/ x 1) (#3%/ x) (#3%/ x 3) (#3%/ x 3 4)
       (#3%/ 9 x 4) (#3%/ 3 x 3) (#3%/ x 3 1/3) (#3%/ 4 x 3 1/3) (#3%/ 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx/ 3) (fx/ 9 4) (fx/ x) (fx/ x 1) (fx/ 1 x) (fx/ x 3) (fx/ x 3 4)
           (fx/ 9 x 4) (fx/ 1 x 1) (fx/ x 1 1) (fx/ 4 x 1 1) (fx/ 50 x 4 y 5))))
    '(#2%list
       0 2 (#2%fx/ x) (#2%fx/ x 1) (#2%fx/ x) (#2%fx/ x 3) (#2%fx/ x 3 4)
       (#2%fx/ 9 x 4) (#2%fx/ 1 x 1) (#2%fx/ x 1 1) (#2%fx/ 4 x 1 1) (#2%fx/ 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx/ 3) (fx/ 9 4) (fx/ x) (fx/ x 1) (fx/ 1 x) (fx/ x 3) (fx/ x 3 4)
           (fx/ 9 x 4) (fx/ 1 x 1) (fx/ x 1 1) (fx/ 4 x 1 1) (fx/ 50 x 4 y 5))))
    '(#3%list
       0 2 (#3%fx/ x) (#3%fx/ x 1) (#3%fx/ x) (#3%fx/ x 3) (#3%fx/ x 3 4)
       (#3%fx/ 9 x 4) (#3%fx/ 1 x 1) (#3%fx/ x 1 1) (#3%fx/ 4 x 1 1) (#3%fx/ 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fxquotient 3) (fxquotient 9 4) (fxquotient x) (fxquotient x 1) (fxquotient 1 x) (fxquotient x 3) (fxquotient x 3 4)
           (fxquotient 9 x 4) (fxquotient 1 x 1) (fxquotient x 1 1) (fxquotient 4 x 1 1) (fxquotient 50 x 4 y 5))))
    '(#2%list
       0 2 (#2%fxquotient x) (#2%fxquotient x 1) (#2%fxquotient x) (#2%fxquotient x 3) (#2%fxquotient x 3 4)
       (#2%fxquotient 9 x 4) (#2%fxquotient 1 x 1) (#2%fxquotient x 1 1) (#2%fxquotient 4 x 1 1) (#2%fxquotient 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fxquotient 3) (fxquotient 9 4) (fxquotient x) (fxquotient x 1) (fxquotient 1 x) (fxquotient x 3) (fxquotient x 3 4)
           (fxquotient 9 x 4) (fxquotient 1 x 1) (fxquotient x 1 1) (fxquotient 4 x 1 1) (fxquotient 50 x 4 y 5))))
    '(#3%list
       0 2 (#3%fxquotient x) (#3%fxquotient x 1) (#3%fxquotient x) (#3%fxquotient x 3) (#3%fxquotient x 3 4)
       (#3%fxquotient 9 x 4) (#3%fxquotient 1 x 1) (#3%fxquotient x 1 1) (#3%fxquotient 4 x 1 1) (#3%fxquotient 50 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl/ 2.0) (fl/ 9.0 4.0) (fl/ x) (fl/ x 1.0) (fl/ 1.0 x) (fl/ x 3.0) (fl/ x 3.0 4.0)
           (fl/ 9.0 x 4.0) (fl/ 3.0 x 3.0) (fl/ x 2.0 .5) (fl/ 4.0 x 2.0 .5)
           (fl/ 50.0 x 4.0 y 5.0))))
    '(#2%list
       .5 2.25 (#2%fl/ x) (#2%fl/ x 1.0) (#2%fl/ x) (#2%fl/ x 3.0) (#2%fl/ x 3.0 4.0)
       (#2%fl/ 9.0 x 4.0) (#2%fl/ 3.0 x 3.0) (#2%fl/ x 2.0 .5) (#2%fl/ 4.0 x 2.0 .5)
       (#2%fl/ 50.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl/ 2.0) (fl/ 9.0 4.0) (fl/ x) (fl/ x 1.0) (fl/ 1.0 x) (fl/ x 3.0) (fl/ x 3.0 4.0)
           (fl/ 9.0 x 4.0) (fl/ 3.0 x 3.0) (fl/ x 2.0 .5) (fl/ 4.0 x 2.0 .5)
           (fl/ 50.0 x 4.0 y 5.0))))
    '(#3%list
       .5 2.25 (#3%fl/ x) (#3%fl/ x 1.0) (#3%fl/ x) (#3%fl/ x 3.0) (#3%fl/ x 3.0 4.0)
       (#3%fl/ 9.0 x 4.0) (#3%fl/ 3.0 x 3.0) (#3%fl/ x 2.0 .5) (#3%fl/ 4.0 x 2.0 .5)
       (#3%fl/ 50.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl/ 2.0) (cfl/ 9.0 4.0) (cfl/ x) (cfl/ x 1.0) (cfl/ 1.0 x) (cfl/ x 3.0) (cfl/ x 3.0 4.0)
           (cfl/ 9.0 x 4.0) (cfl/ 3.0 x 3.0) (cfl/ x 2.0 .5) (cfl/ 4.0 x 2.0 .5)
           (cfl/ 50.0 x 4.0 y 5.0))))
    '(#2%list
       .5 2.25 (#2%cfl/ x) (#2%cfl/ x 1.0) (#2%cfl/ x) (#2%cfl/ x 3.0) (#2%cfl/ x 3.0 4.0)
       (#2%cfl/ 9.0 x 4.0) (#2%cfl/ 3.0 x 3.0) (#2%cfl/ x 2.0 .5) (#2%cfl/ 4.0 x 2.0 .5)
       (#2%cfl/ 50.0 x 4.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl/ 2.0) (cfl/ 9.0 4.0) (cfl/ x) (cfl/ x 1.0) (cfl/ 1.0 x) (cfl/ x 3.0) (cfl/ x 3.0 4.0)
           (cfl/ 9.0 x 4.0) (cfl/ 3.0 x 3.0) (cfl/ x 2.0 .5) (cfl/ 4.0 x 2.0 .5)
           (cfl/ 50.0 x 4.0 y 5.0))))
    '(#3%list
       .5 2.25 (#3%cfl/ x) (#3%cfl/ x 1.0) (#3%cfl/ x) (#3%cfl/ x 3.0) (#3%cfl/ x 3.0 4.0)
       (#3%cfl/ 9.0 x 4.0) (#3%cfl/ 3.0 x 3.0) (#3%cfl/ x 2.0 .5) (#3%cfl/ 4.0 x 2.0 .5)
       (#3%cfl/ 50.0 x 4.0 y 5.0)))

 ; check partial folding of #{2,3}%{fx,}log{and,or,xor}
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (logand)
           (logand -1) (logand 0) (logand 7)
           (logand 5 0) (logand 0 5) (logand 5 -1) (logand -1 x) (logand x 0) (logand 5 3) (logand 5 x) (logand x y)
           (logand 5 0 3) (logand 5 7 -1 6) (logand x -1 y) (logand 13 x 7 y) (logand 13 x 7 0 y) (logand 13 x 7 -1 y))))
    '(#2%list
       -1
       -1 0 7
       0 0 5 (#2%logand x) (begin (#2%logand x) 0) 1 (#2%logand 5 x) (#2%logand x y)
       0 4 (#2%logand x y) (#2%logand 5 x y) (begin (#2%logand x y) 0) (#2%logand 5 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (logand)
           (logand -1) (logand 0) (logand 7)
           (logand 5 0) (logand 0 5) (logand 5 -1) (logand -1 x) (logand x 0) (logand 5 3) (logand 5 x) (logand x y)
           (logand 5 0 3) (logand 5 7 -1 6) (logand x -1 y) (logand 13 x 7 y) (logand 13 x 7 0 y) (logand 13 x 7 -1 y))))
    '(#3%list
       -1
       -1 0 7
       0 0 5 x 0 1 (#3%logand 5 x) (#3%logand x y)
       0 4 (#3%logand x y) (#3%logand 5 x y) 0 (#3%logand 5 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fxlogand)
           (fxlogand -1) (fxlogand 0) (fxlogand 7)
           (fxlogand 5 0) (fxlogand 0 5) (fxlogand 5 -1) (fxlogand -1 x) (fxlogand x 0) (fxlogand 5 3) (fxlogand 5 x) (fxlogand x y)
           (fxlogand 5 0 3) (fxlogand 5 7 -1 6) (fxlogand x -1 y) (fxlogand 13 x 7 y) (fxlogand 13 x 7 0 y) (fxlogand 13 x 7 -1 y))))
    '(#2%list
       -1
       -1 0 7
       0 0 5 (#2%fxlogand x) (begin (#2%fxlogand x) 0) 1 (#2%fxlogand 5 x) (#2%fxlogand x y)
       0 4 (#2%fxlogand x y) (#2%fxlogand 5 x y) (begin (#2%fxlogand x y) 0) (#2%fxlogand 5 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fxlogand)
           (fxlogand -1) (fxlogand 0) (fxlogand 7)
           (fxlogand 5 0) (fxlogand 0 5) (fxlogand 5 -1) (fxlogand -1 x) (fxlogand x 0) (fxlogand 5 3) (fxlogand 5 x) (fxlogand x y)
           (fxlogand 5 0 3) (fxlogand 5 7 -1 6) (fxlogand x -1 y) (fxlogand 13 x 7 y) (fxlogand 13 x 7 0 y) (fxlogand 13 x 7 -1 y))))
    '(#3%list
       -1
       -1 0 7
       0 0 5 x 0 1 (#3%fxlogand 5 x) (#3%fxlogand x y)
       0 4 (#3%fxlogand x y) (#3%fxlogand 5 x y) 0 (#3%fxlogand 5 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fxlogor)
           (fxlogor -1) (fxlogor 0) (fxlogor 7)
           (fxlogor 5 0) (fxlogor 0 5) (fxlogor 5 -1) (fxlogor -1 x) (fxlogor x 0) (fxlogor 5 3) (fxlogor 5 x) (fxlogor x y)
           (fxlogor 5 0 3) (fxlogor 5 7 -1 6) (fxlogor x 0 y) (fxlogor 13 x 7 y) (fxlogor 13 x 7 -1 y) (fxlogor 13 x 7 0 y))))
    '(#2%list
       0
       -1 0 7
       5 5 -1 (begin (#2%fxlogor x) -1) (#2%fxlogor x) 7 (#2%fxlogor 5 x) (#2%fxlogor x y)
       7 -1 (#2%fxlogor x y) (#2%fxlogor 15 x y) (begin (#2%fxlogor x y) -1) (#2%fxlogor 15 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fxlogor)
           (fxlogor -1) (fxlogor 0) (fxlogor 7)
           (fxlogor 5 0) (fxlogor 0 5) (fxlogor 5 -1) (fxlogor -1 x) (fxlogor x 0) (fxlogor 5 3) (fxlogor 5 x) (fxlogor x y)
           (fxlogor 5 0 3) (fxlogor 5 7 -1 6) (fxlogor x 0 y) (fxlogor 13 x 7 y) (fxlogor 13 x 7 -1 y) (fxlogor 13 x 7 0 y))))
    '(#3%list
       0
       -1 0 7
       5 5 -1 -1 x 7 (#3%fxlogor 5 x) (#3%fxlogor x y)
       7 -1 (#3%fxlogor x y) (#3%fxlogor 15 x y) -1 (#3%fxlogor 15 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (logor)
           (logor -1) (logor 0) (logor 7)
           (logor 5 0) (logor 0 5) (logor 5 -1) (logor -1 x) (logor x 0) (logor 5 3) (logor 5 x) (logor x y)
           (logor 5 0 3) (logor 5 7 -1 6) (logor x 0 y) (logor 13 x 7 y) (logor 13 x 7 -1 y) (logor 13 x 7 0 y))))
    '(#2%list
       0
       -1 0 7
       5 5 -1 (begin (#2%logor x) -1) (#2%logor x) 7 (#2%logor 5 x) (#2%logor x y)
       7 -1 (#2%logor x y) (#2%logor 15 x y) (begin (#2%logor x y) -1) (#2%logor 15 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (logor)
           (logor -1) (logor 0) (logor 7)
           (logor 5 0) (logor 0 5) (logor 5 -1) (logor -1 x) (logor x 0) (logor 5 3) (logor 5 x) (logor x y)
           (logor 5 0 3) (logor 5 7 -1 6) (logor x 0 y) (logor 13 x 7 y) (logor 13 x 7 -1 y) (logor 13 x 7 0 y))))
    '(#3%list
       0
       -1 0 7
       5 5 -1 -1 x 7 (#3%logor 5 x) (#3%logor x y)
       7 -1 (#3%logor x y) (#3%logor 15 x y) -1 (#3%logor 15 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (logxor)
           (logxor -1) (logxor 0) (logxor 7)
           (logxor 5 0) (logxor 0 5) (logxor 5 -1) (logxor -1 x) (logxor x 0) (logxor 5 3) (logxor 5 x) (logxor x y)
           (logxor 5 0 3) (logxor 5 7 -1 6) (logxor x 0 y) (logxor 13 x 7 y) (logxor 13 x 7 -1 y) (logxor 13 x 7 0 y))))
    '(#2%list
       0
       -1 0 7
       5 5 -6 (#2%logxor -1 x) (#2%logxor x) 6 (#2%logxor 5 x) (#2%logxor x y)
       6 -5 (#2%logxor x y) (#2%logxor 10 x y) (#2%logxor -11 x y) (#2%logxor 10 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (logxor)
           (logxor -1) (logxor 0) (logxor 7)
           (logxor 5 0) (logxor 0 5) (logxor 5 -1) (logxor -1 x) (logxor x 0) (logxor 5 3) (logxor 5 x) (logxor x y)
           (logxor 5 0 3) (logxor 5 7 -1 6) (logxor x 0 y) (logxor 13 x 7 y) (logxor 13 x 7 -1 y) (logxor 13 x 7 0 y))))
    '(#3%list
       0
       -1 0 7
       5 5 -6 (#3%logxor -1 x) x 6 (#3%logxor 5 x) (#3%logxor x y)
       6 -5 (#3%logxor x y) (#3%logxor 10 x y) (#3%logxor -11 x y) (#3%logxor 10 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fxlogxor)
           (fxlogxor -1) (fxlogxor 0) (fxlogxor 7)
           (fxlogxor 5 0) (fxlogxor 0 5) (fxlogxor 5 -1) (fxlogxor -1 x) (fxlogxor x 0) (fxlogxor 5 3) (fxlogxor 5 x) (fxlogxor x y)
           (fxlogxor 5 0 3) (fxlogxor 5 7 -1 6) (fxlogxor x 0 y) (fxlogxor 13 x 7 y) (fxlogxor 13 x 7 -1 y) (fxlogxor 13 x 7 0 y))))
    '(#2%list
       0
       -1 0 7
       5 5 -6 (#2%fxlogxor -1 x) (#2%fxlogxor x) 6 (#2%fxlogxor 5 x) (#2%fxlogxor x y)
       6 -5 (#2%fxlogxor x y) (#2%fxlogxor 10 x y) (#2%fxlogxor -11 x y) (#2%fxlogxor 10 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fxlogxor)
           (fxlogxor -1) (fxlogxor 0) (fxlogxor 7)
           (fxlogxor 5 0) (fxlogxor 0 5) (fxlogxor 5 -1) (fxlogxor -1 x) (fxlogxor x 0) (fxlogxor 5 3) (fxlogxor 5 x) (fxlogxor x y)
           (fxlogxor 5 0 3) (fxlogxor 5 7 -1 6) (fxlogxor x 0 y) (fxlogxor 13 x 7 y) (fxlogxor 13 x 7 -1 y) (fxlogxor 13 x 7 0 y))))
    '(#3%list
       0
       -1 0 7
       5 5 -6 (#3%fxlogxor -1 x) x 6 (#3%fxlogxor 5 x) (#3%fxlogxor x y)
       6 -5 (#3%fxlogxor x y) (#3%fxlogxor 10 x y) (#3%fxlogxor -11 x y) (#3%fxlogxor 10 x y)))
)



(mat cp0-partial-folding-left-assoc
 ; check partial folding of +, fx+, fl+, and cfl+ when constraint to left-associative
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] 
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (+) (+ 3) (+ 3 4) (+ x) (+ x 0) (+ 0 x) (+ x 3)
           (+ x 3 4) (+ 3 x 4) (+ 3 x -3) (+ 3 x 4 y 5)
           (+ +nan.0 x 4 y 5))))
    '(#2%list 0 3 7 (#2%+ x) (#2%+ x 0) (#2%+ x) (#2%+ x 3)
       (#2%+ x 3 4) (#2%+ 3 x 4) (#2%+ 3 x -3) (#2%+ 3 x 4 y 5)
       (begin (#2%+ +nan.0 x 4 y 5) +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (+) (+ 3) (+ 3 4) (+ x) (+ x 0) (+ 0 x) (+ x 3)
           (+ x 3 4) (+ 3 x 4) (+ 3 x -3) (+ 3 x 4 y 5)
           (+ +nan.0 x 4 y 5))))
    '(#3%list 0 3 7 x (#3%+ x 0) x (#3%+ x 3)
       (#3%+ x 3 4) (#3%+ 3 x 4) (#3%+ 3 x -3) (#3%+ 3 x 4 y 5)
       +nan.0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx+) (fx+ 3) (fx+ 3 4) (fx+ x) (fx+ x 0) (fx+ 0 x) (fx+ x 3)
           (fx+ x 3 4) (fx+ 3 x 4) (fx+ 3 x -3) (fx+ 3 x 4 y 5))))
    '(#2%list 0 3 7 (#2%fx+ x) (#2%fx+ x 0) (#2%fx+ x) (#2%fx+ x 3)
       (#2%fx+ x 3 4) (#2%fx+ 3 x 4) (#2%fx+ 3 x -3) (#2%fx+ 3 x 4 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx+) (fx+ 3) (fx+ 3 4) (fx+ x) (fx+ x 0) (fx+ 0 x) (fx+ x 3)
           (fx+ x 3 4) (fx+ 3 x 4) (fx+ 3 x -3) (fx+ 3 x 4 y 5))))
    '(#3%list 0 3 7 x x x (#3%fx+ 3 x)
       (#3%fx+ 7 x) (#3%fx+ 7 x) x (#3%fx+ 12 x y)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl+) (fl+ 3.0) (fl+ 3.0 4.0) (fl+ x) (fl+ x 0.0) (fl+ x -0.0) (fl+ 0.0 x) (fl+ -0.0 x) (fl+ x 3.0)
           (fl+ x 3.0 4.0) (fl+ 3.0 x 4.0) (fl+ 3.0 x -3.0) (fl+ (truncate -.5) x (/ -inf.0)) (fl+ 3.0 x 4.0 y 5.0)
           (fl+ +nan.0 x 3.0 y 5.0) (fl+ 3.0 x +nan.0 y 5.0))))
    '(#2%list 0.0 3.0 7.0 (#2%fl+ x) (#2%fl+ x 0.0) (#2%fl+ x -0.0) (#2%fl+ 0.0 x) (#2%fl+ x) (#2%fl+ x 3.0)
       (#2%fl+ x 3.0 4.0) (#2%fl+ 3.0 x 4.0) (#2%fl+ 3.0 x -3.0) (#2%fl+ x -0.0) (#2%fl+ 3.0 x 4.0 y 5.0)
       (begin (#2%fl+ +nan.0 x 3.0 y 5.0) +nan.0) (#2%fl+ 3.0 x +nan.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl+) (fl+ 3.0) (fl+ 3.0 4.0) (fl+ x) (fl+ x 0.0) (fl+ x -0.0) (fl+ 0.0 x) (fl+ -0.0 x) (fl+ x 3.0)
           (fl+ x 3.0 4.0) (fl+ 3.0 x 4.0) (fl+ 3.0 x -3.0) (fl+ (truncate -.5) x (/ -inf.0)) (fl+ 3.0 x 4.0 y 5.0)
           (fl+ +nan.0 x 3.0 y 5.0) (fl+ 3.0 x +nan.0 y 5.0))))
    '(#3%list 0.0 3.0 7.0 (#3%fl+ x) (#3%fl+ x 0.0) (#3%fl+ x -0.0) (#3%fl+ 0.0 x) (#3%fl+ x) (#3%fl+ x 3.0)
       (#3%fl+ x 3.0 4.0) (#3%fl+ 3.0 x 4.0) (#3%fl+ 3.0 x -3.0) (#3%fl+ x -0.0) (#3%fl+ 3.0 x 4.0 y 5.0)
       +nan.0 (#3%fl+ 3.0 x +nan.0 y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl+) (cfl+ 3.0) (cfl+ 3.0 4.0) (cfl+ x) (cfl+ x 0.0) (cfl+ x -0.0) (cfl+ 0.0 x) (cfl+ -0.0 x) (cfl+ x 3.0)
           (cfl+ x 3.0 4.0) (cfl+ 3.0 x 4.0) (cfl+ 3.0 x -3.0) (cfl+ (truncate -.5) x (/ -inf.0)) (cfl+ 3.0 x 4.0 y 5.0)
           (cfl+ +nan.0+nan.0i x 3.0 y 5.0) (cfl+ 3.0 x +nan.0+nan.0i y 5.0))))
    '(#2%list 0.0 3.0 7.0 (#2%cfl+ x) (#2%cfl+ x 0.0) (#2%cfl+ x -0.0) (#2%cfl+ 0.0 x) (#2%cfl+ x) (#2%cfl+ x 3.0)
       (#2%cfl+ x 3.0 4.0) (#2%cfl+ 3.0 x 4.0) (#2%cfl+ 3.0 x -3.0) (#2%cfl+ x -0.0) (#2%cfl+ 3.0 x 4.0 y 5.0)
       (begin (#2%cfl+ +nan.0+nan.0i x 3.0 y 5.0) +nan.0+nan.0i) (#2%cfl+ 3.0 x +nan.0+nan.0i y 5.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl+) (cfl+ 3.0) (cfl+ 3.0 4.0) (cfl+ x) (cfl+ x 0.0) (cfl+ x -0.0) (cfl+ 0.0 x) (cfl+ -0.0 x) (cfl+ x 3.0)
           (cfl+ x 3.0 4.0) (cfl+ 3.0 x 4.0) (cfl+ 3.0 x -3.0) (cfl+ (truncate -.5) x (/ -inf.0)) (cfl+ 3.0 x 4.0 y 5.0)
           (cfl+ +nan.0+nan.0i x 3.0 y 5.0) (cfl+ 3.0 x +nan.0+nan.0i y 5.0))))
    '(#3%list 0.0 3.0 7.0 x (#3%cfl+ x 0.0) (#3%cfl+ x -0.0) (#3%cfl+ 0.0 x) x (#3%cfl+ x 3.0)
       (#3%cfl+ x 3.0 4.0) (#3%cfl+ 3.0 x 4.0) (#3%cfl+ 3.0 x -3.0) (#3%cfl+ x -0.0) (#3%cfl+ 3.0 x 4.0 y 5.0)
       +nan.0+nan.0i (#3%cfl+ 3.0 x +nan.0+nan.0i y 5.0)))

 ; check partial folding of *, fx*, fl*, and cfl*
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (*) (* 3) (* 3 4) (* x) (* x 1) (* 1 x) (* x 3)
           (* x 3 4) (* 3 x 4) (* 3 x 1/3) (* 3 x 4 y 5)
           (* 0 x 3 y 5) (* 3 x 0 y 5))))
    '(#2%list 1 3 12 (#2%* x) (#2%* x 1) (#2%* x) (#2%* x 3)
       (#2%* x 3 4) (#2%* 3 x 4) (#2%* 3 x 1/3) (#2%* 3 x 4 y 5)
       (begin (#2%* 0 x 3 y 5) 0) (#2%* 3 x 0 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (*) (* 3) (* 3 4) (* x) (* x 1) (* 1 x) (* x 3)
           (* x 3 4) (* 3 x 4) (* 3 x 1/3) (* 3 x 4 y 5)
           (* 0 x 3 y 5) (* 3 x 0 y 5))))
    '(#3%list 1 3 12 x (#3%* x 1) x (#3%* x 3)
       (#3%* x 3 4) (#3%* 3 x 4) (#3%* 3 x 1/3) (#3%* 3 x 4 y 5)
       0 (#3%* 3 x 0 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fx*) (fx* 3) (fx* 3 4) (fx* x) (fx* x 1) (fx* 1 x) (fx* x 3)
           (fx* x 3 4) (fx* 3 x 4) (fx* 1 x 1) (fx* 3 x 4 y 5)
           (fx* 0 x 3 y 5) (fx* 3 x 0 y 5))))
    '(#2%list 1 3 12 (#2%fx* x) (#2%fx* x 1) (#2%fx* x) (#2%fx* x 3)
       (#2%fx* x 3 4) (#2%fx* 3 x 4) (#2%fx* x 1) (#2%fx* 3 x 4 y 5)
       (begin (#2%fx* 0 x 3 y 5) 0) (#2%fx* 3 x 0 y 5)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fx*) (fx* 3) (fx* 3 4) (fx* x) (fx* x 1) (fx* 1 x) (fx* x 3)
           (fx* x 3 4) (fx* 3 x 4) (fx* 1 x 1) (fx* 3 x 4 y 5)
           (fx* 3 x 0 y 5))))
    '(#3%list 1 3 12 x x x (#3%fx* 3 x)
       (#3%fx* 12 x) (#3%fx* 12 x) x (#3%fx* 60 x y)
       0))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (fl*) (fl* 3.0) (fl* 3.0 4.0) (fl* x) (fl* x 1.0) (fl* 1.0 x) (fl* x 3.0)
           (fl* x 3.0 4.0) (fl* 3.0 x 4.0) (fl* 3.0 x #i1/3) (fl* 3.0 x 4.0 y 5.0)
           (fl* +nan.0 x 3.0 y 4.0) (fl* 3.0 x 4.0 y +nan.0))))
    '(#2%list 1.0 3.0 12.0 (#2%fl* x) (#2%fl* x 1.0) (#2%fl* x) (#2%fl* x 3.0)
       (#2%fl* x 3.0 4.0) (#2%fl* 3.0 x 4.0) (#2%fl* 3.0 x #i1/3) (#2%fl* 3.0 x 4.0 y 5.0)
       (begin (#2%fl* +nan.0 x 3.0 y 4.0) +nan.0) (#2%fl* +3.0 x 4.0 y +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (fl*) (fl* 3.0) (fl* 3.0 4.0) (fl* x) (fl* x 1.0) (fl* 1.0 x) (fl* x 3.0)
           (fl* x 3.0 4.0) (fl* 3.0 x 4.0) (fl* 3.0 x #i1/3) (fl* 3.0 x 4.0 y 5.0)
           (fl* +nan.0 x 3.0 y 4.0) (fl* 3.0 x 4.0 y +nan.0))))
    '(#3%list 1.0 3.0 12.0 (#3%fl* x) (#3%fl* x 1.0) (#3%fl* x) (#3%fl* x 3.0)
       (#3%fl* x 3.0 4.0) (#3%fl* 3.0 x 4.0) (#3%fl* 3.0 x #i1/3) (#3%fl* 3.0 x 4.0 y 5.0)
       +nan.0 (#3%fl* +3.0 x 4.0 y +nan.0)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 2])
      (expand/optimize
        '(list
           (cfl*) (cfl* 3.0) (cfl* 3.0 4.0) (cfl* x) (cfl* x 1.0) (cfl* 1.0 x) (cfl* x 3.0)
           (cfl* x 3.0 4.0) (cfl* 3.0 x 4.0) (cfl* 3.0 x #i1/3) (cfl* 3.0 x 4.0 y 5.0)
           (cfl* +nan.0+nan.0i x 3.0 y 4.0) (cfl* 3.0 x 4.0 y +nan.0+nan.0i))))
    '(#2%list 1.0 3.0 12.0 (#2%cfl* x) (#2%cfl* x 1.0) (#2%cfl* x) (#2%cfl* x 3.0)
       (#2%cfl* x 3.0 4.0) (#2%cfl* 3.0 x 4.0) (#2%cfl* 3.0 x #i1/3) (#2%cfl* 3.0 x 4.0 y 5.0)
       (begin (#2%cfl* +nan.0+nan.0i x 3.0 y 4.0) +nan.0+nan.0i) (#2%cfl* 3.0 x 4.0 y +nan.0+nan.0i)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f]
                   [run-cp0 (lambda (cp0 x) (cp0 x))]
                   [enable-arithmetic-left-associative #t]
                   [optimize-level 3])
      (expand/optimize
        '(list
           (cfl*) (cfl* 3.0) (cfl* 3.0 4.0) (cfl* x) (cfl* x 1.0) (cfl* 1.0 x) (cfl* x 3.0)
           (cfl* x 3.0 4.0) (cfl* 3.0 x 4.0) (cfl* 3.0 x #i1/3) (cfl* 3.0 x 4.0 y 5.0)
           (cfl* +nan.0+nan.0i x 3.0 y 4.0) (cfl* 3.0 x 4.0 y +nan.0+nan.0i))))
    '(#3%list 1.0 3.0 12.0 x (#3%cfl* x 1.0) x (#3%cfl* x 3.0)
       (#3%cfl* x 3.0 4.0) (#3%cfl* 3.0 x 4.0) (#3%cfl* 3.0 x #i1/3) (#3%cfl* 3.0 x 4.0 y 5.0)
       +nan.0+nan.0i (#3%cfl* 3.0 x 4.0 y +nan.0+nan.0i)))
  )

(mat cp0-apply
  (begin
    (define $permutations
      (rec permutations
        (lambda (x*)
          (if (null? x*)
              '()
              (if (null? (cdr x*))
                  (list x*)
                  (let f ([x* x*] [rx* '()])
                    (if (null? x*)
                        '()
                        (append
                          (map (lambda (ls) (cons (car x*) ls)) (permutations (append (cdr x*) rx*)))
                          (f (cdr x*) (cons (car x*) rx*))))))))))
    #t)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply (lambda () 7) '())))
    '7)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%+ x y z)) '(3 4 5))))
    '12)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%+ x y z)) (#%list 3 4 5))))
    '12)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply
           (lambda (x y z) (#%+ (begin (#%write 'a) x) y z))
           (#%list e1 e2 e3))))
    (if (= (optimize-level) 3)
        '(let ([x e1] [y e2] [z e3])
           (#3%+ (begin (#3%write 'a) x) y z))
        '(let ([x e1] [y e2] [z e3])
           (#2%+ (begin (#2%write 'a) x) y z))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%+ '(1 2 3 4))))
    '10)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%+ (#%list 1 2 3 4))))
    '10)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(lambda (x) (#%apply #%+ (#%list 1 2 x 4)))))
    (if (= (optimize-level) 3)
        '(lambda (x) (#3%+ 7 x))
        '(lambda (x) (#2%+ 7 x))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%+ x y z)) (#%list e1 e2 e3))))
    (if (= (optimize-level) 3)
        '(#3%+ e1 e2 e3)
        '(#2%+ e1 e2 e3)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply #%+ (#%list 1 (begin (#%write 'a) 2) 3))))
    (if (= (optimize-level) 3)
        '(begin (#3%write 'a) 6)
        '(begin (#2%write 'a) 6)))
  (let ([expr (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
                (expand/optimize
                  '(#%apply (begin (#%write 'a) #%+)
                     (begin (#%write 'b) 4)
                     (begin
                       (#%write 'c)
                       (#%list
                         1
                         (begin (#%write 'd) 2)
                         (begin (#%write 'e) 3))))))])
    (ormap
      (lambda (groups) (equivalent-expansion? expr `(begin ,@(apply append groups) 10)))
      ($permutations
        (if (= (optimize-level) 3)
            '(((#3%write 'a)) ((#3%write 'b)) ((#3%write 'c) (#3%write 'e) (#3%write 'd)))
            '(((#2%write 'a)) ((#2%write 'b)) ((#2%write 'c) (#2%write 'e) (#2%write 'd)))))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%vector x y)) (#%list e1 2 e3))))
    (if (= (optimize-level) 3)
        '(#3%vector e1 2)
        '(begin e3 (#2%vector e1 2))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(lambda (x) (#%apply x '(1 2 3)))))
    '(lambda (x) (x 1 2 3)))
  (let ([q (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
             (expand/optimize '(#%apply e0 (#%list e1 e2 e3))))])
    (or (equivalent-expansion?  q '(let ([t1 e1] [t2 e2] [t3 e3]) (e0 t1 t2 t3)))
        (equivalent-expansion?  q '(let ([t0 e0]) (t0 e1 e2 e3)))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply
           (case-lambda [(x y) x] [(a b c d e) c])
           (#%list 1 2 3 4 5))))
    '3)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (case-lambda [(x y) x] [r r]) (#%list 1 2 3 4 5))))
    '(#3%list 1 2 3 4 5))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (case-lambda [(x y) x] [r r]) (#%list 1 2 q 4 5))))
    '(#3%list 1 2 q 4 5))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%apply #%+ (#%list 1 2 3 (#%list 4 5)))))
    15)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%apply #%apply #%apply #%apply #%+ (#%list 1 2 3 (#%list 4 5 (#%list 6 7 (#%list* 8 9 (#%list (#%list 10)))))))))
    55)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%apply #%apply #%apply #%+ (#%cons 1 (#%list 2 3 (#%cons* 4 (#%list 5 (#%cons 6 (#%list* 7 (#%list 8 (#%cons 9 '(10))))))))))))
    55)
  (begin
    (define $check-writes
      (lambda (eepat x)
        (define ordered?
          (lambda (ls)
            (define same-prefix?
              (lambda (ls1 ls2)
                (or (null? ls2)
                    (and (eqv? (car ls1) (car ls2))
                         (same-prefix? (cdr ls1) (cdr ls2))))))
            (null?
              (let f ([ls ls] [q '()] [qlen 0])
                (if (null? ls)
                    '()
                    (let ([x (car ls)])
                      (let ([xlen (length x)])
                        (cond
                          [(fx= xlen qlen) (f (cdr ls) x xlen)]
                          [(fx< xlen qlen) ls]
                          [else (and (fx= xlen (fx+ qlen 1))
                                     (same-prefix? x q)
                                     (let ([ls (f (cdr ls) x xlen)])
                                       (and ls (f ls q qlen))))]))))))))
        (syntax-case x (begin $primitive quote)
          [(begin
             (($primitive level write) (quote (d ...)))
             ...
             ans)
           (begin
             (unless (equivalent-expansion? #'ans eepat) (errorf #f "~s is not equivalent to ~s" #'ans eepat))
             (unless (ordered? #'((d ...) ...)) (errorf #f "writes are out-of-order in ~s" x))
             #t)]
          [_ (errorf #f "unexpected output pattern for ~s" x)])))
    #t)
  ($check-writes 55
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '(let ()
                         (import (chezscheme))
                         (let ([list (begin (write '()) list)] [list* (if #t list* list)])
                           (write '(1))
                           ((begin (write '(1 1)) apply)
                            (begin (write '(1 2)) apply)
                            (begin (write '(1 3)) apply)
                            (let ([waste (write '(1 4))]) apply)
                            (begin (write '(1 5)) apply)
                            (begin (write '(1 6)) +)
                            (begin (write '(1 7))
                              ((begin (write '(1 7 1)) list)
                               (begin (write '(1 7 2)) 1)
                               (begin (write '(1 7 3)) 2)
                               (begin (write '(1 7 4)) 3)
                               (begin (write '(1 7 5))
                                 ((begin (write '(1 7 5 1)) list)
                                  (begin (write '(1 7 5 2)) 4)
                                  (begin (write '(1 7 5 3)) 5)
                                  (begin (write '(1 7 5 4))
                                    ((begin (write '(1 7 5 4 1)) list)
                                     (begin (write '(1 7 5 4 2)) 6)
                                     (begin (write '(1 7 5 4 3)) 7)
                                     (begin (write '(1 7 5 4 4))
                                       ((begin (write '(1 7 5 4 4 1)) list*)
                                        (begin (write '(1 7 5 4 4 2)) 8)
                                        (begin (write '(1 7 5 4 4 3)) 9)
                                        (begin (write '(1 7 5 4 4 4))
                                          ((begin (write '(1 7 5 4 4 1)) list)
                                           (begin (write '(1 7 5 4 4 2))
                                             ((begin (write '(1 7 5 4 4 2 1)) list)
                                              (begin (write '(1 7 5 4 4 2 2)) 10)))))))))))))))))))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 (cp0 (cp0 x))))])
      (expand/optimize '(#%apply #%apply #%+ (#%list 1 2 3 (#%list 4 5)))))
    '15)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply (lambda () 7) (#%list* '()))))
    '7)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%+ x y z)) (#%list* 3 4 '(5)))))
    '12)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply #%+ (#%list* e '(2 3)))))
    (if (= (optimize-level) 3)
        '(#3%+ 5 e)
        '(#2%+ 5 e)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply
           (lambda (x y z) (#%+ (begin (#%write 'a) x) y z))
           (#%list* e1 e2 e3 '()))))
    (if (= (optimize-level) 3)
        '(let ([x e1] [y e2] [z e3])
           (#3%+ (begin (#3%write 'a) x) y z))
        '(let ([x e1] [y e2] [z e3])
           (#2%+ (begin (#2%write 'a) x) y z))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%+ x y z)) (#%list* e1 e2 e3 '()))))
    (if (= (optimize-level) 3)
        '(#3%+ e1 e2 e3)
        '(#2%+ e1 e2 e3)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply #%+ (#%list* 1 (begin (#%write 'a) 2) '(3)))))
    (if (= (optimize-level) 3)
        '(begin (#3%write 'a) 6)
        '(begin (#2%write 'a) 6)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize
        '(#%apply (lambda (x y z) (#%vector x y)) (#%list* e1 2 e3 '()))))
    (if (= (optimize-level) 3)
        '(#3%vector e1 2)
        '(begin e3 (#2%vector e1 2))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(#%apply (lambda (x y z) (#%vector x y z)) (#%list* 1 '(2 3)))))
    (if (= (optimize-level) 3)
        '(#3%vector 1 2 3)
        '(#2%vector 1 2 3)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(lambda (r) (#%apply (lambda (x y z) (#%vector x y z)) (#%list* 1 r)))))
    (if (= (optimize-level) 3)
        '(lambda (r) (let ([y (#3%car r)]) (#3%vector 1 y (#3%car (#3%cdr r)))))
        '(lambda (r) (#2%apply (lambda (x y z) (#2%vector x y z)) 1 r))))
  (let ([expr (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
                (expand/optimize
                  '(#%apply (begin (#%write 'a) #%+)
                     (begin (#%write 'b) 4)
                     (begin
                       (#%write 'c)
                       (#%list*
                         1
                         (begin (#%write 'd) 2)
                         (begin (#%write 'e) '(3)))))))])
    (ormap
      (lambda (groups) (equivalent-expansion? expr `(begin ,@(apply append groups) 10)))
      ($permutations
        (if (= (optimize-level) 3)
            '(((#3%write 'a)) ((#3%write 'b)) ((#3%write 'c) (#3%write 'd) (#3%write 'e)))
            '(((#2%write 'a)) ((#2%write 'b)) ((#2%write 'c) (#2%write 'd) (#2%write 'e)))))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(let ([x (cons 0 (list))]) (#%apply #%zero? x))))
    #t)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      ;; don't fold primitive in value context with bad apply convention
      (expand/optimize '(#%apply #%zero? 0)))
    (if (= (optimize-level) 3)
        '(#3%apply #3%zero? 0)
        '(#2%apply #2%zero? 0)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      ;; don't fold primitive in test context with bad apply convention
      (expand/optimize '(if (#%apply #%pair? 1 2 3) 4 5)))
    (if (= (optimize-level) 3)
        '(if (#3%apply #3%pair? 1 2 3) 4 5)
        '(if (#2%apply #2%pair? 1 2 3) 4 5)))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      ;; don't fold primitive in effect context with bad apply convention
      (expand/optimize '(begin (#%apply #%box? 'step) 3)))
    (if (= (optimize-level) 3)
        '(begin (#3%apply #3%box? 'step) 3)
        '(begin (#2%apply #2%box? 'step) 3)))
 )

(mat cp0-car/cdr
  (begin
    (define (expansion-matches? src expect)
      ;; Check that expansion matches or doesn't match under various conditions.
      ;; Expansion should not match in safe mode for expression involving the names
      ;; `$xxx`, `$yyy`, and `$zzz`, but it should match when those are wrapped with
      ;; `add1` (which makes the expression known-single-valued).
      ;; The names `$nontail-xxx`, `$nontail-yyy`, and `$nontail-zzz` must similarly
      ;; be wrapped to match in either safe or unsafe mode, since unsafe mode is obliged
      ;; to preserve non-tailness.
      ;; Other names, including `$xxx-ok`, can match without wrapping.
      (define (contains-id? id l)
        (or (eq? id l)
            (and (pair? l) (or (contains-id? id (car l)) (contains-id? id (cdr l))))))
      (define (primitive->level l)
        (cond
         [(pair? l)
          (if (and (eq? (car l) '$primitive)
                   (null? (cddr l)))
              (cons* (car l) (if (= (optimize-level) 3) 3 2) (cdr l))
              (cons (primitive->level (car l)) (primitive->level (cdr l))))]
         [else l]))
      (define (add-add1s l around-ids)
        (cond
         [(pair? l)
          (if (memq (car l) around-ids)
              `(#%add1 ,l)
              (cons (add-add1s (car l) around-ids) (add-add1s (cdr l) around-ids)))]
         [else l]))      
      (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
        (let* ([nontail-ids '($nontail-xxx $nontail-yyy $nontail-zzz)]
               [non-nontail-ids '($xxx $yyy $zzz)]
               [all-ids (if (= (optimize-level) 3)
                            nontail-ids
                            (append non-nontail-ids nontail-ids))])
          (and (if (andmap (lambda (id) (not (contains-id? id src))) all-ids)
                   (equivalent-expansion? (expand/optimize src)
                                          (primitive->level expect))
                   (not (equivalent-expansion? (expand/optimize src)
                                               (primitive->level expect))))
               (equivalent-expansion? (expand/optimize (add-add1s src all-ids))
                                      (primitive->level (add-add1s expect all-ids)))
               ;; Try subsets:
               (andmap (lambda (ids)
                         (if (ormap (lambda (id) (and (not (member id ids)) (contains-id? id src))) all-ids)
                             (not (equivalent-expansion? (expand/optimize (add-add1s src ids))
                                                         (primitive->level (add-add1s expect ids))))
                             (equivalent-expansion? (expand/optimize (add-add1s src ids))
                                                    (primitive->level (add-add1s expect ids)))))
                       (let loop ([ids all-ids])
                         (if (null? ids)
                             '()
                             (let ([subs (loop (cdr ids))])
                               (append (list (list (car ids)))
                                       subs
                                       (map (lambda (sub) (cons (car ids) sub)) subs))))))))))
    #t)
  (expansion-matches?
    '(begin (#%write 'a)
           ((begin (#%write 'b) #%car)
            (begin (#%write 'c)
              ((begin (#%write 'd) #%cons)
               (begin (#%write 'e) ($nontail-xxx))
               (begin (#%write 'f) ($yyy))))))
    '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'f) ($yyy) (#%write 'e) ($nontail-xxx)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%car)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons)
                    (begin (#%write 'e) ($nontail-xxx))
                    (begin (#%write 'f) ($yyy))))))
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'f) ($yyy) (#%write 'e) ($nontail-xxx)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%car)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list)
                    (begin (#%write 'e) ($nontail-xxx))
                    (begin (#%write 'f) ($yyy))
                    (begin (#%write 'g) ($zzz))))))
    ; other possibilities exist but are too many to list and too difficult to construct with $permutations.
    ; if you see a problem, convert to use $check-writes (defined above)
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'f) ($yyy) (#%write 'g) ($zzz) (#%write 'e) ($nontail-xxx)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%car)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list*)
                    (begin (#%write 'e) ($nontail-xxx))
                    (begin (#%write 'f) ($yyy))
                    (begin (#%write 'g) ($zzz))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'f) ($yyy) (#%write 'g) ($zzz) (#%write 'e) ($nontail-xxx)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%car)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons*)
                    (begin (#%write 'e) ($nontail-xxx))
                    (begin (#%write 'f) ($yyy))
                    (begin (#%write 'g) ($zzz))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'f) ($yyy) (#%write 'g) ($zzz) (#%write 'e) ($nontail-xxx)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($nontail-yyy))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($yyy-ok))
                    (begin (#%write 'g) ($zzz-ok))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%list (begin (#%write 'f) ($yyy-ok)) (begin (#%write 'g) ($zzz-ok)))))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list*)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($yyy-ok))
                    (begin (#%write 'g) ($zzz-ok))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%list* (begin (#%write 'f) ($yyy-ok)) (begin (#%write 'g) ($zzz-ok)))))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons*)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($yyy-ok))
                    (begin (#%write 'g) ($zzz-ok))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%cons* (begin (#%write 'f) ($yyy-ok)) (begin (#%write 'g) ($zzz-ok)))))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list*)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($nontail-yyy))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons*)
                    (begin (#%write 'e) ($xxx))
                    (begin (#%write 'f) ($nontail-yyy))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%list*)
                    (begin (#%write 'e) ($xxx-ok))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%cdr (begin (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok)))))
  (expansion-matches?
   '(begin (#%write 'a)
           ((begin (#%write 'b) #%cdr)
            (begin (#%write 'c)
                   ((begin (#%write 'd) #%cons*)
                    (begin (#%write 'e) ($xxx-ok))))))
    ; other possibilities exist...
   '(begin (#%write 'a) (#%write 'b) (#%cdr (begin (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok)))))
  (expansion-matches?
   '(cdr (let ([x (#%write 1)])
           (cons x (#%write 2))))
   '(begin (#%write 1) (#%write 2)))
  )

(mat cp0-seq-ref
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(vector-ref (vector 1 2 3) 1)))
    2)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(list-ref (list 1 2 3) 1)))
    2)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(list-ref (list* 1 2 3) 1)))
    2)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(list-ref (cons* 1 2 3) 1)))
    2)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(fxvector-ref (fxvector 1 2 3) 1)))
    2)
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level (max (optimize-level) 2)])
      (expand/optimize
        '(string-ref (string #\1 #\2 #\3) 1)))
    #\2)
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) vector-ref)
            (begin (write 'c)
              ((begin (write 'd) vector)
               (begin (write 'e) ($xxx))
               (begin (write 'f) ($nontail-yyy))
               (begin (write 'g) ($zzz))))
            (begin (write 'h) 1)))
    ; other possibilities exist ...
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'g) ($zzz) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) vector-ref)
            (begin (write 'c)
              ((begin (write 'd) vector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 3)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%vector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%vector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 3))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) list-ref)
            (begin (write 'c)
              ((begin (write 'd) list)
               (begin (write 'e) ($xxx))
               (begin (write 'f) ($nontail-yyy))
               (begin (write 'g) ($zzz))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'g) ($zzz) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) list-ref)
            (begin (write 'c)
              ((begin (write 'd) list*)
               (begin (write 'e) ($xxx))
               (begin (write 'f) ($nontail-yyy))
               (begin (write 'g) ($zzz))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'g) ($zzz) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) list-ref)
            (begin (write 'c)
              ((begin (write 'd) cons*)
               (begin (write 'e) ($xxx))
               (begin (write 'f) ($nontail-yyy))
               (begin (write 'g) ($zzz))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx) (#%write 'g) ($zzz) (#%write 'f) ($nontail-yyy)))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) list-ref)
            (begin (write 'c)
              ((begin (write 'd) cons*)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 2)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%list-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%cons*
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 2))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) string-ref)
            (begin (write 'c)
              ((begin (write 'd) string)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) #\y)
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) #\y)
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%string-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%string
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) #\y)
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1)))))
  (parameterize ([enable-type-recovery #f])
   (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) string-ref)
            (begin (write 'c)
              ((begin (write 'd) string)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) 'oops)
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) 'oops)
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%string-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%string
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) 'oops)
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1))))))
  (expansion-matches?
        `(begin (write 'a)
           ((begin (write 'b) string-ref)
            (begin (write 'c)
              ((begin (write 'd) string)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) (,(if (= (optimize-level) 3) '$nontail-yyy '$yyy-ok)))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) ($nontail-yyy))
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%string-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%string
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1)))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) string-ref)
            (begin (write 'c)
              ((begin (write 'd) #2%string)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%string-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#2%string
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) string-ref)
            (begin (write 'c)
              ((begin (write 'd) string)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 3)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%string-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%string
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 3))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) fxvector-ref)
            (begin (write 'c)
              ((begin (write 'd) fxvector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) 121)
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) 121)
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%fxvector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%fxvector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) 121)
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1)))))
  (parameterize ([enable-type-recovery #f])
   (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) fxvector-ref)
            (begin (write 'c)
              ((begin (write 'd) fxvector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) 'oops)
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) 'oops)
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%fxvector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%fxvector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) 'oops)
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1))))))
  (expansion-matches?
        `(begin (write 'a)
           ((begin (write 'b) fxvector-ref)
            (begin (write 'c)
              ((begin (write 'd) fxvector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) (,(if (= (optimize-level) 3) '$nontail-yyy '$yyy-ok)))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
    (if (= (optimize-level) 3)
        '(begin (#%write 'a) (#%write 'b) (#%write 'h) (#%write 'c) (#%write 'd) (#%write 'e) ($xxx-ok) (#%write 'g) ($zzz-ok) (#%write 'f) ($nontail-yyy))
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%fxvector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%fxvector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1)))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) fxvector-ref)
            (begin (write 'c)
              ((begin (write 'd) #2%fxvector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 1)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%fxvector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#2%fxvector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 1))))
  (expansion-matches?
        '(begin (write 'a)
           ((begin (write 'b) fxvector-ref)
            (begin (write 'c)
              ((begin (write 'd) fxvector)
               (begin (write 'e) ($xxx-ok))
               (begin (write 'f) ($yyy-ok))
               (begin (write 'g) ($zzz-ok))))
            (begin (write 'h) 3)))
    ; other possibilities exist...
        '(begin
           (#%write 'a)
           (#%write 'b)
           (#%fxvector-ref
             (begin
               (#%write 'c)
               (#%write 'd)
               (#%fxvector
                 (begin (#%write 'e) ($xxx-ok))
                 (begin (#%write 'f) ($yyy-ok))
                 (begin (#%write 'g) ($zzz-ok))))
             (begin (#%write 'h) 3))))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2])
      (expand/optimize
        '(immutable-vector 1 2 3)))
    ''#(1 2 3))
  (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [optimize-level 2])
      (expand/optimize
        '(lambda (x)
           (let ([v (begin (write 'a) (immutable-vector x 2 3))])
             (list
               (begin (write 'b) (vector-ref v 0))
               (begin (write 'c) (vector-ref v 1))
               (begin (write 'd) (vector-ref v 2)))))))
    '(lambda (x)
       (#2%write 'a)
       (#2%list
         (begin (#2%write 'b) x)
         (begin (#2%write 'c) 2)
         (begin (#2%write 'd) 3))))
  ((lambda (x) (and (member x '("abc" "cab")) #t))
   (with-output-to-string
     (lambda ()
       (vector-ref (begin (write 'a) (immutable-vector (begin (write 'b) 123)))
         (begin (write 'c) 0)))))
 )

(mat let-pushing
  ; make sure letify doesn't drop the let binding for x into the call to cons which would
  ; cause the allocation of z's location not to be in the continuation of the rhs of x.
  (equal?
    (let ([ls '()])
      (let ([th.k (let ([x (call/cc (lambda (k) k))] [z 0])
                    (cons (lambda () (set! z (+ z 1)) z) x))])
        (and (set! ls (cons ((car th.k)) ls))
             (set! ls (cons ((car th.k)) ls))
             ((cdr th.k) (lambda (x) (set! ls (cons 17 ls))))))
      ls)
    '(17 2 1 2 1))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(lambda (x) (letrec ([y (if (pair? x) (#3%car x) x)]) 4))))
    '(lambda (x) 4))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(let ([x e]) (list (list x)))))
    '(#2%list (#2%list e)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(let ([x (lambda (x) x)]) (list (list x) (list 3)))))
    '(#2%list (#2%list (lambda (x) x)) (#2%list 3)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(lambda (y) (let ([x (+ y y)] [z #f]) (list (lambda () (set! z 15) z) x)))))
    '(lambda (y) (let ([x (#2%+ y y)] [z #f]) (#2%list (lambda () (set! z 15) z) x))))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 3])
      (expand/optimize
        '(lambda (y) (let ([x (+ y y)] [z #f]) (list (lambda () (set! z 15) z) x)))))
    ; doesn't push (+ y y) because it's not pure and one of the vars (z) is assigned
    '(lambda (y) (let ([x (#3%+ y y)] [z #f]) (#3%list (lambda () (set! z 15) z) x))))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 3])
      (expand/optimize
        '(lambda (y) (let ([x (make-message-condition y)] [z #f]) (list (lambda () (set! z 15) z) x)))))
    ; does push (make-message-condition y) because it is pure, even though one of the vars (z) is assigned
    '(lambda (y) (let ([z #f]) (#3%list (lambda () (set! z 15) z) (#3%make-message-condition y)))))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2] [compile-profile #f])
      (expand/optimize
        '(let ()
           (define-record foo ((immutable boolean x)))
           (or (foo-x e1) e2))))
    `(let ([g0 e1])
       (if (begin
             (if (#3%record? g0 ',record-type-descriptor?)
                 (#2%void)
                 (#3%$record-oops 'foo-x g0 ',record-type-descriptor?))
             (#3%$object-ref 'boolean g0 ,fixnum?))
           #t
           e2)))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 3] [compile-profile #f])
      (expand/optimize
        '(let ()
           (define-record foo ((immutable boolean x)))
           (or (foo-x e1) e2))))
    `(if (#3%$object-ref 'boolean e1 ,fixnum?) #t e2))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(lambda (v)
           (let ([v2 (if (vector? v) v (error))])
             (let ([q (vector-sort < v2)] [n (#3%vector-length v)])
               (display "1")
               (list q n))))))
    '(lambda (v)
       (let ([v2 (begin (if (#2%vector? v) (#2%void) (#2%error)) v)])
         (let ([q (#2%vector-sort #2%< v2)] [n (#3%vector-length v)])
           (#2%display "1")
           (#2%list q n)))))
  (equivalent-expansion?
    (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 x))] [optimize-level 2])
      (expand/optimize
        '(lambda (v)
           (let ([v2 (if (vector? v) v (error))])
             (let ([q (vector-sort < v2)] [n (or v 72)])
               (display "1")
               (list q n))))))
    '(lambda (v)
       (let ([q (#2%vector-sort #2%< (begin (if (#2%vector? v) (#2%void) (#2%error)) v))]
             [n (if v v 72)])
         (#2%display "1")
         (#2%list q n))))
  ((lambda (x ls) (and (member x ls) #t))
   (with-input-from-string "#(0 1 2 #\\e)"
     (lambda ()
       (with-output-to-string
        (lambda ()
          (define-syntax check
            (identifier-syntax
             (unless (read) ;; !#eof is true
               (raise 'issue))))
          (display
           (let* ([x (read)] ;; confound cp0
                  [e (if (and (vector? x) (= (vector-length x) 4))
                         (vector-ref x 3)
                         (raise 'issue))]
                  [e ((begin (write 'a) check (begin (write 'b) (lambda (x) (display x) (char-upcase x))))
                      (begin (write 'c) check (begin (write 'd) check e)))])
             (if (char? e)
                 e
                 'bad)))))))
   '("abcdeE" "cdabeE"))
  (equivalent-expansion?
   (parameterize ([#%$suppress-primitive-inlining #f] [run-cp0 (lambda (cp0 x) (cp0 (cp0 x)))] [optimize-level 2])
     (expand/optimize
      '(let ()
         (define-syntax <foo> ;; stripped down
           (syntax-rules (assert copy* is? make)
             [(_ assert e0)
              (unless (<foo> is? e0) (raise 'bad))]
             [(_ copy* e0 [a e1])
              (eq? (datum a) 'a)
              (let ([v e0])
                (<foo> assert v)
                (<foo> make
                  [a (let ([a (#3%vector-ref v 1)]) e1)]
                  [b (#3%vector-ref v 2)]))]
             [(_ is? e0)
              (let ([v e0])
                (and (vector? v)
                     (fx= (vector-length v) 3)
                     (eq? (#3%vector-ref v 0) '<foo>)))]
             [(_ make [a e0] [b e1])
              (equal? (datum (a b)) '(a b))
              (immutable-vector '<foo> e0 e1)]
             [(_ field e0)
              (memq (datum field) '(a b))
              (let ([v e0])
                (<foo> assert v)
                (#3%vector-ref v (case 'field [a 1] [b 2])))]))
         (values
          (lambda (x)
            (let* ([x (<foo> copy* x [a 10])]
                   [x (<foo> copy* x [a (+ a 1)])]
                   [x (<foo> copy* x [a (+ a 2)])]
                   [x (<foo> copy* x [a (+ a 3)])])
              (+ (<foo> a x) (<foo> b x))))
          (<foo> make [a 1] [b 2])))))
   '(#2%values
     (lambda (x)
       (if (if (#2%vector? x)
               (if (#3%fx= (#3%vector-length x) 3)
                   (#2%eq? (#3%vector-ref x 0) '<foo>)
                   #f)
               #f)
           (#2%void)
           (#2%raise 'bad))
       (let ([g (#3%vector-ref x 2)])
         (#2%+ 16 g)))
     '#(<foo> 1 2)))
)

(mat equality-of-refs
  (begin
    (define-syntax eqtest
      (syntax-rules ()
        [(_ eqprim) (eqtest eqprim #f)]
        [(_ eqprim generic?)
         (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f] [enable-type-recovery #f])
           (let ([arity-mask (procedure-arity-mask eqprim)] [primref `($primitive ,(if (= (optimize-level) 3) 3 2) eqprim)])
             (define-syntax ifsafe
               (syntax-rules ()
                 [(_ n e1 e2)
                  (if (and (fxbit-set? arity-mask n) (or generic? (= (optimize-level) 3))) e1 e2)]))
             (and
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x)))
                 (ifsafe 1
                   `(lambda (x) #t)
                   `(lambda (x) (,primref x))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim (begin (x) x))))
                 (ifsafe 1
                   `(lambda (x) (x) #t)
                   `(lambda (x) (,primref (begin (x) x)))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (set! x (x x)) (x (eqprim x))))
                 (ifsafe 1
                   `(lambda (x) (set! x (x x)) (x #t))
                   `(lambda (x) (set! x (x x)) (x (,primref x)))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim (x x))))
                 (ifsafe 1
                   `(lambda (x) (x x) #t)
                   `(lambda (x) (,primref (x x)))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x x)))
                 (ifsafe 2
                   `(lambda (x) #t)
                   `(lambda (x) (,primref x x))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim (begin (x) x) x)))
                 (ifsafe 2
                   `(lambda (x) (x) #t)
                   `(lambda (x) (,primref (begin (x) x) x))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x (begin (x) x))))
                 (ifsafe 2
                   `(lambda (x) (x) #t)
                   `(lambda (x) (,primref x (begin (x) x)))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim (begin (x) x) (begin (x x) x))))
                 (ifsafe 2
                   `(lambda (x) (x) (x x) #t)
                   `(lambda (x) (,primref (begin (x) x) (begin (x x) x)))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x y) (eqprim x y)))
                 `(lambda (x y) (,primref x y)))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x x x x x)))
                 (ifsafe 5
                   `(lambda (x) #t)
                   `(lambda (x) (,primref x x x x x))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x y) (eqprim x x x x y)))
                 `(lambda (x y) (,primref x x x x y)))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x x (begin (x) x) x x)))
                 (ifsafe 5
                   `(lambda (x) (x) #t)
                   `(lambda (x) (,primref x x (begin (x) x) x x))))
               (equivalent-expansion?
                 (expand/optimize
                   `(lambda (x) (eqprim x x (begin (set! x 15) x) x x)))
                 `(lambda (x) (,primref x x (begin (set! x 15) x) x x)))
               )))]))
    #t)
  (eqtest eq? #t)
  (eqtest eqv? #t)
  (eqtest equal? #t)
  (eqtest bytevector=?)
  (eqtest enum-set=?)
  (eqtest bound-identifier=?)
  (eqtest free-identifier=?)
  (eqtest ftype-pointer=?)
  (eqtest literal-identifier=?)
  (eqtest time=?)
  (eqtest boolean=?)
  (eqtest symbol=?)
  (eqtest char=?)
  (eqtest char-ci=?)
  (eqtest string=?)
  (eqtest string-ci=?)
  (eqtest r6rs:char=?)
  (eqtest r6rs:char-ci=?)
  (eqtest r6rs:string=?)
  (eqtest r6rs:string-ci=?)
  (eqtest fx=)
  (eqtest fx=?)
  (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
    (equivalent-expansion?
      (expand/optimize
        `(lambda (x) (fl= x x))) ; x could be +nan.0
      `(lambda (x) (($primitive ,(if (fx= (optimize-level) 3) 3 2) fl=) x x))))
  (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
    (equivalent-expansion?
      (expand/optimize
        `(lambda (x) (= x x))) ; x could be +nan.0
      `(lambda (x) (($primitive ,(if (fx= (optimize-level) 3) 3 2) =) x x))))
)

(mat cp0-non-tail
  ;; Make sure that an expression that might depend on a specific
  ;; continuation is not moved out of its continuation --- that is,
  ;; that it's not moved from non-taul to tail position within a
  ;; function. This constaint applies even with optimization level 3,
  ;; since it's about the behavior of programs without errors. Also
  ;; make sure that redudant wrappers are not left around expressions
  ;; where the context otherwise enforces a single-valued result.
  (begin
    (define (simplify-only-nontail? mk)
      (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
        (and
         ;; Identifier is known single-valued, doesn't use continuation:
         (equivalent-expansion?
          (expand/optimize `(lambda (g) ,(mk `g)))
          '(lambda (g) g))
         ;; Call to identifier is not known single-valued, might depend
         ;; on the continuation:
         (not (equivalent-expansion?
               (expand/optimize `(lambda (g) ,(mk `(g))))
               '(lambda (g) (g))))
         ;; When moving into an ignored position, ensure single valued
         ;; in safe mode:
         (equivalent-expansion?
          (expand/optimize `(lambda (g) ,(mk `(g)) 0))
          (if (= 3 (optimize-level))
              '(lambda (g) (g) 0)
              '(lambda (g) (#3%$value (g)) 0)))
         ;; Ditto, but in a nested procedure:
         (not (equivalent-expansion?
               (expand/optimize `(lambda () (lambda (g) ,(mk `(g)))))
               '(lambda () (lambda (g) (g)))))
         ;; Argument position already enforces single-valued and no
         ;; dependency on surrounding continuation:
         (equivalent-expansion?
          (expand/optimize `(lambda (g) (#2%list ,(mk `(g)))))
          '(lambda (g) (#2%list (g))))
         (equivalent-expansion?
          (expand/optimize `(lambda (g) (#3%list ,(mk `(g)))))
          '(lambda (g) (#3%list (g))))
         ;; Same for the test position of `if`:
         (equivalent-expansion?
          (expand/optimize `(lambda (g) (if ,(mk `(g)) 1 2)))
          '(lambda (g) (if (g) 1 2))))))
     #t)
   (simplify-only-nontail? (lambda (e) `(let ([x ,e]) x)))
   (simplify-only-nontail? (lambda (e) `(letrec ([x ,e]) x)))
   (simplify-only-nontail? (lambda (e) `(values ,e)))
   (simplify-only-nontail? (lambda (e) `(list* ,e)))
   (simplify-only-nontail? (lambda (e) `(append ,e)))
   (simplify-only-nontail? (lambda (e) `(append! ,e)))
   (simplify-only-nontail? (lambda (e) `(car (list ,e))))
   (simplify-only-nontail? (lambda (e) `(car (cons ,e 2))))
   (simplify-only-nontail? (lambda (e) `(cdr (cons 2 ,e))))
)

(mat cp0-single-valued
  ;; Make sure that lifted-out expressions retain a single-result
  ;; check in safe mode even when the result is not used, but no
  ;; check in unsafe mode.
  (begin
    (define adds-needed-$value?
      (case-lambda
       [(mk safe-extras)
        (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
          (and
           (equivalent-expansion?
            (expand/optimize `(lambda (g) ,(mk '(g) 3)))
            (if (= (optimize-level) 3)
                '(lambda (g) (g) 3)
                `(lambda (g) ,@safe-extras (#3%$value (g)) 3)))))]
       [(mk) (adds-needed-$value? mk '())]))
    (define posn-decl-expanded
      '((#2%$make-record-type-descriptor
         #!base-rtd 'posn #f #f #f #f
         '#((immutable x) (immutable y)) 'define-record-type)))
     #t)
   (adds-needed-$value? (lambda (e v) `(if (let ([x ,e]) #t) ,v 'other)))
   (adds-needed-$value? (lambda (e v) `(if (list ,e) ,v 'other)))
   (adds-needed-$value? (lambda (e v) `(if (if ,e #t 'yes) ,v 'other)))
   (adds-needed-$value? (lambda (e v) `(if (if ,e #f #f) 'other ,v)))
   (adds-needed-$value? (lambda (e v) `(if (if ,e #f #t) ,v ,v)))
   (adds-needed-$value? (lambda (e v) `(let ([unused 0]) (set! unused ,e) ,v)))
   (adds-needed-$value? (lambda (e v) `(car (cons ,v ,e))))
   (adds-needed-$value? (lambda (e v) `(vector-ref (vector ,v ,e) 0)))
   (adds-needed-$value? (lambda (e v) `(begin
                                         (define-record-type posn
                                           (fields x y))
                                         (make-posn -1 ,e)
                                         ,v))
                        posn-decl-expanded)
   (adds-needed-$value? (lambda (e v) `(let ()
                                         (define-record-type posn
                                           (fields x y))
                                         (posn-x (make-posn ,v ,e))))
                        posn-decl-expanded)
   (adds-needed-$value? (lambda (e v) `(let ()
                                         (define-record-type posn
                                           (fields x y))
                                         (if (make-posn 0 ,e) ,v 'other)))
                        posn-decl-expanded)
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (equivalent-expansion?
      (expand/optimize '(let ([g1 (begin (unknown) (void))]) 10))
      '(begin (unknown) 10)))

   (or (not (enable-cp0))
       (eq? (current-eval) interpret)
       (equal? (let ([mk (lambda (g)
                           (letrec ([f (lambda (x)
                                         (if (= x 100)
                                             (g)
                                             (f (add1 x))))])
                             (lambda () (f 101))))])
                 (map procedure-known-single-valued?
                      (list (mk (lambda () 1))
                            (mk (lambda () (values 1 2))))))
               '(#t #f)))
   
   (or (not (enable-cp0))
       (eq? (current-eval) interpret)
       (procedure-known-single-valued? (lambda (f) (#3%$app/value f))))
   (or (not (enable-cp0))
       (not (procedure-known-single-valued? (lambda (f) (#2%$app/value f)))))
   (or (not (enable-cp0))
       (#%$suppress-primitive-inlining)
       (eq? (current-eval) interpret)
       (procedure-known-single-valued? (case-lambda
                                        [(f) (#3%$app/value f)]
                                        [(f g) (if (g)
                                                   (abort 'oops)
                                                   (#3%$app/value f))])))

   (or (not (enable-cp0))
       (#%$suppress-primitive-inlining)
       (eq? (current-eval) interpret)
       (procedure-known-single-valued? (lambda () (abort 'x))))
   (or (not (enable-cp0))
       (eq? (current-eval) interpret)
       (procedure-known-single-valued? (lambda (f) (#3%$app/no-return f))))
   (or (not (enable-cp0))
       (not (procedure-known-single-valued? (lambda (f) (#2%$app/no-return f)))))
   (or (not (enable-cp0))
       (#%$suppress-primitive-inlining)
       (eq? (current-eval) interpret)
       (procedure-known-single-valued? (case-lambda
                                        [(f) (#3%$app/no-return f)]
                                        [(f g) (if (g)
                                                   (abort 'oops)
                                                   (#3%$app/no-return f))])))
   (or (not (enable-cp0))
       (#%$suppress-primitive-inlining)
       (eq? (current-eval) interpret)
       (let ([mk (make-wrapper-procedure
                  (lambda (x)
                    (+ (x) 1))
                  2
                  'data)])
         (procedure-known-single-valued? (lambda (f)
                                           (if (f #t)
                                               (mk (mk f))
                                               #f))))))

(mat make-wrapper-procedure
  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '((make-wrapper-procedure (lambda (x) x) 2 'ok) 5)))
   5)
  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '((make-arity-wrapper-procedure (lambda (x) x) 2 'ok) 5)))
   5)

  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '((make-wrapper-procedure (lambda (x) x) 2 (g)) 5)))
   (if (= 3 (optimize-level))
       '(begin (g) 5)
       '(begin (#3%$value (g)) 5)))
  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '((make-arity-wrapper-procedure (lambda (x) x) 2 (g)) 5)))
   (if (= 3 (optimize-level))
       '(begin (g) 5)
       '(begin (#3%$value (g)) 5)))

  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '(let ([f (make-wrapper-procedure (lambda (x) x) 2 (g))]) (f 5))))
   (if (= 3 (optimize-level))
       '(begin (g) 5)
       '(begin (#3%$value (g)) 5)))
  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '(let ([f (make-arity-wrapper-procedure (lambda (x) x) 2 (g))]) (f 5))))
   (if (= 3 (optimize-level))
       '(begin (g) 5)
       '(begin (#3%$value (g)) 5)))

  (equivalent-expansion?
   (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
     (expand/optimize '(let ([g (let ([f (make-wrapper-procedure (lambda (x) x) 2 (g))]) f)]) (g 5))))
   (if (= 3 (optimize-level))
       '(begin (g) 5)
       '(begin (#3%$value (g)) 5)))

  (not
   (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(let ([f (#2%make-wrapper-procedure (lambda (x) x) 2 (g))]) (#2%list (g f) (f 5)))))
    '(#2%list (g (#2%make-wrapper-procedure (lambda (x) x) 2 (g))) 5)))
  (not
   (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      (expand/optimize '(let ([f (#2%make-arity-wrapper-procedure (lambda (x) x) 2 (g))]) (#2%list (g f) (f 5)))))
    '(#2%list (g (#2%make-arity-wrapper-procedure (lambda (x) x) 2 (g))) 5)))

  (not
   (equivalent-expansion?
    (parameterize ([enable-cp0 #t] [#%$suppress-primitive-inlining #f])
      ;; arity mismatch:
      (expand/optimize '((make-arity-wrapper-procedure (lambda (x) x) 1 'ok) 5)))
    5))
  )

(mat uncprep-app-variants
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(x y))
     '(x y)))
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app x y))
     '(x y)))
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app x y))
     (if (eqv? 3 (optimize-level))
         '(x y)
         '(#3%$app x y))))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(x y))
     '(x y)))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app x y))
     '(x y)))

  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/no-return x y))
     '($app/no-return x y)))
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/no-return x y))
     (if (eqv? 3 (optimize-level))
         '($app/no-return x y)
         '(#3%$app/no-return x y))))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/no-return x y))
     '($app/no-return x y)))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/no-return x y))
     '($app/no-return x y)))

  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/no-inline x y))
     '($app/no-inline x y)))
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/no-inline x y))
     (if (eqv? 3 (optimize-level))
         '($app/no-inline x y)
         '(#3%$app/no-inline x y))))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/no-inline x y))
     '($app/no-inline x y)))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/no-inline x y))
     '($app/no-inline x y)))

  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/value x y))
     '($app/value x y)))
  (parameterize ([enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/value x y))
     (if (eqv? 3 (optimize-level))
         '($app/value x y)
         '(#3%$app/value x y))))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#%$app/value x y))
     '($app/value x y)))
  (parameterize ([enable-unsafe-application #t]
                 [enable-cp0 #t])
    (equivalent-expansion?
     (expand/optimize '(#3%$app/value x y))
     '($app/value x y)))
)

(mat cross-library-inlining
  (begin
    ;; Make sure inlining doesn't use the wrong `helper`
    (library (cross-library-inlining-test)
      (export a b am bm)
      (import (rnrs))
      (define-syntax def
        (syntax-rules ()
          [(_ id idm)
           (begin
             (define (helper x) (if (zero? x) 'id (helper (- x 1))))
             (define (id x) (helper x))
             ;; causes `helper` to be preserved:
             (define-syntax idm (syntax-rules () [(_) helper])))]))
      (def a am)
      (def b bm))
    #t)
  (eq? 'a (let ()
            (import (cross-library-inlining-test))
            (a 10)))
  (eq? 'b (let ()
            (import (cross-library-inlining-test))
            (b 10)))

  (begin
    (library (check-that-inlined-set!-is-handled-correctly)
      (export make-param)
      (import (scheme))
      (define (make-param initial)
        (let ([v initial])
          (case-lambda
           [() v]
           [(x) (set! v x)]))))
    (import (check-that-inlined-set!-is-handled-correctly))
    (define parameter-porentially-inlined (make-param #f))
    (not (parameter-porentially-inlined)))
  (eq? (void) (parameter-porentially-inlined 'other))
  (eq? 'other (parameter-porentially-inlined))
  )

(cp0-mat cp0-continuation-marks
    (equivalent-expansion?
     (expand/optimize '(lambda () (call/cc (lambda (k) 10))))
     '(lambda () 10))
    (equivalent-expansion?
     (expand/optimize '(call/cc (lambda (k) 10)))
     '10)
    (equivalent-expansion?
     (expand/optimize '(call/1cc (lambda (k) 10)))
     '10)
    (equivalent-expansion?
     (expand/optimize '(call-with-current-continuation (lambda (k) 10)))
     '10)
    (equivalent-expansion?
     (expand/optimize '(with-continuation-mark 'x 'y 10))
     '10)
    (equivalent-expansion?
     (expand/optimize '(with-continuation-mark (go-get-x) 'y 10))
     (if (eqv? (optimize-level) 3)
         '(begin (go-get-x) 10)
         '(begin (#3%$value (go-get-x)) 10)))
    (equivalent-expansion?
     (expand/optimize '(with-continuation-mark 'x (go-get-y) 10))
     (if (eqv? (optimize-level) 3)
         '(begin (go-get-y) 10)
         '(begin (#3%$value (go-get-y)) 10)))
    (equivalent-expansion?
     (expand/optimize '(lambda (z) (with-continuation-mark 'x 'y z)))
     '(lambda (z) z))
    (equivalent-expansion?
     (expand/optimize '(lambda (z) (with-continuation-mark 'x 'y (values z z z))))
     (if (eqv? (optimize-level) 3)
         '(lambda (z) (#3%values z z z))
         '(lambda (z) (#2%values z z z))))
  )
