1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2020-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "BuildIR.h"
10 #include "../Timer.h"
11
12 using namespace vISA;
13
translateVISACFSwitchInst(G4_Operand * indexOpnd,uint8_t numLabels,G4_Label ** labels)14 int IR_Builder::translateVISACFSwitchInst(
15 G4_Operand *indexOpnd, uint8_t numLabels, G4_Label ** labels)
16 {
17 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
18
19 // TGL+ uses pre-increment IP for jmp offset, i.e., offset 0 is infinite loop
20 bool preIncIP = getPlatform() >= GENX_TGLLP;
21 // offsets are in bytes so we have to multiply everything by 16
22 // This requires that the jmpi instructions are never compacted.
23 if (indexOpnd->isImm())
24 {
25 auto val = indexOpnd->asImm()->getInt();
26 if (preIncIP)
27 {
28 val += 1;
29 }
30 indexOpnd = createImm(val * 16, Type_W);
31 }
32 else
33 {
34 G4_Declare *tmpVar = createTempVar(1, Type_D, Any);
35 G4_DstRegRegion* dstOpnd = createDstRegRegion(tmpVar, 1);
36 (void)createBinOp(G4_shl, g4::SIMD1, dstOpnd, indexOpnd,
37 createImm(4, Type_UW), InstOpt_WriteEnable, true);
38 if (preIncIP)
39 {
40 auto src0 = createSrcRegRegion(tmpVar, getRegionScalar());
41 auto src1 = createImm(16, Type_UW);
42 (void) createBinOp(G4_add, g4::SIMD1, createDstRegRegion(tmpVar, 1), src0, src1, InstOpt_WriteEnable, true);
43 }
44
45 indexOpnd = createSrcRegRegion(tmpVar, getRegionScalar());
46 }
47 G4_INST* indirectJmp = createJmp(nullptr, indexOpnd, InstOpt_NoOpt, true);
48
49 for (int i = 0; i < numLabels; i++)
50 {
51 indirectJmp->asCFInst()->addIndirectJmpLabel(labels[i]);
52 }
53
54 return VISA_SUCCESS;
55 }
56
translateVISACFLabelInst(G4_Label * lab)57 int IR_Builder::translateVISACFLabelInst(G4_Label* lab)
58 {
59 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
60
61 createLabelInst(lab, true);
62
63 if (lab->isFuncLabel())
64 {
65 subroutineId++;
66 }
67
68 return VISA_SUCCESS;
69 }
70
translateVISACFCallInst(VISA_Exec_Size execsize,VISA_EMask_Ctrl emask,G4_Predicate * predOpnd,G4_Label * lab)71 int IR_Builder::translateVISACFCallInst(
72 VISA_Exec_Size execsize, VISA_EMask_Ctrl emask,
73 G4_Predicate *predOpnd, G4_Label* lab)
74 {
75 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
76
77 G4_opcode callOpToUse = GetGenOpcodeFromVISAOpcode(ISA_CALL);
78 G4_DstRegRegion* dstOpndToUse = NULL;
79 G4_ExecSize execSize = toExecSize(execsize);
80 G4_Label* srcLabel = lab;
81
82 if (lab->isFCLabel() == true)
83 {
84 callOpToUse = G4_pseudo_fc_call;
85 getFCPatchInfo()->setHasFCCalls(true);
86
87 input_info_t *RetIP = getRetIPArg();
88 G4_Declare *FCRet = createTempVar(2, Type_UD, Four_Word);
89 FCRet->setAliasDeclare(RetIP->dcl, 0);
90 dstOpndToUse = createDstRegRegion(FCRet, 1);
91
92 execSize = g4::SIMD2;
93 }
94
95 G4_InstOpts instOpts = Get_Gen4_Emask(emask, execSize);
96 createInst(
97 predOpnd,
98 callOpToUse,
99 nullptr,
100 g4::NOSAT,
101 execSize,
102 dstOpndToUse,
103 srcLabel,
104 nullptr,
105 instOpts,
106 true);
107
108 return VISA_SUCCESS;
109 }
110
translateVISACFJumpInst(G4_Predicate * predOpnd,G4_Label * lab)111 int IR_Builder::translateVISACFJumpInst(G4_Predicate *predOpnd, G4_Label* lab)
112 {
113 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
114
115 createInst(
116 predOpnd,
117 GetGenOpcodeFromVISAOpcode(ISA_JMP),
118 NULL,
119 g4::NOSAT,
120 g4::SIMD1,
121 NULL,
122 lab,
123 NULL,
124 InstOpt_NoOpt,
125 true);
126
127 return VISA_SUCCESS;
128 }
129
130
translateVISACFFCallInst(VISA_Exec_Size execsize,VISA_EMask_Ctrl emask,G4_Predicate * predOpnd,std::string funcName,uint8_t argSize,uint8_t returnSize)131 int IR_Builder::translateVISACFFCallInst(
132 VISA_Exec_Size execsize, VISA_EMask_Ctrl emask, G4_Predicate *predOpnd,
133 std::string funcName, uint8_t argSize, uint8_t returnSize)
134 {
135 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
136
137 kernel.fg.setHasStackCalls();
138
139 if (getArgSize() < argSize)
140 {
141 setArgSize(argSize);
142 }
143
144 if (getRetVarSize() < returnSize)
145 {
146 setRetVarSize(returnSize);
147 }
148
149 uint8_t exsize = (uint8_t)Get_VISA_Exec_Size(execsize);
150
151 auto callLabel = getFcallLabel(funcName);
152
153 auto fcall = createInst(
154 predOpnd,
155 G4_pseudo_fcall,
156 nullptr,
157 g4::NOSAT,
158 exsize,
159 nullptr,
160 callLabel,
161 nullptr,
162 InstOpt_NoOpt,
163 true);
164
165 addFcallInfo(fcall, argSize, returnSize);
166 return VISA_SUCCESS;
167 }
168
translateVISACFIFCallInst(VISA_Exec_Size execsize,VISA_EMask_Ctrl emask,G4_Predicate * predOpnd,G4_Operand * funcAddr,uint8_t argSize,uint8_t returnSize)169 int IR_Builder::translateVISACFIFCallInst(
170 VISA_Exec_Size execsize, VISA_EMask_Ctrl emask,
171 G4_Predicate *predOpnd, G4_Operand* funcAddr, uint8_t argSize, uint8_t returnSize)
172 {
173 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
174
175 kernel.fg.setHasStackCalls();
176 kernel.setHasIndirectCall();
177
178 if (getArgSize() < argSize)
179 {
180 setArgSize(argSize);
181 }
182
183 if (getRetVarSize() < returnSize)
184 {
185 setRetVarSize(returnSize);
186 }
187
188 uint8_t exsize = (uint8_t)Get_VISA_Exec_Size(execsize);
189
190 auto src0 = funcAddr;
191 if (!src0->isSrcRegRegion() ||
192 (src0->isSrcRegRegion() && (src0->asSrcRegRegion()->getModifier() != Mod_src_undef)))
193 {
194 auto tmpSrc0 = createTempVar(1, Type_D, Any);
195 createMov(g4::SIMD1, createDstRegRegion(tmpSrc0, 1), src0, InstOpt_WriteEnable, true);
196 src0 = createSrcRegRegion(tmpSrc0, getRegionScalar());
197 }
198
199 auto fcall = createInst(predOpnd, G4_pseudo_fcall, nullptr, g4::NOSAT, exsize,
200 nullptr, src0, nullptr, InstOpt_NoOpt, true);
201
202 addFcallInfo(fcall, argSize, returnSize);
203
204 return VISA_SUCCESS;
205 }
206
translateVISACFSymbolInst(const std::string & symbolName,G4_DstRegRegion * dst)207 int IR_Builder::translateVISACFSymbolInst(
208 const std::string& symbolName, G4_DstRegRegion* dst)
209 {
210 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
211
212 if (symbolName.compare("INTEL_PATCH_PRIVATE_MEMORY_SIZE") == 0)
213 {
214 // Relocation for runtime-calculated private memory size
215 auto* privateMemPatch = createRelocImm(Type_UD);
216 dst->setType(Type_UD);
217 G4_INST* mov = createMov(g4::SIMD1, dst, privateMemPatch, InstOpt_WriteEnable, true);
218 RelocationEntry::createRelocation(kernel, *mov, 0, symbolName, GenRelocType::R_SYM_ADDR_32);
219 }
220 else if (Type_D == dst->getType())
221 {
222 auto patchImm = createRelocImm(dst->getType());
223 auto movInst = createMov(g4::SIMD1, dst, patchImm, InstOpt_WriteEnable, true);
224
225 RelocationEntry::createRelocation(kernel, *movInst, 0, symbolName, GenRelocType::R_GLOBAL_IMM_32);
226 }
227 else if (noInt64() || needSwap64ImmLoHi() || VISA_WA_CHECK(getPWaTable(), WaDisallow64BitImmMov))
228 {
229 auto* funcAddrLow = createRelocImm(Type_UD);
230 auto* funcAddrHigh = createRelocImm(Type_UD);
231
232 assert(!dst->isIndirect());
233 // change type from uq to ud, adjust the subRegOff
234 auto dstLo = createDst(dst->getBase(), dst->getRegOff(), dst->getSubRegOff() * 2, 1, Type_UD);
235 G4_INST* movLo = createMov(g4::SIMD1, dstLo, funcAddrLow, InstOpt_WriteEnable, true);
236 // subRegOff will be right following dst's sub-reg
237 auto dstHi = createDst(dst->getBase(), dst->getRegOff(), dst->getSubRegOff() * 2 + 1, 1, Type_UD);
238 G4_INST* movHi = createMov(g4::SIMD1, dstHi, funcAddrHigh, InstOpt_WriteEnable, true);
239
240 RelocationEntry::createRelocation(kernel, *movLo, 0, symbolName, GenRelocType::R_SYM_ADDR_32);
241 RelocationEntry::createRelocation(kernel, *movHi, 0, symbolName, GenRelocType::R_SYM_ADDR_32_HI);
242 }
243 else
244 {
245 // symbolic imm representing symbol's address
246 auto funcAddr = createRelocImm(Type_UQ);
247 auto movInst = createMov(g4::SIMD1, dst, funcAddr, InstOpt_WriteEnable, true);
248
249 RelocationEntry::createRelocation(kernel, *movInst, 0, symbolName, GenRelocType::R_SYM_ADDR);
250 }
251
252 return VISA_SUCCESS;
253 }
254
translateVISACFFretInst(VISA_Exec_Size executionSize,VISA_EMask_Ctrl emask,G4_Predicate * predOpnd)255 int IR_Builder::translateVISACFFretInst(
256 VISA_Exec_Size executionSize, VISA_EMask_Ctrl emask, G4_Predicate *predOpnd)
257 {
258 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
259
260 G4_ExecSize exsize = toExecSize(executionSize);
261 G4_InstOpts instOpts = Get_Gen4_Emask(emask, exsize);
262
263 kernel.fg.setIsStackCallFunc();
264
265 createInst(
266 predOpnd,
267 G4_pseudo_fret,
268 NULL,
269 g4::NOSAT,
270 exsize,
271 NULL,
272 NULL, //src0Opnd
273 NULL,
274 instOpts,
275 true);
276
277 return VISA_SUCCESS;
278 }
279
translateVISACFRetInst(VISA_Exec_Size executionSize,VISA_EMask_Ctrl emask,G4_Predicate * predOpnd)280 int IR_Builder::translateVISACFRetInst(
281 VISA_Exec_Size executionSize, VISA_EMask_Ctrl emask, G4_Predicate *predOpnd)
282 {
283 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
284
285 G4_ExecSize exsize = toExecSize(executionSize);
286 G4_InstOpts instOpts = Get_Gen4_Emask(emask, exsize);
287
288 if (getFCPatchInfo()->getIsCallableKernel() == true)
289 {
290 if (tmpFCRet == nullptr) {
291 input_info_t *RetIP = getRetIPArg();
292 tmpFCRet = createTempVar(2, Type_UD, Four_Word);
293 tmpFCRet->setAliasDeclare(RetIP->dcl, 0);
294 }
295 G4_SrcRegRegion* srcOpndToUse = createSrc(tmpFCRet->getRegVar(), 0, 0, getRegionStride1(),
296 Type_UD);
297
298 createInst(predOpnd,
299 G4_pseudo_fc_ret,
300 NULL,
301 g4::NOSAT,
302 g4::SIMD2,
303 createNullDst(Type_UD),
304 srcOpndToUse,
305 NULL,
306 instOpts,
307 true);
308 }
309 else
310 {
311 createCFInst(predOpnd,
312 subroutineId == 0 ? G4_pseudo_exit : GetGenOpcodeFromVISAOpcode(ISA_RET),
313 exsize,
314 nullptr, nullptr, instOpts, true);
315 }
316
317 return VISA_SUCCESS;
318 }
319
translateVISAGotoInst(G4_Predicate * predOpnd,VISA_Exec_Size executionSize,VISA_EMask_Ctrl emask,G4_Label * label)320 int IR_Builder::translateVISAGotoInst(
321 G4_Predicate* predOpnd,
322 VISA_Exec_Size executionSize, VISA_EMask_Ctrl emask, G4_Label* label)
323 {
324 TIME_SCOPE(VISA_BUILDER_IR_CONSTRUCTION);
325
326 G4_ExecSize exsize = toExecSize(executionSize);
327 G4_InstOpts instOpts = Get_Gen4_Emask(emask, exsize);
328
329 auto cfInst = createInst(
330 predOpnd,
331 G4_goto,
332 nullptr,
333 g4::NOSAT,
334 exsize,
335 nullptr,
336 nullptr,
337 nullptr,
338 instOpts,
339 true);
340 cfInst->asCFInst()->setUip(label);
341
342 return VISA_SUCCESS;
343 }
344