This is a change to the ARM backend that folds or(A, B) into not(and(not(A), not(B))) more often.
This only affects vectors of i1: v4i1, v8i1 and v16i1 because PerformORCombine_i1 is only called by PerformORCombine if those conditions are met:
if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)) return PerformORCombine_i1(N, DCI, Subtarget);
This actually generates better code in my tests, as not and and are essentially free compared to or when manipulating the VPR register.
- and becomes a VPT block (no extra instruction)
- not becomes a vpnot, which is often removed by the MVE VPT Block Insertion pass to create VPT blocks (no extra instructions).
However, I'm not fully sure it's a good change, and I believe the implementation could be better, which is why I need some help to review this.
These can use DL too. The not is in a way coming from the Or.