Index: llvm/lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2423,6 +2423,7 @@ C.CCMask == SystemZ::CCMASK_CMP_NE) { for (SDNode *N : C.Op0->uses()) { if (N->getOpcode() == ISD::SUB && + (!N->getFlags().hasNoSignedWrap() && !N->getFlags().hasNoUnsignedWrap()) && ((N->getOperand(0) == C.Op0 && N->getOperand(1) == C.Op1) || (N->getOperand(0) == C.Op1 && N->getOperand(1) == C.Op0))) { C.Op0 = SDValue(N, 0); Index: llvm/test/CodeGen/SystemZ/int-cmp-62.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/int-cmp-62.ll @@ -0,0 +1,41 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z15 -stop-after=instruction-select | FileCheck %s +; +; Test that a sub that can overflow is not reused during isel as a comparison. + +define i32 @fun0(i32 %a, i32 %b, ptr %dest) { +; CHECK-LABEL: name: fun0 +; CHECK: $r0l = LR $r2l +; CHECK-NEXT: renamable $r2l = nsw SR killed $r2l, renamable $r1l, implicit-def dead $cc +; CHECK-NEXT: CRBReturn killed renamable $r0l, killed renamable $r1l, 6, implicit $r2l +entry: + %cur = load i32, ptr %dest + %res = sub nsw i32 %a, %cur + %cmp = icmp ne i32 %a, %cur + br i1 %cmp, label %exit, label %store + +store: + store i32 %b, ptr %dest + br label %exit + +exit: + ret i32 %res +} + +define i32 @fun1(i32 %a, i32 %b, ptr %dest) { +; CHECK-LABEL: name: fun1 +; CHECK: $r0l = LR $r2l +; CHECK-NEXT: renamable $r2l = nuw SR killed $r2l, renamable $r1l, implicit-def dead $cc +; CHECK-NEXT: CRBReturn killed renamable $r0l, killed renamable $r1l, 6, implicit $r2l +entry: + %cur = load i32, ptr %dest + %res = sub nuw i32 %a, %cur + %cmp = icmp ne i32 %a, %cur + br i1 %cmp, label %exit, label %store + +store: + store i32 %b, ptr %dest + br label %exit + +exit: + ret i32 %res +}