aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/DerivedTypes.h20
-rw-r--r--include/llvm/Intrinsics.td7
-rw-r--r--lib/VMCore/Verifier.cpp28
-rw-r--r--utils/TableGen/CodeGenTarget.cpp28
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp23
5 files changed, 100 insertions, 6 deletions
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index 04a73fe..3bc00e9 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -369,6 +369,26 @@ public:
return VectorType::get(EltTy, VTy->getNumElements());
}
+ /// VectorType::getExtendedElementVectorType - This static method is like
+ /// getInteger except that the element types are twice as wide as the
+ /// elements in the input type.
+ ///
+ static VectorType *getExtendedElementVectorType(const VectorType *VTy) {
+ unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+ const Type *EltTy = IntegerType::get(EltBits * 2);
+ return VectorType::get(EltTy, VTy->getNumElements());
+ }
+
+ /// VectorType::getTruncatedElementVectorType - This static method is like
+ /// getInteger except that the element types are half as wide as the
+ /// elements in the input type.
+ ///
+ static VectorType *getTruncatedElementVectorType(const VectorType *VTy) {
+ unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits();
+ const Type *EltTy = IntegerType::get(EltBits / 2);
+ return VectorType::get(EltTy, VTy->getNumElements());
+ }
+
/// @brief Return the number of elements in the Vector type.
inline unsigned getNumElements() const { return NumElements; }
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 154106e..a641caa 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -74,6 +74,13 @@ class LLVMMatchType<int num>
int Number = num;
}
+// Match the type of another intrinsic parameter that is expected to be
+// an integral vector type, but change the element size to be twice as wide
+// or half as wide as the other type. This is only useful when the intrinsic
+// is overloaded, so the matched type should be declared as iAny.
+class LLVMExtendedElementVectorType<int num> : LLVMMatchType<num>;
+class LLVMTruncatedElementVectorType<int num> : LLVMMatchType<num>;
+
def llvm_void_ty : LLVMType<isVoid>;
def llvm_anyint_ty : LLVMType<iAny>;
def llvm_anyfloat_ty : LLVMType<fAny>;
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 5920773..4a79154 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1313,6 +1313,11 @@ void Verifier::visitInstruction(Instruction &I) {
InstsInThisBlock.insert(&I);
}
+// Flags used by TableGen to mark intrinsic parameters with the
+// LLVMExtendedElementVectorType and LLVMTruncatedElementVectorType classes.
+static const unsigned ExtendedElementVectorType = 0x40000000;
+static const unsigned TruncatedElementVectorType = 0x20000000;
+
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
///
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
@@ -1376,13 +1381,34 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty,
unsigned NumElts = 0;
const Type *EltTy = Ty;
- if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
+ const VectorType *VTy = dyn_cast<VectorType>(Ty);
+ if (VTy) {
EltTy = VTy->getElementType();
NumElts = VTy->getNumElements();
}
if (VT < 0) {
int Match = ~VT;
+
+ // Check flags that indicate a type that is an integral vector type with
+ // elements that are larger or smaller than the elements of the matched
+ // type.
+ if ((Match & (ExtendedElementVectorType |
+ TruncatedElementVectorType)) != 0) {
+ if (!VTy) {
+ CheckFailed("Intrinsic parameter #" + utostr(ArgNo - 1) + " is not "
+ "a vector type.", F);
+ return false;
+ }
+ // Adjust the current Ty (in the opposite direction) rather than
+ // the type being matched against.
+ if ((Match & ExtendedElementVectorType) != 0)
+ Ty = VectorType::getTruncatedElementVectorType(VTy);
+ else
+ Ty = VectorType::getExtendedElementVectorType(VTy);
+ Match &= ~(ExtendedElementVectorType | TruncatedElementVectorType);
+ }
+
const Type *RetTy = FTy->getReturnType();
const StructType *ST = dyn_cast<StructType>(RetTy);
unsigned NumRets = 1;
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index c6e94a5..0039a89 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -483,7 +483,17 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
Record *TyEl = TypeList->getElementAsRecord(i);
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
- MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ VT = IS.RetVTs[TyEl->getValueAsInt("Number")];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ VT == MVT::iAny) && "Expected iAny type");
+ } else
+ VT = getValueType(TyEl->getValueAsDef("VT"));
isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny;
IS.RetVTs.push_back(VT);
IS.RetTypeDefs.push_back(TyEl);
@@ -497,7 +507,21 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
Record *TyEl = TypeList->getElementAsRecord(i);
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
- MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ unsigned MatchTy = TyEl->getValueAsInt("Number");
+ if (MatchTy < IS.RetVTs.size())
+ VT = IS.RetVTs[MatchTy];
+ else
+ VT = IS.ParamVTs[MatchTy - IS.RetVTs.size()];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
+ VT == MVT::iAny) && "Expected iAny type");
+ } else
+ VT = getValueType(TyEl->getValueAsDef("VT"));
isOverloaded |= VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny;
IS.ParamVTs.push_back(VT);
IS.ParamTypeDefs.push_back(TyEl);
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 7883e7c..86e83e5 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -167,7 +167,14 @@ static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
if (ArgType->isSubClassOf("LLVMMatchType")) {
unsigned Number = ArgType->getValueAsInt("Number");
assert(Number < ArgNo && "Invalid matching number!");
- OS << "Tys[" << Number << "]";
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "VectorType::getExtendedElementVectorType"
+ << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "VectorType::getTruncatedElementVectorType"
+ << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
+ else
+ OS << "Tys[" << Number << "]";
} else if (VT == MVT::iAny || VT == MVT::fAny) {
// NOTE: The ArgNo variable here is not the absolute argument number, it is
// the index of the "arbitrary" type in the Tys array passed to the
@@ -281,7 +288,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
if (ArgType->isSubClassOf("LLVMMatchType")) {
unsigned Number = ArgType->getValueAsInt("Number");
assert(Number < j && "Invalid matching number!");
- OS << "~" << Number;
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "~(ExtendedElementVectorType | " << Number << ")";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "~(TruncatedElementVectorType | " << Number << ")";
+ else
+ OS << "~" << Number;
} else {
MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
OS << getEnumName(VT);
@@ -299,7 +311,12 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
if (ArgType->isSubClassOf("LLVMMatchType")) {
unsigned Number = ArgType->getValueAsInt("Number");
assert(Number < j + RetTys.size() && "Invalid matching number!");
- OS << "~" << Number;
+ if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
+ OS << "~(ExtendedElementVectorType | " << Number << ")";
+ else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
+ OS << "~(TruncatedElementVectorType | " << Number << ")";
+ else
+ OS << "~" << Number;
} else {
MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
OS << getEnumName(VT);