@@ -771,7 +771,7 @@ namespace IGC
771771 return std::make_tuple (LHS, isSignedDst, true );
772772 }
773773
774- bool CodeGenPatternMatch::MatchIntegerSatModifier (llvm::SelectInst& I) {
774+ bool CodeGenPatternMatch::MatchIntegerTruncSatModifier (llvm::SelectInst& I) {
775775 // Only match BYTE or WORD.
776776 if (!I.getType ()->isIntegerTy (8 ) && !I.getType ()->isIntegerTy (16 ))
777777 return false ;
@@ -947,8 +947,8 @@ namespace IGC
947947
948948 void CodeGenPatternMatch::visitSelectInst (SelectInst& I)
949949 {
950- bool match = MatchSatModifier (I) ||
951- MatchIntegerSatModifier (I) ||
950+ bool match = MatchFloatingPointSatModifier (I) ||
951+ MatchIntegerTruncSatModifier (I) ||
952952 MatchAbsNeg (I) ||
953953 MatchFPToIntegerWithSaturation (I) ||
954954 MatchMinMax (I) ||
@@ -1111,7 +1111,11 @@ namespace IGC
11111111 match = MatchSampleDerivative (*CI);
11121112 break ;
11131113 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);
11151119 break ;
11161120 case GenISAIntrinsic::GenISA_WaveShuffleIndex:
11171121 match = MatchRegisterRegion (*CI) ||
@@ -1205,7 +1209,7 @@ namespace IGC
12051209 break ;
12061210 case Intrinsic::maxnum:
12071211 case Intrinsic::minnum:
1208- match = MatchSatModifier (I) ||
1212+ match = MatchFloatingPointSatModifier (I) ||
12091213 MatchModifier (I);
12101214 break ;
12111215 default :
@@ -3079,12 +3083,13 @@ namespace IGC
30793083 return true ;
30803084 }
30813085
3082- bool CodeGenPatternMatch::MatchSatModifier (llvm::Instruction& I)
3086+ bool CodeGenPatternMatch::MatchFloatingPointSatModifier (llvm::Instruction& I)
30833087 {
30843088 struct SatPattern : Pattern
30853089 {
30863090 Pattern* pattern;
30873091 SSource source;
3092+ bool isUnsigned;
30883093 virtual void Emit (EmitPass* pass, const DstModifier& modifier)
30893094 {
30903095 DstModifier mod = modifier;
@@ -3101,7 +3106,8 @@ namespace IGC
31013106 };
31023107 bool match = false ;
31033108 llvm::Value* source = nullptr ;
3104- if (isSat (&I, source))
3109+ bool isUnsigned = false ;
3110+ if (isSat (&I, source, isUnsigned))
31053111 {
31063112 SatPattern* satPattern = new (m_allocator) SatPattern ();
31073113 if (llvm::Instruction * inst = llvm::dyn_cast<Instruction>(source))
@@ -3131,6 +3137,83 @@ namespace IGC
31313137 return match;
31323138 }
31333139
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+
31343217 bool CodeGenPatternMatch::MatchPredicate (llvm::SelectInst& I)
31353218 {
31363219 struct PredicatePattern : Pattern
@@ -4414,19 +4497,22 @@ namespace IGC
44144497 return false ;
44154498 }
44164499
4417- bool isSat (llvm::Instruction* sat, llvm::Value*& source)
4500+ bool isSat (llvm::Instruction* sat, llvm::Value*& source, bool & isUnsigned )
44184501 {
44194502 bool found = false ;
44204503 llvm::Value* sources[2 ] = { 0 };
4421- bool typeMatch = sat->getType ()->isFloatingPointTy ();
4422-
4504+ bool floatMatch = sat->getType ()->isFloatingPointTy ();
44234505 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))
44254510 {
44264511 source = intrin->getOperand (0 );
44274512 found = true ;
4513+ isUnsigned = intrin->getIntrinsicID () == GenISAIntrinsic::GenISA_usat;
44284514 }
4429- else if (typeMatch && isMax (sat, sources[0 ], sources[1 ]))
4515+ else if (floatMatch && isMax (sat, sources[0 ], sources[1 ]))
44304516 {
44314517 for (int i = 0 ; i < 2 ; i++)
44324518 {
@@ -4441,6 +4527,7 @@ namespace IGC
44414527 {
44424528 found = true ;
44434529 source = maxSources[1 - j];
4530+ isUnsigned = false ;
44444531 break ;
44454532 }
44464533 }
@@ -4449,7 +4536,7 @@ namespace IGC
44494536 }
44504537 }
44514538 }
4452- else if (typeMatch && isMin (sat, sources[0 ], sources[1 ]))
4539+ else if (floatMatch && isMin (sat, sources[0 ], sources[1 ]))
44534540 {
44544541 for (int i = 0 ; i < 2 ; i++)
44554542 {
@@ -4464,6 +4551,7 @@ namespace IGC
44644551 {
44654552 found = true ;
44664553 source = maxSources[1 - j];
4554+ isUnsigned = false ;
44674555 break ;
44684556 }
44694557 }
0 commit comments