@@ -1572,6 +1572,46 @@ instruction CodeGen::JumpKindToCmov(emitJumpKind condition)
15721572 return s_table[condition];
15731573}
15741574
1575+ // ------------------------------------------------------------------------
1576+ // JumpKindToCcmp:
1577+ // Convert an emitJumpKind to the corresponding ccmp instruction.
1578+ //
1579+ // Arguments:
1580+ // condition - the condition
1581+ //
1582+ // Returns:
1583+ // A ccmp instruction.
1584+ //
1585+ instruction CodeGen::JumpKindToCcmp (emitJumpKind condition)
1586+ {
1587+ static constexpr instruction s_table[EJ_COUNT] = {
1588+ INS_none, INS_none, INS_ccmpo, INS_ccmpno, INS_ccmpb, INS_ccmpae, INS_ccmpe, INS_ccmpne, INS_ccmpbe,
1589+ INS_ccmpa, INS_ccmps, INS_ccmpns, INS_none, INS_none, INS_ccmpl, INS_ccmpge, INS_ccmple, INS_ccmpg,
1590+ };
1591+
1592+ static_assert_no_msg (s_table[EJ_NONE] == INS_none);
1593+ static_assert_no_msg (s_table[EJ_jmp] == INS_none);
1594+ static_assert_no_msg (s_table[EJ_jo] == INS_ccmpo);
1595+ static_assert_no_msg (s_table[EJ_jno] == INS_ccmpno);
1596+ static_assert_no_msg (s_table[EJ_jb] == INS_ccmpb);
1597+ static_assert_no_msg (s_table[EJ_jae] == INS_ccmpae);
1598+ static_assert_no_msg (s_table[EJ_je] == INS_ccmpe);
1599+ static_assert_no_msg (s_table[EJ_jne] == INS_ccmpne);
1600+ static_assert_no_msg (s_table[EJ_jbe] == INS_ccmpbe);
1601+ static_assert_no_msg (s_table[EJ_ja] == INS_ccmpa);
1602+ static_assert_no_msg (s_table[EJ_js] == INS_ccmps);
1603+ static_assert_no_msg (s_table[EJ_jns] == INS_ccmpns);
1604+ static_assert_no_msg (s_table[EJ_jp] == INS_none);
1605+ static_assert_no_msg (s_table[EJ_jnp] == INS_none);
1606+ static_assert_no_msg (s_table[EJ_jl] == INS_ccmpl);
1607+ static_assert_no_msg (s_table[EJ_jge] == INS_ccmpge);
1608+ static_assert_no_msg (s_table[EJ_jle] == INS_ccmple);
1609+ static_assert_no_msg (s_table[EJ_jg] == INS_ccmpg);
1610+
1611+ assert ((condition >= EJ_NONE) && (condition < EJ_COUNT));
1612+ return s_table[condition];
1613+ }
1614+
15751615// ------------------------------------------------------------------------
15761616// genCodeForCompare: Produce code for a GT_SELECT/GT_SELECTCC node.
15771617//
@@ -2259,6 +2299,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
22592299 // Do nothing; these nodes are simply markers for debug info.
22602300 break ;
22612301
2302+ #if defined(TARGET_AMD64)
2303+ case GT_CCMP:
2304+ genCodeForCCMP (treeNode->AsCCMP ());
2305+ break ;
2306+ #endif
2307+
22622308 default :
22632309 {
22642310#ifdef DEBUG
@@ -8938,6 +8984,58 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
89388984 regSet.verifyRegistersUsed (killMask);
89398985}
89408986
8987+ insOpts CodeGen::OptsFromCFlags (insCflags flags)
8988+ {
8989+ unsigned opts = 0x0 ;
8990+ if (flags & INS_FLAGS_CF)
8991+ opts |= INS_OPTS_EVEX_dfv_cf;
8992+ if (flags & INS_FLAGS_ZF)
8993+ opts |= INS_OPTS_EVEX_dfv_zf;
8994+ if (flags & INS_FLAGS_SF)
8995+ opts |= INS_OPTS_EVEX_dfv_sf;
8996+ if (flags & INS_FLAGS_OF)
8997+ opts |= INS_OPTS_EVEX_dfv_of;
8998+ return (insOpts)opts;
8999+ }
9000+
9001+ #ifdef TARGET_AMD64
9002+
9003+ void CodeGen::genCodeForCCMP (GenTreeCCMP* ccmp)
9004+ {
9005+ emitter* emit = GetEmitter ();
9006+ assert (emit->UsePromotedEVEXEncoding ());
9007+
9008+ genConsumeOperands (ccmp);
9009+ GenTree* op1 = ccmp->gtGetOp1 ();
9010+ GenTree* op2 = ccmp->gtGetOp2 ();
9011+ var_types op1Type = genActualType (op1->TypeGet ());
9012+ var_types op2Type = genActualType (op2->TypeGet ());
9013+ emitAttr cmpSize = emitActualTypeSize (op1Type);
9014+ regNumber srcReg1 = op1->GetRegNum ();
9015+
9016+ // No float support or swapping op1 and op2 to generate cmp reg, imm.
9017+ assert (!varTypeIsFloating (op2Type));
9018+ assert (!op1->isContainedIntOrIImmed ());
9019+
9020+ // For the ccmp flags, invert the condition of the compare.
9021+ // For the condition, use the previous compare.
9022+ const GenConditionDesc& condDesc = GenConditionDesc::Get (ccmp->gtCondition );
9023+ instruction ccmpIns = JumpKindToCcmp (condDesc.jumpKind1 );
9024+ insOpts opts = OptsFromCFlags (ccmp->gtFlagsVal );
9025+
9026+ if (op2->isContainedIntOrIImmed ())
9027+ {
9028+ GenTreeIntConCommon* intConst = op2->AsIntConCommon ();
9029+ emit->emitIns_R_I (ccmpIns, cmpSize, srcReg1, (int )intConst->IconValue (), opts);
9030+ }
9031+ else
9032+ {
9033+ regNumber srcReg2 = op2->GetRegNum ();
9034+ emit->emitIns_R_R (ccmpIns, cmpSize, srcReg1, srcReg2, opts);
9035+ }
9036+ }
9037+ #endif // TARGET_AMD64
9038+
89419039#if defined(DEBUG) && defined(TARGET_AMD64)
89429040
89439041/* ****************************************************************************
0 commit comments