diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2020-01-03 16:14:29 +0300 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2020-01-03 17:55:47 +0300 |
commit | 0727e2b90c7b11d5c6be55919c443628d8e2bc6e (patch) | |
tree | 515030ecd57c6e08b3990d9c826a84b9658a20e4 /llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | |
parent | 473deaf34bc942f4ff50d4363e47ddcb510b56e0 (diff) | |
download | bcm5719-llvm-0727e2b90c7b11d5c6be55919c443628d8e2bc6e.tar.gz bcm5719-llvm-0727e2b90c7b11d5c6be55919c443628d8e2bc6e.zip |
[DAGCombiner][X86][AArch64] Generalize `A-(A&B)`->`A&(~B)` fold (PR44448)
The fold 'A - (A & (B - 1))' -> 'A & (0 - B)'
added in 8dab0a4a7d691f2704f1079538e0ef29548db159
is too specific. It should/can just be 'A - (A & B)' -> 'A & (~B)'
Even if we don't manage to fold `~` into B,
we have likely formed `ANDN` node.
Also, this way there's less similar-but-duplicate folds.
Name: X - (X & Y) -> X & (~Y)
%o = and i32 %X, %Y
%r = sub i32 %X, %o
=>
%n = xor i32 %Y, -1
%r = and i32 %X, %n
https://rise4fun.com/Alive/kOUl
See
https://bugs.llvm.org/show_bug.cgi?id=44448
https://reviews.llvm.org/D71499
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 29 |
1 files changed, 9 insertions, 20 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5a8b4d456d9..3bfea38932f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3104,31 +3104,20 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(1), N1.getOperand(0))); - // A - (A & (B - 1)) -> A & (~(B - 1)) -> A & (0 - B) - if (N1.getOpcode() == ISD::AND && N1.hasOneUse()) { + // A - (A & B) -> A & (~B) + if (N1.getOpcode() == ISD::AND) { SDValue A = N1.getOperand(0); - SDValue BDec = N1.getOperand(1); + SDValue B = N1.getOperand(1); if (A != N0) - std::swap(A, BDec); - if (A == N0 && BDec.getOpcode() == ISD::ADD && - isAllOnesOrAllOnesSplat(BDec->getOperand(1))) { - SDValue B = BDec.getOperand(0); - SDValue NegB = - DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), B); - return DAG.getNode(ISD::AND, DL, VT, A, NegB); + std::swap(A, B); + if (A == N0 && + (N1.hasOneUse() || isConstantOrConstantVector(B, /*NoOpaques=*/true))) { + SDValue InvB = + DAG.getNode(ISD::XOR, DL, VT, B, DAG.getAllOnesConstant(DL, VT)); + return DAG.getNode(ISD::AND, DL, VT, A, InvB); } } - // A - (A & C) -> A & (~C) - if (N1.getOpcode() == ISD::AND && N1.getOperand(0) == N0 && - isConstantOrConstantVector(N1.getOperand(1), /*NoOpaques=*/true)) { - SDValue InvC = - DAG.FoldConstantArithmetic(ISD::XOR, DL, VT, N1.getOperand(1).getNode(), - DAG.getAllOnesConstant(DL, VT).getNode()); - assert(InvC && "Constant folding failed"); - return DAG.getNode(ISD::AND, DL, VT, N0, InvC); - } - // fold (X - (-Y * Z)) -> (X + (Y * Z)) if (N1.getOpcode() == ISD::MUL && N1.hasOneUse()) { if (N1.getOperand(0).getOpcode() == ISD::SUB && |