@@ -79,7 +79,7 @@ class SPIRVEmitIntrinsics
79
79
std::unordered_set<Value *> &Visited);
80
80
81
81
// deduce Types of operands of the Instruction if possible
82
- void deduceOperandElementType (Value *I, DenseMap<Value *, Type *> &Collected );
82
+ void deduceOperandElementType (Instruction *I);
83
83
84
84
void preprocessCompositeConstants (IRBuilder<> &B);
85
85
void preprocessUndefs (IRBuilder<> &B);
@@ -275,6 +275,12 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
275
275
if (Ty)
276
276
break ;
277
277
}
278
+ } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
279
+ for (Value *Op : {Ref->getTrueValue (), Ref->getFalseValue ()}) {
280
+ Ty = deduceElementTypeByUsersDeep (Op, Visited);
281
+ if (Ty)
282
+ break ;
283
+ }
278
284
}
279
285
280
286
// remember the found relationship
@@ -374,24 +380,92 @@ Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) {
374
380
return IntegerType::getInt8Ty (I->getContext ());
375
381
}
376
382
377
- // Deduce Types of operands of the Instruction if possible.
378
- void SPIRVEmitIntrinsics::deduceOperandElementType (
379
- Value *I, DenseMap<Value *, Type *> &Collected) {
380
- Type *KnownTy = GR-> findDeducedElementType (I);
381
- if (!KnownTy)
382
- return ;
383
-
383
+ // If the Instruction has Pointer operands with unresolved types, this function
384
+ // tries to deduce them. If the Instruction has Pointer operands with known
385
+ // types which differ from expected, this function tries to insert a bitcast to
386
+ // resolve the issue.
387
+ void SPIRVEmitIntrinsics::deduceOperandElementType (Instruction *I) {
388
+ SmallVector<std::pair<Value *, unsigned >> Ops ;
389
+ Type *KnownElemTy = nullptr ;
384
390
// look for known basic patterns of type inference
385
391
if (auto *Ref = dyn_cast<PHINode>(I)) {
392
+ if (!isPointerTy (I->getType ()) ||
393
+ !(KnownElemTy = GR->findDeducedElementType (I)))
394
+ return ;
386
395
for (unsigned i = 0 ; i < Ref->getNumIncomingValues (); i++) {
387
396
Value *Op = Ref->getIncomingValue (i);
388
- if (!isUntypedPointerTy (Op->getType ()))
389
- continue ;
390
- Type *Ty = GR->findDeducedElementType (Op);
391
- if (!Ty) {
392
- Collected[Op] = KnownTy;
393
- GR->addDeducedElementType (Op, KnownTy);
397
+ if (isPointerTy (Op->getType ()))
398
+ Ops.push_back (std::make_pair (Op, i));
399
+ }
400
+ } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
401
+ if (!isPointerTy (I->getType ()) ||
402
+ !(KnownElemTy = GR->findDeducedElementType (I)))
403
+ return ;
404
+ for (unsigned i = 0 ; i < Ref->getNumOperands (); i++) {
405
+ Value *Op = Ref->getOperand (i);
406
+ if (isPointerTy (Op->getType ()))
407
+ Ops.push_back (std::make_pair (Op, i));
408
+ }
409
+ } else if (auto *Ref = dyn_cast<ICmpInst>(I)) {
410
+ if (!isPointerTy (Ref->getOperand (0 )->getType ()))
411
+ return ;
412
+ Value *Op0 = Ref->getOperand (0 );
413
+ Value *Op1 = Ref->getOperand (1 );
414
+ Type *ElemTy0 = GR->findDeducedElementType (Op0);
415
+ Type *ElemTy1 = GR->findDeducedElementType (Op1);
416
+ if (ElemTy0) {
417
+ KnownElemTy = ElemTy0;
418
+ Ops.push_back (std::make_pair (Op1, 1 ));
419
+ } else if (ElemTy1) {
420
+ KnownElemTy = ElemTy1;
421
+ Ops.push_back (std::make_pair (Op0, 0 ));
422
+ }
423
+ }
424
+
425
+ // There is no enough info to deduce types or all is valid.
426
+ if (!KnownElemTy || Ops.size () == 0 )
427
+ return ;
428
+
429
+ Instruction *User = nullptr ;
430
+ LLVMContext &Ctx = F->getContext ();
431
+ IRBuilder<> B (Ctx);
432
+ for (auto &OpIt : Ops) {
433
+ Value *Op = OpIt.first ;
434
+ // unsigned i = OpIt.second;
435
+ Type *Ty = GR->findDeducedElementType (Op);
436
+ if (Ty == KnownElemTy)
437
+ continue ;
438
+ if (Op->use_empty () ||
439
+ !(User = dyn_cast<Instruction>(Op->use_begin ()->get ())))
440
+ continue ;
441
+
442
+ setInsertPointSkippingPhis (B, User->getNextNode ());
443
+ Value *OpTyVal = Constant::getNullValue (KnownElemTy);
444
+ Type *OpTy = Op->getType ();
445
+ if (!Ty) {
446
+ GR->addDeducedElementType (Op, KnownElemTy);
447
+ // check if there is existing Intrinsic::spv_assign_ptr_type instruction
448
+ auto It = AssignPtrTypeInstr.find (Op);
449
+ if (It == AssignPtrTypeInstr.end ()) {
450
+ CallInst *CI =
451
+ buildIntrWithMD (Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op,
452
+ {B.getInt32 (getPointerAddressSpace (OpTy))}, B);
453
+ AssignPtrTypeInstr[Op] = CI;
454
+ } else {
455
+ It->second ->setArgOperand (
456
+ 1 ,
457
+ MetadataAsValue::get (
458
+ Ctx, MDNode::get (Ctx, ValueAsMetadata::getConstant (OpTyVal))));
394
459
}
460
+ } else {
461
+ SmallVector<Type *, 2 > Types = {OpTy, OpTy};
462
+ MetadataAsValue *VMD = MetadataAsValue::get (
463
+ Ctx, MDNode::get (Ctx, ValueAsMetadata::getConstant (OpTyVal)));
464
+ SmallVector<Value *, 2 > Args = {Op, VMD,
465
+ B.getInt32 (getPointerAddressSpace (OpTy))};
466
+ CallInst *PtrCastI =
467
+ B.CreateIntrinsic (Intrinsic::spv_ptrcast, {Types}, Args);
468
+ I->setOperand (OpIt.second , PtrCastI);
395
469
}
396
470
}
397
471
}
@@ -1145,6 +1219,10 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
1145
1219
insertAssignTypeIntrs (I, B);
1146
1220
insertPtrCastOrAssignTypeInstr (I, B);
1147
1221
}
1222
+
1223
+ for (auto &I : instructions (Func))
1224
+ deduceOperandElementType (&I);
1225
+
1148
1226
for (auto *I : Worklist) {
1149
1227
TrackConstants = true ;
1150
1228
if (!I->getType ()->isVoidTy () || isa<StoreInst>(I))
@@ -1157,36 +1235,6 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
1157
1235
processInstrAfterVisit (I, B);
1158
1236
}
1159
1237
1160
- for (auto &I : instructions (Func)) {
1161
- Type *ITy = I.getType ();
1162
- if (!isPointerTy (ITy))
1163
- continue ;
1164
- DenseMap<Value *, Type *> CollectedTys;
1165
- deduceOperandElementType (&I, CollectedTys);
1166
- Instruction *User;
1167
- LLVMContext &Ctx = F->getContext ();
1168
- for (const auto &Rec : CollectedTys) {
1169
- if (Rec.first ->use_empty () ||
1170
- !(User = dyn_cast<Instruction>(Rec.first ->use_begin ()->get ())))
1171
- continue ;
1172
- Type *OpTy = Rec.first ->getType ();
1173
- Value *OpTyVal = Constant::getNullValue (Rec.second );
1174
- // check if there is existing Intrinsic::spv_assign_ptr_type instruction
1175
- auto It = AssignPtrTypeInstr.find (Rec.first );
1176
- if (It == AssignPtrTypeInstr.end ()) {
1177
- setInsertPointSkippingPhis (B, User->getNextNode ());
1178
- buildIntrWithMD (Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal,
1179
- Rec.first , {B.getInt32 (getPointerAddressSpace (OpTy))},
1180
- B);
1181
- } else {
1182
- It->second ->setArgOperand (
1183
- 1 ,
1184
- MetadataAsValue::get (
1185
- Ctx, MDNode::get (Ctx, ValueAsMetadata::getConstant (OpTyVal))));
1186
- }
1187
- }
1188
- }
1189
-
1190
1238
// check if function parameter types are set
1191
1239
if (!F->isIntrinsic ())
1192
1240
processParamTypes (F, B);
0 commit comments