@@ -1575,6 +1575,46 @@ instruction CodeGen::JumpKindToCmov(emitJumpKind condition)
15751575    return  s_table[condition];
15761576}
15771577
1578+ // ------------------------------------------------------------------------
1579+ //  JumpKindToCcmp:
1580+ //    Convert an emitJumpKind to the corresponding ccmp instruction.
1581+ // 
1582+ //  Arguments:
1583+ //     condition - the condition
1584+ // 
1585+ //  Returns:
1586+ //     A ccmp instruction.
1587+ // 
1588+ instruction CodeGen::JumpKindToCcmp (emitJumpKind condition)
1589+ {
1590+     static  constexpr  instruction s_table[EJ_COUNT] = {
1591+         INS_none,  INS_none,  INS_ccmpo,  INS_ccmpno, INS_ccmpb, INS_ccmpae, INS_ccmpe,  INS_ccmpne, INS_ccmpbe,
1592+         INS_ccmpa, INS_ccmps, INS_ccmpns, INS_none,   INS_none,  INS_ccmpl,  INS_ccmpge, INS_ccmple, INS_ccmpg,
1593+     };
1594+ 
1595+     static_assert_no_msg (s_table[EJ_NONE] == INS_none);
1596+     static_assert_no_msg (s_table[EJ_jmp] == INS_none);
1597+     static_assert_no_msg (s_table[EJ_jo] == INS_ccmpo);
1598+     static_assert_no_msg (s_table[EJ_jno] == INS_ccmpno);
1599+     static_assert_no_msg (s_table[EJ_jb] == INS_ccmpb);
1600+     static_assert_no_msg (s_table[EJ_jae] == INS_ccmpae);
1601+     static_assert_no_msg (s_table[EJ_je] == INS_ccmpe);
1602+     static_assert_no_msg (s_table[EJ_jne] == INS_ccmpne);
1603+     static_assert_no_msg (s_table[EJ_jbe] == INS_ccmpbe);
1604+     static_assert_no_msg (s_table[EJ_ja] == INS_ccmpa);
1605+     static_assert_no_msg (s_table[EJ_js] == INS_ccmps);
1606+     static_assert_no_msg (s_table[EJ_jns] == INS_ccmpns);
1607+     static_assert_no_msg (s_table[EJ_jp] == INS_none);
1608+     static_assert_no_msg (s_table[EJ_jnp] == INS_none);
1609+     static_assert_no_msg (s_table[EJ_jl] == INS_ccmpl);
1610+     static_assert_no_msg (s_table[EJ_jge] == INS_ccmpge);
1611+     static_assert_no_msg (s_table[EJ_jle] == INS_ccmple);
1612+     static_assert_no_msg (s_table[EJ_jg] == INS_ccmpg);
1613+ 
1614+     assert ((condition >= EJ_NONE) && (condition < EJ_COUNT));
1615+     return  s_table[condition];
1616+ }
1617+ 
15781618// ------------------------------------------------------------------------
15791619//  genCodeForCompare: Produce code for a GT_SELECT/GT_SELECTCC node.
15801620// 
@@ -1671,7 +1711,7 @@ void CodeGen::genCodeForSelect(GenTreeOp* select)
16711711}
16721712
16731713//  clang-format off
1674- const  CodeGen:: GenConditionDesc CodeGen:: GenConditionDesc::map[32 ]
1714+ const  GenConditionDesc GenConditionDesc::map[32 ]
16751715{
16761716    { },        //  NONE
16771717    { },        //  1
@@ -2272,6 +2312,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
22722312            //  Do nothing; these nodes are simply markers for debug info.
22732313            break ;
22742314
2315+ #if  defined(TARGET_AMD64)
2316+         case  GT_CCMP:
2317+             genCodeForCCMP (treeNode->AsCCMP ());
2318+             break ;
2319+ #endif 
2320+ 
22752321        default :
22762322        {
22772323#ifdef  DEBUG
@@ -8928,6 +8974,84 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
89288974    regSet.verifyRegistersUsed (killMask);
89298975}
89308976
8977+ // -----------------------------------------------------------------------------------------
8978+ //  OptsFromCFlags - Convert condition flags into approxpriate insOpts.
8979+ // 
8980+ //  Arguments:
8981+ //     flags - The condition flags to be converted.
8982+ // 
8983+ //  Return Value:
8984+ //     An insOpts value encoding the condition flags.
8985+ // 
8986+ //  Notes:
8987+ //     This function maps the condition flags (e.g., CF, ZF, SF, OF) to the appropriate
8988+ //     instruction options used for setting the default flag values in extneded EVEX
8989+ //     encoding conditional instructions.
8990+ // 
8991+ insOpts CodeGen::OptsFromCFlags (insCflags flags)
8992+ {
8993+     unsigned  opts = 0x0 ;
8994+     if  (flags & INS_FLAGS_CF)
8995+         opts |= INS_OPTS_EVEX_dfv_cf;
8996+     if  (flags & INS_FLAGS_ZF)
8997+         opts |= INS_OPTS_EVEX_dfv_zf;
8998+     if  (flags & INS_FLAGS_SF)
8999+         opts |= INS_OPTS_EVEX_dfv_sf;
9000+     if  (flags & INS_FLAGS_OF)
9001+         opts |= INS_OPTS_EVEX_dfv_of;
9002+     return  (insOpts)opts;
9003+ }
9004+ 
9005+ #ifdef  TARGET_AMD64
9006+ 
9007+ // -----------------------------------------------------------------------------------------
9008+ //  genCodeForCCMP - Generate code for a conditional compare (CCMP) node.
9009+ // 
9010+ //  Arguments:
9011+ //     ccmp - The GenTreeCCMP node representing the conditional compare.
9012+ // 
9013+ //  Return Value:
9014+ //     None.
9015+ // 
9016+ //  Notes:
9017+ //     This function generates code for a conditional compare operation. On X86,
9018+ //     comparisons using the extended EVEX encoding and ccmp instruction.
9019+ void  CodeGen::genCodeForCCMP (GenTreeCCMP* ccmp)
9020+ {
9021+     emitter* emit = GetEmitter ();
9022+     assert (emit->UsePromotedEVEXEncoding ());
9023+ 
9024+     genConsumeOperands (ccmp);
9025+     GenTree*  op1     = ccmp->gtGetOp1 ();
9026+     GenTree*  op2     = ccmp->gtGetOp2 ();
9027+     var_types op1Type = genActualType (op1->TypeGet ());
9028+     var_types op2Type = genActualType (op2->TypeGet ());
9029+     emitAttr  cmpSize = emitActualTypeSize (op1Type);
9030+     regNumber srcReg1 = op1->GetRegNum ();
9031+ 
9032+     //  No float support or swapping op1 and op2 to generate cmp reg, imm.
9033+     assert (!varTypeIsFloating (op2Type));
9034+     assert (!op1->isContainedIntOrIImmed ());
9035+ 
9036+     //  For the ccmp flags, invert the condition of the compare.
9037+     //  For the condition, use the previous compare.
9038+     const  GenConditionDesc& condDesc = GenConditionDesc::Get (ccmp->gtCondition );
9039+     instruction             ccmpIns  = JumpKindToCcmp (condDesc.jumpKind1 );
9040+     insOpts                 opts     = OptsFromCFlags (ccmp->gtFlagsVal );
9041+ 
9042+     if  (op2->isContainedIntOrIImmed ())
9043+     {
9044+         GenTreeIntConCommon* intConst = op2->AsIntConCommon ();
9045+         emit->emitIns_R_I (ccmpIns, cmpSize, srcReg1, (int )intConst->IconValue (), opts);
9046+     }
9047+     else 
9048+     {
9049+         regNumber srcReg2 = op2->GetRegNum ();
9050+         emit->emitIns_R_R (ccmpIns, cmpSize, srcReg1, srcReg2, opts);
9051+     }
9052+ }
9053+ #endif  //  TARGET_AMD64
9054+ 
89319055#if  defined(DEBUG) && defined(TARGET_AMD64)
89329056
89339057/* ****************************************************************************
0 commit comments