summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2020-01-03 16:14:29 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2020-01-03 17:55:47 +0300
commit0727e2b90c7b11d5c6be55919c443628d8e2bc6e (patch)
tree515030ecd57c6e08b3990d9c826a84b9658a20e4 /llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
parent473deaf34bc942f4ff50d4363e47ddcb510b56e0 (diff)
downloadbcm5719-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.cpp29
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 &&
OpenPOWER on IntegriCloud