diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index e2dad3d7cc6ed6..ce948c084a4e85 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6294,6 +6294,19 @@ void CodeGen::genCompareFloat(GenTree* treeNode) ins = (op1Type == TYP_FLOAT) ? INS_ucomiss : INS_ucomisd; cmpAttr = emitTypeSize(op1Type); + var_types targetType = treeNode->TypeGet(); + + // Clear target reg in advance via "xor reg,reg" to avoid movzx after SETCC + if ((targetReg != REG_NA) && (op1->GetRegNum() != targetReg) && (op2->GetRegNum() != targetReg) && + !varTypeIsByte(targetType)) + { + regMaskTP targetRegMask = genRegMask(targetReg); + if (((op1->gtGetContainedRegMask() | op2->gtGetContainedRegMask()) & targetRegMask) == 0) + { + instGen_Set_Reg_To_Zero(emitTypeSize(TYP_I_IMPL), targetReg); + targetType = TYP_BOOL; // just a tip for inst_SETCC that movzx is not needed + } + } GetEmitter()->emitInsBinary(ins, cmpAttr, op1, op2); // Are we evaluating this into a register? @@ -6309,7 +6322,7 @@ void CodeGen::genCompareFloat(GenTree* treeNode) condition = GenCondition(GenCondition::P); } - inst_SETCC(condition, treeNode->TypeGet(), targetReg); + inst_SETCC(condition, targetType, targetReg); genProduceReg(tree); } } @@ -6438,6 +6451,8 @@ void CodeGen::genCompareInt(GenTree* treeNode) // Sign jump optimization should only be set the following check assert((tree->gtFlags & GTF_RELOP_SJUMP_OPT) == 0); + var_types targetType = tree->TypeGet(); + if (canReuseFlags && emit->AreFlagsSetToZeroCmp(op1->GetRegNum(), emitTypeSize(type), tree->OperGet())) { JITDUMP("Not emitting compare due to flags being already set\n"); @@ -6449,13 +6464,24 @@ void CodeGen::genCompareInt(GenTree* treeNode) } else { + // Clear target reg in advance via "xor reg,reg" to avoid movzx after SETCC + if ((targetReg != REG_NA) && (op1->GetRegNum() != targetReg) && (op2->GetRegNum() != targetReg) && + !varTypeIsByte(targetType)) + { + regMaskTP targetRegMask = genRegMask(targetReg); + if (((op1->gtGetContainedRegMask() | op2->gtGetContainedRegMask()) & targetRegMask) == 0) + { + instGen_Set_Reg_To_Zero(emitTypeSize(TYP_I_IMPL), targetReg); + targetType = TYP_BOOL; // just a tip for inst_SETCC that movzx is not needed + } + } emit->emitInsBinary(ins, emitTypeSize(type), op1, op2); } // Are we evaluating this into a register? if (targetReg != REG_NA) { - inst_SETCC(GenCondition::FromIntegralRelop(tree), tree->TypeGet(), targetReg); + inst_SETCC(GenCondition::FromIntegralRelop(tree), targetType, targetReg); genProduceReg(tree); } } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 8350e7ad725fb2..640ee36accebc5 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -862,6 +862,31 @@ unsigned GenTree::GetMultiRegCount(Compiler* comp) const return 1; } +//--------------------------------------------------------------- +// gtGetContainedRegMask: Get the reg mask of the node including +// contained nodes (recursive). +// +// Arguments: +// None +// +// Return Value: +// Reg Mask of GenTree node. +// +regMaskTP GenTree::gtGetContainedRegMask() +{ + if (!isContained()) + { + return gtGetRegMask(); + } + + regMaskTP mask = 0; + for (GenTree* operand : Operands()) + { + mask |= operand->gtGetContainedRegMask(); + } + return mask; +} + //--------------------------------------------------------------- // gtGetRegMask: Get the reg mask of the node. // diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index d86d891b303271..af58071a37d20d 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -990,6 +990,7 @@ struct GenTree int GetRegisterDstCount(Compiler* compiler) const; regMaskTP gtGetRegMask() const; + regMaskTP gtGetContainedRegMask(); GenTreeFlags gtFlags;