@@ -58,10 +58,10 @@ struct SYCLInternalizerImpl {
58
58
// / - Promote the function and call the new function instead,
59
59
// / keeping the original function.
60
60
// / - The value appears in a load/store operation: Do nothing
61
- void promoteValue (Value *Val, std::size_t LocalSize) const ;
61
+ void promoteValue (Value *Val, std::size_t LocalSize, bool InAggregate ) const ;
62
62
63
63
void promoteGEPI (GetElementPtrInst *GEPI, const Value *Val,
64
- std::size_t LocalSize) const ;
64
+ std::size_t LocalSize, bool InAggregate ) const ;
65
65
66
66
void promoteCall (CallBase *C, const Value *Val, std::size_t LocalSize) const ;
67
67
@@ -81,23 +81,26 @@ struct SYCLInternalizerImpl {
81
81
// /
82
82
// / Check that an value can be promoted.
83
83
// / For GEP and Call instructions, delegate to the specific implementations.
84
+ // / \p InAggregate indicates that at least one GEP instruction addressing into
85
+ // / an aggregate object was encountered, hence \p Val no longer represents a
86
+ // / pure offset computation on the original candidate argument.
84
87
// / For address-space casts, pointer-to-int conversions and unknown users,
85
88
// / return an error.
86
- Error canPromoteValue (Value *Val, size_t LocalSize) const ;
89
+ Error canPromoteValue (Value *Val, size_t LocalSize, bool InAggregate ) const ;
87
90
88
91
// /
89
- // / Check that the operand of a GEP can be promoted.
90
- // / If the GEP uses more than one index, return an error.
91
- // / Otherwise, check if the GEP itself can be promoted in its users.
92
+ // / Check that the operand of a GEP can be promoted to its users, and
93
+ // / propagate whether it represents a pointer into an aggregate object.
92
94
Error canPromoteGEP (GetElementPtrInst *GEPI, const Value *Val,
93
- size_t LocalSize) const ;
95
+ size_t LocalSize, bool InAggregate ) const ;
94
96
95
97
// /
96
98
// / Check if operand to a function call can be promoted.
97
- // / If the function returns a pointer, return an error.
98
- // / Otherwise, check if the corresponding formal parameter can be promoted in
99
- // / the function body.
100
- Error canPromoteCall (CallBase *C, const Value *Val, size_t LocalSize) const ;
99
+ // / If the function returns a pointer, or the operand points into an aggregate
100
+ // / object, return an error. Otherwise, check if the corresponding formal
101
+ // / parameter can be promoted in the function body.
102
+ Error canPromoteCall (CallBase *C, const Value *Val, size_t LocalSize,
103
+ bool InAggregate) const ;
101
104
102
105
Error checkArgsPromotable (Function *F,
103
106
SmallVectorImpl<size_t > &PromoteArgSizes) const ;
@@ -212,7 +215,8 @@ getUsagesInternalization(const User *U, const Value *V, std::size_t LocalSize) {
212
215
}
213
216
214
217
Error SYCLInternalizerImpl::canPromoteCall (CallBase *C, const Value *Val,
215
- size_t LocalSize) const {
218
+ size_t LocalSize,
219
+ bool InAggregate) const {
216
220
if (isa<PointerType>(C->getType ())) {
217
221
// With opaque pointers, we do not have the necessary information to compare
218
222
// the element-type of the pointer returned by the function and the element
@@ -222,6 +226,12 @@ Error SYCLInternalizerImpl::canPromoteCall(CallBase *C, const Value *Val,
222
226
inconvertibleErrorCode (),
223
227
" It is not safe to promote a called function which returns a pointer." );
224
228
}
229
+ if (InAggregate) {
230
+ return createStringError (
231
+ inconvertibleErrorCode (),
232
+ " Promotion of a pointer into an aggregate object to a called function "
233
+ " is currently not supported." );
234
+ }
225
235
226
236
SmallVector<size_t > InternInfo = getUsagesInternalization (C, Val, LocalSize);
227
237
assert (!InternInfo.empty () && " Value must be used at least once" );
@@ -232,27 +242,23 @@ Error SYCLInternalizerImpl::canPromoteCall(CallBase *C, const Value *Val,
232
242
}
233
243
234
244
Error SYCLInternalizerImpl::canPromoteGEP (GetElementPtrInst *GEPI,
235
- const Value *Val,
236
- size_t LocalSize ) const {
245
+ const Value *Val, size_t LocalSize,
246
+ bool InAggregate ) const {
237
247
if (cast<PointerType>(GEPI->getType ())->getAddressSpace () == AS) {
238
248
// If the GEPI is already using the correct address-space, no change is
239
249
// required.
240
250
return Error::success ();
241
251
}
242
- if (GEPI->getNumIndices () != 1 &&
243
- std::any_of (GEPI->user_begin (), GEPI->user_end (), [](const auto *User) {
244
- return isa<GetElementPtrInst>(User);
245
- })) {
246
- return createStringError (inconvertibleErrorCode (),
247
- " Only one index expected in source of "
248
- " promotable GEP instruction pointer argument" );
249
- }
250
- // Recurse to check all users of the GEP.
251
- return canPromoteValue (GEPI, LocalSize);
252
+ // Recurse to check all users of the GEP. We are either already in
253
+ // `InAggregate` mode, or inspect the current instruction. Recall that a GEP's
254
+ // first index is used to step through the base pointer, whereas any
255
+ // additional indices represent addressing into an aggregrate type.
256
+ return canPromoteValue (GEPI, LocalSize,
257
+ InAggregate || GEPI->getNumIndices () >= 2 );
252
258
}
253
259
254
- Error SYCLInternalizerImpl::canPromoteValue (Value *Val,
255
- size_t LocalSize ) const {
260
+ Error SYCLInternalizerImpl::canPromoteValue (Value *Val, size_t LocalSize,
261
+ bool InAggregate ) const {
256
262
for (auto *U : Val->users ()) {
257
263
auto *I = dyn_cast<Instruction>(U);
258
264
if (!I) {
@@ -272,13 +278,14 @@ Error SYCLInternalizerImpl::canPromoteValue(Value *Val,
272
278
case Instruction::Call:
273
279
case Instruction::Invoke:
274
280
case Instruction::CallBr:
275
- if (auto Err = canPromoteCall (cast<CallBase>(I), Val, LocalSize)) {
281
+ if (auto Err =
282
+ canPromoteCall (cast<CallBase>(I), Val, LocalSize, InAggregate)) {
276
283
return Err;
277
284
}
278
285
break ;
279
286
case Instruction::GetElementPtr:
280
- if (auto Err =
281
- canPromoteGEP (cast<GetElementPtrInst>(I), Val, LocalSize )) {
287
+ if (auto Err = canPromoteGEP (cast<GetElementPtrInst>(I), Val, LocalSize,
288
+ InAggregate )) {
282
289
return Err;
283
290
}
284
291
break ;
@@ -316,7 +323,7 @@ Error SYCLInternalizerImpl::checkArgsPromotable(
316
323
PromoteArgSizes[Index] = 0 ;
317
324
continue ;
318
325
}
319
- if (auto Err = canPromoteValue (Arg, LocalSize)) {
326
+ if (auto Err = canPromoteValue (Arg, LocalSize, /* InAggregate= */ false )) {
320
327
// Set the local size to 0 to indicate that this argument should not be
321
328
// promoted.
322
329
PromoteArgSizes[Index] = 0 ;
@@ -360,30 +367,37 @@ void SYCLInternalizerImpl::promoteCall(CallBase *C, const Value *Val,
360
367
}
361
368
362
369
void SYCLInternalizerImpl::promoteGEPI (GetElementPtrInst *GEPI,
363
- const Value *Val,
364
- std:: size_t LocalSize ) const {
370
+ const Value *Val, std:: size_t LocalSize,
371
+ bool InAggregate ) const {
365
372
// Not PointerType is unreachable. Other case is catched in caller.
366
373
if (cast<PointerType>(GEPI->getType ())->getAddressSpace () != AS) {
367
- remapIndices (GEPI, LocalSize);
374
+ if (!InAggregate)
375
+ remapIndices (GEPI, LocalSize);
368
376
auto *ValTy = cast<PointerType>(Val->getType ());
369
377
GEPI->mutateType (PointerType::getWithSamePointeeType (
370
378
cast<PointerType>(GEPI->getType ()), ValTy->getAddressSpace ()));
371
- return promoteValue (GEPI, LocalSize);
379
+ // Recurse to promote to all users of the GEP. We are either already in
380
+ // `InAggregate` mode, or inspect the current instruction. Recall that a
381
+ // GEP's first index is used to step through the base pointer, whereas any
382
+ // additional indices represent addressing into an aggregrate type.
383
+ return promoteValue (GEPI, LocalSize,
384
+ InAggregate || GEPI->getNumIndices () >= 2 );
372
385
}
373
386
}
374
387
375
- void SYCLInternalizerImpl::promoteValue (Value *Val,
376
- std:: size_t LocalSize ) const {
388
+ void SYCLInternalizerImpl::promoteValue (Value *Val, std:: size_t LocalSize,
389
+ bool InAggregate ) const {
377
390
for (auto *U : Val->users ()) {
378
391
auto *I = cast<Instruction>(U);
379
392
switch (I->getOpcode ()) {
380
393
case Instruction::Call:
381
394
case Instruction::Invoke:
382
395
case Instruction::CallBr:
396
+ assert (!InAggregate);
383
397
promoteCall (cast<CallBase>(I), Val, LocalSize);
384
398
break ;
385
399
case Instruction::GetElementPtr:
386
- promoteGEPI (cast<GetElementPtrInst>(I), Val, LocalSize);
400
+ promoteGEPI (cast<GetElementPtrInst>(I), Val, LocalSize, InAggregate );
387
401
break ;
388
402
case Instruction::Load:
389
403
case Instruction::Store:
@@ -535,7 +549,7 @@ Function *SYCLInternalizerImpl::promoteFunctionArgs(
535
549
if (CreateAllocas) {
536
550
Arg = replaceByNewAlloca (cast<Argument>(Arg), AS, LocalSize);
537
551
}
538
- promoteValue (Arg, LocalSize);
552
+ promoteValue (Arg, LocalSize, /* InAggregate= */ false );
539
553
}
540
554
541
555
TargetInfo.updateAddressSpaceMetadata (NewF, PromoteToLocal, AS);
0 commit comments