@@ -1573,6 +1573,46 @@ instruction CodeGen::JumpKindToCmov(emitJumpKind condition)
15731573 return s_table[condition];
15741574}
15751575
1576+ // ------------------------------------------------------------------------
1577+ // JumpKindToCcmp:
1578+ // Convert an emitJumpKind to the corresponding ccmp instruction.
1579+ //
1580+ // Arguments:
1581+ // condition - the condition
1582+ //
1583+ // Returns:
1584+ // A ccmp instruction.
1585+ //
1586+ instruction CodeGen::JumpKindToCcmp (emitJumpKind condition)
1587+ {
1588+ static constexpr instruction s_table[EJ_COUNT] = {
1589+ INS_none, INS_none, INS_ccmpo, INS_ccmpno, INS_ccmpb, INS_ccmpae, INS_ccmpe, INS_ccmpne, INS_ccmpbe,
1590+ INS_ccmpa, INS_ccmps, INS_ccmpns, INS_none, INS_none, INS_ccmpl, INS_ccmpge, INS_ccmple, INS_ccmpg,
1591+ };
1592+
1593+ static_assert_no_msg (s_table[EJ_NONE] == INS_none);
1594+ static_assert_no_msg (s_table[EJ_jmp] == INS_none);
1595+ static_assert_no_msg (s_table[EJ_jo] == INS_ccmpo);
1596+ static_assert_no_msg (s_table[EJ_jno] == INS_ccmpno);
1597+ static_assert_no_msg (s_table[EJ_jb] == INS_ccmpb);
1598+ static_assert_no_msg (s_table[EJ_jae] == INS_ccmpae);
1599+ static_assert_no_msg (s_table[EJ_je] == INS_ccmpe);
1600+ static_assert_no_msg (s_table[EJ_jne] == INS_ccmpne);
1601+ static_assert_no_msg (s_table[EJ_jbe] == INS_ccmpbe);
1602+ static_assert_no_msg (s_table[EJ_ja] == INS_ccmpa);
1603+ static_assert_no_msg (s_table[EJ_js] == INS_ccmps);
1604+ static_assert_no_msg (s_table[EJ_jns] == INS_ccmpns);
1605+ static_assert_no_msg (s_table[EJ_jp] == INS_none);
1606+ static_assert_no_msg (s_table[EJ_jnp] == INS_none);
1607+ static_assert_no_msg (s_table[EJ_jl] == INS_ccmpl);
1608+ static_assert_no_msg (s_table[EJ_jge] == INS_ccmpge);
1609+ static_assert_no_msg (s_table[EJ_jle] == INS_ccmple);
1610+ static_assert_no_msg (s_table[EJ_jg] == INS_ccmpg);
1611+
1612+ assert ((condition >= EJ_NONE) && (condition < EJ_COUNT));
1613+ return s_table[condition];
1614+ }
1615+
15761616// ------------------------------------------------------------------------
15771617// genCodeForCompare: Produce code for a GT_SELECT/GT_SELECTCC node.
15781618//
@@ -2260,6 +2300,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
22602300 // Do nothing; these nodes are simply markers for debug info.
22612301 break ;
22622302
2303+ #if defined(TARGET_AMD64)
2304+ case GT_CCMP:
2305+ genCodeForCCMP (treeNode->AsCCMP ());
2306+ break ;
2307+ #endif
2308+
22632309 default :
22642310 {
22652311#ifdef DEBUG
@@ -8908,6 +8954,58 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
89088954 regSet.verifyRegistersUsed (killMask);
89098955}
89108956
8957+ insOpts CodeGen::OptsFromCFlags (insCflags flags)
8958+ {
8959+ unsigned opts = 0x0 ;
8960+ if (flags & INS_FLAGS_CF)
8961+ opts |= INS_OPTS_EVEX_dfv_cf;
8962+ if (flags & INS_FLAGS_ZF)
8963+ opts |= INS_OPTS_EVEX_dfv_zf;
8964+ if (flags & INS_FLAGS_SF)
8965+ opts |= INS_OPTS_EVEX_dfv_sf;
8966+ if (flags & INS_FLAGS_OF)
8967+ opts |= INS_OPTS_EVEX_dfv_of;
8968+ return (insOpts)opts;
8969+ }
8970+
8971+ #ifdef TARGET_AMD64
8972+
8973+ void CodeGen::genCodeForCCMP (GenTreeCCMP* ccmp)
8974+ {
8975+ emitter* emit = GetEmitter ();
8976+ assert (emit->UsePromotedEVEXEncoding ());
8977+
8978+ genConsumeOperands (ccmp);
8979+ GenTree* op1 = ccmp->gtGetOp1 ();
8980+ GenTree* op2 = ccmp->gtGetOp2 ();
8981+ var_types op1Type = genActualType (op1->TypeGet ());
8982+ var_types op2Type = genActualType (op2->TypeGet ());
8983+ emitAttr cmpSize = emitActualTypeSize (op1Type);
8984+ regNumber srcReg1 = op1->GetRegNum ();
8985+
8986+ // No float support or swapping op1 and op2 to generate cmp reg, imm.
8987+ assert (!varTypeIsFloating (op2Type));
8988+ assert (!op1->isContainedIntOrIImmed ());
8989+
8990+ // For the ccmp flags, invert the condition of the compare.
8991+ // For the condition, use the previous compare.
8992+ const GenConditionDesc& condDesc = GenConditionDesc::Get (ccmp->gtCondition );
8993+ instruction ccmpIns = JumpKindToCcmp (condDesc.jumpKind1 );
8994+ insOpts opts = OptsFromCFlags (ccmp->gtFlagsVal );
8995+
8996+ if (op2->isContainedIntOrIImmed ())
8997+ {
8998+ GenTreeIntConCommon* intConst = op2->AsIntConCommon ();
8999+ emit->emitIns_R_I (ccmpIns, cmpSize, srcReg1, (int )intConst->IconValue (), opts);
9000+ }
9001+ else
9002+ {
9003+ regNumber srcReg2 = op2->GetRegNum ();
9004+ emit->emitIns_R_R (ccmpIns, cmpSize, srcReg1, srcReg2, opts);
9005+ }
9006+ }
9007+ #endif // TARGET_AMD64
9008+
89119009#if defined(DEBUG) && defined(TARGET_AMD64)
89129010
89139011/* ****************************************************************************
0 commit comments