diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 8dfb47932f844..1d49eb6907006 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1329,6 +1329,19 @@ class emitter IS_INFO isInfo = emitGetSchedInfo(idInsFmt()); return (isInfo & (IS_AM_RW | IS_AM_WR)) != 0; } + + bool idHasMem() const + { + return idHasMemGen() || idHasMemStk() || idHasMemAdr(); + } + bool idHasMemRead() const + { + return idHasMemGenRead() || idHasMemStkRead() || idHasMemAdrRead(); + } + bool idHasMemWrite() const + { + return idHasMemGenWrite() || idHasMemStkWrite() || idHasMemAdrWrite(); + } #endif // defined(TARGET_XARCH) #ifdef TARGET_ARMARCH insOpts idInsOpt() const diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 867af802c6920..83cdb1c6fe72b 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -887,21 +887,30 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, GenCondition return false; } - // Only consider if safe - // if (!emitCanPeepholeLastIns()) { + // Don't consider if not safe return false; } instrDesc* id = emitLastIns; instruction lastIns = id->idIns(); - if (!id->idHasReg1() || (id->idReg1() != reg)) + if (!id->idIsReg1Write() || (id->idReg1() != reg)) { + // Don't consider instructions which didn't write a register return false; } + if (id->idHasMemWrite() || id->idIsReg2Write()) + { + // Don't consider instructions which also wrote a mem location or second register + return false; + } + + assert(!id->idIsReg3Write()); + assert(!id->idIsReg4Write()); + // Certain instruction like and, or and xor modifies exactly same flags // as "test" instruction. // They reset OF and CF to 0 and modifies SF, ZF and PF. @@ -956,8 +965,15 @@ bool emitter::AreFlagsSetForSignJumpOpt(regNumber reg, emitAttr opSize, GenCondi instruction lastIns = id->idIns(); insFormat fmt = id->idInsFmt(); - if (!id->idHasReg1() || (id->idReg1() != reg)) + if (!id->idIsReg1Write() || (id->idReg1() != reg)) + { + // Don't consider instructions which didn't write a register + return false; + } + + if (id->idHasMemWrite() || id->idIsReg2Write()) { + // Don't consider instructions which also wrote a mem location or second register return false; }