1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "BinaryEncodingIGA.h"
10 #include "GTGPU_RT_ASM_Interface.h"
11 #include "iga/IGALibrary/api/igaEncoderWrapper.hpp"
12 #include "Timer.h"
13 #include "BuildIR.h"
14 #include "Common_ISA_framework.h"
15
16 #include <map>
17 #include <utility>
18
19
20 using namespace iga;
21 using namespace vISA;
22
23 // all the gunk related to extended send descriptors
24 struct SendExDescOpts {
25 SendDesc exDesc;
26 int xlen = -1;
27 InstOptSet extraOpts;
28 };
29
30 class BinaryEncodingIGA
31 {
32 int IGAInstId = 0;
33 Mem_Manager& mem;
34 G4_Kernel& kernel;
35 std::string fileName;
36 Kernel* IGAKernel = nullptr;
37 const Model* platformModel;
38 const TARGET_PLATFORM platform;
39
40 public:
41 BinaryEncodingIGA(vISA::Mem_Manager &m, vISA::G4_Kernel& k, std::string fname);
~BinaryEncodingIGA()42 ~BinaryEncodingIGA() {delete IGAKernel;}
43
44 void SetSWSB(G4_INST * inst, SWSB & sw);
45
46 // translates and encodes (formerly "DoAll")
47 void Encode();
48
49 ///////////////////////////////////////////////////////////////////////////
50 // these function translate G4 IR to IGA IR
51 Instruction *translateInstruction(G4_INST *g4inst, Block*& bbNew);
52 void translateInstructionDst(G4_INST *g4inst, Instruction *igaInst);
53 void translateInstructionBranchSrcs(G4_INST *g4inst, Instruction *igaInst, Block*& bbNew);
54 void translateInstructionSrcs(G4_INST *g4inst, Instruction *igaInst);
55
56 void FixInst();
57 void *EmitBinary(size_t& binarySize);
58
59 private:
60 BinaryEncodingIGA(const BinaryEncodingIGA& other);
61 BinaryEncodingIGA& operator=(const BinaryEncodingIGA& other);
62
63 std::map<G4_Label*, Block*> labelToBlockMap;
64
65 public:
66 static ExecSize getIGAExecSize(int execSize);
67 static ChannelOffset getIGAChannelOffset(int offset);
68 static MaskCtrl getIGAMaskCtrl(bool noMask);
69 static RegName getIGAARFName(G4_ArchRegKind areg);
70 static Type getIGAType(G4_Type type, TARGET_PLATFORM genxPlatform);
71
72 /// getIGAInternalPlatform - a helper function to transform visa platform to iga platform
73 static Platform getIGAInternalPlatform(TARGET_PLATFORM genxPlatform);
74
75 static std::pair<const OpSpec *,Subfunction> getIgaOpInfo(
76 const G4_INST *inst, const Model *m, bool allowUnknownOp, const IR_Builder& builder);
77 private:
78 static PredCtrl getIGAPredCtrl(G4_Predicate_Control g4PredCntrl);
79 static Predication getIGAPredication(G4_Predicate* predG4);
getIGABranchCntrl(bool isOn)80 static BranchCntrl getIGABranchCntrl(bool isOn)
81 {
82 return isOn ? BranchCntrl::ON : BranchCntrl::OFF;
83 }
getIGADstModifier(bool sat)84 static DstModifier getIGADstModifier(bool sat)
85 {
86 return sat ? DstModifier::SAT : DstModifier::NONE;
87 }
88 static SrcModifier getIGASrcModifier(G4_SrcModifier srcMod);
89 static Region::Vert getIGAVert(int vstride);
90 static Region::Width getIGAWidth(int width);
91 static Region::Horz getIGAHorz(int hstride);
92 static Region getIGARegion(G4_SrcRegRegion* srcRegion, int srcPos);
93
getIGAImplAcc(G4_AccRegSel accSel) const94 MathMacroExt getIGAImplAcc(G4_AccRegSel accSel) const
95 {
96 switch (accSel)
97 {
98 case ACC2: return MathMacroExt::MME0;
99 case ACC3: return MathMacroExt::MME1;
100 case ACC4: return MathMacroExt::MME2;
101 case ACC5: return MathMacroExt::MME3;
102 case ACC6: return MathMacroExt::MME4;
103 case ACC7: return MathMacroExt::MME5;
104 case ACC8: return MathMacroExt::MME6;
105 case ACC9: return MathMacroExt::MME7;
106 case NOACC: return MathMacroExt::NOMME;
107 default:
108 assert(false && "illegal acc (mme) channel select");
109 return MathMacroExt::INVALID;
110 }
111 }
getIGAImmType(G4_Type type)112 ImmVal::Kind getIGAImmType(G4_Type type)
113 {
114 switch (type)
115 {
116 case Type_UW: return ImmVal::Kind::U16;
117 case Type_W: return ImmVal::Kind::S16;
118 case Type_UD: return ImmVal::Kind::U32;
119 case Type_D: return ImmVal::Kind::S32;
120 case Type_UQ: return ImmVal::Kind::U64;
121 case Type_Q: return ImmVal::Kind::S64;
122 case Type_HF: return ImmVal::Kind::F16;
123 case Type_F: return ImmVal::Kind::F32;
124 case Type_DF: return ImmVal::Kind::F64;
125 case Type_UV:
126 case Type_V:
127 case Type_VF: return ImmVal::Kind::U32;
128 default:
129 assert(false && "invalid immediate type");
130 return ImmVal::Kind::UNDEF;
131 }
132 }
133 InstOptSet getIGAInstOptSet(G4_INST* inst) const;
134
135 SendDesc getIGASendDesc(G4_INST* sendInst) const;
136 SendExDescOpts getIGASendExDesc(G4_INST* sendInst) const;
137 SendDesc encodeExDescImm(G4_INST* sendInst, SendExDescOpts &sdos) const;
138 SendDesc encodeExDescRegA0(G4_INST* sendInst, SendExDescOpts &sdos) const;
139
getIGARegName(G4_Operand * opnd) const140 RegName getIGARegName(G4_Operand* opnd) const
141 {
142 G4_VarBase *base = opnd->getBase();
143 assert(base != nullptr && "base should not be null");
144 if (base->isRegVar())
145 {
146 G4_VarBase *phyReg = base->asRegVar()->getPhyReg();
147 return phyReg->isAreg() ? getIGAARFName(phyReg->asAreg()->getArchRegType()) : RegName::GRF_R;
148 }
149 else
150 {
151 return base->isAreg() ? getIGAARFName(base->asAreg()->getArchRegType()) : RegName::GRF_R;
152 }
153 }
getIGARegRef(G4_Operand * opnd) const154 RegRef getIGARegRef(G4_Operand* opnd) const
155 {
156 RegRef regRef;
157 G4_VarBase *base = opnd->getBase();
158 assert(base != nullptr && "base should not be null");
159 if (base->isGreg())
160 {
161 uint32_t byteAddress = opnd->getLinearizedStart();
162 regRef.regNum = byteAddress / numEltPerGRF<Type_UB>();
163 regRef.subRegNum =
164 (byteAddress % numEltPerGRF<Type_UB>()) / opnd->getTypeSize();
165 }
166 else if (opnd->isSrcRegRegion())
167 {
168 bool valid, subvalid;
169 regRef.regNum = (uint8_t)opnd->asSrcRegRegion()->ExRegNum(valid);
170 regRef.subRegNum = (uint8_t)opnd->asSrcRegRegion()->ExSubRegNum(subvalid);
171 }
172 else
173 {
174 assert(opnd->isDstRegRegion() && "expect DstRegRegion");
175 bool valid, subvalid;
176 regRef.regNum = (uint8_t)opnd->asDstRegRegion()->ExRegNum(valid);
177 regRef.subRegNum = (uint8_t)opnd->asDstRegRegion()->ExSubRegNum(subvalid);
178 }
179 return regRef;
180 }
181
lookupIGABlock(G4_Label * label,Kernel & IGAKernel)182 Block *lookupIGABlock(G4_Label* label, Kernel& IGAKernel)
183 {
184 Block *b = nullptr;
185 auto itr = labelToBlockMap.find(label);
186 if (itr == labelToBlockMap.end())
187 {
188 b = IGAKernel.createBlock();
189 labelToBlockMap[label] = b;
190 }
191 else {
192 b = itr->second;
193 }
194 return b;
195 }
196
197 void getIGAFlagInfo(
198 G4_INST* inst,
199 const OpSpec* opSpec,
200 Subfunction sf,
201 Predication& pred,
202 FlagModifier& condMod,
203 RegRef& flagReg);
204
getIGAFlagReg(G4_VarBase * g4Base) const205 RegRef getIGAFlagReg(G4_VarBase* g4Base) const
206 {
207 RegRef reg = REGREF_INVALID;
208 bool flagRegNumValid = true;
209 reg.regNum = (uint8_t)g4Base->ExRegNum(flagRegNumValid);
210 ASSERT_USER(flagRegNumValid, "Unable to retrieve flag Reg Num for predicate or conditional modifier.");
211 reg.subRegNum = (uint8_t)g4Base->asRegVar()->getPhyRegOff();
212 return reg;
213 }
214
getIGAFlagModifier(G4_CondMod * cMod) const215 FlagModifier getIGAFlagModifier(G4_CondMod* cMod) const
216 {
217 if (cMod == nullptr)
218 {
219 return FlagModifier::NONE;
220 }
221
222 G4_CondModifier mod = cMod->getMod();
223 switch (mod)
224 {
225 case Mod_z: // fallthrough
226 case Mod_e: return FlagModifier::EQ;
227 case Mod_nz: // fallthrough
228 case Mod_ne: return FlagModifier::NE;
229 case Mod_g: return FlagModifier::GT;
230 case Mod_ge: return FlagModifier::GE;
231 case Mod_l: return FlagModifier::LT;
232 case Mod_le: return FlagModifier::LE;
233 case Mod_o: // fallthrough
234 case Mod_r: return FlagModifier::OV;
235 case Mod_u: return FlagModifier::UN;
236 default:
237 ASSERT_USER(false, "Invalid FlagModifier.");
238 return FlagModifier::NONE;
239 }
240 }
241
242 // get IGA type from GenPrecision
getIGAPrecisionType(GenPrecision p) const243 Type getIGAPrecisionType(GenPrecision p) const
244 {
245 switch (p)
246 {
247 case GenPrecision::U1: return Type::U1;
248 case GenPrecision::U2: return Type::U2;
249 case GenPrecision::U4: return Type::U4;
250 case GenPrecision::U8: return Type::UB;
251 case GenPrecision::S2: return Type::S2;
252 case GenPrecision::S4: return Type::S4;
253 case GenPrecision::S8: return Type::B;
254 case GenPrecision::FP16: return Type::HF;
255 case GenPrecision::BF16: return Type::BF;
256 case GenPrecision::BF8: return Type::BF8;
257 case GenPrecision::TF32: return Type::TF32;
258 default:
259 assert(false && "illegal Operand Precision");
260 return Type::INVALID;
261 }
262 }
263
getIGADpasType(G4_InstDpas * DpasInst,int SrcOprdIx) const264 Type getIGADpasType(G4_InstDpas* DpasInst, int SrcOprdIx) const
265 {
266 Type ty;
267 switch (SrcOprdIx) {
268 default:
269 MUST_BE_TRUE(false, "Invalid SrcOprdIx!");
270 break;
271 case 0:
272 {
273 G4_Operand* src0 = DpasInst->getSrc(0);
274 if (src0->isNullReg()) {
275 ty = getIGAType(DpasInst->getDst()->getType(), platform);
276 }
277 else
278 {
279 ty = getIGAType(src0->getType(), platform);
280 }
281 break;
282 }
283 case 1:
284 ty = getIGAPrecisionType(DpasInst->getSrc1Precision());
285 break;
286 case 2:
287 ty = getIGAPrecisionType(DpasInst->getSrc2Precision());
288 break;
289 }
290 return ty;
291 }
292
getIGADpasRegRef(G4_InstDpas * DpasInst,int SrcOprdIx) const293 RegRef getIGADpasRegRef(G4_InstDpas* DpasInst, int SrcOprdIx) const
294 {
295 G4_Operand* src = DpasInst->getSrc(SrcOprdIx);
296 RegRef regref = getIGARegRef(src);
297 if (SrcOprdIx == 2) {
298 // By default, subRegNum is in terms of operand's type (D/UD for
299 // dpas's src1/2). IGA needs it to be in terms of precision type.
300 // Note that no need to do it for src1 as it must be grf-aligned!
301 assert((regref.subRegNum % 2) == 0 &&
302 "Minimum alignemnt of dpas's src2 must be QW");
303 uint32_t bitOffsets = regref.subRegNum * src->getTypeSize() * 8;
304 uint32_t PBits = G4_InstDpas::GetPrecisionSizeInBits(DpasInst->getSrc2Precision());
305 regref.subRegNum = bitOffsets / PBits;
306 }
307 return regref;
308 }
309
getBfnFC(const G4_INST * inst)310 static BfnFC getBfnFC(const G4_INST *inst)
311 {
312 uint8_t funcCtrl = inst->asBfnInst()->getBooleanFuncCtrl();
313 return BfnFC(funcCtrl);
314 }
315 static iga::SFID getSFID(const G4_INST* inst);
316 static MathFC getMathFC(const G4_INST *inst);
317 Type getIGAType(const G4_INST* I, Gen4_Operand_Number O, TARGET_PLATFORM P);
318
319 void *m_kernelBuffer;
320 uint32_t m_kernelBufferSize;
321 }; // class BinaryEncodingIGA
322
323
getIGAInternalPlatform(TARGET_PLATFORM genxPlatform)324 Platform BinaryEncodingIGA::getIGAInternalPlatform(TARGET_PLATFORM genxPlatform)
325 {
326 Platform platform = Platform::INVALID;
327 switch (genxPlatform)
328 {
329 case GENX_BDW:
330 platform = Platform::GEN8;
331 break;
332 case GENX_CHV:
333 platform = Platform::GEN8;
334 break;
335 case GENX_SKL:
336 case GENX_BXT:
337 platform = Platform::GEN9;
338 break;
339 case GENX_ICLLP:
340 platform = Platform::GEN11;
341 break;
342 case GENX_TGLLP:
343 platform = Platform::XE;
344 break;
345 case XeHP_SDV:
346 platform = Platform::XE_HP;
347 break;
348 case GENX_DG2:
349 platform = Platform::XE_HPG;
350 break;
351 case GENX_PVC:
352 platform = Platform::XE_HPC;
353 break;
354 case GENX_PVCXT:
355 platform = Platform::XE_HPC;
356 break;
357 default:
358 break;
359 }
360
361 return platform;
362 }
363
BinaryEncodingIGA(vISA::Mem_Manager & m,vISA::G4_Kernel & k,std::string fname)364 BinaryEncodingIGA::BinaryEncodingIGA(
365 vISA::Mem_Manager &m,
366 vISA::G4_Kernel& k,
367 std::string fname)
368 : mem(m), kernel(k), fileName(fname), m_kernelBuffer(nullptr),
369 m_kernelBufferSize(0), platform(k.fg.builder->getPlatform())
370 {
371 platformModel = Model::LookupModel(getIGAInternalPlatform(getGenxPlatform()));
372 IGAKernel = new Kernel(*platformModel);
373 }
374
getIGAInstOptSet(G4_INST * inst) const375 InstOptSet BinaryEncodingIGA::getIGAInstOptSet(G4_INST* inst) const
376 {
377 InstOptSet options;
378
379 if (inst->isAccWrCtrlInst() && kernel.fg.builder->encodeAccWrEn())
380 {
381 options.add(InstOpt::ACCWREN);
382 }
383 if (inst->isAtomicInst())
384 {
385 options.add(InstOpt::ATOMIC);
386 }
387 if (inst->isBreakPointInst())
388 {
389 options.add(InstOpt::BREAKPOINT);
390 }
391 if (inst->isNoDDChkInst())
392 {
393 options.add(InstOpt::NODDCHK);
394 }
395 if (inst->isNoDDClrInst())
396 {
397 options.add(InstOpt::NODDCLR);
398 }
399 if (inst->isNoPreemptInst())
400 {
401 options.add(InstOpt::NOPREEMPT);
402 }
403 if (inst->isYieldInst())
404 {
405 options.add(InstOpt::SWITCH);
406 }
407 if (inst->isSend())
408 {
409 if (inst->isEOT())
410 {
411 options.add(InstOpt::EOT);
412 }
413 if (inst->isNoSrcDepSet())
414 {
415 options.add(InstOpt::NOSRCDEPSET);
416 }
417 if (inst->asSendInst()->isSerializedInst())
418 {
419 options.add(InstOpt::SERIALIZE);
420 }
421 }
422
423 // Force instruction to be compacted if InstOpt::COMPACTED is given
424 // even if autoCompact is not given to IGA
425 if (inst->isCompactedInst())
426 {
427 options.add(InstOpt::COMPACTED);
428 }
429
430 // Force instruction to be nocompacted
431 if (inst->isNoCompactedInst())
432 {
433 options.add(InstOpt::NOCOMPACT);
434 }
435
436 return options;
437 }
438
439
FixInst()440 void BinaryEncodingIGA::FixInst()
441 {
442 for (auto bb : kernel.fg)
443 {
444 for (auto iter = bb->begin(); iter != bb->end();)
445 {
446 G4_INST* inst = *iter;
447 if (inst->isIntrinsic())
448 {
449 // WA for simulation: remove any intrinsics that should be lowered before binary encoding
450 MUST_BE_TRUE(inst->asIntrinsicInst()->getLoweredByPhase() == Phase::BinaryEncoding,
451 "Unexpected intrinsics in binary encoding");
452 iter = bb->erase(iter);
453 }
454 else
455 {
456 ++iter;
457 }
458 }
459 }
460 }
461
getSFID(const G4_INST * inst)462 iga::SFID BinaryEncodingIGA::getSFID(const G4_INST *inst)
463 {
464 ASSERT_USER(inst->isSend(), "Only send has SFID");
465
466 G4_SendDesc *msgDesc = inst->getMsgDesc();
467 auto funcID = msgDesc->getSFID();
468
469 auto sfid = iga::SFID::INVALID;
470 switch (funcID)
471 {
472 case vISA::SFID::NULL_SFID: sfid = iga::SFID::NULL_; break;
473 case vISA::SFID::SAMPLER: sfid = iga::SFID::SMPL; break;
474 case vISA::SFID::GATEWAY: sfid = iga::SFID::GTWY; break;
475 case vISA::SFID::DP_DC2: sfid = iga::SFID::DC2; break;
476 case vISA::SFID::DP_WRITE: sfid = iga::SFID::RC; break;
477 case vISA::SFID::URB: sfid = iga::SFID::URB; break;
478 case vISA::SFID::SPAWNER: sfid = iga::SFID::TS; break;
479 case vISA::SFID::VME: sfid = iga::SFID::VME; break;
480 case vISA::SFID::DP_CC: sfid = iga::SFID::DCRO; break;
481 case vISA::SFID::DP_DC0: sfid = iga::SFID::DC0; break;
482 case vISA::SFID::DP_PI: sfid = iga::SFID::PIXI; break;
483 case vISA::SFID::DP_DC1: sfid = iga::SFID::DC1; break;
484 case vISA::SFID::CRE: sfid = iga::SFID::CRE; break;
485 case vISA::SFID::SLM: sfid = iga::SFID::SLM; break;
486 case vISA::SFID::UGM: sfid = iga::SFID::UGM; break;
487 case vISA::SFID::BTD: sfid = iga::SFID::BTD; break;
488 case vISA::SFID::RTHW: sfid = iga::SFID::RTA; break;
489 case vISA::SFID::TGM: sfid = iga::SFID::TGM; break;
490 case vISA::SFID::UGML: sfid = iga::SFID::UGML; break;
491 default:
492 ASSERT_USER(false, "Unknow SFID generated from vISA");
493 break;
494 }
495
496 return sfid;
497 }
getMathFC(const G4_INST * inst)498 MathFC BinaryEncodingIGA::getMathFC(const G4_INST *inst)
499 {
500 G4_MathOp mathControlValue = inst->asMathInst()->getMathCtrl();
501
502 switch (mathControlValue)
503 {
504 case MATH_INV: return MathFC::INV;
505 case MATH_LOG: return MathFC::LOG;
506 case MATH_EXP: return MathFC::EXP;
507 case MATH_SQRT: return MathFC::SQT;
508 case MATH_RSQ: return MathFC::RSQT;
509 case MATH_SIN: return MathFC::SIN;
510 case MATH_COS: return MathFC::COS;
511 case MATH_FDIV: return MathFC::FDIV;
512 case MATH_POW: return MathFC::POW;
513 case MATH_INT_DIV: return MathFC::IDIV;
514 case MATH_INT_DIV_QUOT: return MathFC::IQOT;
515 case MATH_INT_DIV_REM: return MathFC::IREM;
516 case MATH_INVM: return MathFC::INVM;
517 case MATH_RSQRTM: return MathFC::RSQTM;
518 default:
519 ASSERT_USER(false, "invalid math subfunction");
520 return MathFC::INVALID;
521 }
522 }
523
524
525 //
526 // Return the IGA op for the given vISA instruction <op> for platform p.
527 // <inst> is sometimes necessary to compute the subopcode (e.g., send)
528 // As vISA may call this function to access instruction properties such as
529 // saturation and conditional modifier and this may happen before all pseudo
530 // opperations are lowered, <allowUnknownOp> may be used to suppress assert;
531 // an invalid will be returned in this case.
532 //
getIgaOpInfo(const G4_INST * inst,const Model * m,bool allowUnknownOp,const IR_Builder & builder)533 std::pair<const OpSpec *,Subfunction> BinaryEncodingIGA::getIgaOpInfo(
534 const G4_INST *inst, const Model *m, bool allowUnknownOp, const IR_Builder& builder)
535 {
536 Platform p = m->platform;
537 Op igaOp = Op::INVALID;
538 Subfunction sf = InvalidFC::INVALID;
539 switch (inst->opcode())
540 {
541 case G4_illegal: igaOp = Op::ILLEGAL; break;
542 case G4_mov: igaOp = Op::MOV; break;
543 case G4_sel: igaOp = Op::SEL; break;
544 case G4_movi: igaOp = Op::MOVI; break;
545 case G4_not: igaOp = Op::NOT; break;
546 case G4_and: igaOp = Op::AND; break;
547 case G4_or: igaOp = Op::OR; break;
548 case G4_xor: igaOp = Op::XOR; break;
549 case G4_shr: igaOp = Op::SHR; break;
550 case G4_shl: igaOp = Op::SHL; break;
551 case G4_smov: igaOp = Op::SMOV; break;
552 case G4_asr: igaOp = Op::ASR; break;
553 case G4_ror: igaOp = Op::ROR; break;
554 case G4_rol: igaOp = Op::ROL; break;
555 case G4_cmp: igaOp = Op::CMP; break;
556 case G4_cmpn: igaOp = Op::CMPN; break;
557 case G4_csel: igaOp = Op::CSEL; break;
558 case G4_bfrev: igaOp = Op::BFREV; break;
559 case G4_bfe: igaOp = Op::BFE; break;
560 case G4_bfi1: igaOp = Op::BFI1; break;
561 case G4_bfi2: igaOp = Op::BFI2; break;
562 case G4_jmpi: igaOp = Op::JMPI; break;
563 case G4_brd: igaOp = Op::BRD; break;
564 case G4_if: igaOp = Op::IF; break;
565 case G4_brc: igaOp = Op::BRC; break;
566 case G4_else: igaOp = Op::ELSE; break;
567 case G4_endif: igaOp = Op::ENDIF; break;
568 case G4_while: igaOp = Op::WHILE; break;
569 case G4_break: igaOp = Op::BREAK; break;
570 case G4_cont: igaOp = Op::CONT; break;
571 case G4_halt: igaOp = Op::HALT; break;
572 case G4_call:
573 {
574 igaOp = Op::CALL;
575 // check if we're using calla for indirect call
576 if (builder.supportCallaRegSrc()) {
577 // check if we're doing indiret call
578 if (inst->getSrc(0)->isGreg() || inst->getSrc(0)->isA0())
579 igaOp = Op::CALLA;
580 }
581 break;
582 }
583 case G4_return: igaOp = Op::RET; break;
584 case G4_goto: igaOp = Op::GOTO; break;
585 case G4_join: igaOp = Op::JOIN; break;
586 case G4_wait:
587 if (p >= Platform::XE)
588 {
589 igaOp = Op::SYNC;
590 sf = SyncFC::BAR;
591 }
592 else
593 {
594 igaOp = Op::WAIT;
595 }
596 break;
597 case G4_send:
598 igaOp = Op::SEND;
599 sf = getSFID(inst);
600 break;
601 case G4_sendc:
602 igaOp = Op::SENDC;
603 sf = getSFID(inst);
604 break;
605 case G4_sends:
606 sf = getSFID(inst);
607 if (p >= Platform::XE) {
608 // G4 IR still calls send sends after Xe
609 igaOp = Op::SEND;
610 } else {
611 igaOp = Op::SENDS;
612 }
613 break;
614 case G4_sendsc:
615 sf = getSFID(inst);
616 if (p >= Platform::XE) {
617 // G4 IR still calls send sends after Xe
618 igaOp = Op::SENDC;
619 } else {
620 igaOp = Op::SENDSC;
621 }
622 break;
623 case G4_math:
624 sf = getMathFC(inst);
625 igaOp = Op::MATH;
626 break;
627 case G4_add: igaOp = Op::ADD; break;
628 case G4_mul: igaOp = Op::MUL; break;
629 case G4_avg: igaOp = Op::AVG; break;
630 case G4_frc: igaOp = Op::FRC; break;
631 case G4_rndu: igaOp = Op::RNDU; break;
632 case G4_rndd: igaOp = Op::RNDD; break;
633 case G4_rnde: igaOp = Op::RNDE; break;
634 case G4_rndz: igaOp = Op::RNDZ; break;
635 case G4_mac: igaOp = Op::MAC; break;
636 case G4_mach:
637 igaOp = Op::MACH;
638 if (inst->getPlatform() >= GENX_PVC && !inst->isAccWrCtrlInst())
639 {
640 igaOp = Op::MACL;
641 }
642 break;
643 case G4_lzd: igaOp = Op::LZD; break;
644 case G4_fbh: igaOp = Op::FBH; break;
645 case G4_fbl: igaOp = Op::FBL; break;
646 case G4_cbit: igaOp = Op::CBIT; break;
647 case G4_addc: igaOp = Op::ADDC; break;
648 case G4_subb: igaOp = Op::SUBB; break;
649 case G4_sad2: igaOp = Op::SAD2; break;
650 case G4_sada2: igaOp = Op::SADA2; break;
651 case G4_dp4: igaOp = Op::DP4; break;
652 case G4_dph: igaOp = Op::DPH; break;
653 case G4_dp3: igaOp = Op::DP3; break;
654 case G4_dp2: igaOp = Op::DP2; break;
655 case G4_dp4a: igaOp = Op::DP4A; break;
656 case G4_dpas:
657 case G4_dpasw:
658 {
659 igaOp = inst->opcode() == G4_dpasw ? Op::DPASW : Op::DPAS;
660 G4_InstDpas* dpasInst = inst->asDpasInst();
661 uint8_t D = dpasInst->getSystolicDepth();
662 uint8_t C = dpasInst->getRepeatCount();
663 sf = GetDpasFC(D, C);
664 break;
665 }
666 case G4_add3: igaOp = Op::ADD3; break;
667 case G4_bfn:
668 igaOp = Op::BFN;
669 sf = getBfnFC(inst);
670 break;
671 case G4_line: igaOp = Op::LINE; break;
672 case G4_pln: igaOp = Op::PLN; break;
673 case G4_mad: igaOp = Op::MAD; break;
674 case G4_lrp: igaOp = Op::LRP; break;
675 case G4_madm: igaOp = Op::MADM; break;
676 case G4_nop: igaOp = Op::NOP; break;
677 case G4_label:
678 break;
679 case G4_pseudo_mad: igaOp = Op::MAD; break;
680 case G4_do:
681 ASSERT_USER(!allowUnknownOp, "G4_do is not GEN ISA OPCODE.");
682 break;
683 case G4_pseudo_and: igaOp = Op::AND; break;
684 case G4_pseudo_or: igaOp = Op::OR; break;
685 case G4_pseudo_xor: igaOp = Op::XOR; break;
686 case G4_pseudo_not: igaOp = Op::NOT; break;
687 case G4_pseudo_fcall: igaOp = Op::CALL; break;
688 case G4_pseudo_fret: igaOp = Op::RET; break;
689 case G4_pseudo_sada2: igaOp = Op::SADA2; break;
690 case G4_pseudo_exit:
691 ASSERT_USER(!allowUnknownOp, "G4_pseudo_exit not GEN ISA OPCODE.");
692 break;
693 case G4_pseudo_fc_call: igaOp = Op::CALL; break;
694 case G4_pseudo_fc_ret: igaOp = Op::RET; break;
695 case G4_intrinsic:
696 ASSERT_USER(!allowUnknownOp, "G4_intrinsic not GEN ISA OPCODE.");
697 break;
698 case G4_sync_nop:
699 igaOp = Op::SYNC;
700 sf = SyncFC::NOP;
701 break;
702 case G4_sync_allrd:
703 igaOp = Op::SYNC;
704 sf = SyncFC::ALLRD;
705 break;
706 case G4_sync_allwr:
707 igaOp = Op::SYNC;
708 sf = SyncFC::ALLWR;
709 break;
710 case G4_sync_fence:
711 igaOp = Op::SYNC;
712 sf = SyncFC::FENCE;
713 break;
714 case G4_fcvt:
715 igaOp = Op::MOV;
716 break;
717 case G4_srnd: igaOp = Op::SRND; break;
718 case G4_NUM_OPCODE:
719 assert(false);
720 break;
721 case G4_mulh:
722 ASSERT_USER(!allowUnknownOp, "G4_mulh is not GEN ISA OPCODE.");
723 break;
724 case G4_madw:
725 ASSERT_USER(!allowUnknownOp, "G4_madw not GEN ISA OPCODE.");
726 break;
727 default:
728 ASSERT_USER(!allowUnknownOp, "INVALID opcode.");
729 break;
730 }
731 const OpSpec *os = &m->lookupOpSpec(igaOp);
732 return std::pair<const OpSpec *,Subfunction>(os, sf);
733 }
734
SetSWSB(G4_INST * inst,SWSB & sw)735 void BinaryEncodingIGA::SetSWSB(G4_INST *inst, SWSB &sw)
736 {
737 // Set token, e.g. $0
738 using SWSBTokenType = vISA::G4_INST::SWSBTokenType;
739 if (inst->tokenHonourInstruction() && (inst->getTokenType() == SWSBTokenType::SB_SET))
740 {
741 sw.tokenType = SWSB::TokenType::SET;
742 sw.sbid = inst->getToken();
743 }
744
745 if (inst->opcode() == G4_mad && inst->hasNoACCSBSet())
746 {
747 sw.spToken = SWSB::SpecialToken::NOACCSBSET;
748 }
749 // Set distance, e.g. A@1
750 using DistanceType = vISA::G4_INST::DistanceType;
751 if ((unsigned)inst->getDistance())
752 {
753 // check the distance type for multi-dist-pipes
754 if (kernel.fg.builder->hasThreeALUPipes() ||
755 kernel.fg.builder->hasFourALUPipes()) {
756 switch (inst->getDistanceTypeXe())
757 {
758 case DistanceType::DIST:
759 sw.distType = SWSB::DistType::REG_DIST;
760 break;
761 case DistanceType::DISTALL:
762 sw.distType = SWSB::DistType::REG_DIST_ALL;
763 break;
764 case DistanceType::DISTINT:
765 sw.distType = SWSB::DistType::REG_DIST_INT;
766 break;
767 case DistanceType::DISTFLOAT:
768 sw.distType = SWSB::DistType::REG_DIST_FLOAT;
769 break;
770 case DistanceType::DISTLONG:
771 sw.distType = SWSB::DistType::REG_DIST_LONG;
772 break;
773 case DistanceType::DISTMATH:
774 sw.distType = SWSB::DistType::REG_DIST_MATH;
775 break;
776 default:
777 break;
778 }
779 }
780 else
781 {
782 // there is only one pipe on single-dist-pipe platform,
783 // must be REG_DIST
784 sw.distType = SWSB::DistType::REG_DIST;
785 }
786 sw.minDist = (uint32_t)inst->getDistance();
787 }
788
789 // Set token dependency, e.g. $1.src
790 if (inst->getTokenType() == SWSBTokenType::AFTER_READ ||
791 inst->getTokenType() == SWSBTokenType::AFTER_WRITE)
792 {
793 uint8_t token = (uint8_t)inst->getToken();
794 if (inst->getTokenType() == SWSBTokenType::AFTER_READ)
795 {
796 sw.tokenType = SWSB::TokenType::SRC;
797 }
798 else if (inst->getTokenType() == SWSBTokenType::AFTER_WRITE)
799 {
800 sw.tokenType = SWSB::TokenType::DST;
801 }
802 sw.sbid = token;
803 }
804 return;
805 }
806
getIGAFlagInfo(G4_INST * inst,const OpSpec * opSpec,Subfunction sf,Predication & pred,FlagModifier & condMod,RegRef & flagReg)807 void BinaryEncodingIGA::getIGAFlagInfo(
808 G4_INST* inst,
809 const OpSpec* opSpec,
810 Subfunction sf,
811 Predication& pred,
812 FlagModifier& condMod,
813 RegRef& flagReg)
814 {
815 G4_Predicate* predG4 = inst->getPredicate();
816 G4_CondMod* condModG4 = inst->getCondMod();
817 RegRef predFlag;
818 bool hasPredFlag = false;
819
820 if (opSpec->supportsPredication() && predG4 != nullptr)
821 {
822 pred = getIGAPredication(predG4);
823 predFlag = getIGAFlagReg(predG4->getBase());
824 flagReg = predFlag;
825 hasPredFlag = true;
826 }
827
828 bool hasImplicitModifier =
829 opSpec->is(Op::MATH) && IsMacro(sf.math);
830
831 if ((opSpec->supportsFlagModifier() || hasImplicitModifier) &&
832 condModG4 != nullptr)
833 {
834 condMod = getIGAFlagModifier(condModG4);
835 // in case for min/max sel instruction, it could have CondMod but has no flag registers
836 if (condModG4->getBase() != nullptr) {
837 flagReg = getIGAFlagReg(condModG4->getBase());
838 // pred and condMod Flags must be the same
839 assert(!hasPredFlag || predFlag == flagReg);
840 }
841 }
842 }
843
844 #if 0
845 static void DebugCaching(G4_Kernel &kernel)
846 {
847 std::map<uint32_t,std::pair<Caching,Caching>> descs;
848 for (auto bb : kernel.fg) {
849 for (auto inst : *bb)
850 {
851 if (inst->isSend()) {
852 G4_SendDescRaw *sd = inst->getMsgDescRaw();
853 if (sd) {
854 descs[sd->getDesc()] = sd->getCaching();
855 }
856 }
857 }
858 }
859 for (const auto &p : descs) {
860 std::cerr << std::hex << "0x" << p.first <<
861 " ===>"
862 " L1=" << std::dec << int(p.second.first) <<
863 " L3=" << std::dec << int(p.second.second) <<
864 "\n";
865 }
866 }
867 #endif
868
Encode()869 void BinaryEncodingIGA::Encode()
870 {
871 // DebugCaching(this->kernel);
872
873 FixInst();
874 Block* currBB = nullptr;
875
876 auto isFirstInstLabel = [this]()
877 {
878 for (auto bb : kernel.fg)
879 {
880 for (auto inst : *bb)
881 {
882 return inst->isLabel();
883 }
884 }
885 return false;
886 };
887
888 // Make the size of the first BB be multiple of 4 instructions, and do not compact
889 // any instructions in it, so that the size of the first BB is multiple of 64 bytes
890 if (kernel.hasPerThreadPayloadBB() || kernel.hasComputeFFIDProlog())
891 {
892 G4_BB* first_bb = *kernel.fg.begin();
893 size_t num_inst = first_bb->size();
894 assert(num_inst != 0 && "the first BB must not be empty");
895 // label instructions don't count. Only the first instruction could be a label
896 if (first_bb->front()->isLabel())
897 --num_inst;
898
899 if (num_inst % 4 != 0) {
900 size_t num_nop = 4 - (num_inst % 4);
901 for (size_t i = 0; i < num_nop; ++i)
902 first_bb->push_back(
903 kernel.fg.builder->createNop(InstOpt_NoCompact));
904 }
905 // set all instruction to be NoCompact
906 for (auto inst : *first_bb)
907 {
908 inst->setOptionOn(InstOpt_NoCompact);
909 }
910 }
911
912 if (!isFirstInstLabel())
913 {
914 // create a new BB if kernel does not start with label
915 currBB = IGAKernel->createBlock();
916 IGAKernel->appendBlock(currBB);
917 }
918
919 std::list<std::pair<Instruction*, G4_INST*>> encodedInsts;
920 Block *bbNew = nullptr;
921 for (auto bb : this->kernel.fg)
922 {
923 for (auto inst : *bb)
924 {
925 bbNew = nullptr;
926 if (inst->isLabel())
927 {
928 // note that we create a new IGA BB per label instead of directly mapping vISA BB to IGA BB,
929 // as some vISA BBs can have multiple labels (e.g., multiple endifs)
930 G4_Label* label = inst->getLabel();
931 currBB = lookupIGABlock(label, *IGAKernel);
932 IGAKernel->appendBlock(currBB);
933 continue;
934 }
935
936 Instruction *igaInst = translateInstruction(inst, bbNew);
937 if (!igaInst) {
938 // assertion failure already reported
939 continue;
940 }
941
942 igaInst->addInstOpts(getIGAInstOptSet(inst));
943
944 if (getPlatformGeneration(platform) >= PlatformGen::XE) {
945 SWSB sw;
946 SetSWSB(inst, sw);
947
948 SWSB::InstType instTy = SWSB::InstType::UNKNOWN;
949 if (inst->isMathPipeInst())
950 instTy = SWSB::InstType::MATH;
951 else if (inst->isDpas())
952 instTy = SWSB::InstType::DPAS;
953 else if (inst->isSend())
954 instTy = SWSB::InstType::SEND;
955 else
956 instTy = SWSB::InstType::OTHERS;
957
958 // Verify if swsb is in encode-able dist and token combination
959 if (!sw.verify(GetIGASWSBEncodeMode(*kernel.fg.builder), instTy))
960 IGA_ASSERT_FALSE("Invalid swsb dist and token combination");
961 igaInst->setSWSB(sw);
962 }
963
964 #if _DEBUG
965 igaInst->validate();
966 #endif
967 currBB->appendInstruction(igaInst);
968
969 if (bbNew)
970 {
971 // Fall through block is created.
972 // So the new block needs to become current block
973 // so that jump offsets can be calculated correctly
974 currBB = bbNew;
975 }
976 // If, in future, we generate multiple binary inst
977 // for a single G4_INST, then it should be safe to
978 // make pair between the G4_INST and first encoded
979 // binary inst.
980 encodedInsts.push_back(std::make_pair(igaInst, inst));
981 }
982 }
983
984 kernel.setAsmCount(IGAInstId);
985
986 if (m_kernelBuffer)
987 {
988 m_kernelBufferSize = 0;
989 delete static_cast<uint8_t*>(m_kernelBuffer);
990 m_kernelBuffer = nullptr;
991 }
992
993
994 { // time the encoding
995 TIME_SCOPE(IGA_ENCODER);
996 bool autoCompact = kernel.getOption(vISA_Compaction);
997 if (platform == GENX_PVC)
998 autoCompact = false; // PVC-A0 compaction is off (IGA only does B0+)
999
1000 KernelEncoder encoder(IGAKernel, autoCompact);
1001 encoder.setSWSBEncodingMode(GetIGASWSBEncodeMode(*kernel.fg.builder));
1002
1003 if (kernel.getOption(vISA_EnableIGASWSB))
1004 {
1005 encoder.enableIGAAutoDeps();
1006 }
1007
1008 encoder.encode();
1009
1010 m_kernelBufferSize = encoder.getBinarySize();
1011 m_kernelBuffer = allocCodeBlock(m_kernelBufferSize);
1012 memcpy_s(m_kernelBuffer, m_kernelBufferSize, encoder.getBinary(), m_kernelBufferSize);
1013 }
1014
1015 // encodedPC is available after encoding
1016 for (auto&& inst : encodedInsts)
1017 {
1018 inst.second->setGenOffset(inst.first->getPC());
1019 }
1020 if (kernel.hasPerThreadPayloadBB())
1021 {
1022 kernel.fg.builder->getJitInfo()->offsetToSkipPerThreadDataLoad =
1023 kernel.getPerThreadNextOff();
1024 }
1025 if (kernel.hasCrossThreadPayloadBB())
1026 {
1027 kernel.fg.builder->getJitInfo()->offsetToSkipCrossThreadDataLoad =
1028 kernel.getCrossThreadNextOff();
1029 }
1030 if (kernel.hasComputeFFIDProlog())
1031 {
1032 // something weird will happen if kernel has both PerThreadProlog and ComputeFFIDProlog
1033 assert(!kernel.hasPerThreadPayloadBB() && !kernel.hasCrossThreadPayloadBB());
1034 kernel.fg.builder->getJitInfo()->offsetToSkipSetFFIDGP =
1035 kernel.getComputeFFIDGPNextOff();
1036 kernel.fg.builder->getJitInfo()->offsetToSkipSetFFIDGP1 =
1037 kernel.getComputeFFIDGP1NextOff();
1038 }
1039 }
1040
translateInstruction(G4_INST * g4inst,Block * & bbNew)1041 Instruction *BinaryEncodingIGA::translateInstruction(
1042 G4_INST *g4inst, Block*& bbNew)
1043 {
1044 Instruction *igaInst = nullptr;
1045 auto opinfo = getIgaOpInfo(g4inst, platformModel, false, *kernel.fg.builder);
1046 // common fields: op, predicate, flag reg, exec size, exec mask offset,
1047 // mask ctrl, conditional modifier
1048 const OpSpec* opSpec = opinfo.first;
1049 if (opSpec == nullptr || !opSpec->isValid())
1050 {
1051 std::cerr << "INVALID opcode " << G4_Inst_Table[g4inst->opcode()].str << "\n";
1052 ASSERT_USER(false, "INVALID OPCODE.");
1053 return nullptr;
1054 }
1055 Op igaOp = opSpec->op;
1056 Subfunction sf = opinfo.second;
1057 Predication pred;
1058 RegRef flagReg {0, 0};
1059 ExecSize execSize = getIGAExecSize(g4inst->getExecSize());
1060 ChannelOffset chOff = getIGAChannelOffset(g4inst->getMaskOffset());
1061 MaskCtrl maskCtrl =
1062 getIGAMaskCtrl(g4inst->opcode() == G4_jmpi || g4inst->isWriteEnableInst());
1063 FlagModifier condModifier = FlagModifier::NONE;
1064
1065 getIGAFlagInfo(g4inst, opSpec, sf, pred, condModifier, flagReg);
1066
1067 if (opSpec->isBranching())
1068 {
1069 BranchCntrl brnchCtrl = getIGABranchCntrl(g4inst->asCFInst()->isBackward());
1070 igaInst = IGAKernel->createBranchInstruction(
1071 *opSpec,
1072 pred,
1073 flagReg,
1074 execSize,
1075 chOff,
1076 maskCtrl,
1077 brnchCtrl);
1078 }
1079 else if (opSpec->isSendOrSendsFamily())
1080 {
1081 SendDesc desc = getIGASendDesc(g4inst);
1082 SendExDescOpts sdos = getIGASendExDesc(g4inst);
1083 igaInst =
1084 IGAKernel->createSendInstruction(
1085 *opSpec,
1086 sf.send,
1087 pred,
1088 flagReg,
1089 execSize,
1090 chOff,
1091 maskCtrl,
1092 sdos.exDesc,
1093 desc);
1094
1095 ASSERT_USER(igaInst, "Instruction is NULL");
1096 if (!igaInst) {
1097 return nullptr;
1098 }
1099
1100 igaInst->setSrc1Length(sdos.xlen);
1101 igaInst->addInstOpts(sdos.extraOpts);
1102 }
1103 else if (opSpec->op == Op::NOP)
1104 {
1105 igaInst = IGAKernel->createNopInstruction();
1106 }
1107 else if (opSpec->op == Op::ILLEGAL)
1108 {
1109 igaInst = IGAKernel->createIllegalInstruction();
1110 }
1111 else
1112 {
1113 igaInst =
1114 IGAKernel->createBasicInstruction(
1115 *opSpec,
1116 pred,
1117 flagReg,
1118 execSize,
1119 chOff,
1120 maskCtrl,
1121 condModifier,
1122 sf);
1123 }
1124
1125 ASSERT_USER(igaInst, "Instruction is NULL");
1126 if (!igaInst) {
1127 // only on asserts; this should only happen if memory allocation
1128 // fails for some reason
1129 return nullptr;
1130 }
1131
1132 igaInst->setID(IGAInstId++);
1133 igaInst->setLoc(g4inst->getCISAOff()); // make IGA src off track CISA id
1134
1135 if (opSpec->supportsDestination())
1136 {
1137 translateInstructionDst(g4inst, igaInst);
1138 }
1139
1140 if (opSpec->isBranching() &&
1141 igaOp != Op::JMPI &&
1142 igaOp != Op::RET &&
1143 igaOp != Op::CALL &&
1144 igaOp != Op::CALLA &&
1145 igaOp != Op::BRC &&
1146 igaOp != Op::BRD)
1147 {
1148 translateInstructionBranchSrcs(g4inst, igaInst, bbNew);
1149 }
1150 else
1151 {
1152 translateInstructionSrcs(g4inst, igaInst);
1153 }
1154
1155 return igaInst;
1156 }
1157
translateInstructionDst(G4_INST * g4inst,Instruction * igaInst)1158 void BinaryEncodingIGA::translateInstructionDst(
1159 G4_INST *g4inst, Instruction *igaInst)
1160 {
1161 assert(g4inst->getDst() && "dst must not be null");
1162 G4_DstRegRegion* dst = g4inst->getDst();
1163 DstModifier dstModifier = getIGADstModifier(g4inst->getSaturate());
1164 Region::Horz hstride = getIGAHorz(dst->getHorzStride());
1165 Type type = getIGAType(g4inst, Opnd_dst, platform);
1166
1167 // workaround for SKL bug
1168 // not all bits are copied from immediate descriptor
1169 if (g4inst->isSend() && platform >= GENX_SKL && platform < GENX_ICLLP)
1170 {
1171 const G4_SendDescRaw* msgDesc = g4inst->getMsgDescRaw();
1172 assert(msgDesc && "expected raw descriptor");
1173 G4_Operand* descOpnd = g4inst->isSplitSend() ?
1174 g4inst->getSrc(2) : g4inst->getSrc(1);
1175 if (!descOpnd->isImm() && msgDesc->is16BitReturn())
1176 {
1177 type = Type::HF;
1178 }
1179 }
1180
1181 if (igaInst->isMacro())
1182 {
1183 RegRef regRef = getIGARegRef(dst);
1184 Region::Horz hstride = getIGAHorz(dst->getHorzStride());
1185 igaInst->setMacroDestination(
1186 dstModifier,
1187 getIGARegName(dst),
1188 regRef,
1189 getIGAImplAcc(dst->getAccRegSel()),
1190 hstride,
1191 type);
1192 }
1193 else if (dst->getRegAccess() == Direct)
1194 {
1195 igaInst->setDirectDestination(
1196 dstModifier,
1197 getIGARegName(dst),
1198 getIGARegRef(dst),
1199 hstride,
1200 type);
1201 }
1202 else
1203 { // Operand::Kind::INDIRECT
1204 RegRef regRef {0, 0};
1205 bool valid;
1206 regRef.subRegNum = (uint8_t)dst->ExIndSubRegNum(valid);
1207 igaInst->setInidirectDestination(
1208 dstModifier,
1209 regRef,
1210 dst->getAddrImm(),
1211 hstride,
1212 type);
1213 }
1214 }
1215
translateInstructionBranchSrcs(G4_INST * inst,Instruction * igaInst,Block * & bbNew)1216 void BinaryEncodingIGA::translateInstructionBranchSrcs(
1217 G4_INST *inst, Instruction *igaInst, Block*& bbNew)
1218 {
1219 if (inst->asCFInst()->getJip())
1220 {
1221 // encode jip/uip for branch inst
1222 // note that it does not apply to jmpi/call/ret/brc/brd,
1223 // which may have register sources. Their label appears directly as
1224 // source operand instead.
1225 G4_Operand* uip = inst->asCFInst()->getUip();
1226 G4_Operand* jip = inst->asCFInst()->getJip();
1227 //iga will take care off
1228 if (uip)
1229 {
1230 igaInst->setLabelSource(SourceIndex::SRC1,
1231 lookupIGABlock(uip->asLabel(), *IGAKernel), Type::UD);
1232 }
1233
1234 igaInst->setLabelSource(SourceIndex::SRC0,
1235 lookupIGABlock(jip->asLabel(), *IGAKernel), Type::UD);
1236 }
1237 else
1238 {
1239 // Creating a fall through block
1240 bbNew = IGAKernel->createBlock();
1241 igaInst->setLabelSource(SourceIndex::SRC0, bbNew, Type::UD);
1242 IGAKernel->appendBlock(bbNew);
1243 }
1244 }
1245
translateInstructionSrcs(G4_INST * inst,Instruction * igaInst)1246 void BinaryEncodingIGA::translateInstructionSrcs(
1247 G4_INST *inst, Instruction *igaInst)
1248 {
1249 // set source operands
1250 int numSrcToEncode = inst->getNumSrc();
1251 if (inst->isSend())
1252 {
1253 // skip desc/exdesc as they are handled separately
1254 numSrcToEncode = inst->isSplitSend() ? 2 : 1;
1255
1256 if (numSrcToEncode == 1 && platformModel->platform >= Platform::XE)
1257 {
1258 RegRef regTemp(0, 0);
1259 Region rgnTemp = Region::SRC010;
1260
1261 igaInst->setDirectSource(
1262 SourceIndex::SRC1,
1263 SrcModifier::NONE,
1264 RegName::ARF_NULL,
1265 regTemp,
1266 rgnTemp,
1267 Type::INVALID);
1268 }
1269 }
1270 if (platform >= GENX_ICLLP
1271 && inst->opcode() == G4_movi && numSrcToEncode == 1)
1272 {
1273 // From ICL, 'movi' becomes a binary instruction with an
1274 // optional immediate operand, which needs encoding as null
1275 // or imm32. So far, within vISA jitter, 'movi' is still
1276 // modeled as unary instruction, setting src1 to null for
1277 // platforms >= CNL.
1278 RegRef regTemp(0, 0);
1279 Region rgnTemp = Region::SRC110;
1280 igaInst->setDirectSource(SourceIndex::SRC1,
1281 SrcModifier::NONE,
1282 RegName::ARF_NULL,
1283 regTemp, rgnTemp,
1284 Type::UB);
1285 }
1286 for (int i = 0; i < numSrcToEncode; i++)
1287 {
1288 SourceIndex opIx = SourceIndex::SRC0;
1289 switch (i) {
1290 case 0: opIx = SourceIndex::SRC0; break;
1291 case 1: opIx = SourceIndex::SRC1; break;
1292 case 2: opIx = SourceIndex::SRC2; break;
1293 default:
1294 assert(0 && "invalid source index number");
1295 break;
1296 }
1297
1298 G4_Operand* src = inst->getSrc(i);
1299
1300 if (src->isSrcRegRegion())
1301 {
1302 G4_SrcRegRegion* srcRegion = src->asSrcRegRegion();
1303 SrcModifier srcMod = getIGASrcModifier(srcRegion->getModifier());
1304 Region region = getIGARegion(srcRegion, i);
1305 Type type = Type::INVALID;
1306
1307 // let IGA take care of types for send/s instructions
1308 if (!igaInst->getOpSpec().isSendOrSendsFamily())
1309 {
1310 type = getIGAType(inst, inst->getSrcOperandNum(i), platform);
1311 }
1312 else if (i == 0 && platform >= GENX_SKL && platform < GENX_ICLLP)
1313 {
1314 // work around for SKL bug
1315 // not all bits are copied from immediate descriptor
1316 G4_SendDescRaw* msgDesc = inst->getMsgDescRaw();
1317 assert(msgDesc && "expected raw descriptor");
1318 G4_Operand* descOpnd = inst->isSplitSend() ?
1319 inst->getSrc(2) : inst->getSrc(1);
1320 if (!descOpnd->isImm() && msgDesc->is16BitInput())
1321 {
1322 type = Type::HF;
1323 }
1324 }
1325
1326 if (igaInst->isMacro())
1327 {
1328 auto accRegSel =
1329 srcRegion->isNullReg() ? NOACC : srcRegion->getAccRegSel();
1330 RegRef regRef = getIGARegRef(srcRegion);
1331 igaInst->setMacroSource(
1332 opIx,
1333 srcMod,
1334 getIGARegName(srcRegion),
1335 regRef,
1336 getIGAImplAcc(accRegSel),
1337 region,
1338 type);
1339 }
1340 else if (inst->isDpas())
1341 {
1342 assert(srcRegion->getRegAccess() == Direct &&
1343 "dpas does not support indirect GRF operands");
1344 G4_InstDpas* dpasInst = inst->asDpasInst();
1345 RegRef regRef = getIGADpasRegRef(dpasInst, i);
1346 type = getIGADpasType(dpasInst, i);
1347
1348 igaInst->setDirectSource(
1349 opIx,
1350 srcMod,
1351 getIGARegName(srcRegion),
1352 regRef,
1353 region,
1354 type);
1355 }
1356 else if (srcRegion->getRegAccess() == Direct)
1357 {
1358 igaInst->setDirectSource(
1359 opIx,
1360 srcMod,
1361 getIGARegName(srcRegion),
1362 getIGARegRef(srcRegion),
1363 region,
1364 type);
1365 }
1366 else
1367 {
1368 RegRef regRef {0, 0};
1369 bool valid;
1370 regRef.subRegNum = (uint8_t)srcRegion->ExIndSubRegNum(valid);
1371 // set to GRF for indirect register access
1372 iga::RegName regName = iga::RegName::GRF_R;
1373
1374 igaInst->setInidirectSource(
1375 opIx,
1376 srcMod,
1377 regName,
1378 regRef,
1379 srcRegion->getAddrImm(),
1380 region,
1381 type);
1382 }
1383 }
1384 else if (src->isLabel())
1385 {
1386 igaInst->setLabelSource(opIx,
1387 lookupIGABlock(src->asLabel(), *IGAKernel), Type::UD);
1388 }
1389 else if (src->isImm())
1390 {
1391 Type type = getIGAType(src->getType(), platform);
1392 ImmVal val;
1393 val = src->asImm()->getImm();
1394 val.kind = getIGAImmType(src->getType());
1395 igaInst->setImmediateSource(opIx, val, type);
1396 }
1397 else
1398 {
1399 IGA_ASSERT_FALSE("unexpected src kind");
1400 }
1401 } // for
1402 }
1403
getIGASendDesc(G4_INST * sendInst) const1404 SendDesc BinaryEncodingIGA::getIGASendDesc(G4_INST* sendInst) const
1405 {
1406 SendDesc desc;
1407 assert(sendInst->isSend() && "expect send inst");
1408 G4_Operand* msgDesc = sendInst->isSplitSend() ?
1409 sendInst->getSrc(2) : sendInst->getSrc(1);
1410 if (msgDesc->isImm())
1411 {
1412 desc.type = SendDesc::Kind::IMM;
1413 desc.imm = (uint32_t)msgDesc->asImm()->getImm();
1414 // This is a WA that needs to add fence.ugm before EOT
1415 // fence.ugm.invalidate.tile works, but performance for raytracing
1416 // might be affected. HW team came out a way to get around of it
1417 // by using reserved Flush TYPE = 6, with the following
1418 // DG2_Backup_Mode = 0
1419 // Flush_Range = 0
1420 // (So, it is fence.ugm.6.tile !)
1421 auto msgDesc = sendInst->asSendInst()->getMsgDesc();
1422 if (msgDesc->isLSC() && msgDesc->isFence())
1423 {
1424 // Flush Type : bit[14:12]
1425 uint32_t flushTy = ((desc.imm >> 12) & 0x7);
1426 if (flushTy == 6)
1427 {
1428 // DG2 fence desc
1429 // both backupMode(bit[18]) and flushRange(bit[15]) must be zero
1430 constexpr uint32_t backupMode = (1 << 18), flushRange = (1 << 15);
1431 desc.imm = desc.imm & ~(backupMode | flushRange);
1432 }
1433 }
1434 }
1435 else
1436 {
1437 desc.type = SendDesc::Kind::REG32A;
1438 desc.reg.regNum = 0; // must be a0
1439 bool valid = false;
1440 desc.reg.subRegNum = (uint8_t)msgDesc->asSrcRegRegion()->ExSubRegNum(valid);
1441 assert(valid && "invalid subreg");
1442 }
1443
1444 return desc;
1445 }
1446
1447 ///////////////////////////////////////////////////////////////////////////////
1448 // ExDesc encoding
encodeExDescSendUnary(G4_INST * sendInst,int & xlen,InstOptSet & extraOpts)1449 static SendDesc encodeExDescSendUnary(
1450 G4_INST* sendInst, int& xlen, InstOptSet& extraOpts)
1451 {
1452 SendDesc exDescIga;
1453
1454 // old unary packed send
1455 // exDesc is stored in SendMsgDesc and must be IMM
1456 G4_SendDescRaw* descG4 = sendInst->getMsgDescRaw();
1457 assert(descG4 != nullptr && "expected raw send");
1458
1459 exDescIga.type = SendDesc::Kind::IMM;
1460 uint32_t tVal = descG4->getExtendedDesc();
1461
1462 if (getPlatformGeneration(sendInst->getPlatform()) >= PlatformGen::XE)
1463 {
1464 // We must clear the funcID in the extended message.
1465 // In Xe+ this is part of the EU encoding, not the descriptor.
1466 // vISA/G4IR still treat it as part of the descriptor.
1467 tVal = tVal & 0xFFFFFFF0;
1468
1469 // clear the EOT bit which is not part of exDesc
1470 tVal &= ~(1 << 5);
1471 }
1472 exDescIga.imm = tVal;
1473
1474 // non-split send implies Src1.Length == 0
1475 xlen = 0;
1476
1477 return exDescIga;
1478 }
1479
1480 ////////////////////////////////////////////////////////////////////
1481 // these handle binary sends (old "sends" and Xe+ "send"
1482 //
encodeExDescImm(G4_INST * sendInst,SendExDescOpts & sdos) const1483 SendDesc BinaryEncodingIGA::encodeExDescImm(
1484 G4_INST* sendInst,
1485 SendExDescOpts &sdos) const
1486 {
1487 SendDesc exDescIga;
1488
1489 G4_Operand* exDescG4 = sendInst->getSrc(3);
1490 G4_SendDescRaw* descG4 = sendInst->getMsgDescRaw();
1491 assert(descG4 != nullptr && "expected raw descriptor");
1492
1493 sdos.xlen = (int)descG4->extMessageLength();
1494 //
1495 exDescIga.type = SendDesc::Kind::IMM;
1496 exDescIga.imm = (uint32_t)exDescG4->asImm()->getImm();
1497 // We must clear the funcID in the extended message for Xe+
1498 // because it is part of the EU instruction, not the descriptor,
1499 // and, vISA/G4-IR still thinks of it as part of the descriptor.
1500 //
1501 // Ditto for the EOT bit which is moved out of extDesc
1502 //
1503 // The extended message format
1504 // struct ExtendedMsgDescLayout {
1505 // uint32_t funcID : 4; // bit 0:3 << not part of ExDesc
1506 // uint32_t unnamed1 : 1; // bit 4
1507 // uint32_t eot : 1; // bit 5 << not part of ExDesc
1508 // uint32_t extMsgLength : 5; // bit 6:10
1509 // uint32_t unnamed2 : 5; // bit 11:15
1510 // uint32_t extFuncCtrl : 16; // bit 16:31
1511 // };
1512 if (getPlatformGeneration(sendInst->getPlatform()) >= PlatformGen::XE)
1513 {
1514 exDescIga.imm &= 0xFFFFFFC0;
1515 }
1516 if (kernel.fg.builder->encodeSendSrc1Length())
1517 {
1518 // In DG2+ ExDesc[10:6] is no longer Src1.Length even for imm
1519 // and the field is always part of the EU encoding
1520 if (descG4->isCPSEnabled()) {
1521 sdos.extraOpts.add(InstOpt::CPS);
1522 }
1523 // We must keep ExDesc[10:6] as Src1.Len until we fix the
1524 // 100s of uses that assume this.
1525 // IGA expects these bits to be 0's on this platform
1526 //
1527 // FIXME: remove the if guard once we enable DG2
1528 // (i.e. once DG2 targets IGA DG2 and not XE_HP, we should clear
1529 // the bottom 12b for DG2 too) and only use the IR fields above
1530 // (exDescArg.{cps,src1Length})
1531 exDescIga.imm &= 0xFFFFF000;
1532 }
1533 // Note: ExBSO is never permitted for imm descriptors
1534
1535 // clear the EOT bit which is not part of exDesc on XE+
1536 if (getPlatformGeneration(sendInst->getPlatform()) >= PlatformGen::XE)
1537 exDescIga.imm &= ~(1 << 5);
1538
1539 return exDescIga;
1540 }
1541
encodeExDescRegA0(G4_INST * sendInst,SendExDescOpts & sdos) const1542 SendDesc BinaryEncodingIGA::encodeExDescRegA0(
1543 G4_INST* sendInst, SendExDescOpts &sdos) const
1544 {
1545 G4_Operand* exDescG4 = sendInst->getSrc(3);
1546 const G4_SendDescRaw* descG4 = sendInst->getMsgDescRaw();
1547 assert(descG4 != nullptr && "expected raw descriptor");
1548
1549 SendDesc exDescIga;
1550 exDescIga.type = SendDesc::Kind::REG32A;
1551 exDescIga.reg.regNum = 0; // must be a0
1552 bool valid = false;
1553 exDescIga.reg.subRegNum =
1554 (uint16_t)exDescG4->asSrcRegRegion()->ExSubRegNum(valid);
1555 assert(valid && "invalid subreg");
1556
1557 if (kernel.fg.builder->useNewExtDescFormat() && descG4->isCPSEnabled()) {
1558 // CPS is an instruction option if using RegDesc+ExBSO
1559 sdos.extraOpts.add(InstOpt::CPS);
1560 }
1561
1562 // By default all RegDesc in the new descriptor format will use
1563 // the ExBSO model if at all possible
1564 bool encodeExBso = kernel.fg.builder->useNewExtDescFormat();
1565 // On DG2 LSC mustn't use ExBSO for BTI (hardware restriction).
1566 // If this is an LSC descriptor, then dig out the LscAddrType field and
1567 // compare to 3 (which means BTI).
1568 const bool isLsc = descG4->isLscOp();
1569 const bool isLscBti = isLsc && descG4->getLscAddrType() == LSC_ADDR_TYPE_BTI;
1570 const bool isUgm = sendInst->getMsgDesc()->getSFID() == vISA::SFID::UGM;
1571 encodeExBso &= !isLscBti;
1572 if (encodeExBso)
1573 sdos.extraOpts.add(InstOpt::EXBSO);
1574
1575 // G4 IR keeps Src1.Length (xlen) separate. So it's known,
1576 // (even with a reg desc in nonExBSO mode)
1577 sdos.xlen = (int)descG4->extMessageLength();
1578
1579 return exDescIga;
1580 }
1581
1582
1583
getIGASendExDesc(G4_INST * sendInst) const1584 SendExDescOpts BinaryEncodingIGA::getIGASendExDesc(G4_INST* sendInst) const {
1585 SendExDescOpts sdos;
1586
1587 assert(sendInst->isSend() && "expect send inst");
1588
1589 if (sendInst->isEOT())
1590 sdos.extraOpts.add(InstOpt::EOT);
1591
1592 if (sendInst->isSplitSend())
1593 {
1594 const G4_Operand* exDesc = sendInst->getSrc(3);
1595 sdos.exDesc = exDesc->isImm() ?
1596 encodeExDescImm(sendInst, sdos) :
1597 encodeExDescRegA0(sendInst, sdos);
1598 }
1599 else
1600 {
1601 sdos.exDesc = encodeExDescSendUnary(sendInst, sdos.xlen, sdos.extraOpts);
1602 }
1603
1604 return sdos;
1605 }
1606
EmitBinary(size_t & binarySize)1607 void *BinaryEncodingIGA::EmitBinary(size_t& binarySize)
1608 {
1609 binarySize = m_kernelBufferSize;
1610
1611 if (kernel.getOption(vISA_GenerateBinary))
1612 {
1613 std::string binFileName = fileName + ".dat";
1614 if (CisaFramework::allowDump(*kernel.getOptions(), binFileName))
1615 {
1616 std::string errStr;
1617 std::ofstream os(binFileName, std::ios::binary);
1618 if (!os)
1619 {
1620 errStr = "Can't open " + binFileName + ".\n";
1621 MUST_BE_TRUE(0, errStr);
1622 return nullptr;
1623 }
1624 os.write((const char*)m_kernelBuffer, binarySize);
1625 }
1626 }
1627
1628 return m_kernelBuffer;
1629 }
1630
getIGAExecSize(int execSize)1631 ExecSize BinaryEncodingIGA::getIGAExecSize(int execSize)
1632 {
1633 switch (execSize)
1634 {
1635 case 1: return ExecSize::SIMD1;
1636 case 2: return ExecSize::SIMD2;
1637 case 4: return ExecSize::SIMD4;
1638 case 8: return ExecSize::SIMD8;
1639 case 16: return ExecSize::SIMD16;
1640 case 32: return ExecSize::SIMD32;
1641 default:
1642 assert(false && "illegal simd size");
1643 return ExecSize::INVALID;
1644 }
1645 }
1646
getIGAChannelOffset(int offset)1647 ChannelOffset BinaryEncodingIGA::getIGAChannelOffset(int offset)
1648 {
1649 switch (offset)
1650 {
1651 case 0: return ChannelOffset::M0;
1652 case 4: return ChannelOffset::M4;
1653 case 8: return ChannelOffset::M8;
1654 case 12: return ChannelOffset::M12;
1655 case 16: return ChannelOffset::M16;
1656 case 20: return ChannelOffset::M20;
1657 case 24: return ChannelOffset::M24;
1658 case 28: return ChannelOffset::M28;
1659 default:
1660 assert(false && "illegal mask offset");
1661 return ChannelOffset::M0;
1662 }
1663 }
1664
getIGAMaskCtrl(bool noMask)1665 MaskCtrl BinaryEncodingIGA::getIGAMaskCtrl(bool noMask)
1666 {
1667 return noMask ? MaskCtrl::NOMASK : MaskCtrl::NORMAL;
1668 }
1669
getIGAARFName(G4_ArchRegKind areg)1670 RegName BinaryEncodingIGA::getIGAARFName(G4_ArchRegKind areg)
1671 {
1672 switch (areg)
1673 {
1674 case AREG_NULL: return RegName::ARF_NULL;
1675 case AREG_A0: return RegName::ARF_A;
1676 case AREG_ACC0:
1677 case AREG_ACC1: return RegName::ARF_ACC;
1678 case AREG_MASK0: return RegName::ARF_CE;
1679 case AREG_MS0: return RegName::ARF_MSG;
1680 case AREG_DBG: return RegName::ARF_DBG;
1681 case AREG_SR0: return RegName::ARF_SR;
1682 case AREG_CR0: return RegName::ARF_CR;
1683 case AREG_N0:
1684 case AREG_N1: return RegName::ARF_N;
1685 case AREG_IP: return RegName::ARF_IP;
1686 case AREG_F0:
1687 case AREG_F1:
1688 case AREG_F2:
1689 case AREG_F3:
1690 return RegName::ARF_F;
1691 case AREG_TM0: return RegName::ARF_TM;
1692 case AREG_TDR0: return RegName::ARF_TDR;
1693 case AREG_SP: return RegName::ARF_SP;
1694 default:
1695 assert(false && "illegal ARF");
1696 return RegName::INVALID;
1697 }
1698 }
1699
getIGAType(const G4_INST * I,Gen4_Operand_Number O,TARGET_PLATFORM P)1700 Type BinaryEncodingIGA::getIGAType(const G4_INST* I, Gen4_Operand_Number O, TARGET_PLATFORM P)
1701 {
1702
1703 G4_Type Ty = I->getOperand(O)->getType();
1704 if (I->opcode() == G4_fcvt)
1705 {
1706 if (Ty == Type_UB)
1707 {
1708 return Type::BF8;
1709 }
1710 if (Ty == Type_UD)
1711 {
1712 return Type::TF32;
1713 }
1714 }
1715 if (I->opcode() == G4_srnd)
1716 {
1717 if (O == Opnd_dst && Ty == Type_UB)
1718 {
1719 return Type::BF8;
1720 }
1721 }
1722 return getIGAType(Ty, P);
1723 }
1724
getIGAType(G4_Type type,TARGET_PLATFORM genxPlatform)1725 Type BinaryEncodingIGA::getIGAType(G4_Type type, TARGET_PLATFORM genxPlatform)
1726 {
1727 switch (type)
1728 {
1729 case Type_UB: return Type::UB;
1730 case Type_B: return Type::B;
1731 case Type_UW: return Type::UW;
1732 case Type_W: return Type::W;
1733 case Type_UD: return Type::UD;
1734 case Type_D: return Type::D;
1735 case Type_UQ: return Type::UQ;
1736 case Type_Q: return Type::Q;
1737 case Type_HF: return Type::HF;
1738 case Type_F: return Type::F;
1739 case Type_DF: return Type::DF;
1740 case Type_UV: return Type::UV;
1741 case Type_V: return Type::V;
1742 case Type_VF: return Type::VF;
1743 case Type_NF: return Type::NF;
1744 case Type_BF: return Type::BF;
1745 default:
1746 assert(false && "illegal type");
1747 return Type::INVALID;
1748 }
1749 }
1750
getIGAPredCtrl(G4_Predicate_Control g4PrCtl)1751 PredCtrl BinaryEncodingIGA::getIGAPredCtrl(G4_Predicate_Control g4PrCtl)
1752 {
1753 switch (g4PrCtl)
1754 {
1755 case PRED_DEFAULT: return PredCtrl::SEQ;
1756 case PRED_ANY2H: return PredCtrl::ANY2H;
1757 case PRED_ANY4H: return PredCtrl::ANY4H;
1758 case PRED_ANY8H: return PredCtrl::ANY8H;
1759 case PRED_ANY16H: return PredCtrl::ANY16H;
1760 case PRED_ANY32H: return PredCtrl::ANY32H;
1761 case PRED_ALL2H: return PredCtrl::ALL2H;
1762 case PRED_ALL4H: return PredCtrl::ALL4H;
1763 case PRED_ALL8H: return PredCtrl::ALL8H;
1764 case PRED_ALL16H: return PredCtrl::ALL16H;
1765 case PRED_ALL32H: return PredCtrl::ALL32H;
1766 case PRED_ANYV: return PredCtrl::ANYV;
1767 case PRED_ALLV: return PredCtrl::ALLV;
1768 case PRED_ANY_WHOLE: return PredCtrl::ANY;
1769 case PRED_ALL_WHOLE: return PredCtrl::ALL;
1770 default:
1771 assert(false && "illegal predicate control");
1772 return PredCtrl::NONE;
1773 }
1774 }
1775
getIGAPredication(G4_Predicate * predG4)1776 Predication BinaryEncodingIGA::getIGAPredication(G4_Predicate* predG4)
1777 {
1778 Predication pred;
1779 if (predG4)
1780 {
1781 pred.function = getIGAPredCtrl(predG4->getControl());
1782 pred.inverse = predG4->getState() != PredState_Plus;
1783 }
1784 return pred;
1785 }
1786
getIGASrcModifier(G4_SrcModifier srcMod)1787 SrcModifier BinaryEncodingIGA::getIGASrcModifier(G4_SrcModifier srcMod)
1788 {
1789 switch (srcMod)
1790 {
1791 case Mod_Minus: return SrcModifier::NEG;
1792 case Mod_Abs: return SrcModifier::ABS;
1793 case Mod_Minus_Abs: return SrcModifier::NEG_ABS;
1794 case Mod_Not: return SrcModifier::NEG;
1795 case Mod_src_undef: return SrcModifier::NONE;
1796 default:
1797 assert(false && "illegal source modifier");
1798 return SrcModifier::NONE;
1799 }
1800 }
1801
getIGAVert(int vstride)1802 Region::Vert BinaryEncodingIGA::getIGAVert(int vstride)
1803 {
1804 switch (vstride)
1805 {
1806 case 0: return Region::Vert::VT_0;
1807 case 1: return Region::Vert::VT_1;
1808 case 2: return Region::Vert::VT_2;
1809 case 4: return Region::Vert::VT_4;
1810 case 8: return Region::Vert::VT_8;
1811 case 16: return Region::Vert::VT_16;
1812 case 32: return Region::Vert::VT_32;
1813 case UNDEFINED_SHORT: return Region::Vert::VT_VxH;
1814 default:
1815 assert(false && "illegal vstride");
1816 return Region::Vert::VT_INVALID;
1817 }
1818 }
1819
getIGAWidth(int width)1820 Region::Width BinaryEncodingIGA::getIGAWidth(int width)
1821 {
1822 switch (width)
1823 {
1824 case 1: return Region::Width::WI_1;
1825 case 2: return Region::Width::WI_2;
1826 case 4: return Region::Width::WI_4;
1827 case 8: return Region::Width::WI_8;
1828 case 16: return Region::Width::WI_16;
1829 default:
1830 assert(false && "illegal width");
1831 return Region::Width::WI_INVALID;
1832 }
1833 }
1834
getIGAHorz(int hstride)1835 Region::Horz BinaryEncodingIGA::getIGAHorz(int hstride)
1836 {
1837 switch (hstride)
1838 {
1839 case 0: return Region::Horz::HZ_0;
1840 case 1: return Region::Horz::HZ_1;
1841 case 2: return Region::Horz::HZ_2;
1842 case 4: return Region::Horz::HZ_4;
1843 default:
1844 assert(false && "illegal hstride");
1845 return Region::Horz::HZ_INVALID;
1846 }
1847 }
1848
getIGARegion(G4_SrcRegRegion * srcRegion,int srcPos)1849 Region BinaryEncodingIGA::getIGARegion(
1850 G4_SrcRegRegion* srcRegion, int srcPos)
1851 {
1852 Region igaRegion;
1853 const RegionDesc* region = srcRegion->getRegion();
1854 if ((srcRegion->getInst()->getNumSrc() == 3 &&
1855 !srcRegion->getInst()->isSend()))
1856 {
1857 // special handling for 3src instructions
1858 if (srcPos != 2)
1859 {
1860 // for src0 and src1, IGA/GED does not like width to be set
1861 igaRegion.set(
1862 getIGAVert(region->vertStride),
1863 Region::Width::WI_INVALID,
1864 getIGAHorz(region->horzStride));
1865 }
1866 else
1867 {
1868 // for src2, IGA expects both VS and W to be invalid
1869 igaRegion.set(
1870 Region::Vert::VT_INVALID,
1871 Region::Width::WI_INVALID,
1872 getIGAHorz(region->horzStride));
1873 }
1874 }
1875 else
1876 {
1877 igaRegion.set(
1878 getIGAVert(region->vertStride),
1879 getIGAWidth(region->width),
1880 getIGAHorz(region->horzStride));
1881 }
1882 return igaRegion;
1883 }
1884
EncodeKernelIGA(vISA::Mem_Manager & m,vISA::G4_Kernel & k,const std::string & fname)1885 EncodeResult vISA::EncodeKernelIGA(
1886 vISA::Mem_Manager &m,
1887 vISA::G4_Kernel& k,
1888 const std::string &fname)
1889 {
1890 EncodeResult r;
1891 BinaryEncodingIGA encoder(m, k, fname);
1892 encoder.Encode();
1893 r.binary = encoder.EmitBinary(r.binaryLen);
1894 return r;
1895 }
1896
GetIGASWSBEncodeMode(const IR_Builder & builder)1897 SWSB_ENCODE_MODE vISA::GetIGASWSBEncodeMode(const IR_Builder& builder) {
1898 if (getPlatformGeneration(builder.getPlatform()) < PlatformGen::XE)
1899 return SWSB_ENCODE_MODE::SWSBInvalidMode;
1900
1901 if (builder.hasThreeALUPipes()) {
1902 return SWSB_ENCODE_MODE::ThreeDistPipe;
1903 }
1904 else if (builder.hasFourALUPipes()) {
1905 if (builder.getPlatform() == GENX_PVC)
1906 return SWSB_ENCODE_MODE::FourDistPipe;
1907 return SWSB_ENCODE_MODE::FourDistPipeReduction;
1908 }
1909
1910 return SWSB_ENCODE_MODE::SingleDistPipe;
1911 }
1912
GetModel(TARGET_PLATFORM p)1913 static const Model *GetModel(TARGET_PLATFORM p)
1914 {
1915 const Model *m = Model::LookupModel(
1916 BinaryEncodingIGA::getIGAInternalPlatform(p));
1917 return m;
1918 }
1919
InstSupportsSaturationIGA(TARGET_PLATFORM p,const G4_INST & i,const IR_Builder & builder)1920 bool vISA::InstSupportsSaturationIGA(TARGET_PLATFORM p, const G4_INST &i, const IR_Builder& builder)
1921 {
1922 const Model *m = GetModel(p);
1923 if(m)
1924 {
1925 auto oi = BinaryEncodingIGA::getIgaOpInfo(&i, m, true, builder);
1926 return oi.first && oi.first->isValid() && oi.first->supportsSaturation();
1927 }
1928 else
1929 {
1930 return false;
1931 }
1932 }
1933
InstSupportsSrcModifierIGA(TARGET_PLATFORM p,const G4_INST & i,const IR_Builder & builder)1934 bool vISA::InstSupportsSrcModifierIGA(TARGET_PLATFORM p, const G4_INST &i, const IR_Builder& builder)
1935 {
1936 const Model *m = GetModel(p);
1937 if(m)
1938 {
1939 auto oi = BinaryEncodingIGA::getIgaOpInfo(&i, m, true, builder);
1940 return oi.first && oi.first->isValid() && oi.first->supportsSourceModifiers();
1941 }
1942 else
1943 {
1944 return false;
1945 }
1946 }
1947
1948