Skip to content

Commit 0b34546

Browse files
krystian-andrzejewskisys_zuul
authored and
sys_zuul
committed
Introduction of new intrinsics to handle saturation modifier for some operations
Change-Id: I1ed63ceace5b48792d42cfe9c396c312bb8c624e
1 parent 931ea39 commit 0b34546

File tree

5 files changed

+132
-16
lines changed

5 files changed

+132
-16
lines changed

IGC/Compiler/CISACodeGen/EmitVISAPass.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,6 +1854,22 @@ void EmitPass::EmitMinMax(bool isMin, bool isUnsigned, const SSource sources[2],
18541854
EmitSimpleAlu(opCode, dst, srcs[0], srcs[1]);
18551855
}
18561856

1857+
void IGC::EmitPass::EmitUAdd(llvm::BinaryOperator* inst, const DstModifier& modifier)
1858+
{
1859+
// the emit function should be called only if saturation is enabled. In other case the signedness of
1860+
// the instruction doesn't play a role in case of computing the instruction.
1861+
IGC_ASSERT(modifier.sat == true);
1862+
CVariable* srcs[2] = { GetSymbol(inst->getOperand(0)), GetSymbol(inst->getOperand(1)) };
1863+
1864+
// create new aliases for the operands and the destination
1865+
srcs[0] = m_currShader->BitCast(srcs[0], GetUnsignedType(srcs[0]->GetType()));
1866+
srcs[1] = m_currShader->BitCast(srcs[1], GetUnsignedType(srcs[1]->GetType()));
1867+
CVariable* dst = m_currShader->BitCast(m_destination, GetUnsignedType(m_destination->GetType()));
1868+
m_encoder->SetDstModifier(modifier);
1869+
1870+
EmitSimpleAlu(EOPCODE::llvm_add, dst, srcs[0], srcs[1]);
1871+
}
1872+
18571873
void EmitPass::EmitFullMul32(bool isUnsigned, const SSource sources[2], const DstModifier& dstMod) {
18581874
CVariable* srcs[2] = { nullptr, nullptr };
18591875
srcs[0] = GetSrcVariable(sources[0]);

IGC/Compiler/CISACodeGen/EmitVISAPass.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class EmitPass : public llvm::FunctionPass
117117
void EmitSimpleAlu(EOPCODE opCode, const SSource source[2], const DstModifier& modifier);
118118
void EmitSimpleAlu(EOPCODE opCode, CVariable* dst, CVariable* src0, CVariable* src1);
119119
void EmitMinMax(bool isMin, bool isUnsigned, const SSource source[2], const DstModifier& modifier);
120+
void EmitUAdd(llvm::BinaryOperator* inst, const DstModifier& modifier);
120121
void EmitFullMul32(bool isUnsigned, const SSource srcs[2], const DstModifier& dstMod);
121122
void EmitFPToIntWithSat(bool isUnsigned, bool needBitCast, VISA_Type type, const SSource& source, const DstModifier& modifier);
122123
void EmitNoModifier(llvm::Instruction* inst);

IGC/Compiler/CISACodeGen/PatternMatchPass.cpp

Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

IGC/Compiler/CISACodeGen/PatternMatchPass.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ namespace IGC
204204

205205
Pattern* Match(llvm::Instruction& inst);
206206
bool MatchAbsNeg(llvm::Instruction& I);
207-
bool MatchSatModifier(llvm::Instruction& I);
207+
bool MatchFloatingPointSatModifier(llvm::Instruction& I);
208+
bool MatchIntegerSatModifier(llvm::Instruction& I);
208209
bool MatchPredicate(llvm::SelectInst& I);
209210
bool MatchSelectModifier(llvm::SelectInst& I);
210211
bool MatchPow(llvm::IntrinsicInst& I);
@@ -228,7 +229,7 @@ namespace IGC
228229
std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToIntegerSatWithExactConstant(llvm::CastInst* I);
229230
std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToSignedIntSatWithInexactConstant(llvm::SelectInst* I);
230231
std::tuple<llvm::Value*, unsigned, VISA_Type> isFPToUnsignedIntSatWithInexactConstant(llvm::SelectInst* I);
231-
bool MatchIntegerSatModifier(llvm::SelectInst& I);
232+
bool MatchIntegerTruncSatModifier(llvm::SelectInst& I);
232233
std::tuple<llvm::Value*, bool, bool> isIntegerSatTrunc(llvm::SelectInst*);
233234

234235
bool MatchSIToFPZExt(llvm::SIToFPInst* S2FI);
@@ -323,7 +324,7 @@ namespace IGC
323324
bool IsNegate(llvm::BinaryOperator& modifier, llvm::Value*& negateSource);
324325
bool IsZero(llvm::Value* v);
325326
bool isAbs(llvm::Value* abs, e_modifier& mod, llvm::Value*& source);
326-
bool isSat(llvm::Instruction* sat, llvm::Value*& source);
327+
bool isSat(llvm::Instruction* sat, llvm::Value*& source, bool& isUnsigned);
327328
bool isOne(llvm::Value* zero);
328329
bool isMinOrMax(llvm::Value* inst, llvm::Value*& source0, llvm::Value*& source1, bool& isMin, bool& isUnsigned);
329330
bool isCandidateForConstantPool(llvm::Value * val);

IGC/GenISAIntrinsics/Intrinsic_definitions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,16 @@
903903
[(0, "source")],
904904
"NoMem"]],
905905
####################################################################################################
906+
"GenISA_usat": ["",
907+
[("anyint", "result"),
908+
[(0, "source")],
909+
"NoMem"]],
910+
####################################################################################################
911+
"GenISA_isat": ["",
912+
[("anyint", "result"),
913+
[(0, "source")],
914+
"NoMem"]],
915+
####################################################################################################
906916
"GenISA_ftof_rte": ["",
907917
[("anyfloat", "result"),
908918
[("anyfloat", "input")],

0 commit comments

Comments
 (0)