@@ -118,52 +118,74 @@ static Type *getPointerUseType(Function *F, Op Opcode, unsigned ArgNo) {
118118 }
119119}
120120
121- void SPIRVTypeScavenger::deduceIntrinsicTypes (Function &F, Intrinsic::ID Id) {
122- static constexpr unsigned Return = ~0U ;
123- auto AddParameter = [&](unsigned ArgNo, DeducedType Ty) {
124- if (ArgNo == Return) {
125- // TODO: Handle return types properly.
126- } else {
127- Argument *Arg = F.getArg (ArgNo);
128- LLVM_DEBUG (dbgs () << " Parameter " << *Arg << " of " << F.getName ()
129- << " has type " << Ty << " \n " );
130- DeducedTypes[Arg] = Ty;
121+ bool SPIRVTypeScavenger::typeIntrinsicCall (
122+ CallBase &CB, SmallVectorImpl<std::pair<unsigned , DeducedType>> &ArgTys) {
123+ Function *TargetFn = CB.getCalledFunction ();
124+ assert (TargetFn && TargetFn->isDeclaration () &&
125+ " Call is not an intrinsic function call" );
126+ LLVMContext &Ctx = TargetFn->getContext ();
127+
128+ if (auto IntrinID = TargetFn->getIntrinsicID ()) {
129+ switch (IntrinID) {
130+ case Intrinsic::memcpy: {
131+ // First two parameters are pointers, but it may be any pointer type.
132+ DeducedType MemcpyTy = new DeferredType;
133+ ArgTys.emplace_back (0 , MemcpyTy);
134+ ArgTys.emplace_back (1 , MemcpyTy);
135+ break ;
131136 }
132- };
133- LLVMContext &Ctx = F.getContext ();
137+ case Intrinsic::memset:
138+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
139+ break ;
140+ case Intrinsic::lifetime_start:
141+ case Intrinsic::lifetime_end:
142+ case Intrinsic::invariant_start:
143+ // These intrinsics were stored as i8* as typed pointers, and the SPIR-V
144+ // writer will expect these to be i8*, even if they can be any pointer
145+ // type.
146+ ArgTys.emplace_back (1 , Type::getInt8Ty (Ctx));
147+ break ;
148+ case Intrinsic::invariant_end:
149+ // This is like invariant_start with an extra string parameter in the
150+ // beginning (so the pointer object moves to argument two).
151+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
152+ ArgTys.emplace_back (2 , Type::getInt8Ty (Ctx));
153+ break ;
154+ case Intrinsic::var_annotation:
155+ case Intrinsic::ptr_annotation:
156+ // The first parameter of these is an i8*.
157+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
158+ [[fallthrough]];
159+ case Intrinsic::annotation:
160+ // Second and third parameters are strings, which should be constants
161+ // for global variables. Nominally, this is i8*, but we specifically
162+ // *do not* want to insert bitcast instructions (they need to remain
163+ // global constants).
164+ break ;
165+ case Intrinsic::stacksave:
166+ // TODO: support return type.
167+ break ;
168+ case Intrinsic::stackrestore:
169+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
170+ break ;
171+ case Intrinsic::instrprof_cover:
172+ case Intrinsic::instrprof_increment:
173+ case Intrinsic::instrprof_increment_step:
174+ case Intrinsic::instrprof_value_profile:
175+ // llvm.instrprof.* intrinsics are not supported
176+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
177+ break ;
178+ // TODO: handle masked gather/scatter intrinsics. This requires support
179+ // for vector-of-pointers in the type scavenger.
180+ default :
181+ return false ;
182+ }
183+ } else if (TargetFn->getName ().startswith (" _Z18__spirv_ocl_printf" )) {
184+ ArgTys.emplace_back (0 , Type::getInt8Ty (Ctx));
185+ } else
186+ return false ;
134187
135- switch (Id) {
136- case Intrinsic::memcpy:
137- // First parameter is a pointer, but it may be any pointer type.
138- return ;
139- case Intrinsic::lifetime_start:
140- case Intrinsic::lifetime_end:
141- case Intrinsic::invariant_start:
142- case Intrinsic::invariant_end:
143- AddParameter (1 , Type::getInt8Ty (Ctx));
144- return ;
145- // Second and third parameters are strings, which mean nothing.
146- case Intrinsic::annotation:
147- return ;
148- case Intrinsic::var_annotation:
149- case Intrinsic::ptr_annotation:
150- AddParameter (0 , Type::getInt8Ty (Ctx));
151- // Second and third parameters are strings, so they can be any type.
152- return ;
153- case Intrinsic::stacksave:
154- AddParameter (Return, Type::getInt8Ty (Ctx));
155- return ;
156- case Intrinsic::stackrestore:
157- AddParameter (0 , Type::getInt8Ty (Ctx));
158- return ;
159- // llvm.instrprof.* intrinsics are not supported
160- case Intrinsic::instrprof_cover:
161- case Intrinsic::instrprof_increment:
162- case Intrinsic::instrprof_increment_step:
163- case Intrinsic::instrprof_value_profile:
164- AddParameter (0 , Type::getInt8Ty (Ctx));
165- return ;
166- }
188+ return true ;
167189}
168190
169191static Type *getParamType (const AttributeList &AL, unsigned ArgNo) {
@@ -222,15 +244,13 @@ void SPIRVTypeScavenger::deduceFunctionType(Function &F) {
222244 }
223245 }
224246
225- if (auto IntrinID = F.getIntrinsicID ()) {
226- deduceIntrinsicTypes (F, IntrinID);
227- }
228-
229247 // If the function is a mangled name, try to recover types from the Itanium
230248 // name mangling.
231249 if (F.getName ().startswith (" _Z" )) {
232250 SmallVector<Type *, 8 > ParamTypes;
233- getParameterTypes (&F, ParamTypes);
251+ if (!getParameterTypes (&F, ParamTypes)) {
252+ return ;
253+ }
234254 for (Argument *Arg : PointerArgs) {
235255 if (auto *Ty = dyn_cast<TypedPointerType>(ParamTypes[Arg->getArgNo ()])) {
236256 DeducedTypes[Arg] = Ty->getElementType ();
@@ -447,15 +467,17 @@ void SPIRVTypeScavenger::correctUseTypes(Instruction &I) {
447467 // If we have an identified function for the call instruction, map the
448468 // arguments we pass in to the argument requirements of the function.
449469 if (Function *F = CB->getCalledFunction ()) {
450- for (Use &U : CB->args ()) {
451- // If we're calling a var-arg method, we have more operands than the
452- // function has parameters. Bail out if we hit that point.
453- unsigned ArgNo = CB->getArgOperandNo (&U);
454- if (ArgNo >= F->arg_size ())
455- break ;
456- if (U->getType ()->isPointerTy ())
457- PointerOperands.emplace_back (
458- U.getOperandNo (), computePointerElementType (F->getArg (ArgNo)));
470+ if (!F->isDeclaration () || !typeIntrinsicCall (*CB, PointerOperands)) {
471+ for (Use &U : CB->args ()) {
472+ // If we're calling a var-arg method, we have more operands than the
473+ // function has parameters. Bail out if we hit that point.
474+ unsigned ArgNo = CB->getArgOperandNo (&U);
475+ if (ArgNo >= F->arg_size ())
476+ break ;
477+ if (U->getType ()->isPointerTy ())
478+ PointerOperands.emplace_back (
479+ U.getOperandNo (), computePointerElementType (F->getArg (ArgNo)));
480+ }
459481 }
460482 }
461483 }
0 commit comments