EarlyCSE currently attempts to eliminate equivalent comparisons like this:
fcmp ugt %a, %b fcmp ult %b, %a
where the operands are swapped, by using getSwappedPredicate() to find what the equivalent predicate would be. However, it does not take account of comparisons between identical operands, like "fcmp ugt %a, %a". For identical operands getSwappedPredicate() is poorly defined as there is no other predicate that computes the same result. The net effect is that some instruction pairs hash differently, but compare equally, using hasher DenseMapInfo<SimpleValue>::getHashValue and equality DenseMapInfo<SimpleValue>::isEqual. For example:
fcmp ugt %a, %a fcmp ult %a, %a
have different predicates as inputs to the hash, but then compare equal because one of the predicates gets flipped in the equality function.
DenseMap doesn't expect inconsistent hash/equality, which has tripped assertion failures in online fuzzers [0] as least once. However because EarlyCSE (legitimately) uses pointer values in its hash, that doesn't happen often, instead it usually causes nondeterministic behaviour. Running the test in this patch results in a different output to the auto-generated one about 50% of the time on Ubuntu 18.04 and LLVM compiled with clang / libstdc++.
The functional change in this patch filters out the edge case of identical operands. The regression test reproduces the problem with reasonable frequency, however it's not clear how useful it is in general: because the broken behaviour depends on pointer values, it's hard to test.
[0] https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7892
If I'm reading this correctly, the problem only exists for fcmps not icmps right? If so, please restrict the early return to fcmps.