[llvm] [SelectionDAG] fold (not (sub Y, X)) -> (add X, ~Y) (PR #147825)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 27 01:45:51 PDT 2025
================
@@ -9980,12 +9980,19 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
}
// fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant.
- // FIXME: We can also do this with single-use sub, but this causes an infinite
- // loop
- if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB) {
+ // fold (not (sub Y, X)) -> (add X, ~Y) for targets with efficient AND-NOT
+ // when Y is single-use and not constant.
+ // FIXME: We cannot do this whenever the target has a hasAndNot, or any other
+ // instruction where the backend will prefer that. Currently, this is only
+ // really a problem for ARM and AArch64, which will have the same rules for
+ // when it has And Not for, in specifically AArch64's case, also xor-not and
+ // or-not Otherwise we end up with an infinite loop.
+ if (N0.getOpcode() == ISD::SUB && isAllOnesConstant(N1) && N0.hasOneUse()) {
SDValue N00 = N0.getOperand(0), N01 = N0.getOperand(1);
- if (isa<ConstantSDNode>(N00)) {
- SDValue NotY = DAG.getNOT(DL, N00, VT); // N00 = ~N00
+ if (isa<ConstantSDNode>(N00) || (N00.hasOneUse() && !TLI.hasAndNot(N01))) {
+ SDValue NotY =
+ DAG.getNode(ISD::XOR, SDLoc(N00), VT, N00, N1); // N00 = ~N00
----------------
RKSimon wrote:
Still better to use getNOT for clarity
https://github.com/llvm/llvm-project/pull/147825
More information about the llvm-commits
mailing list