diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 524fb0b8800a8..ca3fa55706db4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3762,12 +3762,15 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { } } - // If there's no chance any bit will need to borrow from an adjacent bit: - // sub C, X --> xor X, C + // If there's no chance of borrowing from adjacent bits, then sub is xor: + // sub C0, X --> xor X, C0 if (ConstantSDNode *C0 = isConstOrConstSplat(N0)) { - if (!C0->isOpaque() && - (~DAG.computeKnownBits(N1).Zero).isSubsetOf(C0->getAPIntValue())) - return DAG.getNode(ISD::XOR, DL, VT, N1, N0); + if (!C0->isOpaque()) { + const APInt &C0Val = C0->getAPIntValue(); + const APInt &MaybeOnes = ~DAG.computeKnownBits(N1).Zero; + if ((C0Val - MaybeOnes) == (C0Val ^ MaybeOnes)) + return DAG.getNode(ISD::XOR, DL, VT, N1, N0); + } } return SDValue(); diff --git a/llvm/test/CodeGen/AArch64/sub1.ll b/llvm/test/CodeGen/AArch64/sub1.ll index 611426e1d6b86..01f8f312a8919 100644 --- a/llvm/test/CodeGen/AArch64/sub1.ll +++ b/llvm/test/CodeGen/AArch64/sub1.ll @@ -26,15 +26,14 @@ define i8 @masked_sub_i8(i8 %x) { ret i8 %m } -; TODO: Borrow from the MSB is ok. +; Borrow from the MSB is ok. define i8 @masked_sub_high_bit_mask_i8(i8 %x) { ; CHECK-LABEL: masked_sub_high_bit_mask_i8: ; CHECK: // %bb.0: ; CHECK-NEXT: mov w8, #-96 -; CHECK-NEXT: mov w9, #60 ; CHECK-NEXT: and w8, w0, w8 -; CHECK-NEXT: sub w0, w9, w8 +; CHECK-NEXT: eor w0, w8, #0x3c ; CHECK-NEXT: ret %maskx = and i8 %x, 160 ; 0b10100000 %s = sub i8 60, %maskx ; 0b00111100