@@ -118,8 +118,9 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
118
118
public:
119
119
enum
120
120
{
121
- DoPostOrder = true ,
122
- UseExecutionOrder = true
121
+ DoPreOrder = true ,
122
+ UseExecutionOrder = true ,
123
+ DoLclVarsOnly = true ,
123
124
};
124
125
125
126
MaskConversionsCheckVisitor (Compiler* compiler, weight_t bbWeight, MaskConversionsWeightTable* weightsTable)
@@ -129,16 +130,29 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
129
130
{
130
131
}
131
132
132
- Compiler::fgWalkResult PostOrderVisit (GenTree** use, GenTree* user)
133
+ Compiler::fgWalkResult PreOrderVisit (GenTree** use, GenTree* user)
133
134
{
135
+ GenTreeLclVarCommon* lclOp = (*use)->AsLclVarCommon ();
136
+ LclVarDsc* varDsc = m_compiler->lvaGetDesc (lclOp);
137
+
138
+ if (!varTypeIsSIMDOrMask (varDsc))
139
+ {
140
+ return fgWalkResult::WALK_CONTINUE;
141
+ }
142
+
143
+ // Get the existing weighting (if any).
144
+ MaskConversionsWeight* weight = weightsTable->LookupPointerOrAdd (lclOp->GetLclNum (), MaskConversionsWeight ());
145
+
146
+ JITDUMP (" %s V%02d at [%06u] " , GenTree::OpName (lclOp->gtOper ), lclOp->GetLclNum (),
147
+ m_compiler->dspTreeID (lclOp));
148
+
134
149
GenTreeHWIntrinsic* convertOp = nullptr ;
135
150
136
151
bool isLocalStore = false ;
137
152
bool isLocalUse = false ;
138
- bool isInvalid = false ;
139
153
bool hasConversion = false ;
140
154
141
- switch ((*use) ->OperGet ())
155
+ switch (lclOp ->OperGet ())
142
156
{
143
157
case GT_STORE_LCL_VAR:
144
158
{
@@ -147,9 +161,9 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
147
161
// Look for:
148
162
// use:STORE_LCL_VAR(ConvertMaskToVector(x))
149
163
150
- if ((*use)-> AsLclVar () ->Data ()->OperIsConvertMaskToVector ())
164
+ if (lclOp ->Data ()->OperIsConvertMaskToVector ())
151
165
{
152
- convertOp = (*use)-> AsLclVar () ->Data ()->AsHWIntrinsic ();
166
+ convertOp = lclOp ->Data ()->AsHWIntrinsic ();
153
167
hasConversion = true ;
154
168
}
155
169
break ;
@@ -164,7 +178,7 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
164
178
// -or-
165
179
// user: ConditionalSelect(use:LCL_VAR(x), y, z)
166
180
167
- if (user->OperIsHWIntrinsic ())
181
+ if ((user != nullptr ) && user->OperIsHWIntrinsic ())
168
182
{
169
183
GenTreeHWIntrinsic* hwintrin = user->AsHWIntrinsic ();
170
184
NamedIntrinsic ni = hwintrin->GetHWIntrinsicId ();
@@ -186,7 +200,7 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
186
200
// emit `vblendmps zmm1 {k1}, zmm2, zmm3` instead of containing the CndSel
187
201
// as part of something like `vaddps zmm1 {k1}, zmm2, zmm3`
188
202
189
- if (hwintrin->Op (1 ) == (*use) )
203
+ if (hwintrin->Op (1 ) == lclOp )
190
204
{
191
205
convertOp = user->AsHWIntrinsic ();
192
206
hasConversion = true ;
@@ -197,25 +211,19 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
197
211
}
198
212
199
213
default :
200
- break ;
214
+ // LCL_ADDR (can show up unexposed due to retbufs), or partial
215
+ // use/store. We do not handle these.
216
+ weight->InvalidateWeight ();
217
+ JITDUMP (" is unhandled. " );
218
+ return fgWalkResult::WALK_CONTINUE;
201
219
}
202
220
203
221
if (isLocalStore || isLocalUse)
204
222
{
205
- GenTreeLclVarCommon* lclOp = (*use)->AsLclVarCommon ();
206
- LclVarDsc* varDsc = m_compiler->lvaGetDesc (lclOp->GetLclNum ());
207
-
208
- // Get the existing weighting (if any).
209
- MaskConversionsWeight defaultWeight;
210
- MaskConversionsWeight* weight = weightsTable->LookupPointerOrAdd (lclOp->GetLclNum (), defaultWeight);
211
-
212
- JITDUMP (" Local %s V%02d at [%06u] " , isLocalStore ? " store" : " use" , lclOp->GetLclNum (),
213
- m_compiler->dspTreeID (lclOp));
214
-
215
223
// Cannot convert any locals with an exposed address.
216
224
if (varDsc->IsAddressExposed ())
217
225
{
218
- JITDUMP (" is address exposed elsewhere . " );
226
+ JITDUMP (" is address exposed. " );
219
227
weight->InvalidateWeight ();
220
228
return fgWalkResult::WALK_CONTINUE;
221
229
}
@@ -345,29 +353,34 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
345
353
assert (lclOp != nullptr );
346
354
347
355
// Get the existing weighting.
348
- MaskConversionsWeight weight;
349
- bool found = weightsTable->Lookup (lclOp->GetLclNum (), &weight);
350
- assert (found);
356
+ MaskConversionsWeight* weight = weightsTable->LookupPointer (lclOp->GetLclNum ());
357
+
358
+ if (weight == nullptr )
359
+ {
360
+ return fgWalkResult::WALK_CONTINUE;
361
+ }
351
362
352
363
// Quit if the cost of changing is higher or is invalid.
353
- if (weight. currentCost <= weight. switchCost || weight. invalid )
364
+ if (weight-> currentCost <= weight-> switchCost || weight-> invalid )
354
365
{
355
366
JITDUMP (" Local %s V%02d at [%06u] will not be converted. " , isLocalStore ? " store" : " use" ,
356
367
lclOp->GetLclNum (), Compiler::dspTreeID (lclOp));
357
- weight. DumpTotalWeight ();
368
+ weight-> DumpTotalWeight ();
358
369
return fgWalkResult::WALK_CONTINUE;
359
370
}
360
371
361
372
JITDUMP (" Local %s V%02d at [%06u] will be converted. " , isLocalStore ? " store" : " use" , lclOp->GetLclNum (),
362
373
Compiler::dspTreeID (lclOp));
363
- weight. DumpTotalWeight ();
374
+ weight-> DumpTotalWeight ();
364
375
365
376
// Fix up the type of the lcl and the lclvar.
366
377
assert (lclOp->gtType != TYP_MASK);
367
378
var_types lclOrigType = lclOp->gtType ;
368
379
lclOp->gtType = TYP_MASK;
369
- LclVarDsc* varDsc = m_compiler->lvaGetDesc (lclOp->GetLclNum ());
370
- varDsc->lvType = TYP_MASK;
380
+
381
+ LclVarDsc* varDsc = m_compiler->lvaGetDesc (lclOp->GetLclNum ());
382
+ assert (varTypeIsSIMDOrMask (varDsc));
383
+ varDsc->lvType = TYP_MASK;
371
384
372
385
// Add or remove a conversion
373
386
@@ -390,9 +403,9 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
390
403
391
404
// There is not enough information in the lcl to get simd types. Instead reuse the cached
392
405
// simd types from the removed convert nodes.
393
- assert (weight. simdBaseJitType != CORINFO_TYPE_UNDEF);
394
- lclOp->Data () = m_compiler->gtNewSimdCvtVectorToMaskNode (TYP_MASK, lclOp->Data (), weight. simdBaseJitType ,
395
- weight. simdSize );
406
+ assert (weight-> simdBaseJitType != CORINFO_TYPE_UNDEF);
407
+ lclOp->Data () = m_compiler->gtNewSimdCvtVectorToMaskNode (TYP_MASK, lclOp->Data (), weight-> simdBaseJitType ,
408
+ weight-> simdSize );
396
409
}
397
410
398
411
else if (isLocalUse && removeConversion)
@@ -414,9 +427,9 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
414
427
415
428
// There is not enough information in the lcl to get simd types. Instead reuse the cached simd
416
429
// types from the removed convert nodes.
417
- assert (weight. simdBaseJitType != CORINFO_TYPE_UNDEF);
430
+ assert (weight-> simdBaseJitType != CORINFO_TYPE_UNDEF);
418
431
*use =
419
- m_compiler->gtNewSimdCvtMaskToVectorNode (lclOrigType, lclOp, weight. simdBaseJitType , weight. simdSize );
432
+ m_compiler->gtNewSimdCvtMaskToVectorNode (lclOrigType, lclOp, weight-> simdBaseJitType , weight-> simdSize );
420
433
}
421
434
422
435
JITDUMP (" Updated %s V%02d at [%06u] to mask (%s conversion)\n " , isLocalStore ? " store" : " use" ,
@@ -521,7 +534,7 @@ PhaseStatus Compiler::fgOptimizeMaskConversions()
521
534
// Only check statements where there is a local of type TYP_SIMD/TYP_MASK.
522
535
for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList ())
523
536
{
524
- if (varTypeIsSIMDOrMask (lcl))
537
+ if (varTypeIsSIMDOrMask (lvaGetDesc ( lcl) ))
525
538
{
526
539
// Parse the entire statement.
527
540
MaskConversionsCheckVisitor ev (this , block->getBBWeight (this ), &weightsTable);
0 commit comments