@@ -65,6 +65,10 @@ class SPIRVEmitIntrinsics
65
65
Type *deduceElementType (Value *I);
66
66
Type *deduceElementTypeHelper (Value *I);
67
67
Type *deduceElementTypeHelper (Value *I, std::unordered_set<Value *> &Visited);
68
+ Type *deduceElementTypeByValueDeep (Type *ValueTy, Value *Operand,
69
+ std::unordered_set<Value *> &Visited);
70
+ Type *deduceElementTypeByUsersDeep (Value *Op,
71
+ std::unordered_set<Value *> &Visited);
68
72
69
73
// deduce nested types of composites
70
74
Type *deduceNestedTypeHelper (User *U);
@@ -176,6 +180,44 @@ static inline void reportFatalOnTokenType(const Instruction *I) {
176
180
false );
177
181
}
178
182
183
+ // Set element pointer type to the given value of ValueTy and tries to
184
+ // specify this type further (recursively) by Operand value, if needed.
185
+ Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep (
186
+ Type *ValueTy, Value *Operand, std::unordered_set<Value *> &Visited) {
187
+ Type *Ty = ValueTy;
188
+ if (Operand) {
189
+ if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
190
+ if (Type *NestedTy = deduceElementTypeHelper (Operand, Visited))
191
+ Ty = TypedPointerType::get (NestedTy, PtrTy->getAddressSpace ());
192
+ } else {
193
+ Ty = deduceNestedTypeHelper (dyn_cast<User>(Operand), Ty, Visited);
194
+ }
195
+ }
196
+ return Ty;
197
+ }
198
+
199
+ // Traverse User instructions to deduce an element pointer type of the operand.
200
+ Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep (
201
+ Value *Op, std::unordered_set<Value *> &Visited) {
202
+ if (!Op || !isPointerTy (Op->getType ()))
203
+ return nullptr ;
204
+
205
+ if (auto PType = dyn_cast<TypedPointerType>(Op->getType ()))
206
+ return PType->getElementType ();
207
+
208
+ // maybe we already know operand's element type
209
+ if (Type *KnownTy = GR->findDeducedElementType (Op))
210
+ return KnownTy;
211
+
212
+ for (User *OpU : Op->users ()) {
213
+ if (Instruction *Inst = dyn_cast<Instruction>(OpU)) {
214
+ if (Type *Ty = deduceElementTypeHelper (Inst, Visited))
215
+ return Ty;
216
+ }
217
+ }
218
+ return nullptr ;
219
+ }
220
+
179
221
// Deduce and return a successfully deduced Type of the Instruction,
180
222
// or nullptr otherwise.
181
223
Type *SPIRVEmitIntrinsics::deduceElementTypeHelper (Value *I) {
@@ -206,21 +248,27 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
206
248
} else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
207
249
Ty = Ref->getResultElementType ();
208
250
} else if (auto *Ref = dyn_cast<GlobalValue>(I)) {
209
- Ty = Ref->getValueType ();
210
- if (Value *Op = Ref->getNumOperands () > 0 ? Ref->getOperand (0 ) : nullptr ) {
211
- if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
212
- if (Type *NestedTy = deduceElementTypeHelper (Op, Visited))
213
- Ty = TypedPointerType::get (NestedTy, PtrTy->getAddressSpace ());
214
- } else {
215
- Ty = deduceNestedTypeHelper (dyn_cast<User>(Op), Ty, Visited);
216
- }
217
- }
251
+ Ty = deduceElementTypeByValueDeep (
252
+ Ref->getValueType (),
253
+ Ref->getNumOperands () > 0 ? Ref->getOperand (0 ) : nullptr , Visited);
218
254
} else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
219
255
Ty = deduceElementTypeHelper (Ref->getPointerOperand (), Visited);
220
256
} else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
221
257
if (Type *Src = Ref->getSrcTy (), *Dest = Ref->getDestTy ();
222
258
isPointerTy (Src) && isPointerTy (Dest))
223
259
Ty = deduceElementTypeHelper (Ref->getOperand (0 ), Visited);
260
+ } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
261
+ Value *Op = Ref->getNewValOperand ();
262
+ Ty = deduceElementTypeByValueDeep (Op->getType (), Op, Visited);
263
+ } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
264
+ Value *Op = Ref->getValOperand ();
265
+ Ty = deduceElementTypeByValueDeep (Op->getType (), Op, Visited);
266
+ } else if (auto *Ref = dyn_cast<PHINode>(I)) {
267
+ for (unsigned i = 0 ; i < Ref->getNumIncomingValues (); i++) {
268
+ Ty = deduceElementTypeByUsersDeep (Ref->getIncomingValue (i), Visited);
269
+ if (Ty)
270
+ break ;
271
+ }
224
272
}
225
273
226
274
// remember the found relationship
@@ -293,6 +341,22 @@ Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(
293
341
return NewTy;
294
342
}
295
343
}
344
+ } else if (auto *VecTy = dyn_cast<VectorType>(OrigTy)) {
345
+ if (Value *Op = U->getNumOperands () > 0 ? U->getOperand (0 ) : nullptr ) {
346
+ Type *OpTy = VecTy->getElementType ();
347
+ Type *Ty = OpTy;
348
+ if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
349
+ if (Type *NestedTy = deduceElementTypeHelper (Op, Visited))
350
+ Ty = TypedPointerType::get (NestedTy, PtrTy->getAddressSpace ());
351
+ } else {
352
+ Ty = deduceNestedTypeHelper (dyn_cast<User>(Op), OpTy, Visited);
353
+ }
354
+ if (Ty != OpTy) {
355
+ Type *NewTy = VectorType::get (Ty, VecTy->getElementCount ());
356
+ GR->addDeducedCompositeType (U, NewTy);
357
+ return NewTy;
358
+ }
359
+ }
296
360
}
297
361
298
362
return OrigTy;
@@ -578,7 +642,8 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
578
642
579
643
// Handle calls to builtins (non-intrinsics):
580
644
CallInst *CI = dyn_cast<CallInst>(I);
581
- if (!CI || CI->isIndirectCall () || CI->getCalledFunction ()->isIntrinsic ())
645
+ if (!CI || CI->isIndirectCall () || CI->isInlineAsm () ||
646
+ !CI->getCalledFunction () || CI->getCalledFunction ()->isIntrinsic ())
582
647
return ;
583
648
584
649
// collect information about formal parameter types
@@ -929,6 +994,10 @@ Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
929
994
// maybe we already know operand's element type
930
995
if (Type *KnownTy = GR->findDeducedElementType (OpArg))
931
996
return KnownTy;
997
+ // try to deduce from the operand itself
998
+ Visited.clear ();
999
+ if (Type *Ty = deduceElementTypeHelper (OpArg, Visited))
1000
+ return Ty;
932
1001
// search in actual parameter's users
933
1002
for (User *OpU : OpArg->users ()) {
934
1003
Instruction *Inst = dyn_cast<Instruction>(OpU);
0 commit comments