Index: llvm/lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2425,6 +2425,12 @@ if (N->getOpcode() == ISD::SUB && ((N->getOperand(0) == C.Op0 && N->getOperand(1) == C.Op1) || (N->getOperand(0) == C.Op1 && N->getOperand(1) == C.Op0))) { + // Disable the nsw and nuw flags: the backend needs to handle + // overflow as well during comparison elimination. + SDNodeFlags Flags = N->getFlags(); + Flags.setNoSignedWrap(false); + Flags.setNoUnsignedWrap(false); + N->setFlags(Flags); C.Op0 = SDValue(N, 0); C.Op1 = DAG.getConstant(0, DL, N->getValueType(0)); return; Index: llvm/test/CodeGen/SystemZ/int-cmp-62.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/int-cmp-62.ll @@ -0,0 +1,39 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z15 | FileCheck %s +; +; Test that a CC result of a sub that can overflow is tested with the right predicate. + +define i32 @fun0(i32 %a, i32 %b, ptr %dest) { +; CHECK-LABEL: fun0 +; CHECK: s %r2, 0(%r4) +; CHECK: bner %r14 +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: fun1 +; CHECK: s %r2, 0(%r4) +; CHECK: bner %r14 +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 +}