Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10148,6 +10148,13 @@ if (SDValue ABD = combineABSToABD(N, DAG, TLI)) return ABD; + // fold (abs (sub nsw x, y)) -> abds(x, y) + if (N->getOperand(0).getOpcode() == ISD::SUB && + N->getOperand(0)->getFlags().hasNoSignedWrap() && + TLI.isOperationLegalOrCustom(ISD::ABDS, VT)) + return DAG.getNode(ISD::ABDS, SDLoc(N), VT, N->getOperand(0).getOperand(0), + N->getOperand(0).getOperand(1)); + // fold (abs (sign_extend_inreg x)) -> (zero_extend (abs (truncate x))) // iff zero_extend/truncate are free. if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) { Index: llvm/test/CodeGen/AArch64/neon-abd.ll =================================================================== --- llvm/test/CodeGen/AArch64/neon-abd.ll +++ llvm/test/CodeGen/AArch64/neon-abd.ll @@ -409,8 +409,7 @@ define <16 x i8> @sabd_v16i8_nsw(<16 x i8> %a, <16 x i8> %b) #0 { ; CHECK-LABEL: sabd_v16i8_nsw: ; CHECK: // %bb.0: -; CHECK-NEXT: sub v0.16b, v0.16b, v1.16b -; CHECK-NEXT: abs v0.16b, v0.16b +; CHECK-NEXT: sabd v0.16b, v0.16b, v1.16b ; CHECK-NEXT: ret %sub = sub nsw <16 x i8> %a, %b %abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %sub, i1 true) @@ -420,8 +419,7 @@ define <8 x i16> @sabd_v8i16_nsw(<8 x i16> %a, <8 x i16> %b) #0 { ; CHECK-LABEL: sabd_v8i16_nsw: ; CHECK: // %bb.0: -; CHECK-NEXT: sub v0.8h, v0.8h, v1.8h -; CHECK-NEXT: abs v0.8h, v0.8h +; CHECK-NEXT: sabd v0.8h, v0.8h, v1.8h ; CHECK-NEXT: ret %sub = sub nsw <8 x i16> %a, %b %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) @@ -431,8 +429,7 @@ define <4 x i32> @sabd_v4i32_nsw(<4 x i32> %a, <4 x i32> %b) #0 { ; CHECK-LABEL: sabd_v4i32_nsw: ; CHECK: // %bb.0: -; CHECK-NEXT: sub v0.4s, v0.4s, v1.4s -; CHECK-NEXT: abs v0.4s, v0.4s +; CHECK-NEXT: sabd v0.4s, v0.4s, v1.4s ; CHECK-NEXT: ret %sub = sub nsw <4 x i32> %a, %b %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true)