llvm.org GIT mirror llvm / b09333f
[IntrinsicEmitter] Extend argument overloading with forward references. Extend the mechanism to overload intrinsic arguments by using either backward or forward references to the overloadable arguments. In for example: def int_something : Intrinsic<[LLVMPointerToElt<0>], [llvm_anyvector_ty], []>; LLVMPointerToElt<0> is a forward reference to the overloadable operand of type 'llvm_anyvector_ty' and would allow intrinsics such as: declare i32* @llvm.something.v4i32(<4 x i32>); declare i64* @llvm.something.v2i64(<2 x i64>); where the result pointer type is deduced from the element type of the first argument. If the returned pointer is not a pointer to the element type, LLVM will give an error: Intrinsic has incorrect return type! i64* (<4 x i32>)* @llvm.something.v4i32 Reviewers: RKSimon, arsenm, rnk, greened Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D62995 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363233 91177308-0d34-0410-b5e6-96231b3b80d8 Sander de Smalen 2 months ago
6 changed file(s) with 195 addition(s) and 75 deletion(s). Raw diff Collapse all Expand all
115115 AK_AnyInteger,
116116 AK_AnyFloat,
117117 AK_AnyVector,
118 AK_AnyPointer
118 AK_AnyPointer,
119 AK_MatchType = 7
119120 };
120121
121122 unsigned getArgumentNumber() const {
160161 /// of IITDescriptors.
161162 void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T);
162163
163 /// Match the specified type (which comes from an intrinsic argument or return
164 /// value) with the type constraints specified by the .td file. If the given
165 /// type is an overloaded type it is pushed to the ArgTys vector.
164 enum MatchIntrinsicTypesResult {
165 MatchIntrinsicTypes_Match = 0,
166 MatchIntrinsicTypes_NoMatchRet = 1,
167 MatchIntrinsicTypes_NoMatchArg = 2,
168 };
169
170 /// Match the specified function type with the type constraints specified by
171 /// the .td file. If the given type is an overloaded type it is pushed to the
172 /// ArgTys vector.
166173 ///
167174 /// Returns false if the given type matches with the constraints, true
168175 /// otherwise.
169 bool matchIntrinsicType(Type *Ty, ArrayRef &Infos,
170 SmallVectorImpl &ArgTys);
176 MatchIntrinsicTypesResult
177 matchIntrinsicSignature(FunctionType *FTy, ArrayRef &Infos,
178 SmallVectorImpl &ArgTys);
171179
172180 /// Verify if the intrinsic has variable arguments. This method is intended to
173181 /// be called after all the fixed arguments have been matched first.
10461046 #include "llvm/IR/IntrinsicImpl.inc"
10471047 #undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN
10481048
1049 bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef &Infos,
1050 SmallVectorImpl &ArgTys) {
1049 using DeferredIntrinsicMatchPair =
1050 std::pair>;
1051
1052 static bool matchIntrinsicType(
1053 Type *Ty, ArrayRef &Infos,
1054 SmallVectorImpl &ArgTys,
1055 SmallVectorImpl &DeferredChecks,
1056 bool IsDeferredCheck) {
10511057 using namespace Intrinsic;
10521058
10531059 // If we ran out of descriptors, there are too many arguments.
10541060 if (Infos.empty()) return true;
1061
1062 // Do this before slicing off the 'front' part
1063 auto InfosRef = Infos;
1064 auto DeferCheck = [&DeferredChecks, &InfosRef](Type *T) {
1065 DeferredChecks.emplace_back(T, InfosRef);
1066 return false;
1067 };
1068
10551069 IITDescriptor D = Infos.front();
10561070 Infos = Infos.slice(1);
10571071
10691083 case IITDescriptor::Vector: {
10701084 VectorType *VT = dyn_cast(Ty);
10711085 return !VT || VT->getNumElements() != D.Vector_Width ||
1072 matchIntrinsicType(VT->getElementType(), Infos, ArgTys);
1086 matchIntrinsicType(VT->getElementType(), Infos, ArgTys,
1087 DeferredChecks, IsDeferredCheck);
10731088 }
10741089 case IITDescriptor::Pointer: {
10751090 PointerType *PT = dyn_cast(Ty);
10761091 return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace ||
1077 matchIntrinsicType(PT->getElementType(), Infos, ArgTys);
1092 matchIntrinsicType(PT->getElementType(), Infos, ArgTys,
1093 DeferredChecks, IsDeferredCheck);
10781094 }
10791095
10801096 case IITDescriptor::Struct: {
10831099 return true;
10841100
10851101 for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)
1086 if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys))
1102 if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys,
1103 DeferredChecks, IsDeferredCheck))
10871104 return true;
10881105 return false;
10891106 }
10901107
10911108 case IITDescriptor::Argument:
1092 // Two cases here - If this is the second occurrence of an argument, verify
1093 // that the later instance matches the previous instance.
1109 // If this is the second occurrence of an argument,
1110 // verify that the later instance matches the previous instance.
10941111 if (D.getArgumentNumber() < ArgTys.size())
10951112 return Ty != ArgTys[D.getArgumentNumber()];
10961113
1097 // Otherwise, if this is the first instance of an argument, record it and
1098 // verify the "Any" kind.
1099 assert(D.getArgumentNumber() == ArgTys.size() && "Table consistency error");
1114 if (D.getArgumentNumber() > ArgTys.size() ||
1115 D.getArgumentKind() == IITDescriptor::AK_MatchType)
1116 return IsDeferredCheck || DeferCheck(Ty);
1117
1118 assert(D.getArgumentNumber() == ArgTys.size() && !IsDeferredCheck &&
1119 "Table consistency error");
11001120 ArgTys.push_back(Ty);
11011121
11021122 switch (D.getArgumentKind()) {
11051125 case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy();
11061126 case IITDescriptor::AK_AnyVector: return !isa(Ty);
11071127 case IITDescriptor::AK_AnyPointer: return !isa(Ty);
1128 default: break;
11081129 }
11091130 llvm_unreachable("all argument kinds not covered");
11101131
11111132 case IITDescriptor::ExtendArgument: {
1112 // This may only be used when referring to a previous vector argument.
1133 // If this is a forward reference, defer the check for later.
11131134 if (D.getArgumentNumber() >= ArgTys.size())
1114 return true;
1135 return IsDeferredCheck || DeferCheck(Ty);
11151136
11161137 Type *NewTy = ArgTys[D.getArgumentNumber()];
11171138 if (VectorType *VTy = dyn_cast(NewTy))
11241145 return Ty != NewTy;
11251146 }
11261147 case IITDescriptor::TruncArgument: {
1127 // This may only be used when referring to a previous vector argument.
1148 // If this is a forward reference, defer the check for later.
11281149 if (D.getArgumentNumber() >= ArgTys.size())
1129 return true;
1150 return IsDeferredCheck || DeferCheck(Ty);
11301151
11311152 Type *NewTy = ArgTys[D.getArgumentNumber()];
11321153 if (VectorType *VTy = dyn_cast(NewTy))
11391160 return Ty != NewTy;
11401161 }
11411162 case IITDescriptor::HalfVecArgument:
1142 // This may only be used when referring to a previous vector argument.
1163 // If this is a forward reference, defer the check for later.
11431164 return D.getArgumentNumber() >= ArgTys.size() ||
11441165 !isa(ArgTys[D.getArgumentNumber()]) ||
11451166 VectorType::getHalfElementsVectorType(
11461167 cast(ArgTys[D.getArgumentNumber()])) != Ty;
11471168 case IITDescriptor::SameVecWidthArgument: {
1148 if (D.getArgumentNumber() >= ArgTys.size())
1149 return true;
1169 if (D.getArgumentNumber() >= ArgTys.size()) {
1170 // Defer check and subsequent check for the vector element type.
1171 Infos = Infos.slice(1);
1172 return IsDeferredCheck || DeferCheck(Ty);
1173 }
11501174 auto *ReferenceType = dyn_cast(ArgTys[D.getArgumentNumber()]);
11511175 auto *ThisArgType = dyn_cast(Ty);
11521176 // Both must be vectors of the same number of elements or neither.
11591183 return true;
11601184 EltTy = ThisArgType->getVectorElementType();
11611185 }
1162 return matchIntrinsicType(EltTy, Infos, ArgTys);
1186 return matchIntrinsicType(EltTy, Infos, ArgTys, DeferredChecks,
1187 IsDeferredCheck);
11631188 }
11641189 case IITDescriptor::PtrToArgument: {
11651190 if (D.getArgumentNumber() >= ArgTys.size())
1166 return true;
1191 return IsDeferredCheck || DeferCheck(Ty);
11671192 Type * ReferenceType = ArgTys[D.getArgumentNumber()];
11681193 PointerType *ThisArgType = dyn_cast(Ty);
11691194 return (!ThisArgType || ThisArgType->getElementType() != ReferenceType);
11701195 }
11711196 case IITDescriptor::PtrToElt: {
11721197 if (D.getArgumentNumber() >= ArgTys.size())
1173 return true;
1198 return IsDeferredCheck || DeferCheck(Ty);
11741199 VectorType * ReferenceType =
11751200 dyn_cast (ArgTys[D.getArgumentNumber()]);
11761201 PointerType *ThisArgType = dyn_cast(Ty);
11801205 }
11811206 case IITDescriptor::VecOfAnyPtrsToElt: {
11821207 unsigned RefArgNumber = D.getRefArgNumber();
1183
1184 // This may only be used when referring to a previous argument.
1185 if (RefArgNumber >= ArgTys.size())
1186 return true;
1187
1188 // Record the overloaded type
1189 assert(D.getOverloadArgNumber() == ArgTys.size() &&
1190 "Table consistency error");
1191 ArgTys.push_back(Ty);
1208 if (RefArgNumber >= ArgTys.size()) {
1209 if (IsDeferredCheck)
1210 return true;
1211 // If forward referencing, already add the pointer-vector type and
1212 // defer the checks for later.
1213 ArgTys.push_back(Ty);
1214 return DeferCheck(Ty);
1215 }
1216
1217 if (!IsDeferredCheck){
1218 assert(D.getOverloadArgNumber() == ArgTys.size() &&
1219 "Table consistency error");
1220 ArgTys.push_back(Ty);
1221 }
11921222
11931223 // Verify the overloaded type "matches" the Ref type.
11941224 // i.e. Ty is a vector with the same width as Ref.
12101240 llvm_unreachable("unhandled");
12111241 }
12121242
1243 Intrinsic::MatchIntrinsicTypesResult
1244 Intrinsic::matchIntrinsicSignature(FunctionType *FTy,
1245 ArrayRef &Infos,
1246 SmallVectorImpl &ArgTys) {
1247 SmallVector DeferredChecks;
1248 if (matchIntrinsicType(FTy->getReturnType(), Infos, ArgTys, DeferredChecks,
1249 false))
1250 return MatchIntrinsicTypes_NoMatchRet;
1251
1252 unsigned NumDeferredReturnChecks = DeferredChecks.size();
1253
1254 for (auto Ty : FTy->params())
1255 if (matchIntrinsicType(Ty, Infos, ArgTys, DeferredChecks, false))
1256 return MatchIntrinsicTypes_NoMatchArg;
1257
1258 for (unsigned I = 0, E = DeferredChecks.size(); I != E; ++I) {
1259 DeferredIntrinsicMatchPair &Check = DeferredChecks[I];
1260 if (matchIntrinsicType(Check.first, Check.second, ArgTys, DeferredChecks,
1261 true))
1262 return I < NumDeferredReturnChecks ? MatchIntrinsicTypes_NoMatchRet
1263 : MatchIntrinsicTypes_NoMatchArg;
1264 }
1265
1266 return MatchIntrinsicTypes_Match;
1267 }
1268
12131269 bool
12141270 Intrinsic::matchIntrinsicVarArg(bool isVarArg,
12151271 ArrayRef &Infos) {
12431299 getIntrinsicInfoTableEntries(ID, Table);
12441300 ArrayRef TableRef = Table;
12451301
1246 // If we encounter any problems matching the signature with the descriptor
1247 // just give up remangling. It's up to verifier to report the discrepancy.
1248 if (Intrinsic::matchIntrinsicType(FTy->getReturnType(), TableRef, ArgTys))
1302 if (Intrinsic::matchIntrinsicSignature(FTy, TableRef, ArgTys))
12491303 return None;
1250 for (auto Ty : FTy->params())
1251 if (Intrinsic::matchIntrinsicType(Ty, TableRef, ArgTys))
1252 return None;
12531304 if (Intrinsic::matchIntrinsicVarArg(FTy->isVarArg(), TableRef))
12541305 return None;
12551306 }
41534153 getIntrinsicInfoTableEntries(ID, Table);
41544154 ArrayRef TableRef = Table;
41554155
4156 // Walk the descriptors to extract overloaded types.
41564157 SmallVector ArgTys;
4157 Assert(!Intrinsic::matchIntrinsicType(IFTy->getReturnType(),
4158 TableRef, ArgTys),
4158 Intrinsic::MatchIntrinsicTypesResult Res =
4159 Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys);
4160 Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,
41594161 "Intrinsic has incorrect return type!", IF);
4160 for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i)
4161 Assert(!Intrinsic::matchIntrinsicType(IFTy->getParamType(i),
4162 TableRef, ArgTys),
4163 "Intrinsic has incorrect argument type!", IF);
4162 Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,
4163 "Intrinsic has incorrect argument type!", IF);
41644164
41654165 // Verify if the intrinsic call matches the vararg property.
41664166 if (IsVarArg)
10181018 getIntrinsicInfoTableEntries(IID, Table);
10191019 ArrayRef TableRef = Table;
10201020
1021 // Validate function argument and return types, extracting overloaded types
1022 // along the way.
10211023 FunctionType *FTy = II->getCalledFunction()->getFunctionType();
10221024 SmallVector OverloadTys;
1023 Intrinsic::matchIntrinsicType(FTy->getReturnType(), TableRef, OverloadTys);
1024 for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
1025 Intrinsic::matchIntrinsicType(FTy->getParamType(i), TableRef, OverloadTys);
1026
1027 // Get the new return type overload of the intrinsic.
1025 Intrinsic::matchIntrinsicSignature(FTy, TableRef, OverloadTys);
1026
10281027 Module *M = II->getParent()->getParent()->getParent();
10291028 Type *EltTy = II->getType()->getVectorElementType();
10301029 Type *NewTy = (NewNumElts == 1) ? EltTy : VectorType::get(EltTy, NewNumElts);
590590 TargetPrefix + ".'!");
591591 }
592592
593 ListInit *RetTypes = R->getValueAsListInit("RetTypes");
594 ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
595
596 // First collate a list of overloaded types.
597 std::vector OverloadedVTs;
598 for (ListInit *TypeList : {RetTypes, ParamTypes}) {
599 for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
600 Record *TyEl = TypeList->getElementAsRecord(i);
601 assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
602
603 if (TyEl->isSubClassOf("LLVMMatchType"))
604 continue;
605
606 MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
607 if (MVT(VT).isOverloaded()) {
608 OverloadedVTs.push_back(VT);
609 isOverloaded = true;
610 }
611 }
612 }
613
593614 // Parse the list of return types.
594 std::vector OverloadedVTs;
595 ListInit *TypeList = R->getValueAsListInit("RetTypes");
615 ListInit *TypeList = RetTypes;
596616 for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
597617 Record *TyEl = TypeList->getElementAsRecord(i);
598618 assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
612632 } else {
613633 VT = getValueType(TyEl->getValueAsDef("VT"));
614634 }
615 if (MVT(VT).isOverloaded()) {
616 OverloadedVTs.push_back(VT);
617 isOverloaded = true;
618 }
619635
620636 // Reject invalid types.
621637 if (VT == MVT::isVoid)
627643 }
628644
629645 // Parse the list of parameter types.
630 TypeList = R->getValueAsListInit("ParamTypes");
646 TypeList = ParamTypes;
631647 for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
632648 Record *TyEl = TypeList->getElementAsRecord(i);
633649 assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
652668 "Expected iAny or vAny type");
653669 } else
654670 VT = getValueType(TyEl->getValueAsDef("VT"));
655
656 if (MVT(VT).isOverloaded()) {
657 OverloadedVTs.push_back(VT);
658 isOverloaded = true;
659 }
660671
661672 // Reject invalid types.
662673 if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
257257 #endif
258258
259259 static void EncodeFixedType(Record *R, std::vector &ArgCodes,
260 std::vector &Sig) {
260 unsigned &NextArgCode,
261 std::vector &Sig,
262 ArrayRef Mapping) {
261263
262264 if (R->isSubClassOf("LLVMMatchType")) {
263 unsigned Number = R->getValueAsInt("Number");
265 unsigned Number = Mapping[R->getValueAsInt("Number")];
264266 assert(Number < ArgCodes.size() && "Invalid matching number!");
265267 if (R->isSubClassOf("LLVMExtendedType"))
266268 Sig.push_back(IIT_EXTEND_ARG);
279281 Sig.push_back(IIT_PTR_TO_ARG);
280282 else if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
281283 Sig.push_back(IIT_VEC_OF_ANYPTRS_TO_ELT);
282 unsigned ArgNo = ArgCodes.size();
283 ArgCodes.push_back(3 /*vAny*/);
284284 // Encode overloaded ArgNo
285 Sig.push_back(ArgNo);
285 Sig.push_back(NextArgCode++);
286286 // Encode LLVMMatchType ArgNo
287287 Sig.push_back(Number);
288288 return;
290290 Sig.push_back(IIT_PTR_TO_ELT);
291291 else
292292 Sig.push_back(IIT_ARG);
293 return Sig.push_back((Number << 3) | ArgCodes[Number]);
293 return Sig.push_back((Number << 3) | 7 /*IITDescriptor::AK_MatchType*/);
294294 }
295295
296296 MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
308308 Sig.push_back(IIT_ARG);
309309
310310 // Figure out what arg # this is consuming, and remember what kind it was.
311 unsigned ArgNo = ArgCodes.size();
312 ArgCodes.push_back(Tmp);
311 assert(NextArgCode < ArgCodes.size() && ArgCodes[NextArgCode] == Tmp &&
312 "Invalid or no ArgCode associated with overloaded VT!");
313 unsigned ArgNo = NextArgCode++;
313314
314315 // Encode what sort of argument it must be in the low 3 bits of the ArgNo.
315316 return Sig.push_back((ArgNo << 3) | Tmp);
327328 } else {
328329 Sig.push_back(IIT_PTR);
329330 }
330 return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig);
331 return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig,
332 Mapping);
331333 }
332334 }
333335
352354 EncodeFixedValueType(VT, Sig);
353355 }
354356
357 static void UpdateArgCodes(Record *R, std::vector &ArgCodes,
358 unsigned int &NumInserted,
359 SmallVectorImpl &Mapping) {
360 if (R->isSubClassOf("LLVMMatchType")) {
361 if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
362 ArgCodes.push_back(3 /*vAny*/);
363 ++NumInserted;
364 }
365 return;
366 }
367
368 unsigned Tmp = 0;
369 switch (getValueType(R->getValueAsDef("VT"))) {
370 default: break;
371 case MVT::iPTRAny:
372 ++Tmp;
373 LLVM_FALLTHROUGH;
374 case MVT::vAny:
375 ++Tmp;
376 LLVM_FALLTHROUGH;
377 case MVT::fAny:
378 ++Tmp;
379 LLVM_FALLTHROUGH;
380 case MVT::iAny:
381 ++Tmp;
382 LLVM_FALLTHROUGH;
383 case MVT::Any:
384 unsigned OriginalIdx = ArgCodes.size() - NumInserted;
385 assert(OriginalIdx >= Mapping.size());
386 Mapping.resize(OriginalIdx+1);
387 Mapping[OriginalIdx] = ArgCodes.size();
388 ArgCodes.push_back(Tmp);
389 break;
390 }
391 }
392
355393 #if defined(_MSC_VER) && !defined(__clang__)
356394 #pragma optimize("",on)
357395 #endif
362400 std::vector &TypeSig) {
363401 std::vector ArgCodes;
364402
403 // Add codes for any overloaded result VTs.
404 unsigned int NumInserted = 0;
405 SmallVector ArgMapping;
406 for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
407 UpdateArgCodes(Int.IS.RetTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
408
409 // Add codes for any overloaded operand VTs.
410 for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
411 UpdateArgCodes(Int.IS.ParamTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
412
413 unsigned NextArgCode = 0;
365414 if (Int.IS.RetVTs.empty())
366415 TypeSig.push_back(IIT_Done);
367416 else if (Int.IS.RetVTs.size() == 1 &&
381430 }
382431
383432 for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
384 EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig);
433 EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
434 ArgMapping);
385435 }
386436
387437 for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
388 EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
438 EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
439 ArgMapping);
389440 }
390441
391442 static void printIITEntry(raw_ostream &OS, unsigned char X) {