Skip to content

Commit fa441b4

Browse files
aratajewsys_zuul
authored and
sys_zuul
committed
Fix bugs in image/sampler tracking to properly track argument when
compiling with -cl-opt-disable Change-Id: I1168ad986790c6ec61345af7b29b4f3ef02e6e77
1 parent a86006a commit fa441b4

File tree

1 file changed

+84
-109
lines changed

1 file changed

+84
-109
lines changed

IGC/Compiler/Optimizer/OCLBIUtils.cpp

Lines changed: 84 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -224,62 +224,14 @@ Argument* CImagesBI::CImagesUtils::findImageFromBufferPtr(const MetaDataUtils& M
224224
Value* 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

Comments
 (0)