3
3
4
4
#include " jitpch.h"
5
5
6
- #if defined(TARGET_ARM64 )
6
+ #if defined(FEATURE_MASKED_HW_INTRINSICS )
7
7
8
8
struct MaskConversionsWeight
9
9
{
@@ -19,8 +19,13 @@ struct MaskConversionsWeight
19
19
// Conversion of mask to vector is one instruction.
20
20
static constexpr const weight_t costOfConvertMaskToVector = 1.0 ;
21
21
22
+ #if defined(TARGET_ARM64)
22
23
// Conversion of vector to mask is two instructions.
23
24
static constexpr const weight_t costOfConvertVectorToMask = 2.0 ;
25
+ #else
26
+ // Conversion of vector to mask is one instructions.
27
+ static constexpr const weight_t costOfConvertVectorToMask = 1.0 ;
28
+ #endif
24
29
25
30
// The simd types of the Lcl Store after conversion to vector.
26
31
CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF;
@@ -136,6 +141,7 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
136
141
switch ((*use)->OperGet ())
137
142
{
138
143
case GT_STORE_LCL_VAR:
144
+ {
139
145
isLocalStore = true ;
140
146
141
147
// Look for:
@@ -147,19 +153,48 @@ class MaskConversionsCheckVisitor final : public GenTreeVisitor<MaskConversionsC
147
153
hasConversion = true ;
148
154
}
149
155
break ;
156
+ }
150
157
151
158
case GT_LCL_VAR:
159
+ {
152
160
isLocalUse = true ;
153
161
154
162
// Look for:
155
- // user:ConvertVectorToMask(use:LCL_VAR(x)))
163
+ // user: ConvertVectorToMask(use:LCL_VAR(x)))
164
+ // -or-
165
+ // user: ConditionalSelect(use:LCL_VAR(x), y, z)
156
166
157
- if (user->OperIsConvertVectorToMask ())
167
+ if (user->OperIsHWIntrinsic ())
158
168
{
159
- convertOp = user->AsHWIntrinsic ();
160
- hasConversion = true ;
169
+ GenTreeHWIntrinsic* hwintrin = user->AsHWIntrinsic ();
170
+ NamedIntrinsic ni = hwintrin->GetHWIntrinsicId ();
171
+
172
+ if (hwintrin->OperIsConvertVectorToMask ())
173
+ {
174
+ convertOp = user->AsHWIntrinsic ();
175
+ hasConversion = true ;
176
+ }
177
+ else if (hwintrin->OperIsVectorConditionalSelect ())
178
+ {
179
+ // We don't actually have a convert here, but we do have a case where
180
+ // the mask is being used in a ConditionalSelect and therefore can be
181
+ // consumed directly as a mask. While the IR shows TYP_SIMD, it gets
182
+ // handled in lowering as part of the general embedded-mask support.
183
+
184
+ // We notably don't check that op2->isEmbeddedMaskingCompatibleHWIntrinsic()
185
+ // because we can still consume the mask directly in such cases. We'll just
186
+ // emit `vblendmps zmm1 {k1}, zmm2, zmm3` instead of containing the CndSel
187
+ // as part of something like `vaddps zmm1 {k1}, zmm2, zmm3`
188
+
189
+ if (hwintrin->Op (1 ) == (*use))
190
+ {
191
+ convertOp = user->AsHWIntrinsic ();
192
+ hasConversion = true ;
193
+ }
194
+ }
161
195
}
162
196
break ;
197
+ }
163
198
164
199
default :
165
200
break ;
@@ -254,6 +289,12 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
254
289
255
290
Compiler::fgWalkResult PostOrderVisit (GenTree** use, GenTree* user)
256
291
{
292
+ #if defined(TARGET_ARM64)
293
+ static constexpr const int ConvertVectorToMaskValueOp = 2 ;
294
+ #else
295
+ static constexpr const int ConvertVectorToMaskValueOp = 1 ;
296
+ #endif
297
+
257
298
GenTreeLclVarCommon* lclOp = nullptr ;
258
299
bool isLocalStore = false ;
259
300
bool isLocalUse = false ;
@@ -276,11 +317,12 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
276
317
isLocalStore = true ;
277
318
addConversion = true ;
278
319
}
279
- else if ((*use)->OperIsConvertVectorToMask () && (*use)->AsHWIntrinsic ()->Op (2 )->OperIs (GT_LCL_VAR))
320
+ else if ((*use)->OperIsConvertVectorToMask () &&
321
+ (*use)->AsHWIntrinsic ()->Op (ConvertVectorToMaskValueOp)->OperIs (GT_LCL_VAR))
280
322
{
281
323
// Found
282
324
// user(use:ConvertVectorToMask(LCL_VAR(x)))
283
- lclOp = (*use)->AsHWIntrinsic ()->Op (2 )->AsLclVarCommon ();
325
+ lclOp = (*use)->AsHWIntrinsic ()->Op (ConvertVectorToMaskValueOp )->AsLclVarCommon ();
284
326
isLocalUse = true ;
285
327
removeConversion = true ;
286
328
}
@@ -393,7 +435,7 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
393
435
MaskConversionsWeightTable* weightsTable;
394
436
};
395
437
396
- #endif // TARGET_ARM64
438
+ #endif // FEATURE_MASKED_HW_INTRINSICS
397
439
398
440
// ------------------------------------------------------------------------
399
441
// fgOptimizeMaskConversions: Allow locals to be of Mask type
@@ -445,7 +487,7 @@ class MaskConversionsUpdateVisitor final : public GenTreeVisitor<MaskConversions
445
487
//
446
488
PhaseStatus Compiler::fgOptimizeMaskConversions ()
447
489
{
448
- #if defined(TARGET_ARM64 )
490
+ #if defined(FEATURE_MASKED_HW_INTRINSICS )
449
491
450
492
if (opts.OptimizationDisabled ())
451
493
{
@@ -476,10 +518,10 @@ PhaseStatus Compiler::fgOptimizeMaskConversions()
476
518
{
477
519
for (Statement* const stmt : block->Statements ())
478
520
{
479
- // Only check statements where there is a local of type TYP_SIMD16 /TYP_MASK.
521
+ // Only check statements where there is a local of type TYP_SIMD /TYP_MASK.
480
522
for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList ())
481
523
{
482
- if (lcl-> TypeIs (TYP_SIMD16, TYP_MASK ))
524
+ if (varTypeIsSIMDOrMask (lcl ))
483
525
{
484
526
// Parse the entire statement.
485
527
MaskConversionsCheckVisitor ev (this , block->getBBWeight (this ), &weightsTable);
@@ -504,10 +546,10 @@ PhaseStatus Compiler::fgOptimizeMaskConversions()
504
546
{
505
547
for (Statement* const stmt : block->Statements ())
506
548
{
507
- // Only check statements where there is a local of type TYP_SIMD16 /TYP_MASK.
549
+ // Only check statements where there is a local of type TYP_SIMD /TYP_MASK.
508
550
for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList ())
509
551
{
510
- if (lcl-> TypeIs (TYP_SIMD16, TYP_MASK ))
552
+ if (varTypeIsSIMDOrMask (lcl ))
511
553
{
512
554
// Parse the entire statement.
513
555
MaskConversionsUpdateVisitor ev (this , stmt, &weightsTable);
@@ -524,8 +566,7 @@ PhaseStatus Compiler::fgOptimizeMaskConversions()
524
566
}
525
567
526
568
return PhaseStatus::MODIFIED_EVERYTHING;
527
-
528
569
#else
529
570
return PhaseStatus::MODIFIED_NOTHING;
530
- #endif // TARGET_ARM64
571
+ #endif // FEATURE_MASKED_HW_INTRINSICS
531
572
}
0 commit comments