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