The logic in EarlyCSE that looks through 'not' operations in the

predicate recognizes e.g. that `select (not (cmp sgt X, Y)), X, Y` is

equivalent to `select (cmp sgt X, Y), Y, X`. Without this change,

however, only the latter is recognized as a form of `smin X, Y`, so the

two expressions receive different hash codes. This leads to missed

optimization opportunities when the quadratic probing for the two hashes

doesn't happen to collide, and assertion failures when probing doesn't

collide on insertion but does collide on a subsequent table grow

operation.

This change inverts the order of some of the pattern matching, checking

first for the optional `not` and then for the min/max/abs patterns, so

that e.g. both expressions above are recognized as a form of `smin X, Y`.

It also adds an assertion to isEqual verifying that it implies equal

hash codes; this fires when there's a collision during insertion, not

just grow, and so will make it easier to notice if these functions fall

out of sync again.