Intrinsics: introduce llvm_any_ty aka ValueType Any
authorRamkumar Ramachandra <artagnon@gmail.com>
Thu, 22 Jan 2015 20:14:38 +0000 (20:14 +0000)
committerRamkumar Ramachandra <artagnon@gmail.com>
Thu, 22 Jan 2015 20:14:38 +0000 (20:14 +0000)
Specifically, gc.result benefits from this greatly. Instead of:

gc.result.int.*
gc.result.float.*
gc.result.ptr.*
...

We now have a gc.result.* that can specialize to literally any type.

Differential Revision: http://reviews.llvm.org/D7020

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

15 files changed:
docs/Statepoints.rst
include/llvm/CodeGen/MachineValueType.h
include/llvm/CodeGen/ValueTypes.td
include/llvm/IR/Intrinsics.h
include/llvm/IR/Intrinsics.td
lib/Analysis/TargetTransformInfo.cpp
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/IR/IRBuilder.cpp
lib/IR/Statepoint.cpp
lib/IR/Verifier.cpp
test/CodeGen/X86/statepoint-call-lowering.ll
test/CodeGen/X86/statepoint-stackmap-format.ll
utils/TableGen/CodeGenDAGPatterns.cpp
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/IntrinsicEmitter.cpp

index 53643b1c6d31f77c39b6ff403c1fa19d616a9257..68b74626a547ebd45db06159f504de0c716b6d78 100644 (file)
@@ -236,13 +236,7 @@ Syntax:
 ::
 
       declare type*
