From 0727e2b90c7b11d5c6be55919c443628d8e2bc6e Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 3 Jan 2020 16:14:29 +0300 Subject: [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 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 29 +++++++++------------------ 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp') 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 && -- cgit v1.2.3