@@ -771,7 +771,7 @@ namespace IGC
771
771
return std::make_tuple (LHS, isSignedDst, true );
772
772
}
773
773
774
- bool CodeGenPatternMatch::MatchIntegerSatModifier (llvm::SelectInst& I) {
774
+ bool CodeGenPatternMatch::MatchIntegerTruncSatModifier (llvm::SelectInst& I) {
775
775
// Only match BYTE or WORD.
776
776
if (!I.getType ()->isIntegerTy (8 ) && !I.getType ()->isIntegerTy (16 ))
777
777
return false ;
@@ -947,8 +947,8 @@ namespace IGC
947
947
948
948
void CodeGenPatternMatch::visitSelectInst (SelectInst& I)
949
949
{
950
- bool match = MatchSatModifier (I) ||
951
- MatchIntegerSatModifier (I) ||
950
+ bool match = MatchFloatingPointSatModifier (I) ||
951
+ MatchIntegerTruncSatModifier (I) ||
952
952
MatchAbsNeg (I) ||
953
953
MatchFPToIntegerWithSaturation (I) ||
954
954
MatchMinMax (I) ||
@@ -1111,7 +1111,11 @@ namespace IGC
1111
1111
match = MatchSampleDerivative (*CI);
1112
1112
break ;
1113
1113
case GenISAIntrinsic::GenISA_fsat:
1114
- match = MatchSatModifier (I);
1114
+ match = MatchFloatingPointSatModifier (I);
1115
+ break ;
1116
+ case GenISAIntrinsic::GenISA_usat:
1117
+ case GenISAIntrinsic::GenISA_isat:
1118
+ match = MatchIntegerSatModifier (I);
1115
1119
break ;
1116
1120
case GenISAIntrinsic::GenISA_WaveShuffleIndex:
1117
1121
match = MatchRegisterRegion (*CI) ||
@@ -1205,7 +1209,7 @@ namespace IGC
1205
1209
break ;
1206
1210
case Intrinsic::maxnum:
1207
1211
case Intrinsic::minnum:
1208
- match = MatchSatModifier (I) ||
1212
+ match = MatchFloatingPointSatModifier (I) ||
1209
1213
MatchModifier (I);
1210
1214
break ;
1211
1215
default :
@@ -3079,12 +3083,13 @@ namespace IGC
3079
3083
return true ;
3080
3084
}
3081
3085
3082
- bool CodeGenPatternMatch::MatchSatModifier (llvm::Instruction& I)
3086
+ bool CodeGenPatternMatch::MatchFloatingPointSatModifier (llvm::Instruction& I)
3083
3087
{
3084
3088
struct SatPattern : Pattern
3085
3089
{
3086
3090
Pattern* pattern;
3087
3091
SSource source;
3092
+ bool isUnsigned;
3088
3093
virtual void Emit (EmitPass* pass, const DstModifier& modifier)
3089
3094
{
3090
3095
DstModifier mod = modifier;
@@ -3101,7 +3106,8 @@ namespace IGC
3101
3106
};
3102
3107
bool match = false ;
3103
3108
llvm::Value* source = nullptr ;
3104
- if (isSat (&I, source))
3109
+ bool isUnsigned = false ;
3110
+ if (isSat (&I, source, isUnsigned))
3105
3111
{
3106
3112
SatPattern* satPattern = new (m_allocator) SatPattern ();
3107
3113
if (llvm::Instruction * inst = llvm::dyn_cast<Instruction>(source))
@@ -3131,6 +3137,83 @@ namespace IGC
3131
3137
return match;
3132
3138
}
3133
3139
3140
+ bool CodeGenPatternMatch::MatchIntegerSatModifier (llvm::Instruction& I)
3141
+ {
3142
+ // a default pattern
3143
+ struct SatPattern : Pattern
3144
+ {
3145
+ Pattern* pattern;
3146
+ virtual void Emit (EmitPass* pass, const DstModifier& modifier)
3147
+ {
3148
+ DstModifier mod = modifier;
3149
+ mod.sat = true ;
3150
+ pattern->Emit (pass, mod);
3151
+ }
3152
+ };
3153
+
3154
+ // a special pattern is required because of the fact that the instruction works on unsigned values
3155
+ // whereas the default type is signed for arithmetic instructions
3156
+ struct UAddPattern : Pattern
3157
+ {
3158
+ BinaryOperator* inst;
3159
+
3160
+ virtual void Emit (EmitPass* pass, const DstModifier& modifier)
3161
+ {
3162
+ DstModifier mod = modifier;
3163
+ mod.sat = true ;
3164
+ pass->EmitUAdd (inst, modifier);
3165
+ }
3166
+ };
3167
+
3168
+ bool match = false ;
3169
+ llvm::Value* source = nullptr ;
3170
+ bool isUnsigned = false ;
3171
+ if (isSat (&I, source, isUnsigned))
3172
+ {
3173
+ IGC_ASSERT (llvm::isa<Instruction>(source));
3174
+
3175
+ // As an heuristic we only match saturate if the instruction has one use
3176
+ // to avoid duplicating expensive instructions and increasing reg pressure
3177
+ // without improve code quality this may be refined in the future
3178
+ if (llvm::Instruction* sourceInst = llvm::cast<llvm::Instruction>(source);
3179
+ sourceInst->hasOneUse () && SupportsSaturate (sourceInst))
3180
+ {
3181
+ if (llvm::BinaryOperator* binaryOpInst = llvm::dyn_cast<llvm::BinaryOperator>(source);
3182
+ binaryOpInst && (binaryOpInst->getOpcode () == llvm::BinaryOperator::BinaryOps::Add) && isUnsigned)
3183
+ {
3184
+ match = true ;
3185
+ UAddPattern* uAddPattern = new (m_allocator) UAddPattern ();
3186
+ uAddPattern->inst = binaryOpInst;
3187
+ AddPattern (uAddPattern);
3188
+ }
3189
+ else if (binaryOpInst && (binaryOpInst->getOpcode () == llvm::BinaryOperator::BinaryOps::Add) && !isUnsigned)
3190
+ {
3191
+ match = true ;
3192
+ SatPattern* satPattern = new (m_allocator) SatPattern ();
3193
+ satPattern->pattern = Match (*sourceInst);
3194
+ AddPattern (satPattern);
3195
+ }
3196
+ else if (llvm::GenIntrinsicInst * genIsaInst = llvm::dyn_cast<llvm::GenIntrinsicInst>(source);
3197
+ genIsaInst &&
3198
+ (genIsaInst->getIntrinsicID () == llvm::GenISAIntrinsic::ID::GenISA_dp4a_ss ||
3199
+ genIsaInst->getIntrinsicID () == llvm::GenISAIntrinsic::ID::GenISA_dp4a_su ||
3200
+ genIsaInst->getIntrinsicID () == llvm::GenISAIntrinsic::ID::GenISA_dp4a_uu ||
3201
+ genIsaInst->getIntrinsicID () == llvm::GenISAIntrinsic::ID::GenISA_dp4a_us))
3202
+ {
3203
+ match = true ;
3204
+ SatPattern* satPattern = new (m_allocator) SatPattern ();
3205
+ satPattern->pattern = Match (*sourceInst);
3206
+ AddPattern (satPattern);
3207
+ }
3208
+ else
3209
+ {
3210
+ IGC_ASSERT_MESSAGE (0 , " An undefined pattern match" );
3211
+ }
3212
+ }
3213
+ }
3214
+ return match;
3215
+ }
3216
+
3134
3217
bool CodeGenPatternMatch::MatchPredicate (llvm::SelectInst& I)
3135
3218
{
3136
3219
struct PredicatePattern : Pattern
@@ -4414,19 +4497,22 @@ namespace IGC
4414
4497
return false ;
4415
4498
}
4416
4499
4417
- bool isSat (llvm::Instruction* sat, llvm::Value*& source)
4500
+ bool isSat (llvm::Instruction* sat, llvm::Value*& source, bool & isUnsigned )
4418
4501
{
4419
4502
bool found = false ;
4420
4503
llvm::Value* sources[2 ] = { 0 };
4421
- bool typeMatch = sat->getType ()->isFloatingPointTy ();
4422
-
4504
+ bool floatMatch = sat->getType ()->isFloatingPointTy ();
4423
4505
GenIntrinsicInst* intrin = dyn_cast<GenIntrinsicInst>(sat);
4424
- if (intrin && intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_fsat)
4506
+ if (intrin &&
4507
+ (intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_fsat ||
4508
+ intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_usat ||
4509
+ intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_isat))
4425
4510
{
4426
4511
source = intrin->getOperand (0 );
4427
4512
found = true ;
4513
+ isUnsigned = intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_usat;
4428
4514
}
4429
- else if (typeMatch && isMax (sat, sources[0 ], sources[1 ]))
4515
+ else if (floatMatch && isMax (sat, sources[0 ], sources[1 ]))
4430
4516
{
4431
4517
for (int i = 0 ; i < 2 ; i++)
4432
4518
{
@@ -4441,6 +4527,7 @@ namespace IGC
4441
4527
{
4442
4528
found = true ;
4443
4529
source = maxSources[1 - j];
4530
+ isUnsigned = false ;
4444
4531
break ;
4445
4532
}
4446
4533
}
@@ -4449,7 +4536,7 @@ namespace IGC
4449
4536
}
4450
4537
}
4451
4538
}
4452
- else if (typeMatch && isMin (sat, sources[0 ], sources[1 ]))
4539
+ else if (floatMatch && isMin (sat, sources[0 ], sources[1 ]))
4453
4540
{
4454
4541
for (int i = 0 ; i < 2 ; i++)
4455
4542
{
@@ -4464,6 +4551,7 @@ namespace IGC
4464
4551
{
4465
4552
found = true ;
4466
4553
source = maxSources[1 - j];
4554
+ isUnsigned = false ;
4467
4555
break ;
4468
4556
}
4469
4557
}
0 commit comments