I think count == 1 is wrong. What if there were two constant columns, select 1, 2 ... union all select 1, 2 .... When they are removed you have an empty union.
Can you add a test case SELECT ... FROM (SELECT 2 AS x ... UNION ALL SELECT 3 ...) WHERE x > 5? It's a negative test case, of course, but it there's a real danger the logic would get confused by two columns that are constant but are different constants, so it's worth testing.
Just curious, why did you pull up constants (creating a Project) rather than just pulling up predicates? Predicates are more powerful. For instance, in the above case you could easily pull pull up the predicate x = 2 or x = 3 in the above case. Then select ... from v where x > 5 would benefit.
You rely on RexNode.hashCode and .equals. RexInputRef has .hashCode and .equals but RexCall does not. You only use RexInputRef, so I think you're OK, but be careful. (Yes, we should probably add hashNode and equals for all RexNode sub-classes.)