@@ -164,6 +164,21 @@ bool emitter::DoesWriteZeroFlag(instruction ins)
164164 return (CodeGenInterface::instInfo[ins] & Writes_ZF) != 0 ;
165165}
166166
167+ // ------------------------------------------------------------------------
168+ // DoesWriteSignFlag: check if the instruction writes the
169+ // SF flag.
170+ //
171+ // Arguments:
172+ // ins - instruction to test
173+ //
174+ // Return Value:
175+ // true if instruction writes the SF flag, false otherwise.
176+ //
177+ bool emitter::DoesWriteSignFlag (instruction ins)
178+ {
179+ return (CodeGenInterface::instInfo[ins] & Writes_SF) != 0 ;
180+ }
181+
167182// ------------------------------------------------------------------------
168183// DoesResetOverflowAndCarryFlags: check if the instruction resets the
169184// OF and CF flag to 0.
@@ -338,6 +353,11 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr
338353{
339354 assert (reg != REG_NA);
340355
356+ if (!emitComp->opts .OptimizationEnabled ())
357+ {
358+ return false ;
359+ }
360+
341361 // Don't look back across IG boundaries (possible control flow)
342362 if (emitCurIGinsCnt == 0 && ((emitCurIG->igFlags & IGF_EXTEND) == 0 ))
343363 {
@@ -393,6 +413,79 @@ bool emitter::AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps tr
393413 return false ;
394414}
395415
416+ // ------------------------------------------------------------------------
417+ // AreFlagsSetToForSignJumpOpt: checks if the previous instruction set the SF if the tree
418+ // node qualifies for a jg/jle to jns/js optimization
419+ //
420+ // Arguments:
421+ // reg - register of interest
422+ // opSize - size of register
423+ // relop - relational tree node
424+ //
425+ // Return Value:
426+ // true if the tree node qualifies for the jg/jle to jns/js optimization
427+ // false if not, or if we can't safely determine
428+ //
429+ // Notes:
430+ // Currently only looks back one instruction.
431+ bool emitter::AreFlagsSetForSignJumpOpt (regNumber reg, emitAttr opSize, GenTree* relop)
432+ {
433+ assert (reg != REG_NA);
434+
435+ if (!emitComp->opts .OptimizationEnabled ())
436+ {
437+ return false ;
438+ }
439+
440+ // Don't look back across IG boundaries (possible control flow)
441+ if (emitCurIGinsCnt == 0 && ((emitCurIG->igFlags & IGF_EXTEND) == 0 ))
442+ {
443+ return false ;
444+ }
445+
446+ instrDesc* id = emitLastIns;
447+ instruction lastIns = id->idIns ();
448+ insFormat fmt = id->idInsFmt ();
449+
450+ // make sure op1 is a reg
451+ switch (fmt)
452+ {
453+ case IF_RWR_CNS:
454+ case IF_RRW_CNS:
455+ case IF_RRW_SHF:
456+ case IF_RWR_RRD:
457+ case IF_RRW_RRD:
458+ case IF_RWR_MRD:
459+ case IF_RWR_SRD:
460+ case IF_RRW_SRD:
461+ case IF_RWR_ARD:
462+ case IF_RRW_ARD:
463+ case IF_RWR:
464+ case IF_RRD:
465+ case IF_RRW:
466+ break ;
467+ default :
468+ return false ;
469+ }
470+
471+ if (id->idReg1 () != reg)
472+ {
473+ return false ;
474+ }
475+
476+ // If we have a GT_GE/GT_LT which generates an jge/jl, and the previous instruction
477+ // sets the SF, we can omit a test instruction and check for jns/js.
478+ if ((relop->OperGet () == GT_GE || relop->OperGet () == GT_LT) && !GenCondition::FromRelop (relop).IsUnsigned ())
479+ {
480+ if (DoesWriteSignFlag (lastIns) && IsFlagsAlwaysModified (id))
481+ {
482+ return id->idOpSize () == opSize;
483+ }
484+ }
485+
486+ return false ;
487+ }
488+
396489// ------------------------------------------------------------------------
397490// IsDstSrcImmAvxInstruction: Checks if the instruction has a "reg, reg/mem, imm" or
398491// "reg/mem, reg, imm" form for the legacy, VEX, and EVEX
0 commit comments