-        @gc.result_ptr(i32 %statepoint_token)
-
-      declare fX
-        @gc.result_float(i32 %statepoint_token)
-
-      declare iX
-        @gc.result_int(i32 %statepoint_token)
+        @gc.result(i32 %statepoint_token)
 
 Overview:
 """""""""
index e3fbfe89c203e78986fa5c98a58d63146ce4a9f7..7ad782f0b72003930e36ec164ea120399f3b2605 100644 (file)
@@ -152,7 +152,11 @@ namespace llvm {
 
       // iPTR - An int value the size of the pointer of the current
       // target.  This should only be used internal to tblgen!
-      iPTR           = 255
+      iPTR           = 255,
+
+      // Any - Any type. This is used for intrinsics that have overloadings.
+      // This is only for tblgen's consumption!
+      Any            = 256
     };
 
     SimpleValueType SimpleTy;
@@ -245,7 +249,8 @@ namespace llvm {
 
     /// isOverloaded - Return true if this is an overloaded type for TableGen.
     bool isOverloaded() const {
-      return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
+      return (SimpleTy==MVT::Any  ||
+              SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
               SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
     }
 
@@ -380,6 +385,7 @@ namespace llvm {
       case iAny:
       case fAny:
       case vAny:
+      case Any:
         llvm_unreachable("Value type is overloaded.");
       case Metadata:
         llvm_unreachable("Value type is metadata.");
index b5fa0e8c6a23174d45bca03b55a492bd997ec44e..756262f6dadfb2e71d0f544c32084e5fb4cd53c4 100644 (file)
@@ -98,3 +98,6 @@ def iAny   : ValueType<0  , 254>;
 
 // Pseudo valuetype mapped to the current pointer size.
 def iPTR   : ValueType<0  , 255>;
+
+// Pseudo valuetype to represent "any type of any size".
+def Any    : ValueType<0  , 256>;
index 56d1e4af26aa077cd585c33d4b1db708d3703ae8..addd78cea4ed6c094758a9a28464159dbf51dbc4 100644 (file)
@@ -41,7 +41,7 @@ namespace Intrinsic {
 #undef GET_INTRINSIC_ENUM_VALUES
     , num_intrinsics
   };
-  
+
   /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
   std::string getName(ID id, ArrayRef<Type*> Tys = None);
 
@@ -69,7 +69,7 @@ namespace Intrinsic {
 
   /// Map a MS builtin name to an intrinsic ID.
   ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName);
-  
+
   /// This is a type descriptor which explains the type requirements of an
   /// intrinsic. This is returned by getIntrinsicInfoTableEntries.
   struct IITDescriptor {
@@ -79,7 +79,7 @@ namespace Intrinsic {
       Argument, ExtendArgument, TruncArgument, HalfVecArgument,
       SameVecWidthArgument, PtrToArgument
     } Kind;
-    
+
     union {
       unsigned Integer_Width;
       unsigned Float_Width;
@@ -88,8 +88,9 @@ namespace Intrinsic {
       unsigned Struct_NumElements;
       unsigned Argument_Info;
     };
-    
+
     enum ArgKind {
+      AK_Any,
       AK_AnyInteger,
       AK_AnyFloat,
       AK_AnyVector,
@@ -99,25 +100,25 @@ namespace Intrinsic {
       assert(Kind == Argument || Kind == ExtendArgument ||
              Kind == TruncArgument || Kind == HalfVecArgument ||
              Kind == SameVecWidthArgument || Kind == PtrToArgument);
-      return Argument_Info >> 2;
+      return Argument_Info >> 3;
     }
     ArgKind getArgumentKind() const {
       assert(Kind == Argument || Kind == ExtendArgument ||
              Kind == TruncArgument || Kind == HalfVecArgument ||
              Kind == SameVecWidthArgument || Kind == PtrToArgument);
-      return (ArgKind)(Argument_Info & 3);
+      return (ArgKind)(Argument_Info & 7);
     }
-    
+
     static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
       IITDescriptor Result = { K, { Field } };
       return Result;
     }
   };
-  
+
   /// Return the IIT table descriptor for the specified intrinsic into an array
   /// of IITDescriptors.
   void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
-  
+
 } // End Intrinsic namespace
 
 } // End llvm namespace
index a1188bccdc25826be43860ba7a18e6a9316b8895..12651ef21bd777fb880da7764e25d69319125444 100644 (file)
@@ -123,6 +123,7 @@ class LLVMPointerTo<int num> : LLVMMatchType<num>;
 class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>;
 
 def llvm_void_ty       : LLVMType<isVoid>;
+def llvm_any_ty        : LLVMType<Any>;
 def llvm_anyint_ty     : LLVMType<iAny>;
 def llvm_anyfloat_ty   : LLVMType<fAny>;
 def llvm_anyvector_ty  : LLVMType<vAny>;
@@ -516,14 +517,16 @@ def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
                                [llvm_anyptr_ty, llvm_i32_ty,
                                 llvm_i32_ty, llvm_vararg_ty]>;
 
+def int_experimental_gc_result   : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>;
+def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
+                                [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
+
+// Deprecated: will be removed in a couple of weeks
 def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
-def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], 
+def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
                                                  [llvm_i32_ty]>;
 def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>;
 
-def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
-                                [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
-
 //===-------------------------- Other Intrinsics --------------------------===//
 //
 def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
index ef3909b326f9e3d6ce2427f86cf79ba3c8468c90..e33178517146bdb968567a7cd9897533b70325de 100644 (file)
@@ -416,6 +416,7 @@ struct NoTTI final : ImmutablePass, TargetTransformInfo {
     case Intrinsic::experimental_gc_result_int:
     case Intrinsic::experimental_gc_result_float:
     case Intrinsic::experimental_gc_result_ptr:
+    case Intrinsic::experimental_gc_result:
     case Intrinsic::experimental_gc_relocate:
       // These intrinsics don't actually represent code after lowering.
       return TCC_Free;
index 456679211e9cfb2da3940dd11cc7aba745e38195..8c25783f4ea1c4018783fe72456e8c606e9585bc 100644 (file)
@@ -5604,7 +5604,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
   }
   case Intrinsic::experimental_gc_result_int:
   case Intrinsic::experimental_gc_result_float:
-  case Intrinsic::experimental_gc_result_ptr: {
+  case Intrinsic::experimental_gc_result_ptr:
+  case Intrinsic::experimental_gc_result: {
     visitGCResult(I);
     return nullptr;
   }
index ef1f2267682bcee6398ae3d1e025a646aef2fc63..dd29e7ae24fc307ca2df2fa5b63b842907fbfeb8 100644 (file)
@@ -263,16 +263,7 @@ CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
 CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,
                                        Type *ResultType,
                                        const Twine &Name) {
- Intrinsic::ID ID;
- if (ResultType->isIntegerTy()) {
-   ID = Intrinsic::experimental_gc_result_int;
- } else if (ResultType->isFloatingPointTy()) {
-   ID = Intrinsic::experimental_gc_result_float;
- } else if (ResultType->isPointerTy()) {
-   ID = Intrinsic::experimental_gc_result_ptr;
- } else {
-   llvm_unreachable("unimplemented result type for gc.result");
- }
+ Intrinsic::ID ID = Intrinsic::experimental_gc_result;
  Module *M = BB->getParent()->getParent();
  Type *Types[] = {ResultType};
  Value *FnGCResult = Intrinsic::getDeclaration(M, ID, Types);
index 270c0166ebbcb52ecfc5714533b4cb9acecae691..450651a0807a493f7de7295d28a3b34a98bb50a8 100644 (file)
@@ -54,7 +54,8 @@ bool llvm::isGCResult(const Instruction *inst) {
     if (Function *F = call->getCalledFunction()) {
       return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int ||
               F->getIntrinsicID() == Intrinsic::experimental_gc_result_float ||
-              F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr);
+              F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr ||
+              F->getIntrinsicID() == Intrinsic::experimental_gc_result);
     }
   }
   return false;
index 8a523c280162fa3b2f2a33fb2e9d8b940372534b..25dc41b4f5380d8d359260e8a24c8c56da8c5ba5 100644 (file)
@@ -2391,6 +2391,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
     ArgTys.push_back(Ty);
 
     switch (D.getArgumentKind()) {
+    case IITDescriptor::AK_Any:        return false; // Success
     case IITDescriptor::AK_AnyInteger: return !Ty->isIntOrIntVectorTy();
     case IITDescriptor::AK_AnyFloat:   return !Ty->isFPOrFPVectorTy();
     case IITDescriptor::AK_AnyVector:  return !isa<VectorType>(Ty);
@@ -2721,7 +2722,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
   }
   case Intrinsic::experimental_gc_result_int:
   case Intrinsic::experimental_gc_result_float:
-  case Intrinsic::experimental_gc_result_ptr: {
+  case Intrinsic::experimental_gc_result_ptr:
+  case Intrinsic::experimental_gc_result: {
     // Are we tied to a statepoint properly?
     CallSite StatepointCS(CI.getArgOperand(0));
     const Function *StatepointFn =
index 1432c279837c30b9be1610c424d2cb0cda45e5a6..e1a1369534ff257bbc5dad434a1a722701506df3 100644 (file)
@@ -21,7 +21,7 @@ define i1 @test_i1_return() gc "statepoint-example" {
 ; CHECK: retq
 entry:
   %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0)
-  %call1 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
+  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
   ret i1 %call1
 }
 
@@ -33,7 +33,7 @@ define i32 @test_i32_return() gc "statepoint-example" {
 ; CHECK: retq
 entry:
   %safepoint_token = tail call i32 (i32 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0)
-  %call1 = call zeroext i32 @llvm.experimental.gc.result.int.i32(i32 %safepoint_token)
+  %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
   ret i32 %call1
 }
 
@@ -45,7 +45,7 @@ define i32* @test_i32ptr_return() gc "statepoint-example" {
 ; CHECK: retq
 entry:
   %safepoint_token = tail call i32 (i32* ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0)
-  %call1 = call i32* @llvm.experimental.gc.result.ptr.p0i32(i32 %safepoint_token)
+  %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
   ret i32* %call1
 }
 
@@ -57,7 +57,7 @@ define float @test_float_return() gc "statepoint-example" {
 ; CHECK: retq
 entry:
   %safepoint_token = tail call i32 (float ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0)
-  %call1 = call float @llvm.experimental.gc.result.float.f32(i32 %safepoint_token)
+  %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
   ret float %call1
 }
 
@@ -72,7 +72,7 @@ define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
 entry:
   %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
   %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
-  %call2 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
+  %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
   ret i1 %call2
 }
 
@@ -88,16 +88,16 @@ entry:
 }
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
-declare i1 @llvm.experimental.gc.result.int.i1(i32)
+declare i1 @llvm.experimental.gc.result.i1(i32)
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()*, i32, i32, ...)
-declare i32 @llvm.experimental.gc.result.int.i32(i32)
+declare i32 @llvm.experimental.gc.result.i32(i32)
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...)
-declare i32* @llvm.experimental.gc.result.ptr.p0i32(i32)
+declare i32* @llvm.experimental.gc.result.p0i32(i32)
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...)
-declare float @llvm.experimental.gc.result.float.f32(i32)
+declare float @llvm.experimental.gc.result.f32(i32)
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...)
 
index 7ca09ddfc294d4a11d419a5de13180b31e5ba501..e452a63e8eabbdc62d91e6db6a869baefa2f3b1b 100644 (file)
@@ -22,7 +22,7 @@ entry:
   %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
   store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
   %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
-  %call1 = call zeroext i1 @llvm.experimental.gc.result.int.i1(i32 %safepoint_token)
+  %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
   %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6)
   %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
 ; 
@@ -30,7 +30,7 @@ entry:
 }
 
 declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
-declare i1 @llvm.experimental.gc.result.int.i1(i32)
+declare i1 @llvm.experimental.gc.result.i1(i32)
 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) #3
 
 
index c3de37e94533d48f0700a2de121792790d5cc656..20bf29eb8598593a160bcf42fadbdd1044f9a294 100644 (file)
@@ -53,7 +53,7 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
     EnforceVector(TP);
   else {
     assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
-            VT == MVT::iPTRAny) && "Not a concrete type!");
+            VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
     TypeVec.push_back(VT);
   }
 }
index e727a0e3f7ac56b636fd985832667b7bef039f28..47c8e0bd36f5f47cf6347e4926baaa44ca85f4bf 100644 (file)
@@ -57,6 +57,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
   case MVT::i32:      return "MVT::i32";
   case MVT::i64:      return "MVT::i64";
   case MVT::i128:     return "MVT::i128";
+  case MVT::Any:      return "MVT::Any";
   case MVT::iAny:     return "MVT::iAny";
   case MVT::fAny:     return "MVT::fAny";
   case MVT::vAny:     return "MVT::vAny";
index c0cf92d76187327fbf849606849618288709c679..87f9c90dc4a759a24564b41f9cc373d289fc8756 100644 (file)
@@ -309,7 +309,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
       Sig.push_back(IIT_HALF_VEC_ARG);
     else if (R->isSubClassOf("LLVMVectorSameWidth")) {
       Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
-      Sig.push_back((Number << 2) | ArgCodes[Number]);
+      Sig.push_back((Number << 3) | ArgCodes[Number]);
       MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
       EncodeFixedValueType(VT, Sig);
       return;
@@ -319,7 +319,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
     }
     else
       Sig.push_back(IIT_ARG);
-    return Sig.push_back((Number << 2) | ArgCodes[Number]);
+    return Sig.push_back((Number << 3) | ArgCodes[Number]);
   }
 
   MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
@@ -330,7 +330,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
   case MVT::iPTRAny: ++Tmp; // FALL THROUGH.
   case MVT::vAny: ++Tmp; // FALL THROUGH.
   case MVT::fAny: ++Tmp; // FALL THROUGH.
-  case MVT::iAny: {
+  case MVT::iAny: ++Tmp; // FALL THROUGH.
+  case MVT::Any: {
     // If this is an "any" valuetype, then the type is the type of the next
     // type in the list specified to getIntrinsic().
     Sig.push_back(IIT_ARG);
@@ -339,8 +340,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
     unsigned ArgNo = ArgCodes.size();
     ArgCodes.push_back(Tmp);
 
-    // Encode what sort of argument it must be in the low 2 bits of the ArgNo.
-    return Sig.push_back((ArgNo << 2) | Tmp);
+    // Encode what sort of argument it must be in the low 3 bits of the ArgNo.
+    return Sig.push_back((ArgNo << 3) | Tmp);
   }
 
   case MVT::iPTR: {