@@ -224,62 +224,14 @@ Argument* CImagesBI::CImagesUtils::findImageFromBufferPtr(const MetaDataUtils& M
224224Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument (CallInst* pCallInst, unsigned int paramIndex, const MetaDataUtils* pMdUtils, const IGC::ModuleMetaData* modMD)
225225{
226226 std::vector<ConstantInt*> gepIndices;
227-
228- std::function<Value* (Value*)> track = [&track](Value* pVal) -> Value *
229- {
230- for (auto U : pVal->users ())
231- {
232- if (auto * GEP = dyn_cast<GetElementPtrInst>(U))
233- {
234- if (!GEP->hasAllZeroIndices ())
235- continue ;
236-
237- if (auto * leaf = track (GEP))
238- return leaf;
239- }
240- else if (CastInst * inst = dyn_cast<CastInst>(U))
241- {
242- if (auto * leaf = track (inst))
243- return leaf;
244- }
245- else if (auto * ST = dyn_cast<StoreInst>(U))
246- {
247- return ST->getValueOperand ();
248- }
249- }
250-
251- return nullptr ;
252- };
253-
254- std::function<Value* (Value*)> findAlloca = [&](Value* pVal) -> Value *
255- {
256- if (auto * GEP = dyn_cast<GetElementPtrInst>(pVal))
257- {
258- if (!GEP->hasAllConstantIndices ())
259- return nullptr ;
260-
261- for (unsigned int i = GEP->getNumIndices (); i > 1 ; --i)
262- gepIndices.push_back (cast<ConstantInt>(GEP->getOperand (i)));
263-
264- if (auto * leaf = findAlloca (GEP->getOperand (0 )))
265- return leaf;
266- }
267- else if (CastInst * inst = dyn_cast<CastInst>(pVal))
268- {
269- if (auto * leaf = findAlloca (inst->getOperand (0 )))
270- return leaf;
271- }
272- else if (auto * allocaInst = dyn_cast<AllocaInst>(pVal))
273- {
274- return allocaInst;
275- }
276- return nullptr ;
277- };
278-
279227 using VisitedValuesSetType = SmallPtrSet<Value*, 10 >;
280- std::function<Value*(Value*, unsigned int , VisitedValuesSetType)> findArgument =
281- [&](Value* pVal, unsigned int depth, VisitedValuesSetType visitedValues) -> Value *
228+ VisitedValuesSetType visitedValues;
282229
230+ // This lambda looks for the value stored into alloca. A specific case here is that
231+ // alloca can contain pointer instead of value. In such case, we also looks into another allocas
232+ // containing the same pointer.
233+ std::function<Value*(Value*, unsigned int )> findArgument =
234+ [&](Value* pVal, unsigned int depth) -> Value *
283235 {
284236 if (!pVal) return nullptr ;
285237
@@ -294,11 +246,12 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
294246 if (!GEP->hasAllConstantIndices ())
295247 return nullptr ;
296248
297- if (GEP->getNumIndices () > depth + 1 )
249+ unsigned numIndices = GEP->getNumIndices ();
250+ if (numIndices > depth + 1 )
298251 continue ;
299252
300253 bool matchingGep = false ;
301- for (unsigned int i = 1 ; i < GEP-> getNumIndices () ; ++i)
254+ for (unsigned int i = 1 ; i < numIndices ; ++i)
302255 {
303256 if (gepIndices[depth - i]->getZExtValue () == cast<ConstantInt>(GEP->getOperand (i + 1 ))->getZExtValue ())
304257 matchingGep = true ;
@@ -312,25 +265,57 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
312265 if (!matchingGep)
313266 continue ;
314267
315- if (auto * leaf = findArgument (GEP, depth - (GEP->getNumIndices () - 1 ), visitedValues))
268+ unsigned reducedIndices = numIndices - 1 ;
269+ if (auto * leaf = findArgument (GEP, depth - reducedIndices))
270+ {
271+ IGC_ASSERT (gepIndices.size () >= reducedIndices);
272+ gepIndices.resize (gepIndices.size () - reducedIndices);
316273 return leaf;
274+ }
317275 }
318276 else if (CastInst * inst = dyn_cast<CastInst>(U))
319277 {
320- if (auto * leaf = findArgument (inst, depth, visitedValues ))
278+ if (auto * leaf = findArgument (inst, depth))
321279 return leaf;
322280 }
323281 else if (CallInst * callInst = dyn_cast<CallInst>(U))
324282 {
325283 if (callInst->getCalledFunction ()->getIntrinsicID () == Intrinsic::memcpy)
326284 {
327- if (auto * leaf = findArgument (findAlloca (callInst->getOperand (1 )), depth, visitedValues))
285+ return callInst->getOperand (1 );
286+ }
287+ }
288+ else if (LoadInst * loadInst = dyn_cast<LoadInst>(U))
289+ {
290+ // Continue tracing load if it's type is a pointer. Example(tracing %1 alloca value):
291+ // %0 = alloca %opencl.image2d_t.read_only addrspace(1)*, align 8
292+ // %1 = alloca %opencl.image2d_t.read_only addrspace(1)*, align 8
293+ // %2 = load %opencl.image2d_t.read_only addrspace(1)*, %opencl.image2d_t.read_only addrspace(1)** %1, align 8
294+ // store %opencl.image2d_t.read_only addrspace(1)* %2, %opencl.image2d_t.read_only addrspace(1)** %0, align 8
295+ // %3 = load % opencl.image2d_t.read_only addrspace(1)*, %opencl.image2d_t.read_only addrspace(1)** %0, align 8
296+ // We cannot ignore load if alloca type is a pointer.
297+ if (loadInst->getType ()->isPointerTy ())
298+ {
299+ if (auto * leaf = findArgument (loadInst, depth))
328300 return leaf;
329301 }
330302 }
331303 else if (auto * ST = dyn_cast<StoreInst>(U))
332304 {
333- return ST->getValueOperand ();
305+ Value* V = ST->getValueOperand ();
306+ if (V == pVal)
307+ {
308+ // If we are here, it means that alloca value is stored into another alloca.
309+ // Check if value is pointer type, if so, it means that our object can be accessed
310+ // through another alloca and we need to continue tracing it.
311+ if (V->getType ()->isPointerTy ())
312+ {
313+ if (auto * leaf = findArgument (ST->getPointerOperand (), depth))
314+ return leaf;
315+ }
316+ }
317+ else
318+ return ST->getValueOperand ();
334319 }
335320 }
336321 return nullptr ;
@@ -339,6 +324,7 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
339324 Value* baseValue = pCallInst->getOperand (paramIndex);
340325 while (true )
341326 {
327+ visitedValues.insert (baseValue);
342328 if (isa<Argument>(baseValue))
343329 {
344330 // Reached an Argument, return it.
@@ -458,6 +444,38 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
458444 }
459445 }
460446 }
447+ else if (AllocaInst * alloca = dyn_cast<AllocaInst>(baseValue))
448+ {
449+ auto * pArg = findArgument (alloca, gepIndices.size ());
450+ if (pArg)
451+ {
452+ if ((isa<Argument>(pArg) || isa<ConstantInt>(pArg)))
453+ {
454+ return pArg;
455+ }
456+ else
457+ {
458+ baseValue = pArg;
459+ continue ;
460+ }
461+ }
462+ else
463+ {
464+ // Cannot trace, it could be a bindless or indirect access
465+ return nullptr ;
466+ }
467+ }
468+ else if (GetElementPtrInst * gep = dyn_cast<GetElementPtrInst>(baseValue))
469+ {
470+ if (!gep->hasAllConstantIndices ())
471+ return nullptr ;
472+
473+ for (unsigned int i = gep->getNumIndices (); i > 1 ; --i)
474+ gepIndices.push_back (cast<ConstantInt>(gep->getOperand (i)));
475+
476+ baseValue = gep->getOperand (0 );
477+ continue ;
478+ }
461479 else if (LoadInst * load = dyn_cast<LoadInst>(baseValue))
462480 {
463481 // Found a LoadInst, it could be
@@ -477,59 +495,16 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
477495 pSamplerVal->getAggregateElement (0U ) : pSamplerVal;
478496 }
479497
480- // Simple case:
481- // If, after stripping casts and zero GEPs, we make it to alloca then the base of that alloca must contain the image.
482- // track() will walk through casts and zero GEPs that don't change the offset of the pointer until arriving at the store
483- // (assuming it is the only store to that location for an image) whose value should be the image argument.
484- Value* pVal = addr->stripPointerCasts ();
485- if (isa<AllocaInst>(pVal))
498+ if (isa<LoadInst>(addr) ||
499+ isa<AllocaInst>(addr) ||
500+ isa<GetElementPtrInst>(addr))
486501 {
487- auto * pArg = track (pVal);
488- if (pArg)
489- {
490- if ((isa<Argument>(pArg) || isa<ConstantInt>(pArg)))
491- {
492- return pArg;
493- }
494- else if (isa<LoadInst>(pArg))
495- {
496- // If tracked value is load instruction, it means that 'pVal' alloca uses value from another alloca.
497- // Let's make a try to recursively track argument stored into that another alloca.
498- baseValue = pArg;
499- continue ;
500- }
501- }
502- }
503-
504- // More complicated case:
505- // We need to go through non-zero GEPs, memcpys and casts to reach an argument.
506- // In the same time we need to track the indices for geps as there might be more loads/stores to given alloca.
507- if (GetElementPtrInst * getElementPtr = dyn_cast<GetElementPtrInst>(addr))
508- {
509- addr = findAlloca (getElementPtr);
510- if (addr && isa<AllocaInst>(addr))
511- {
512- VisitedValuesSetType visitedValues;
513- auto * pArg = findArgument (addr, gepIndices.size (), visitedValues);
514- if (pArg && isa<Argument>(pArg))
515- {
516- return pArg;
517- }
518- else
519- {
520- // Cannot trace, it could be indirect access
521- return nullptr ;
522- }
523- }
524- else
525- {
526- // Cannot trace, it could be indirect access
527- return nullptr ;
528- }
502+ baseValue = addr;
503+ continue ;
529504 }
530505 else
531506 {
532- IGC_ASSERT_MESSAGE (getElementPtr , " Expected GEP instruction. " );
507+ IGC_ASSERT_MESSAGE (0 , " Unexpected instruction" );
533508 return nullptr ;
534509 }
535510 }
0 commit comments