Intrinsics: add LLVMHalfElementsVectorType constraint
authorTim Northover <tnorthover@apple.com>
Sat, 29 Mar 2014 07:04:54 +0000 (07:04 +0000)
committerTim Northover <tnorthover@apple.com>
Sat, 29 Mar 2014 07:04:54 +0000 (07:04 +0000)
This is like the LLVMMatchType, except the verifier checks that the
second argument is a vector with the same base type and half the
number of elements.

This will be used by the ARM64 backend.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205079 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DerivedTypes.h
include/llvm/IR/Intrinsics.h
include/llvm/IR/Intrinsics.td
lib/IR/Function.cpp
lib/IR/Verifier.cpp
utils/TableGen/IntrinsicEmitter.cpp

index 758ef71a1f0f200f0f2f6677ba822a1a49cf4b72..71d9973bcb822d969909ccc8689a8bf848906ae3 100644 (file)
@@ -400,6 +400,26 @@ public:
     return VectorType::get(EltTy, VTy->getNumElements());
   }
 
+  /// VectorType::getHalfElementsVectorType - This static method returns
+  /// a VectorType with half as many elements as the input type and the
+  /// same element type.
+  ///
+  static VectorType *getHalfElementsVectorType(VectorType *VTy) {
+    unsigned NumElts = VTy->getNumElements();
+    assert ((NumElts & 1) == 0 &&
+            "Cannot halve vector with odd number of elements.");
+    return VectorType::get(VTy->getElementType(), NumElts/2);
+  }
+
+  /// VectorType::getDoubleElementsVectorType - This static method returns
+  /// a VectorType with twice  as many elements as the input type and the
+  /// same element type.
+  ///
+  static VectorType *getDoubleElementsVectorType(VectorType *VTy) {
+    unsigned NumElts = VTy->getNumElements();
+    return VectorType::get(VTy->getElementType(), NumElts*2);
+  }
+
   /// isValidElementType - Return true if the specified type is valid as a
   /// element type.
   static bool isValidElementType(Type *ElemTy);
index b3e58b7cc40766f18603601319b6dcb793ca76e6..839bbbd8b47d318ec7c022f7fe580bdd341d5c60 100644 (file)
@@ -79,7 +79,7 @@ namespace Intrinsic {
     enum IITDescriptorKind {
       Void, VarArg, MMX, Metadata, Half, Float, Double,
       Integer, Vector, Pointer, Struct,
-      Argument, ExtendArgument, TruncArgument,
+      Argument, ExtendArgument, TruncArgument, HalfVecArgument
     } Kind;
     
     union {
@@ -99,12 +99,12 @@ namespace Intrinsic {
     };
     unsigned getArgumentNumber() const {
       assert(Kind == Argument || Kind == ExtendArgument ||
-             Kind == TruncArgument);
+             Kind == TruncArgument || Kind == HalfVecArgument);
       return Argument_Info >> 2;
     }
     ArgKind getArgumentKind() const {
       assert(Kind == Argument || Kind == ExtendArgument ||
-             Kind == TruncArgument);
+             Kind == TruncArgument || Kind == HalfVecArgument);
       return (ArgKind)(Argument_Info&3);
     }
     
index 91bf99eab2e863e3c611597c970a4ed2aed76814..3e6c08dd236b514512787d2b11d32a11c0c3ad75 100644 (file)
@@ -113,6 +113,10 @@ class LLVMMatchType<int num>
 class LLVMExtendedType<int num> : LLVMMatchType<num>;
 class LLVMTruncatedType<int num> : LLVMMatchType<num>;
 
+// Match the type of another intrinsic parameter that is expected to be a
+// vector type, but change the element count to be half as many
+class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>;
+
 def llvm_void_ty       : LLVMType<isVoid>;
 def llvm_anyint_ty     : LLVMType<iAny>;
 def llvm_anyfloat_ty   : LLVMType<fAny>;
index f690ee077695c54e192332c3cae4eee08ea59d58..c2ea0e1e4dab90ff603719b6065c6ab6091ccd0f 100644 (file)
@@ -470,7 +470,8 @@ enum IIT_Info {
   IIT_TRUNC_ARG = 24,
   IIT_ANYPTR = 25,
   IIT_V1   = 26,
-  IIT_VARARG = 27
+  IIT_VARARG = 27,
+  IIT_HALF_VEC_ARG = 28
 };
 
 
@@ -568,6 +569,12 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
                                              ArgInfo));
     return;
   }
+  case IIT_HALF_VEC_ARG: {
+    unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+    OutputTable.push_back(IITDescriptor::get(IITDescriptor::HalfVecArgument,
+                                             ArgInfo));
+    return;
+  }
   case IIT_EMPTYSTRUCT:
     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0));
     return;
@@ -672,6 +679,9 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
     assert(ITy->getBitWidth() % 2 == 0);
     return IntegerType::get(Context, ITy->getBitWidth() / 2);
   }
+  case IITDescriptor::HalfVecArgument:
+    return VectorType::getHalfElementsVectorType(cast<VectorType>(
+                                                  Tys[D.getArgumentNumber()]));
   }
   llvm_unreachable("unhandled");
 }
index aa84f230d015fc903d100dcbf07f1a8f58574039..089ad1ca5f2500e6cd3f4ce7299ee7fbc4f8a9cf 100644 (file)
@@ -2206,6 +2206,12 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
 
     return Ty != NewTy;
   }
+  case IITDescriptor::HalfVecArgument:
+    // This may only be used when referring to a previous vector argument.
+    return D.getArgumentNumber() >= ArgTys.size() ||
+           !isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
+           VectorType::getHalfElementsVectorType(
+                         cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
   }
   llvm_unreachable("unhandled");
 }
index dc32dfa858442906542c021bc7cbf1bd81ed6f9b..7b0a2b6c6d252f56536a6c3975898dba9b9b5aae 100644 (file)
@@ -250,7 +250,8 @@ enum IIT_Info {
   IIT_TRUNC_ARG = 24,
   IIT_ANYPTR = 25,
   IIT_V1   = 26,
-  IIT_VARARG = 27
+  IIT_VARARG = 27,
+  IIT_HALF_VEC_ARG = 28
 };
 
 
@@ -296,6 +297,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
       Sig.push_back(IIT_EXTEND_ARG);
     else if (R->isSubClassOf("LLVMTruncatedType"))
       Sig.push_back(IIT_TRUNC_ARG);
+    else if (R->isSubClassOf("LLVMHalfElementsVectorType"))
+      Sig.push_back(IIT_HALF_VEC_ARG);
     else
       Sig.push_back(IIT_ARG);
     return Sig.push_back((Number << 2) | ArgCodes[Number]);