@@ -298,8 +298,8 @@ bool Compiler::optCSE_canSwap(GenTree* op1, GenTree* op2)
298298/* static */
299299bool Compiler::optCSEcostCmpEx::operator ()(const CSEdsc* dsc1, const CSEdsc* dsc2)
300300{
301- GenTree* exp1 = dsc1->csdTree ;
302- GenTree* exp2 = dsc2->csdTree ;
301+ GenTree* exp1 = dsc1->csdTreeList . tslTree ;
302+ GenTree* exp2 = dsc2->csdTreeList . tslTree ;
303303
304304 auto expCost1 = exp1->GetCostEx ();
305305 auto expCost2 = exp2->GetCostEx ();
@@ -334,8 +334,8 @@ bool Compiler::optCSEcostCmpEx::operator()(const CSEdsc* dsc1, const CSEdsc* dsc
334334/* static */
335335bool Compiler::optCSEcostCmpSz::operator ()(const CSEdsc* dsc1, const CSEdsc* dsc2)
336336{
337- GenTree* exp1 = dsc1->csdTree ;
338- GenTree* exp2 = dsc2->csdTree ;
337+ GenTree* exp1 = dsc1->csdTreeList . tslTree ;
338+ GenTree* exp2 = dsc2->csdTreeList . tslTree ;
339339
340340 auto expCost1 = exp1->GetCostSz ();
341341 auto expCost2 = exp2->GetCostSz ();
@@ -434,7 +434,7 @@ void CSEdsc::ComputeNumLocals(Compiler* compiler)
434434 };
435435
436436 LocalCountingVisitor lcv (compiler);
437- lcv.WalkTree (&csdTree , nullptr );
437+ lcv.WalkTree (&csdTreeList. tslTree , nullptr );
438438
439439 numDistinctLocals = lcv.m_count ;
440440 numLocalOccurrences = lcv.m_occurrences ;
@@ -615,99 +615,85 @@ unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt)
615615
616616 for (hashDsc = optCSEhash[hval]; hashDsc; hashDsc = hashDsc->csdNextInBucket )
617617 {
618- if (hashDsc->csdHashKey = = key)
618+ if (hashDsc->csdHashKey ! = key)
619619 {
620- // Check for mismatched types on GT_CNS_INT nodes
621- if ((tree->OperGet () == GT_CNS_INT) && (tree->TypeGet () != hashDsc->csdTree ->TypeGet ()))
622- {
623- continue ;
624- }
620+ continue ;
621+ }
622+
623+ assert (hashDsc->csdTreeList .tslTree != nullptr );
625624
626- treeStmtLst* newElem;
625+ // Check for mismatched types on GT_CNS_INT nodes
626+ if ((tree->OperGet () == GT_CNS_INT) && (tree->TypeGet () != hashDsc->csdTreeList .tslTree ->TypeGet ()))
627+ {
628+ continue ;
629+ }
627630
628- // Have we started the list of matching nodes?
631+ // Have we started the list of matching nodes?
629632
630- if (hashDsc->csdTreeList == nullptr )
633+ if (hashDsc->csdTreeList .tslNext == nullptr )
634+ {
635+ // This is the second time we see this value. Handle cases
636+ // where the first value dominates the second one and we can
637+ // already prove that the first one is _not_ going to be a
638+ // valid def for the second one, due to the second one having
639+ // more exceptions. This happens for example in code like
640+ // CASTCLASS(x, y) where the "CASTCLASS" just adds exceptions
641+ // on top of "x". In those cases it is always better to let the
642+ // second value be the def.
643+ // It also happens for GT_COMMA, but that one is special cased
644+ // above; this handling is a less special-casey version of the
645+ // GT_COMMA handling above. However, it is quite limited since
646+ // it only handles the def/use being in the same block.
647+ if (compCurBB == hashDsc->csdTreeList .tslBlock )
631648 {
632- // This is the second time we see this value. Handle cases
633- // where the first value dominates the second one and we can
634- // already prove that the first one is _not_ going to be a
635- // valid def for the second one, due to the second one having
636- // more exceptions. This happens for example in code like
637- // CASTCLASS(x, y) where the "CASTCLASS" just adds exceptions
638- // on top of "x". In those cases it is always better to let the
639- // second value be the def.
640- // It also happens for GT_COMMA, but that one is special cased
641- // above; this handling is a less special-casey version of the
642- // GT_COMMA handling above. However, it is quite limited since
643- // it only handles the def/use being in the same block.
644- if (compCurBB == hashDsc->csdBlock )
649+ GenTree* prevTree = hashDsc->csdTreeList .tslTree ;
650+ ValueNum prevVnLib = prevTree->GetVN (VNK_Liberal);
651+ if (prevVnLib != vnLib)
645652 {
646- GenTree* prevTree = hashDsc->csdTree ;
647- ValueNum prevVnLib = prevTree->GetVN (VNK_Liberal);
648- if (prevVnLib != vnLib)
653+ ValueNum prevExceptionSet = vnStore->VNExceptionSet (prevVnLib);
654+ ValueNum curExceptionSet = vnStore->VNExceptionSet (vnLib);
655+ if ((prevExceptionSet != curExceptionSet) &&
656+ vnStore->VNExcIsSubset (curExceptionSet, prevExceptionSet))
649657 {
650- ValueNum prevExceptionSet = vnStore->VNExceptionSet (prevVnLib);
651- ValueNum curExceptionSet = vnStore->VNExceptionSet (vnLib);
652- if ((prevExceptionSet != curExceptionSet) &&
653- vnStore->VNExcIsSubset (curExceptionSet, prevExceptionSet))
654- {
655- JITDUMP (" Skipping CSE candidate for tree [%06u]; tree [%06u] is a better candidate with "
656- " more exceptions\n " ,
657- prevTree->gtTreeID , tree->gtTreeID );
658- prevTree->gtCSEnum = 0 ;
659- hashDsc->csdStmt = stmt;
660- hashDsc->csdTree = tree;
661- tree->gtCSEnum = (signed char )hashDsc->csdIndex ;
662- return hashDsc->csdIndex ;
663- }
658+ JITDUMP (" Skipping CSE candidate for tree [%06u]; tree [%06u] is a better candidate with "
659+ " more exceptions\n " ,
660+ prevTree->gtTreeID , tree->gtTreeID );
661+ prevTree->gtCSEnum = 0 ;
662+ hashDsc->csdTreeList .tslStmt = stmt;
663+ hashDsc->csdTreeList .tslTree = tree;
664+ tree->gtCSEnum = (signed char )hashDsc->csdIndex ;
665+ return hashDsc->csdIndex ;
664666 }
665667 }
666-
667- // Create the new element based upon the matching hashDsc element.
668-
669- newElem = new (this , CMK_TreeStatementList) treeStmtLst;
670-
671- newElem->tslTree = hashDsc->csdTree ;
672- newElem->tslStmt = hashDsc->csdStmt ;
673- newElem->tslBlock = hashDsc->csdBlock ;
674- newElem->tslNext = nullptr ;
675-
676- /* Start the list with the first CSE candidate recorded */
677-
678- hashDsc->csdTreeList = newElem;
679- hashDsc->csdTreeLast = newElem;
680-
681- hashDsc->csdIsSharedConst = isSharedConst;
682668 }
683669
684- noway_assert (hashDsc->csdTreeList );
670+ hashDsc->csdIsSharedConst = isSharedConst;
671+ }
685672
686- /* Append this expression to the end of the list */
673+ // Append this expression to the end of the list
687674
688- newElem = new (this , CMK_TreeStatementList) treeStmtLst;
675+ treeStmtLst* newElem = new (this , CMK_TreeStatementList) treeStmtLst;
689676
690- newElem->tslTree = tree;
691- newElem->tslStmt = stmt;
692- newElem->tslBlock = compCurBB;
693- newElem->tslNext = nullptr ;
677+ newElem->tslTree = tree;
678+ newElem->tslStmt = stmt;
679+ newElem->tslBlock = compCurBB;
680+ newElem->tslNext = nullptr ;
694681
695- hashDsc->csdTreeLast ->tslNext = newElem;
696- hashDsc->csdTreeLast = newElem;
682+ hashDsc->csdTreeLast ->tslNext = newElem;
683+ hashDsc->csdTreeLast = newElem;
697684
698- optDoCSE = true ; // Found a duplicate CSE tree
685+ optDoCSE = true ; // Found a duplicate CSE tree
699686
700- /* Have we assigned a CSE index? */
701- if (hashDsc->csdIndex == 0 )
702- {
703- newCSE = true ;
704- break ;
705- }
706-
707- assert (FitsIn<signed char >(hashDsc->csdIndex ));
708- tree->gtCSEnum = ((signed char )hashDsc->csdIndex );
709- return hashDsc->csdIndex ;
687+ /* Have we assigned a CSE index? */
688+ if (hashDsc->csdIndex == 0 )
689+ {
690+ newCSE = true ;
691+ break ;
710692 }
693+
694+ assert (FitsIn<signed char >(hashDsc->csdIndex ));
695+ tree->gtCSEnum = ((signed char )hashDsc->csdIndex );
696+ return hashDsc->csdIndex ;
711697 }
712698
713699 if (!newCSE)
@@ -763,10 +749,12 @@ unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt)
763749 hashDsc->defExcSetPromise = vnStore->VNForEmptyExcSet ();
764750 hashDsc->defExcSetCurrent = vnStore->VNForNull (); // uninit value
765751
766- hashDsc->csdTree = tree;
767- hashDsc->csdStmt = stmt;
768- hashDsc->csdBlock = compCurBB;
769- hashDsc->csdTreeList = nullptr ;
752+ hashDsc->csdTreeList .tslTree = tree;
753+ hashDsc->csdTreeList .tslStmt = stmt;
754+ hashDsc->csdTreeList .tslBlock = compCurBB;
755+ hashDsc->csdTreeList .tslNext = nullptr ;
756+
757+ hashDsc->csdTreeLast = &hashDsc->csdTreeList ;
770758
771759 /* Append the entry to the hash bucket */
772760
@@ -801,11 +789,11 @@ unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt)
801789 hashDsc->csdIndex = CSEindex;
802790
803791 /* Update the gtCSEnum field in the original tree */
804- noway_assert (hashDsc->csdTreeList -> tslTree ->gtCSEnum == 0 );
792+ noway_assert (hashDsc->csdTreeList . tslTree ->gtCSEnum == 0 );
805793 assert (FitsIn<signed char >(CSEindex));
806794
807- hashDsc->csdTreeList -> tslTree ->gtCSEnum = ((signed char )CSEindex);
808- noway_assert (((unsigned )hashDsc->csdTreeList -> tslTree ->gtCSEnum ) == CSEindex);
795+ hashDsc->csdTreeList . tslTree ->gtCSEnum = ((signed char )CSEindex);
796+ noway_assert (((unsigned )hashDsc->csdTreeList . tslTree ->gtCSEnum ) == CSEindex);
809797
810798 tree->gtCSEnum = ((signed char )CSEindex);
811799
@@ -975,7 +963,7 @@ void Compiler::optValnumCSE_InitDataFlow()
975963 {
976964 CSEdsc* dsc = optCSEtab[inx];
977965 unsigned CSEindex = dsc->csdIndex ;
978- treeStmtLst* lst = dsc->csdTreeList ;
966+ treeStmtLst* lst = & dsc->csdTreeList ;
979967 noway_assert (lst);
980968
981969 while (lst != nullptr )
@@ -1101,13 +1089,13 @@ void Compiler::optValnumCSE_SetUpAsyncByrefKills()
11011089 CSEdsc* dsc = optCSEtab[inx - 1 ];
11021090 assert (dsc->csdIndex == inx);
11031091 bool isByRef = false ;
1104- if (dsc->csdTree ->TypeIs (TYP_BYREF))
1092+ if (dsc->csdTreeList . tslTree ->TypeIs (TYP_BYREF))
11051093 {
11061094 isByRef = true ;
11071095 }
1108- else if (dsc->csdTree ->TypeIs (TYP_STRUCT))
1096+ else if (dsc->csdTreeList . tslTree ->TypeIs (TYP_STRUCT))
11091097 {
1110- ClassLayout* layout = dsc->csdTree ->GetLayout (this );
1098+ ClassLayout* layout = dsc->csdTreeList . tslTree ->GetLayout (this );
11111099 isByRef = layout->HasGCByRef ();
11121100 }
11131101
@@ -2528,14 +2516,14 @@ void CSE_HeuristicParameterized::GetFeatures(CSEdsc* cse, double* features)
25282516 return ;
25292517 }
25302518
2531- const unsigned char costEx = cse->csdTree ->GetCostEx ();
2519+ const unsigned char costEx = cse->csdTreeList . tslTree ->GetCostEx ();
25322520 const double deMinimis = 1e-3 ;
25332521 const double deMinimusAdj = -log (deMinimis);
25342522
25352523 features[0 ] = costEx;
25362524 features[1 ] = deMinimusAdj + log (max (deMinimis, cse->csdUseWtCnt ));
25372525 features[2 ] = deMinimusAdj + log (max (deMinimis, cse->csdDefWtCnt ));
2538- features[3 ] = cse->csdTree ->GetCostSz ();
2526+ features[3 ] = cse->csdTreeList . tslTree ->GetCostSz ();
25392527 features[4 ] = cse->csdUseCount ;
25402528 features[5 ] = cse->csdDefCount ;
25412529
@@ -2545,9 +2533,9 @@ void CSE_HeuristicParameterized::GetFeatures(CSEdsc* cse, double* features)
25452533 const bool isLiveAcrossCall = cse->csdLiveAcrossCall ;
25462534
25472535 features[6 ] = booleanScale * isLiveAcrossCall;
2548- features[7 ] = booleanScale * varTypeUsesIntReg (cse->csdTree ->TypeGet ());
2536+ features[7 ] = booleanScale * varTypeUsesIntReg (cse->csdTreeList . tslTree ->TypeGet ());
25492537
2550- const bool isConstant = cse->csdTree ->OperIsConst ();
2538+ const bool isConstant = cse->csdTreeList . tslTree ->OperIsConst ();
25512539 const bool isSharedConstant = cse->csdIsSharedConst ;
25522540
25532541 features[8 ] = booleanScale * (isConstant & !isSharedConstant);
@@ -2573,7 +2561,7 @@ void CSE_HeuristicParameterized::GetFeatures(CSEdsc* cse, double* features)
25732561 unsigned maxPostorderNum = 0 ;
25742562 BasicBlock* minPostorderBlock = nullptr ;
25752563 BasicBlock* maxPostorderBlock = nullptr ;
2576- for (treeStmtLst* treeList = cse->csdTreeList ; treeList != nullptr ; treeList = treeList->tslNext )
2564+ for (treeStmtLst* treeList = & cse->csdTreeList ; treeList != nullptr ; treeList = treeList->tslNext )
25772565 {
25782566 BasicBlock* const treeBlock = treeList->tslBlock ;
25792567 unsigned postorderNum = treeBlock->bbPostorderNum ;
@@ -2602,12 +2590,12 @@ void CSE_HeuristicParameterized::GetFeatures(CSEdsc* cse, double* features)
26022590
26032591 // More
26042592 //
2605- features[17 ] = booleanScale * ((cse->csdTree ->gtFlags & GTF_CALL) != 0 );
2593+ features[17 ] = booleanScale * ((cse->csdTreeList . tslTree ->gtFlags & GTF_CALL) != 0 );
26062594 features[18 ] = deMinimusAdj + log (max (deMinimis, cse->csdUseCount * cse->csdUseWtCnt ));
26072595 features[19 ] = deMinimusAdj + log (max (deMinimis, cse->numLocalOccurrences * cse->csdUseWtCnt ));
26082596 features[20 ] = booleanScale * ((double )(blockSpread) / numBBs);
26092597
2610- const bool isContainable = cse->csdTree ->OperIs (GT_ADD, GT_NOT, GT_MUL, GT_LSH);
2598+ const bool isContainable = cse->csdTreeList . tslTree ->OperIs (GT_ADD, GT_NOT, GT_MUL, GT_LSH);
26112599 features[21 ] = booleanScale * isContainable;
26122600 features[22 ] = booleanScale * (isContainable && isLowCost);
26132601
@@ -3172,7 +3160,7 @@ void CSE_HeuristicRLHook::GetFeatures(CSEdsc* cse, int* features)
31723160 unsigned maxPostorderNum = 0 ;
31733161 BasicBlock* minPostorderBlock = nullptr ;
31743162 BasicBlock* maxPostorderBlock = nullptr ;
3175- for (treeStmtLst* treeList = cse->csdTreeList ; treeList != nullptr ; treeList = treeList->tslNext )
3163+ for (treeStmtLst* treeList = & cse->csdTreeList ; treeList != nullptr ; treeList = treeList->tslNext )
31763164 {
31773165 BasicBlock* const treeBlock = treeList->tslBlock ;
31783166 unsigned postorderNum = treeBlock->bbPostorderNum ;
@@ -3232,13 +3220,13 @@ void CSE_HeuristicRLHook::GetFeatures(CSEdsc* cse, int* features)
32323220 features[i++] = type;
32333221 features[i++] = cse->IsViable () ? 1 : 0 ;
32343222 features[i++] = cse->csdLiveAcrossCall ? 1 : 0 ;
3235- features[i++] = cse->csdTree ->OperIsConst () ? 1 : 0 ;
3223+ features[i++] = cse->csdTreeList . tslTree ->OperIsConst () ? 1 : 0 ;
32363224 features[i++] = cse->csdIsSharedConst ? 1 : 0 ;
32373225 features[i++] = isMakeCse ? 1 : 0 ;
3238- features[i++] = ((cse->csdTree ->gtFlags & GTF_CALL) != 0 ) ? 1 : 0 ;
3239- features[i++] = cse->csdTree ->OperIs (GT_ADD, GT_NOT, GT_MUL, GT_LSH) ? 1 : 0 ;
3240- features[i++] = cse->csdTree ->GetCostEx ();
3241- features[i++] = cse->csdTree ->GetCostSz ();
3226+ features[i++] = ((cse->csdTreeList . tslTree ->gtFlags & GTF_CALL) != 0 ) ? 1 : 0 ;
3227+ features[i++] = cse->csdTreeList . tslTree ->OperIs (GT_ADD, GT_NOT, GT_MUL, GT_LSH) ? 1 : 0 ;
3228+ features[i++] = cse->csdTreeList . tslTree ->GetCostEx ();
3229+ features[i++] = cse->csdTreeList . tslTree ->GetCostSz ();
32423230 features[i++] = cse->csdUseCount ;
32433231 features[i++] = cse->csdDefCount ;
32443232 features[i++] = (int )cse->csdUseWtCnt ;
@@ -4271,7 +4259,7 @@ void CSE_Heuristic::SortCandidates()
42714259 for (unsigned cnt = 0 ; cnt < m_pCompiler->optCSECandidateCount ; cnt++)
42724260 {
42734261 CSEdsc* dsc = sortTab[cnt];
4274- GenTree* expr = dsc->csdTree ;
4262+ GenTree* expr = dsc->csdTreeList . tslTree ;
42754263
42764264 weight_t def;
42774265 weight_t use;
@@ -4281,13 +4269,13 @@ void CSE_Heuristic::SortCandidates()
42814269 {
42824270 def = dsc->csdDefCount ; // def count
42834271 use = dsc->csdUseCount ; // use count (excluding the implicit uses at defs)
4284- cost = dsc->csdTree ->GetCostSz ();
4272+ cost = dsc->csdTreeList . tslTree ->GetCostSz ();
42854273 }
42864274 else
42874275 {
42884276 def = dsc->csdDefWtCnt ; // weighted def count
42894277 use = dsc->csdUseWtCnt ; // weighted use count (excluding the implicit uses at defs)
4290- cost = dsc->csdTree ->GetCostEx ();
4278+ cost = dsc->csdTreeList . tslTree ->GetCostEx ();
42914279 }
42924280
42934281 if (!Compiler::Is_Shared_Const_CSE (dsc->csdHashKey ))
@@ -4840,7 +4828,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate)
48404828 ValueNum bestVN = ValueNumStore::NoVN;
48414829 bool bestIsDef = false ;
48424830 ssize_t bestConstValue = 0 ;
4843- treeStmtLst* lst = dsc->csdTreeList ;
4831+ treeStmtLst* lst = & dsc->csdTreeList ;
48444832
48454833 while (lst != nullptr )
48464834 {
@@ -4931,7 +4919,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate)
49314919 }
49324920 else // !isSharedConst
49334921 {
4934- lst = dsc->csdTreeList ;
4922+ lst = & dsc->csdTreeList ;
49354923 GenTree* firstTree = lst->tslTree ;
49364924 printf (" In %s, CSE (oper = %s, type = %s) has differing VNs: " , m_pCompiler->info .compFullName ,
49374925 GenTree::OpName (firstTree->OperGet ()), varTypeName (firstTree->TypeGet ()));
@@ -4956,7 +4944,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate)
49564944 ArrayStack<UseDefLocation> defUses (m_pCompiler->getAllocator (CMK_CSE));
49574945
49584946 // First process the defs.
4959- for (lst = dsc->csdTreeList ; lst != nullptr ; lst = lst->tslNext )
4947+ for (lst = & dsc->csdTreeList ; lst != nullptr ; lst = lst->tslNext )
49604948 {
49614949 GenTree* const exp = lst->tslTree ;
49624950 Statement* const stmt = lst->tslStmt ;
@@ -5065,7 +5053,7 @@ void CSE_HeuristicCommon::PerformCSE(CSE_Candidate* successfulCandidate)
50655053 }
50665054
50675055 // Now process the actual uses.
5068- for (lst = dsc->csdTreeList ; lst != nullptr ; lst = lst->tslNext )
5056+ for (lst = & dsc->csdTreeList ; lst != nullptr ; lst = lst->tslNext )
50695057 {
50705058 GenTree* const exp = lst->tslTree ;
50715059 Statement* const stmt = lst->tslStmt ;
0 commit comments