Two new optimizer types for flow-sensitive type propagation

CONSTRAINT-PROPAGATE optimizers can add new information about the
state of the world after/if the function has returned.  Function
type declarations/propagation suffice for simple patterns (e.g.
return types, or unconditional type requirements on arguments),
but this optimizer is more general.

Such optimizers receive two arguments, the combination node and the
current set of constraints, and return a sequence of constraints.
Constraints are lists of three or four values:
 1. a constraint kind (either TYPEP, <, >, or EQL);
 2, 3. two arguments, either LVARs, LAMBDA-VARs or a CTYPE;
 4. optionally, whether the meaning of the constraint must be
    flipped.
This mimics the (defstruct (constraint ...)) in constraint.lisp.
If any of the argument is NIL, the constraint is skipped; otherwise,
it is added to current set of constraints.  Optimizers have access
to that set, and can thus map LVARs to LAMBDA-VARs thanks to
OK-LVAR-LAMBDA-VAR.

CONSTRAINT-PROPAGATE-IF optimizers can instead hook into the
interpretation of functions as predicate, when their result feeds
into an IF node.  They also receive the node and the current set
of constraints as arguments, and return four values.  The first two
values are an LVAR and a CTYPE: if they are non-NIL, that LVAR is
of that CTYPE iff the combination returns true.  The two remaining
values are sequences of constraints (see previous paragraph) for
the consequent (if-true) and alternative (if-false) branches,
respectively.  These are useful for more complex tests, but also
to represent partial information, e.g., if an EQUAL test fails,
the two values are not EQL either.
More complicated TYPEP tests are marginally transparent to type propagation

Expansions for TYPEP are wrapped in %typep-wrapper, a fancy identity. The
additional arguments track what value is being tested for what type, which
helps inform constraint propagation, as well as detecting redundant type
tests.

Such a wrapper is a hindrance to lower level control flow rewriting that are
essential for decent code generation. After a single pass of constraint
propagation, the wrapper evaporates and the TYPEP expansion becomes as opaque
as it is now.
[N]BUTLAST perform a single pass over the list

The old code would first count the number of conses, and then
SUBSEQ/(RPLACD/NTHCDR).  Instead traverse the list with two offset
pointers that advance in lockstep.

Based on a patch by Johan Andersson, on lp#1245697.