@@ -106,6 +106,97 @@ char OpenCLPrintfResolution::ID = 0;
106106// | < vec_element_3 > |
107107// |------------------------------|
108108
109+ // Looks for a GlobalVariable related with given value.
110+ // Returns nullptr if on the way to the global variable
111+ // found anything that is not :
112+ // * a CastInst
113+ // * a GEP with non-zero indices
114+ // * a SelectInst
115+ // * a PHINode
116+ // In case of select or phi instruction two operands are added to the vector.
117+ // In another case only one is added.
118+ inline SmallVector<Value*, 2 > getGlobalVariable (Value* const v)
119+ {
120+ SmallVector<Value *, 2 > curr;
121+ curr.push_back (v);
122+
123+ while (nullptr != curr.front () || nullptr != curr.back ())
124+ {
125+ if (curr.size () == 1 && isa<GlobalVariable>(curr.front ()))
126+ {
127+ break ;
128+ }
129+ else if (curr.size () == 2 && (isa<GlobalVariable>(curr.front ()) && isa<GlobalVariable>(curr.back ())))
130+ {
131+ break ;
132+ }
133+
134+ if (CastInst* castInst = dyn_cast<CastInst>(curr.front ()))
135+ {
136+ curr.pop_back ();
137+ curr.push_back (castInst->getOperand (0 ));
138+ }
139+ else if (GetElementPtrInst* getElemPtrInst = dyn_cast<GetElementPtrInst>(curr.front ()))
140+ {
141+ if (curr.size () == 2 )
142+ {
143+ if (GetElementPtrInst* getElemPtrInst2 = dyn_cast<GetElementPtrInst>(curr.back ()))
144+ {
145+ curr.pop_back ();
146+ curr.pop_back ();
147+ curr.push_back (getElemPtrInst->hasAllZeroIndices () ? getElemPtrInst->getPointerOperand () : nullptr );
148+ curr.push_back (getElemPtrInst2->hasAllZeroIndices () ? getElemPtrInst2->getPointerOperand () : nullptr );
149+ }
150+ }
151+ else
152+ {
153+ curr.pop_back ();
154+ curr.push_back (getElemPtrInst->hasAllZeroIndices () ? getElemPtrInst->getPointerOperand () : nullptr );
155+ }
156+ }
157+ else if (SelectInst* selectInst = dyn_cast<SelectInst>(curr.front ()))
158+ {
159+ if (curr.size () == 2 )
160+ {
161+ // Nested select instruction is not supported
162+ curr.front () = nullptr ;
163+ curr.back () = nullptr ;
164+ }
165+ else
166+ {
167+ curr.pop_back ();
168+ curr.push_back (selectInst->getOperand (1 ));
169+ curr.push_back (selectInst->getOperand (2 ));
170+ }
171+ }
172+ else if (PHINode* phiNode = dyn_cast<PHINode>(curr.front ()))
173+ {
174+ if (curr.size () == 2 )
175+ {
176+ // Nested phi instruction is not supported
177+ curr.front () = nullptr ;
178+ curr.back () = nullptr ;
179+ }
180+ else
181+ {
182+ curr.pop_back ();
183+ curr.push_back (phiNode->getOperand (0 ));
184+ curr.push_back (phiNode->getOperand (1 ));
185+ }
186+ }
187+ else
188+ {
189+ // Unhandled value type
190+ curr.front () = nullptr ;
191+ if (curr.size () == 2 )
192+ {
193+ curr.back () = nullptr ;
194+ }
195+ }
196+ }
197+ return curr;
198+ }
199+
109200OpenCLPrintfResolution::OpenCLPrintfResolution () : FunctionPass(ID), m_atomicAddFunc(nullptr )
110201{
111202 initializeOpenCLPrintfResolutionPass (*PassRegistry::getPassRegistry ());
@@ -225,24 +316,24 @@ std::string OpenCLPrintfResolution::getEscapedString(const ConstantDataSequentia
225316 return Name;
226317}
227318
228- Value* OpenCLPrintfResolution::processPrintfString (Value* arg , Function& F)
319+ Value* OpenCLPrintfResolution::processPrintfString (Value* printfArg , Function& F)
229320{
230321 GlobalVariable* formatString = nullptr ;
231-
232- if (isa<GlobalVariable>(arg))
322+ SmallVector<Value*, 2 > curr = getGlobalVariable (printfArg);
323+ SmallVector<unsigned int , 2 > sv;
324+ for (auto curr_i : curr)
233325 {
234- formatString = dyn_cast_or_null<GlobalVariable>(arg);
235- if ((nullptr == formatString) || !formatString->hasInitializer ())
326+ auto & curr_e = *curr_i;
327+
328+ formatString = dyn_cast_or_null<GlobalVariable>(&curr_e);
329+ ConstantDataArray* formatStringConst = ((nullptr != formatString) && (formatString->hasInitializer ())) ?
330+ dyn_cast<ConstantDataArray>(formatString->getInitializer ()) :
331+ nullptr ;
332+
333+ if (nullptr == formatStringConst)
236334 {
237335 IGC_ASSERT_MESSAGE (0 , " Unexpected printf argument (expected string literal)" );
238- return ConstantInt::get (m_int32Type, -1 );
239- }
240- ConstantDataArray* formatStringConst = dyn_cast<ConstantDataArray>(formatString->getInitializer ());
241- std::string escaped_string = getEscapedString (formatStringConst);
242-
243- // preventing MD enries duplication
244- if (m_MapStringStringIndex.find (escaped_string) != m_MapStringStringIndex.end ()) {
245- return ConstantInt::get (m_int32Type, m_MapStringStringIndex[escaped_string]);
336+ return 0 ;
246337 }
247338
248339 if (m_CGContext->type == ShaderType::RAYTRACING_SHADER)
@@ -259,107 +350,78 @@ Value* OpenCLPrintfResolution::processPrintfString(Value* arg, Function& F)
259350 Metadata* stringIndexVal = ConstantAsMetadata::get (
260351 ConstantInt::get (m_int32Type, m_stringIndex));
261352
353+ sv.push_back (m_stringIndex++);
354+
355+ std::string escaped_string = getEscapedString (formatStringConst);
262356 MDString* final_string = MDString::get (*m_context, escaped_string);
263357
264358 args.push_back (stringIndexVal);
265359 args.push_back (final_string);
266360
267361 MDNode* itemMDNode = MDNode::get (*m_context, args);
268362 namedMDNode->addOperand (itemMDNode);
269-
270- m_MapStringStringIndex[escaped_string] = m_stringIndex;
271-
272- return ConstantInt::get (m_int32Type, m_stringIndex++);
273- }
274- else if (CastInst* castInst = dyn_cast<CastInst>(arg))
275- {
276- return processPrintfString (castInst->getOperand (0 ), F);
277- }
278- else if (GetElementPtrInst* getElemPtrInst = dyn_cast<GetElementPtrInst>(arg))
279- {
280- IGC_ASSERT_MESSAGE (getElemPtrInst->hasAllZeroIndices (), " Only All Zero indices GEP supported" );
281- return processPrintfString (getElemPtrInst->getPointerOperand (), F);
282363 }
283- else if (SelectInst* selectInst = dyn_cast<SelectInst>(arg))
284- {
285- SelectInst* selectInst2 = SelectInst::Create (selectInst->getOperand (0 ),
286- processPrintfString (selectInst->getOperand (1 ), F),
287- processPrintfString (selectInst->getOperand (2 ), F),
288- " " , selectInst);
289- return selectInst2;
290- }
291- else if (PHINode* phiNode = dyn_cast<PHINode>(arg))
364+
365+ // Checks if the vector have two elements.
366+ // If it has it adds a new phi/select instruction that is responsible
367+ // for the correct execution of the basic instruction.
368+ // This information is forwarded to the store instruction.
369+ if (curr.size () == 2 )
292370 {
293- unsigned inNum = phiNode->getNumIncomingValues ();
294- PHINode* phiNode2 = PHINode::Create (m_int32Type, inNum, " " , phiNode);
295- for (unsigned i = 0 ; i < inNum; i++)
371+ if (GetElementPtrInst* getElemPtrInst = dyn_cast<GetElementPtrInst>(printfArg))
296372 {
297- phiNode2->addIncoming (processPrintfString (phiNode->getIncomingValue (i), F), phiNode->getIncomingBlock (i));
373+ if (PHINode* phiNode = dyn_cast<PHINode>(getElemPtrInst->getPointerOperand ()))
374+ {
375+ PHINode* phiNode2 = PHINode::Create (m_int32Type, 2 , " " , phiNode);
376+ phiNode2->addIncoming (ConstantInt::get (m_int32Type, sv.front ()), phiNode->getIncomingBlock (0 ));
377+ phiNode2->addIncoming (ConstantInt::get (m_int32Type, sv.back ()), phiNode->getIncomingBlock (1 ));
378+ return phiNode2;
379+ }
380+ }
381+ else if (SelectInst* selectInst = dyn_cast<SelectInst>(printfArg))
382+ {
383+ SelectInst* selectInst2 = SelectInst::Create (selectInst->getOperand (0 ), ConstantInt::get (m_int32Type, sv.front ()),
384+ ConstantInt::get (m_int32Type, sv.back ()), " " , selectInst);
385+ return selectInst2;
386+ }
387+ else
388+ {
389+ IGC_ASSERT_MESSAGE (0 , " Instructions in the vector are not supported!" );
298390 }
299- return phiNode2;
300- }
301- else
302- {
303- IGC_ASSERT_MESSAGE (0 , " Unsupported Instruction!" );
304391 }
305392
306393 ModuleMetaData* modMd = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData ();
307394 if (IGC_IS_FLAG_ENABLED (EnableZEBinary) || modMd->compOpt .EnableZEBinary )
308395 {
309- return arg ;
396+ return printfArg ;
310397 }
311398 else
312399 {
313- return ConstantInt::get (m_int32Type, - 1 );
400+ return ConstantInt::get (m_int32Type, m_stringIndex - 1 );
314401 }
315402}
316403
317- // Checks pathes to global variables and returns true if all paths lead to constant strings.
318- // Only these instructions acepted in pathes:
319- // * a CastInst
320- // * a GEP with all-zero indices
321- // * a SelectInst
322- // * a PHINode
323- // It is expected that the paths are not looped.
324- bool OpenCLPrintfResolution::argIsString (Value* arg)
404+
405+ bool OpenCLPrintfResolution::argIsString (Value* printfArg)
325406{
326- if (isa<GlobalVariable>(arg))
407+ GlobalVariable* formatString = nullptr ;
408+ SmallVector<Value*, 2 > curr = getGlobalVariable (printfArg);
409+
410+ for (auto curr_i : curr)
327411 {
328- GlobalVariable* formatString = dyn_cast_or_null<GlobalVariable>(arg);
412+ auto & curr_e = *curr_i;
413+ formatString = dyn_cast_or_null<GlobalVariable>(&curr_e);
329414 if (nullptr == formatString || !formatString->hasInitializer ())
330415 {
331416 return false ;
332417 }
333418 ConstantDataArray* formatStringConst = dyn_cast<ConstantDataArray>(formatString->getInitializer ());
334419 if (!formatStringConst || !formatStringConst->isCString ())
335420 {
336- return false ;
337- }
338- return true ;
339- }
340- else if (CastInst* castInst = dyn_cast<CastInst>(arg))
341- {
342- return argIsString (castInst->getOperand (0 ));
343- }
344- if (GetElementPtrInst* getElemPtrInst = dyn_cast<GetElementPtrInst>(arg))
345- {
346- return getElemPtrInst->hasAllZeroIndices () && argIsString (getElemPtrInst->getPointerOperand ());
347- }
348- else if (SelectInst* selectInst = dyn_cast<SelectInst>(arg))
349- {
350- return argIsString (selectInst->getOperand (1 )) &&
351- argIsString (selectInst->getOperand (2 ));
352- }
353- else if (PHINode* phiNode = dyn_cast<PHINode>(arg))
354- {
355- for (unsigned i = 0 ; i < phiNode->getNumIncomingValues (); i++)
356- {
357- if (!argIsString (phiNode->getIncomingValue (i)))
358- return false ;
421+ return false ;
359422 }
360- return true ;
361423 }
362- return false ;
424+ return true ;
363425}
364426
365427std::string OpenCLPrintfResolution::getPrintfStringsMDNodeName (Function& F)
0 commit comments