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 "Kernel.hpp"
10 #include "../IR/Messages.hpp"
11
12 using namespace iga;
13
Kernel(const Model & model)14 Kernel::Kernel(const Model &model)
15 : m_model(model)
16 , m_mem(4096)
17 {
18 }
19
~Kernel()20 Kernel::~Kernel()
21 {
22 // Since in a kernel blocks are allocated using the memory pool,
23 // when the Kernel is freed, the memory pool is deleted and destructors
24 // for Blocks are never called. This means the InstList's memory pools
25 // was never deleted and we need to do it here.
26 //
27 // Also, Instruction's fields with destructors need running
28 // (e.g. m_comment)
29 for (Block *bb : m_blocks) {
30 bb->~Block();
31 }
32 }
33
getInstructionCount() const34 size_t Kernel::getInstructionCount() const
35 {
36 size_t n = 0;
37 for (const Block *b : getBlockList()) {
38 n += b->getInstList().size();
39 }
40 return n;
41 }
42
43
createBlock()44 Block *Kernel::createBlock()
45 {
46 return new(&m_mem)Block();
47 }
48
49
appendBlock(Block * blk)50 void Kernel::appendBlock(Block *blk)
51 {
52 m_blocks.push_back(blk);
53 }
54
55
createBasicInstruction(const OpSpec & os,const Predication & predOpnd,const RegRef & freg,ExecSize execSize,ChannelOffset chOff,MaskCtrl mc,FlagModifier condMod,Subfunction sf)56 Instruction *Kernel::createBasicInstruction(
57 const OpSpec& os,
58 const Predication& predOpnd,
59 const RegRef& freg,
60 ExecSize execSize,
61 ChannelOffset chOff,
62 MaskCtrl mc,
63 FlagModifier condMod,
64 Subfunction sf)
65 {
66 Instruction *inst = new(&m_mem)Instruction(os, execSize, chOff, mc);
67 inst->setSubfunction(sf);
68
69 inst->setPredication(predOpnd);
70 inst->setFlagModifier(condMod);
71 inst->setFlagReg(freg);
72
73 return inst;
74 }
75
76
createBranchInstruction(const OpSpec & os,const Predication & predOpnd,const RegRef & flagReg,ExecSize execSize,ChannelOffset chOff,MaskCtrl ectr,Subfunction sf)77 Instruction *Kernel::createBranchInstruction(
78 const OpSpec &os,
79 const Predication &predOpnd,
80 const RegRef &flagReg,
81 ExecSize execSize,
82 ChannelOffset chOff,
83 MaskCtrl ectr,
84 Subfunction sf)
85 {
86 Instruction *inst = new(&m_mem)Instruction(
87 os,
88 execSize,
89 chOff,
90 ectr);
91 if (os.supportsSubfunction())
92 inst->setSubfunction(sf); // only branch control for now
93
94 inst->setPredication(predOpnd);
95 inst->setFlagReg(flagReg);
96
97 return inst;
98 }
99
100
createSendInstruction(const OpSpec & op,SFID sfid,const Predication & predOpnd,const RegRef & flagReg,ExecSize execSize,ChannelOffset chOff,MaskCtrl ectr,const SendDesc & exDesc,const SendDesc & desc)101 Instruction *Kernel::createSendInstruction(
102 const OpSpec &op,
103 SFID sfid,
104 const Predication &predOpnd,
105 const RegRef &flagReg,
106 ExecSize execSize,
107 ChannelOffset chOff,
108 MaskCtrl ectr,
109 const SendDesc &exDesc,
110 const SendDesc &desc)
111 {
112 Instruction *inst = new(&m_mem)Instruction(
113 op,
114 execSize,
115 chOff,
116 ectr);
117 inst->setSubfunction(sfid);
118
119 inst->setPredication(predOpnd);
120 inst->setFlagReg(flagReg);
121
122 inst->setExtMsgDesc(exDesc);
123 inst->setMsgDesc(desc);
124
125 ///////////////////////////////////////////////////////////////////////////
126 // make a best effort to set payload lengths
127 int dstLen = -1, src0Len = -1, src1Len = -1;
128 //
129 Platform p = inst->getOpSpec().platform;
130 bool immDescsHaveLens = desc.isImm();
131 if (immDescsHaveLens) {
132 dstLen = (int)((desc.imm >> 20) & 0x1F);
133 } else if (desc.isImm()) {
134 // if we at least have the SFID and an immediate descriptor
135 // try and deduce it from descriptor details we make a
136 // best-effort for exDesc, but may not need it specifically
137 PayloadLengths lens(
138 p,
139 sfid,
140 inst->getExecSize(),
141 desc.imm);
142 dstLen = lens.dstLen;
143 }
144 inst->setDstLength(dstLen);
145 //
146 if (src0Len < 0 && immDescsHaveLens) {
147 src0Len = (int)((desc.imm >> 25) & 0xF);
148 }
149 inst->setSrc0Length(src0Len);
150 //
151 if (src1Len < 0) {
152 // copy Src1.Length if no one else set it
153 bool immExDescHasSrc1Len = exDesc.isImm();
154 // ExBSO case will be handled by decoder/parser
155 //
156 // Src1.Length is imm xlen ExDesc[10:6] when ...:
157 // - ICL/TGL/XeHP: IsImm()
158 // - XeHPG+: never (always EU[96:92] for imm descs)
159 immExDescHasSrc1Len &= p < Platform::XE_HPG;
160 if (immExDescHasSrc1Len) {
161 src1Len = (exDesc.imm >> 6) & 0x1F;
162 }
163 }
164 inst->setSrc1Length(src1Len);
165
166 return inst;
167 }
168
169
createNopInstruction()170 Instruction *Kernel::createNopInstruction()
171 {
172 Instruction *inst = new(&m_mem)Instruction(
173 m_model.lookupOpSpec(Op::NOP),
174 ExecSize::SIMD1,
175 ChannelOffset::M0,
176 MaskCtrl::NORMAL);
177
178 const Predication predOpnd;
179 inst->setPredication(predOpnd);
180 inst->setFlagModifier(FlagModifier::NONE);
181 inst->setFlagReg(REGREF_ZERO_ZERO);
182
183 return inst;
184 }
185
186
createIllegalInstruction()187 Instruction *Kernel::createIllegalInstruction()
188 {
189 Instruction *inst = new(&m_mem)Instruction(
190 m_model.lookupOpSpec(Op::ILLEGAL),
191 ExecSize::SIMD1,
192 ChannelOffset::M0,
193 MaskCtrl::NORMAL);
194
195 const Predication predOpnd;
196 inst->setPredication(predOpnd);
197 inst->setFlagModifier(FlagModifier::NONE);
198 inst->setFlagReg(REGREF_ZERO_ZERO);
199
200 return inst;
201 }
202
createSyncInstruction(SWSB & sw,const OpSpec & ops,SyncFC sf,MemManager & mem)203 static Instruction *createSyncInstruction(
204 SWSB &sw, const OpSpec &ops, SyncFC sf, MemManager &mem)
205 {
206 Instruction *inst = new(&mem)Instruction(
207 ops,
208 ExecSize::SIMD1,
209 ChannelOffset::M0,
210 MaskCtrl::NOMASK);
211 inst->setSubfunction(sf);
212
213 const Predication predOpnd;
214 inst->setPredication(predOpnd);
215 inst->setFlagModifier(FlagModifier::NONE);
216 inst->setFlagReg(REGREF_ZERO_ZERO);
217 inst->setSWSB(sw);
218 inst->setSource(SourceIndex::SRC0, Operand::SRC_REG_NULL_UD);
219
220 return inst;
221 }
createSyncNopInstruction(SWSB sw)222 Instruction *Kernel::createSyncNopInstruction(SWSB sw)
223 {
224 return createSyncInstruction(sw,
225 m_model.lookupOpSpec(Op::SYNC), SyncFC::NOP, m_mem);
226 }
createSyncAllRdInstruction(SWSB sw)227 Instruction *Kernel::createSyncAllRdInstruction(SWSB sw)
228 {
229 return createSyncInstruction(sw,
230 m_model.lookupOpSpec(Op::SYNC), SyncFC::ALLRD, m_mem);
231 }
createSyncAllWrInstruction(SWSB sw)232 Instruction *Kernel::createSyncAllWrInstruction(SWSB sw)
233 {
234 return createSyncInstruction(sw,
235 m_model.lookupOpSpec(Op::SYNC), SyncFC::ALLWR, m_mem);
236 }
237