Index: lib/Target/SystemZ/SystemZElimCompare.cpp =================================================================== --- lib/Target/SystemZ/SystemZElimCompare.cpp +++ lib/Target/SystemZ/SystemZElimCompare.cpp @@ -320,7 +320,14 @@ unsigned MIFlags = Desc.TSFlags; // See which compare-style condition codes are available. - unsigned ReusableCCMask = SystemZII::getCompareZeroCCMask(MIFlags); + unsigned CCValues = SystemZII::getCCValues(MIFlags); + unsigned ReusableCCMask; + if (MI.getFlag(MachineInstr::NoSWrap) && + (MIFlags & SystemZII::CCIfNoSWrapOnly)) { + CCValues &= ~SystemZ::CCMASK_ARITH_OVERFLOW; + ReusableCCMask = CCValues; + } else + ReusableCCMask = SystemZII::getCompareZeroCCMask(MIFlags); // For unsigned comparisons with zero, only equality makes sense. unsigned CompareFlags = Compare.getDesc().TSFlags; @@ -330,7 +337,6 @@ if (ReusableCCMask == 0) return false; - unsigned CCValues = SystemZII::getCCValues(MIFlags); assert((ReusableCCMask & ~CCValues) == 0 && "Invalid CCValues"); bool MIEquivalentToCmp = Index: lib/Target/SystemZ/SystemZInstrFormats.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFormats.td +++ lib/Target/SystemZ/SystemZInstrFormats.td @@ -90,6 +90,10 @@ // in cases where a distinction exists. bit IsLogical = 0; + // True if the (add or sub) instruction sets CC according its CCValues, but + // only if the 'nsw' flag is set. + bit CCIfNoSWrapOnly = 0; + let TSFlags{0} = SimpleBDXLoad; let TSFlags{1} = SimpleBDXStore; let TSFlags{2} = Has20BitOffset; @@ -101,6 +105,7 @@ let TSFlags{18} = CCMaskFirst; let TSFlags{19} = CCMaskLast; let TSFlags{20} = IsLogical; + let TSFlags{21} = CCIfNoSWrapOnly; } //===----------------------------------------------------------------------===// Index: lib/Target/SystemZ/SystemZInstrInfo.h =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.h +++ lib/Target/SystemZ/SystemZInstrInfo.h @@ -46,7 +46,8 @@ CompareZeroCCMaskShift = 14, CCMaskFirst = (1 << 18), CCMaskLast = (1 << 19), - IsLogical = (1 << 20) + IsLogical = (1 << 20), + CCIfNoSWrapOnly = (1 << 21) }; static inline unsigned getAccessSize(unsigned int Flags) { Index: lib/Target/SystemZ/SystemZInstrInfo.cpp =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.cpp +++ lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -1036,6 +1036,12 @@ } } +static void transferMIFlag(MachineInstr *OldMI, MachineInstr *NewMI, + MachineInstr::MIFlag Flag) { + if (OldMI->getFlag(Flag)) + NewMI->setFlag(Flag); +} + MachineInstr *SystemZInstrInfo::convertToThreeAddress( MachineFunction::iterator &MFI, MachineInstr &MI, LiveVariables *LV) const { MachineBasicBlock *MBB = MI.getParent(); @@ -1141,6 +1147,7 @@ .addImm(0) .addImm(MI.getOperand(2).getImm()); transferDeadCC(&MI, BuiltMI); + transferMIFlag(&MI, BuiltMI, MachineInstr::NoSWrap); return BuiltMI; } @@ -1291,6 +1298,7 @@ if (MemDesc.TSFlags & SystemZII::HasIndex) MIB.addReg(0); transferDeadCC(&MI, MIB); + transferMIFlag(&MI, MIB, MachineInstr::NoSWrap); return MIB; } } Index: lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.td +++ lib/Target/SystemZ/SystemZInstrInfo.td @@ -818,10 +818,8 @@ //===----------------------------------------------------------------------===// let Defs = [CC] in { - let CCValues = 0xF, CompareZeroCCMask = 0x8 in { - def LPR : UnaryRR <"lpr", 0x10, z_iabs, GR32, GR32>; - def LPGR : UnaryRRE<"lpgr", 0xB900, z_iabs, GR64, GR64>; - } + def LPR : UnaryRR <"lpr", 0x10, z_iabs, GR32, GR32>; + def LPGR : UnaryRRE<"lpgr", 0xB900, z_iabs, GR64, GR64>; let CCValues = 0xE, CompareZeroCCMask = 0xE in def LPGFR : UnaryRRE<"lpgfr", 0xB910, null_frag, GR64, GR32>; } @@ -831,10 +829,8 @@ defm : SXU; let Defs = [CC] in { - let CCValues = 0xF, CompareZeroCCMask = 0x8 in { - def LNR : UnaryRR <"lnr", 0x11, z_inegabs, GR32, GR32>; - def LNGR : UnaryRRE<"lngr", 0xB901, z_inegabs, GR64, GR64>; - } + def LNR : UnaryRR <"lnr", 0x11, z_inegabs, GR32, GR32>; + def LNGR : UnaryRRE<"lngr", 0xB901, z_inegabs, GR64, GR64>; let CCValues = 0xE, CompareZeroCCMask = 0xE in def LNGFR : UnaryRRE<"lngfr", 0xB911, null_frag, GR64, GR32>; } @@ -844,10 +840,8 @@ defm : SXU; let Defs = [CC] in { - let CCValues = 0xF, CompareZeroCCMask = 0x8 in { - def LCR : UnaryRR <"lcr", 0x13, ineg, GR32, GR32>; - def LCGR : UnaryRRE<"lcgr", 0xB903, ineg, GR64, GR64>; - } + def LCR : UnaryRR <"lcr", 0x13, ineg, GR32, GR32>; + def LCGR : UnaryRRE<"lcgr", 0xB903, ineg, GR64, GR64>; let CCValues = 0xE, CompareZeroCCMask = 0xE in def LCGFR : UnaryRRE<"lcgfr", 0xB913, null_frag, GR64, GR32>; } @@ -915,7 +909,7 @@ //===----------------------------------------------------------------------===// // Addition producing a signed overflow flag. -let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in { +let Defs = [CC], CCValues = 0xF, CCIfNoSWrapOnly = 1 in { // Addition of a register. let isCommutable = 1 in { defm AR : BinaryRRAndK<"ar", 0x1A, 0xB9F8, z_sadd, GR32, GR32>; @@ -1017,7 +1011,7 @@ //===----------------------------------------------------------------------===// // Subtraction producing a signed overflow flag. -let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in { +let Defs = [CC], CCValues = 0xF, CCIfNoSWrapOnly = 1 in { // Subtraction of a register. defm SR : BinaryRRAndK<"sr", 0x1B, 0xB9F9, z_ssub, GR32, GR32>; def SGFR : BinaryRRE<"sgfr", 0xB919, null_frag, GR64, GR32>; Index: test/CodeGen/SystemZ/int-cmp-44.ll =================================================================== --- test/CodeGen/SystemZ/int-cmp-44.ll +++ test/CodeGen/SystemZ/int-cmp-44.ll @@ -14,7 +14,7 @@ ; CHECK-NEXT: ber %r14 ; CHECK: br %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -30,10 +30,10 @@ define i32 @f2(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f2: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: bner %r14 +; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp ne i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -45,14 +45,13 @@ ret i32 %res } -; SLT requires a comparison. +; ...and again with SLT. define i32 @f3(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f3: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: cibl %r2, 0, 0(%r14) -; CHECK: br %r14 +; CHECK: blr %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp slt i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -64,14 +63,13 @@ ret i32 %res } -; ...SLE too. +; ...and again with SLE. define i32 @f4(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f4: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: cible %r2, 0, 0(%r14) -; CHECK: br %r14 +; CHECK: bler %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp sle i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -83,14 +81,13 @@ ret i32 %res } -; ...SGT too. +; ...and again with SGT. define i32 @f5(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f5: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: cibh %r2, 0, 0(%r14) -; CHECK: br %r14 +; CHECK: bhr %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp sgt i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -102,14 +99,13 @@ ret i32 %res } -; ...SGE too. +; ...and again with SGE. define i32 @f6(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f6: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: cibhe %r2, 0, 0(%r14) -; CHECK: br %r14 +; CHECK: bher %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 %cmp = icmp sge i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -125,11 +121,11 @@ define i32 @f7(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f7: ; CHECK: s %r2, 0(%r4) -; CHECK-NEXT: bner %r14 +; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: %cur = load i32, i32 *%dest - %res = sub i32 %a, %cur + %res = sub nsw i32 %a, %cur %cmp = icmp ne i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -141,15 +137,14 @@ ret i32 %res } -; ...but not for ordered comparisons. +; ...and again with SLT. define i32 @f8(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f8: ; CHECK: s %r2, 0(%r4) -; CHECK-NEXT: cibl %r2, 0, 0(%r14) -; CHECK: br %r14 +; CHECK: blr %r14 entry: %cur = load i32, i32 *%dest - %res = sub i32 %a, %cur + %res = sub nsw i32 %a, %cur %cmp = icmp slt i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -445,10 +440,10 @@ ; CHECK-LABEL: f23: ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: st %r2, 0(%r4) -; CHECK-NEXT: bner %r14 +; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: - %res = add i32 %a, 1000000 + %res = add nsw i32 %a, 1000000 store i32 %res, i32 *%dest1 %cmp = icmp ne i32 %res, 0 br i1 %cmp, label %exit, label %store @@ -491,10 +486,10 @@ ; CHECK-NEXT: #APP ; CHECK-NEXT: blah ; CHECK-NEXT: #NO_APP -; CHECK-NEXT: bner %r14 +; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 call void asm sideeffect "blah", "r"(i32 %add) %cmp = icmp ne i32 %add, 0 br i1 %cmp, label %exit, label %store @@ -540,7 +535,7 @@ ; CHECK-NEXT: cibe %r2, 0, 0(%r14) ; CHECK: br %r14 entry: - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %sub = sub i32 %b, %add store i32 %sub, i32 *%dest1 %cmp = icmp eq i32 %add, 0 @@ -851,11 +846,11 @@ define i32 @f41(i32 %a, i32 %b, i32 *%dest) { ; CHECK-LABEL: f41: ; CHECK: s %r2, 0(%r4) -; CHECK-NEXT: bner %r14 +; CHECK-NEXT: blhr %r14 ; CHECK: br %r14 entry: %cur = load i32, i32 *%dest - %res = sub i32 %a, %cur + %res = sub nsw i32 %a, %cur %cmp = icmp ne i32 %a, %cur br i1 %cmp, label %exit, label %store Index: test/CodeGen/SystemZ/int-cmp-45.ll =================================================================== --- test/CodeGen/SystemZ/int-cmp-45.ll +++ test/CodeGen/SystemZ/int-cmp-45.ll @@ -3,14 +3,14 @@ ; ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 -no-integrated-as | FileCheck %s -; Addition provides enough for equality comparisons with zero. First teest +; Addition provides enough for equality comparisons with zero. First test ; the EQ case with LOC. define i32 @f1(i32 %a, i32 %b, i32 *%cptr) { ; CHECK-LABEL: f1: ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: loce %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %add, 0 %c = load i32, i32 *%cptr %arg = select i1 %cmp, i32 %c, i32 %b @@ -24,7 +24,7 @@ ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: stoce %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %add, 0 %c = load i32, i32 *%cptr %newval = select i1 %cmp, i32 %b, i32 %c @@ -36,9 +36,9 @@ define i32 @f3(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: f3: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: locrne %r3, %r4 +; CHECK-NEXT: locrlh %r3, %r4 ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %add, 0 %arg = select i1 %cmp, i32 %b, i32 %c call void asm sideeffect "blah $0", "{r3}"(i32 %arg) @@ -49,9 +49,9 @@ define i32 @f4(i32 %a, i32 %b, i32 *%cptr) { ; CHECK-LABEL: f4: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: locne %r3, 0(%r4) +; CHECK-NEXT: loclh %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %add, 0 %c = load i32, i32 *%cptr %arg = select i1 %cmp, i32 %b, i32 %c @@ -63,9 +63,9 @@ define i32 @f5(i32 %a, i32 %b, i32 *%cptr) { ; CHECK-LABEL: f5: ; CHECK: afi %r2, 1000000 -; CHECK-NEXT: stocne %r3, 0(%r4) +; CHECK-NEXT: stoclh %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp eq i32 %add, 0 %c = load i32, i32 *%cptr %newval = select i1 %cmp, i32 %c, i32 %b @@ -79,7 +79,7 @@ ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: locre %r3, %r4 ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp ne i32 %add, 0 %arg = select i1 %cmp, i32 %b, i32 %c call void asm sideeffect "blah $0", "{r3}"(i32 %arg) @@ -92,7 +92,7 @@ ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: loce %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp ne i32 %add, 0 %c = load i32, i32 *%cptr %arg = select i1 %cmp, i32 %b, i32 %c @@ -106,7 +106,7 @@ ; CHECK: afi %r2, 1000000 ; CHECK-NEXT: stoce %r3, 0(%r4) ; CHECK: br %r14 - %add = add i32 %a, 1000000 + %add = add nsw i32 %a, 1000000 %cmp = icmp ne i32 %add, 0 %c = load i32, i32 *%cptr %newval = select i1 %cmp, i32 %c, i32 %b Index: test/CodeGen/SystemZ/loop-01.ll =================================================================== --- test/CodeGen/SystemZ/loop-01.ll +++ test/CodeGen/SystemZ/loop-01.ll @@ -94,7 +94,7 @@ ; CHECK: aghi [[REG:%r[0-5]]], -1 ; CHECK: lr [[REG2:%r[0-5]]], [[REG]] ; CHECK: stg [[REG2]], -; CHECK: jne {{\..*}} +; CHECK: cgijlh [[REG]], 0, {{\..*}} ; CHECK: br %r14 entry: br label %loop