If Y is non-zero we can simplify the ge/le -> gt/lt
(X ^ Y_NonZero) u>= X --> (X ^ Y_NonZero) u> X
(X ^ Y_NonZero) u<= X --> (X ^ Y_NonZero) u< X
(X ^ Y_NonZero) s>= X --> (X ^ Y_NonZero) s> X
(X ^ Y_NonZero) s<= X --> (X ^ Y_NonZero) s< X
Differential D144608
[InstCombine] Add transforms for `(icmp {u|s}ge/le (xor X, Y), X)` Authored by goldstein.w.n on Feb 22 2023, 5:20 PM.
Details If Y is non-zero we can simplify the ge/le -> gt/lt (X ^ Y_NonZero) u>= X --> (X ^ Y_NonZero) u> X (X ^ Y_NonZero) u<= X --> (X ^ Y_NonZero) u< X (X ^ Y_NonZero) s>= X --> (X ^ Y_NonZero) s> X (X ^ Y_NonZero) s<= X --> (X ^ Y_NonZero) s< X
Diff Detail
Event TimelineComment Actions This is adding a lot of code to a function that's already too big. A helper function will make it easier to read. This seems like 2 or 3 independent patches? I just looked at the first group of 4 Alive proofs, and those seem fine.
| |||||||||||||||||||||||||||
Can we canonicalize the xor as operand 0?
It shouldn't make much difference on this patch, but that would make the next one smaller.
// Normalize xor operand as operand 0. CmpInst::Predicate Pred = I.getPredicate(); if (match(Op1, m_c_Xor(m_Specific(Op0), m_Value()))) { std::swap(Op0, Op1); Pred = ICmpInst::getSwappedPredicate(Pred); } if (!match(Op0, m_c_Xor(m_Specific(Op1), m_Value(A)))) return nullptr;