diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -8235,8 +8235,11 @@ Swap = true; } } - // 64-bit check whether we can use CSINC. - } else if ((TrueVal == FalseVal + 1) || (TrueVal + 1 == FalseVal)) { + // 64-bit check whether we can use CSINC. To avoid signed integer + // overflow the condition ignores wrap around, which is already + // handled by CSINV above. + } else if (1 == + std::max(TrueVal, FalseVal) - std::min(TrueVal, FalseVal)) { Opcode = AArch64ISD::CSINC; if (TrueVal > FalseVal) { diff --git a/llvm/test/CodeGen/AArch64/arm64-csel.ll b/llvm/test/CodeGen/AArch64/arm64-csel.ll --- a/llvm/test/CodeGen/AArch64/arm64-csel.ll +++ b/llvm/test/CodeGen/AArch64/arm64-csel.ll @@ -264,6 +264,34 @@ ret i64 %. } +; Regression test for TrueVal + 1 overflow +define i64 @foo18_overflow1(i64 %a, i64 %b) nounwind readnone optsize ssp { +; CHECK-LABEL: foo18_overflow1: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: cmp x0, x1 +; CHECK-NEXT: mov x8, #9223372036854775807 +; CHECK-NEXT: csel x0, x8, xzr, gt +; CHECK-NEXT: ret +entry: + %cmp = icmp sgt i64 %a, %b + %. = select i1 %cmp, i64 9223372036854775807, i64 0 + ret i64 %. +} + +; Regression test for FalseVal + 1 overflow +define i64 @foo18_overflow2(i64 %a, i64 %b) nounwind readnone optsize ssp { +; CHECK-LABEL: foo18_overflow2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: cmp x0, x1 +; CHECK-NEXT: mov x8, #9223372036854775807 +; CHECK-NEXT: csel x0, xzr, x8, gt +; CHECK-NEXT: ret +entry: + %cmp = icmp sgt i64 %a, %b + %. = select i1 %cmp, i64 0, i64 9223372036854775807 + ret i64 %. +} + define i64 @foo19(i64 %a, i64 %b, i64 %c) { ; CHECK-LABEL: foo19: ; CHECK: // %bb.0: // %entry