@@ -98,6 +98,8 @@ class SPIRVEmitIntrinsics
98
98
return B.CreateIntrinsic (IntrID, {Types}, Args);
99
99
}
100
100
101
+ void buildAssignPtr (IRBuilder<> &B, Type *ElemTy, Value *Arg);
102
+
101
103
void replaceMemInstrUses (Instruction *Old, Instruction *New, IRBuilder<> &B);
102
104
void processInstrAfterVisit (Instruction *I, IRBuilder<> &B);
103
105
void insertAssignPtrTypeIntrs (Instruction *I, IRBuilder<> &B);
@@ -111,6 +113,7 @@ class SPIRVEmitIntrinsics
111
113
void insertPtrCastOrAssignTypeInstr (Instruction *I, IRBuilder<> &B);
112
114
void processGlobalValue (GlobalVariable &GV, IRBuilder<> &B);
113
115
void processParamTypes (Function *F, IRBuilder<> &B);
116
+ void processParamTypesByFunHeader (Function *F, IRBuilder<> &B);
114
117
Type *deduceFunParamElementType (Function *F, unsigned OpIdx);
115
118
Type *deduceFunParamElementType (Function *F, unsigned OpIdx,
116
119
std::unordered_set<Function *> &FVisited);
@@ -194,6 +197,17 @@ static inline void reportFatalOnTokenType(const Instruction *I) {
194
197
false );
195
198
}
196
199
200
+ void SPIRVEmitIntrinsics::buildAssignPtr (IRBuilder<> &B, Type *ElemTy,
201
+ Value *Arg) {
202
+ CallInst *AssignPtrTyCI =
203
+ buildIntrWithMD (Intrinsic::spv_assign_ptr_type, {Arg->getType ()},
204
+ Constant::getNullValue (ElemTy), Arg,
205
+ {B.getInt32 (getPointerAddressSpace (Arg->getType ()))}, B);
206
+ GR->addDeducedElementType (AssignPtrTyCI, ElemTy);
207
+ GR->addDeducedElementType (Arg, ElemTy);
208
+ AssignPtrTypeInstr[Arg] = AssignPtrTyCI;
209
+ }
210
+
197
211
// Set element pointer type to the given value of ValueTy and tries to
198
212
// specify this type further (recursively) by Operand value, if needed.
199
213
Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep (
@@ -232,6 +246,19 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
232
246
return nullptr ;
233
247
}
234
248
249
+ // Implements what we know in advance about intrinsics and builtin calls
250
+ // TODO: consider feasibility of this particular case to be generalized by
251
+ // encoding knowledge about intrinsics and builtin calls by corresponding
252
+ // specification rules
253
+ static Type *getPointeeTypeByCallInst (StringRef DemangledName,
254
+ Function *CalledF, unsigned OpIdx) {
255
+ if ((DemangledName.starts_with (" __spirv_ocl_printf(" ) ||
256
+ DemangledName.starts_with (" printf(" )) &&
257
+ OpIdx == 0 )
258
+ return IntegerType::getInt8Ty (CalledF->getContext ());
259
+ return nullptr ;
260
+ }
261
+
235
262
// Deduce and return a successfully deduced Type of the Instruction,
236
263
// or nullptr otherwise.
237
264
Type *SPIRVEmitIntrinsics::deduceElementTypeHelper (Value *I) {
@@ -795,6 +822,8 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
795
822
return ;
796
823
797
824
// collect information about formal parameter types
825
+ std::string DemangledName =
826
+ getOclOrSpirvBuiltinDemangledName (CI->getCalledFunction ()->getName ());
798
827
Function *CalledF = CI->getCalledFunction ();
799
828
SmallVector<Type *, 4 > CalledArgTys;
800
829
bool HaveTypes = false ;
@@ -811,10 +840,15 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
811
840
if (!ElemTy && hasPointeeTypeAttr (CalledArg))
812
841
ElemTy = getPointeeTypeByAttr (CalledArg);
813
842
if (!ElemTy) {
814
- for (User *U : CalledArg->users ()) {
815
- if (Instruction *Inst = dyn_cast<Instruction>(U)) {
816
- if ((ElemTy = deduceElementTypeHelper (Inst)) != nullptr )
817
- break ;
843
+ ElemTy = getPointeeTypeByCallInst (DemangledName, CalledF, OpIdx);
844
+ if (ElemTy) {
845
+ GR->addDeducedElementType (CalledArg, ElemTy);
846
+ } else {
847
+ for (User *U : CalledArg->users ()) {
848
+ if (Instruction *Inst = dyn_cast<Instruction>(U)) {
849
+ if ((ElemTy = deduceElementTypeHelper (Inst)) != nullptr )
850
+ break ;
851
+ }
818
852
}
819
853
}
820
854
}
@@ -823,8 +857,6 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
823
857
}
824
858
}
825
859
826
- std::string DemangledName =
827
- getOclOrSpirvBuiltinDemangledName (CI->getCalledFunction ()->getName ());
828
860
if (DemangledName.empty () && !HaveTypes)
829
861
return ;
830
862
@@ -835,8 +867,14 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
835
867
continue ;
836
868
837
869
// Constants (nulls/undefs) are handled in insertAssignPtrTypeIntrs()
838
- if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand))
839
- continue ;
870
+ if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand)) {
871
+ // However, we may have assumptions about the formal argument's type and
872
+ // may have a need to insert a ptr cast for the actual parameter of this
873
+ // call.
874
+ Argument *CalledArg = CalledF->getArg (OpIdx);
875
+ if (!GR->findDeducedElementType (CalledArg))
876
+ continue ;
877
+ }
840
878
841
879
Type *ExpectedType =
842
880
OpIdx < CalledArgTys.size () ? CalledArgTys[OpIdx] : nullptr ;
@@ -1102,9 +1140,13 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
1102
1140
(II->paramHasAttr (OpNo, Attribute::ImmArg))))
1103
1141
continue ;
1104
1142
B.SetInsertPoint (I);
1105
- auto *NewOp =
1106
- buildIntrWithMD (Intrinsic::spv_track_constant,
1107
- {Op->getType (), Op->getType ()}, Op, Op, {}, B);
1143
+ Value *OpTyVal = Op;
1144
+ if (Op->getType ()->isTargetExtTy ())
1145
+ OpTyVal = Constant::getNullValue (
1146
+ IntegerType::get (I->getContext (), GR->getPointerSize ()));
1147
+ auto *NewOp = buildIntrWithMD (Intrinsic::spv_track_constant,
1148
+ {Op->getType (), OpTyVal->getType ()}, Op,
1149
+ OpTyVal, {}, B);
1108
1150
I->setOperand (OpNo, NewOp);
1109
1151
}
1110
1152
}
@@ -1179,28 +1221,29 @@ Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
1179
1221
return nullptr ;
1180
1222
}
1181
1223
1182
- void SPIRVEmitIntrinsics::processParamTypes (Function *F, IRBuilder<> &B) {
1224
+ void SPIRVEmitIntrinsics::processParamTypesByFunHeader (Function *F,
1225
+ IRBuilder<> &B) {
1183
1226
B.SetInsertPointPastAllocas (F);
1184
1227
for (unsigned OpIdx = 0 ; OpIdx < F->arg_size (); ++OpIdx) {
1185
1228
Argument *Arg = F->getArg (OpIdx);
1186
1229
if (!isUntypedPointerTy (Arg->getType ()))
1187
1230
continue ;
1231
+ Type *ElemTy = GR->findDeducedElementType (Arg);
1232
+ if (!ElemTy && hasPointeeTypeAttr (Arg) &&
1233
+ (ElemTy = getPointeeTypeByAttr (Arg)) != nullptr )
1234
+ buildAssignPtr (B, ElemTy, Arg);
1235
+ }
1236
+ }
1188
1237
1238
+ void SPIRVEmitIntrinsics::processParamTypes (Function *F, IRBuilder<> &B) {
1239
+ B.SetInsertPointPastAllocas (F);
1240
+ for (unsigned OpIdx = 0 ; OpIdx < F->arg_size (); ++OpIdx) {
1241
+ Argument *Arg = F->getArg (OpIdx);
1242
+ if (!isUntypedPointerTy (Arg->getType ()))
1243
+ continue ;
1189
1244
Type *ElemTy = GR->findDeducedElementType (Arg);
1190
- if (!ElemTy) {
1191
- if (hasPointeeTypeAttr (Arg) &&
1192
- (ElemTy = getPointeeTypeByAttr (Arg)) != nullptr ) {
1193
- GR->addDeducedElementType (Arg, ElemTy);
1194
- } else if ((ElemTy = deduceFunParamElementType (F, OpIdx)) != nullptr ) {
1195
- CallInst *AssignPtrTyCI = buildIntrWithMD (
1196
- Intrinsic::spv_assign_ptr_type, {Arg->getType ()},
1197
- Constant::getNullValue (ElemTy), Arg,
1198
- {B.getInt32 (getPointerAddressSpace (Arg->getType ()))}, B);
1199
- GR->addDeducedElementType (AssignPtrTyCI, ElemTy);
1200
- GR->addDeducedElementType (Arg, ElemTy);
1201
- AssignPtrTypeInstr[Arg] = AssignPtrTyCI;
1202
- }
1203
- }
1245
+ if (!ElemTy && (ElemTy = deduceFunParamElementType (F, OpIdx)) != nullptr )
1246
+ buildAssignPtr (B, ElemTy, Arg);
1204
1247
}
1205
1248
}
1206
1249
@@ -1217,6 +1260,8 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
1217
1260
AggrConstTypes.clear ();
1218
1261
AggrStores.clear ();
1219
1262
1263
+ processParamTypesByFunHeader (F, B);
1264
+
1220
1265
// StoreInst's operand type can be changed during the next transformations,
1221
1266
// so we need to store it in the set. Also store already transformed types.
1222
1267
for (auto &I : instructions (Func)) {
0 commit comments