diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 2f069e7c1c90d..2447b18e8b327 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -11475,7 +11475,9 @@ SDValue TargetLowering::expandAddSubSat(SDNode *Node, SelectionDAG &DAG) const { } // usub.sat(a, 1) -> sub(a, zext(a != 0)) - if (Opcode == ISD::USUBSAT && isOneOrOneSplat(RHS)) { + // Prefer this on targets without legal/cost-effective overflow-carry nodes. + if (Opcode == ISD::USUBSAT && isOneOrOneSplat(RHS) && + !isOperationLegalOrCustom(ISD::USUBO_CARRY, VT)) { LHS = DAG.getFreeze(LHS); SDValue Zero = DAG.getConstant(0, dl, VT); EVT BoolVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT); diff --git a/llvm/test/CodeGen/AArch64/and-mask-removal.ll b/llvm/test/CodeGen/AArch64/and-mask-removal.ll index 855fe5caf97b2..5046c0571ad2b 100644 --- a/llvm/test/CodeGen/AArch64/and-mask-removal.ll +++ b/llvm/test/CodeGen/AArch64/and-mask-removal.ll @@ -483,9 +483,9 @@ define i64 @pr58109(i8 signext %0) { ; CHECK-SD-LABEL: pr58109: ; CHECK-SD: ; %bb.0: ; CHECK-SD-NEXT: add w8, w0, #1 -; CHECK-SD-NEXT: ands w8, w8, #0xff -; CHECK-SD-NEXT: cset w9, ne -; CHECK-SD-NEXT: sub w0, w8, w9 +; CHECK-SD-NEXT: and w8, w8, #0xff +; CHECK-SD-NEXT: subs w8, w8, #1 +; CHECK-SD-NEXT: csel w0, wzr, w8, lo ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: pr58109: diff --git a/llvm/test/CodeGen/AArch64/usub_sat_plus.ll b/llvm/test/CodeGen/AArch64/usub_sat_plus.ll index 2793aeb163c94..9f1e2eeb04781 100644 --- a/llvm/test/CodeGen/AArch64/usub_sat_plus.ll +++ b/llvm/test/CodeGen/AArch64/usub_sat_plus.ll @@ -8,6 +8,24 @@ declare i16 @llvm.usub.sat.i16(i16, i16) declare i32 @llvm.usub.sat.i32(i32, i32) declare i64 @llvm.usub.sat.i64(i64, i64) +define i32 @sat_dec_i32(i32 %x) nounwind { +; CHECK-SD-LABEL: sat_dec_i32: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: subs w8, w0, #1 +; CHECK-SD-NEXT: csel w0, wzr, w8, lo +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: sat_dec_i32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: subs w8, w0, #1 +; CHECK-GI-NEXT: cset w9, lo +; CHECK-GI-NEXT: tst w9, #0x1 +; CHECK-GI-NEXT: csel w0, wzr, w8, ne +; CHECK-GI-NEXT: ret + %tmp = call i32 @llvm.usub.sat.i32(i32 %x, i32 1) + ret i32 %tmp +} + define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind { ; CHECK-SD-LABEL: func32: ; CHECK-SD: // %bb.0: diff --git a/llvm/test/CodeGen/X86/combine-sub-usat.ll b/llvm/test/CodeGen/X86/combine-sub-usat.ll index 7ec4e062930db..e601c5733bd42 100644 --- a/llvm/test/CodeGen/X86/combine-sub-usat.ll +++ b/llvm/test/CodeGen/X86/combine-sub-usat.ll @@ -116,9 +116,9 @@ define <8 x i16> @combine_zero_v8i16(<8 x i16> %a0) { define i32 @combine_dec_i32(i32 %a0) { ; CHECK-LABEL: combine_dec_i32: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: cmpl $1, %edi -; CHECK-NEXT: adcl $-1, %eax +; CHECK-NEXT: xorl %eax, %eax +; CHECK-NEXT: subl $1, %edi +; CHECK-NEXT: cmovael %edi, %eax ; CHECK-NEXT: retq %1 = call i32 @llvm.usub.sat.i32(i32 %a0, i32 1) ret i32 %1