@@ -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//
@@ -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
@@ -8933,6 +8979,58 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
89338979 regSet.verifyRegistersUsed (killMask);
89348980}
89358981
8982+ insOpts CodeGen::OptsFromCFlags (insCflags flags)
8983+ {
8984+ unsigned opts = 0x0 ;
8985+ if (flags & INS_FLAGS_CF)
8986+ opts |= INS_OPTS_EVEX_dfv_cf;
8987+ if (flags & INS_FLAGS_ZF)
8988+ opts |= INS_OPTS_EVEX_dfv_zf;
8989+ if (flags & INS_FLAGS_SF)
8990+ opts |= INS_OPTS_EVEX_dfv_sf;
8991+ if (flags & INS_FLAGS_OF)
8992+ opts |= INS_OPTS_EVEX_dfv_of;
8993+ return (insOpts)opts;
8994+ }
8995+
8996+ #ifdef TARGET_AMD64
8997+
8998+ void CodeGen::genCodeForCCMP (GenTreeCCMP* ccmp)
8999+ {
9000+ emitter* emit = GetEmitter ();
9001+ assert (emit->UsePromotedEVEXEncoding ());
9002+
9003+ genConsumeOperands (ccmp);
9004+ GenTree* op1 = ccmp->gtGetOp1 ();
9005+ GenTree* op2 = ccmp->gtGetOp2 ();
9006+ var_types op1Type = genActualType (op1->TypeGet ());
9007+ var_types op2Type = genActualType (op2->TypeGet ());
9008+ emitAttr cmpSize = emitActualTypeSize (op1Type);
9009+ regNumber srcReg1 = op1->GetRegNum ();
9010+
9011+ // No float support or swapping op1 and op2 to generate cmp reg, imm.
9012+ assert (!varTypeIsFloating (op2Type));
9013+ assert (!op1->isContainedIntOrIImmed ());
9014+
9015+ // For the ccmp flags, invert the condition of the compare.
9016+ // For the condition, use the previous compare.
9017+ const GenConditionDesc& condDesc = GenConditionDesc::Get (ccmp->gtCondition );
9018+ instruction ccmpIns = JumpKindToCcmp (condDesc.jumpKind1 );
9019+ insOpts opts = OptsFromCFlags (ccmp->gtFlagsVal );
9020+
9021+ if (op2->isContainedIntOrIImmed ())
9022+ {
9023+ GenTreeIntConCommon* intConst = op2->AsIntConCommon ();
9024+ emit->emitIns_R_I (ccmpIns, cmpSize, srcReg1, (int )intConst->IconValue (), opts);
9025+ }
9026+ else
9027+ {
9028+ regNumber srcReg2 = op2->GetRegNum ();
9029+ emit->emitIns_R_R (ccmpIns, cmpSize, srcReg1, srcReg2, opts);
9030+ }
9031+ }
9032+ #endif // TARGET_AMD64
9033+
89369034#if defined(DEBUG) && defined(TARGET_AMD64)
89379035
89389036/* ****************************************************************************
0 commit comments