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