@@ -224,62 +224,14 @@ Argument* CImagesBI::CImagesUtils::findImageFromBufferPtr(const MetaDataUtils& M
224
224
Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument (CallInst* pCallInst, unsigned int paramIndex, const MetaDataUtils* pMdUtils, const IGC::ModuleMetaData* modMD)
225
225
{
226
226
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
-
279
227
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;
282
229
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 *
283
235
{
284
236
if (!pVal) return nullptr ;
285
237
@@ -294,11 +246,12 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
294
246
if (!GEP->hasAllConstantIndices ())
295
247
return nullptr ;
296
248
297
- if (GEP->getNumIndices () > depth + 1 )
249
+ unsigned numIndices = GEP->getNumIndices ();
250
+ if (numIndices > depth + 1 )
298
251
continue ;
299
252
300
253
bool matchingGep = false ;
301
- for (unsigned int i = 1 ; i < GEP-> getNumIndices () ; ++i)
254
+ for (unsigned int i = 1 ; i < numIndices ; ++i)
302
255
{
303
256
if (gepIndices[depth - i]->getZExtValue () == cast<ConstantInt>(GEP->getOperand (i + 1 ))->getZExtValue ())
304
257
matchingGep = true ;
@@ -312,25 +265,57 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
312
265
if (!matchingGep)
313
266
continue ;
314
267
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);
316
273
return leaf;
274
+ }
317
275
}
318
276
else if (CastInst * inst = dyn_cast<CastInst>(U))
319
277
{
320
- if (auto * leaf = findArgument (inst, depth, visitedValues ))
278
+ if (auto * leaf = findArgument (inst, depth))
321
279
return leaf;
322
280
}
323
281
else if (CallInst * callInst = dyn_cast<CallInst>(U))
324
282
{
325
283
if (callInst->getCalledFunction ()->getIntrinsicID () == Intrinsic::memcpy )
326
284
{
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))
328
300
return leaf;
329
301
}
330
302
}
331
303
else if (auto * ST = dyn_cast<StoreInst>(U))
332
304
{
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 ();
334
319
}
335
320
}
336
321
return nullptr ;
@@ -339,6 +324,7 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
339
324
Value* baseValue = pCallInst->getOperand (paramIndex);
340
325
while (true )
341
326
{
327
+ visitedValues.insert (baseValue);
342
328
if (isa<Argument>(baseValue))
343
329
{
344
330
// Reached an Argument, return it.
@@ -458,6 +444,38 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
458
444
}
459
445
}
460
446
}
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
+ }
461
479
else if (LoadInst * load = dyn_cast<LoadInst>(baseValue))
462
480
{
463
481
// Found a LoadInst, it could be
@@ -477,59 +495,16 @@ Value* CImagesBI::CImagesUtils::traceImageOrSamplerArgument(CallInst* pCallInst,
477
495
pSamplerVal->getAggregateElement (0U ) : pSamplerVal;
478
496
}
479
497
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))
486
501
{
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 ;
529
504
}
530
505
else
531
506
{
532
- IGC_ASSERT_MESSAGE (getElementPtr , " Expected GEP instruction. " );
507
+ IGC_ASSERT_MESSAGE (0 , " Unexpected instruction" );
533
508
return nullptr ;
534
509
}
535
510
}
0 commit comments