diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -1692,17 +1692,23 @@ /// MI and CmpInstr /// or if MI opcode is not the S form there must be neither defs of flags /// nor uses of flags between MI and CmpInstr. -/// - and C/V flags are not used after CmpInstr +/// - and C flag is not used after CmpInstr static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI) { + // NOTE this assertion guarantees that MI.getOpcode() is the S-form of add or + // subtraction. assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END); const unsigned CmpOpcode = CmpInstr.getOpcode(); if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode)) return false; + assert((CmpInstr.getOperand(2).isImm() && + CmpInstr.getOperand(2).getImm() == 0) && + "Caller guarantees that CmpInstr compares with constant 0"); + std::optional NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI); - if (!NZVCUsed || NZVCUsed->C || NZVCUsed->V) + if (!NZVCUsed || NZVCUsed->C) return false; AccessKind AccessToCheck = AK_Write; 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 @@ -79,8 +79,7 @@ define i32@foo6(i32 %a, i32 %b) nounwind ssp { ; CHECK-LABEL: foo6: ; CHECK: // %bb.0: // %common.ret -; CHECK-NEXT: sub w8, w0, w1 -; CHECK-NEXT: cmp w8, #0 +; CHECK-NEXT: subs w8, w0, w1 ; CHECK-NEXT: csinc w0, w8, wzr, le ; CHECK-NEXT: ret %sub = sub nsw i32 %a, %b