OSDN Git Service

Change how extended types are represented in MVTs. Instead of fiddling
authorDan Gohman <gohman@apple.com>
Mon, 3 Nov 2008 17:56:27 +0000 (17:56 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 3 Nov 2008 17:56:27 +0000 (17:56 +0000)
bits, use a union of a SimpleValueType enum and a regular Type*.

This increases the size of MVT on 64-bit hosts from 32 bits to 64 bits.
In most cases, this doesn't add significant overhead. There are places
in codegen that use arrays of MVTs, so these are now larger, but
they're small in common cases.

This eliminates restrictions on the size of integer types and vector
types that can be represented in codegen. As the included testcase
demonstrates, it's now possible to codegen very large add operations.
There are still some complications with using very large types. PR2880
is still open so they can't be used as return values on normal targets,
there are no libcalls defined for very large integers so operations
like multiply and divide aren't supported.

This also introduces a minimal tablgen Type library, capable of
handling IntegerType and VectorType. This will allow parts of
TableGen that don't depend on using SimpleValueType values to handle
arbitrary integer and vector types.

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

include/llvm/CodeGen/ValueTypes.h
lib/VMCore/ValueTypes.cpp
test/CodeGen/X86/i2k.ll [new file with mode: 0644]
utils/TableGen/CMakeLists.txt
utils/TableGen/TGValueTypes.cpp [new file with mode: 0644]

index 561616b..a6fa57d 100644 (file)
@@ -26,7 +26,6 @@ namespace llvm {
 
   struct MVT { // MVT = Machine Value Type
   public:
-
     enum SimpleValueType {
       // If you change this numbering, you must change the values in
       // ValueTypes.td as well!
@@ -87,10 +86,14 @@ 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,
+
+      // LastSimpleValueType - The greatest valid SimpleValueType value.
+      LastSimpleValueType = 255
     };
 
-    /// MVT - This type holds low-level value types. Valid values include any of
+  private:
+    /// This union holds low-level value types. Valid values include any of
     /// the values in the SimpleValueType enum, or any value returned from one
     /// of the MVT methods.  Any value type equal to one of the SimpleValueType
     /// enum values is a "simple" value type.  All others are "extended".
@@ -99,48 +102,22 @@ namespace llvm {
     /// All legal value types must be simple, but often there are some simple
     /// value types that are not legal.
     ///
-    /// @internal
-    /// Extended types are either vector types or arbitrary precision integers.
-    /// Arbitrary precision integers have iAny in the first SimpleTypeBits bits,
-    /// and the bit-width in the next PrecisionBits bits, offset by minus one.
-    /// Vector types are encoded by having the first
-    /// SimpleTypeBits+PrecisionBits bits encode the vector element type
-    /// (which must be a scalar type, possibly an arbitrary precision integer)
-    /// and the remaining VectorBits upper bits encode the vector length, offset
-    /// by one.
-    ///
-    /// 32--------------16-----------8-------------0
-    ///  | Vector length | Precision | Simple type |
-    ///  |               |      Vector element     |
-    ///
-
-  private:
-
-    static const int SimpleTypeBits = 8;
-    static const int PrecisionBits  = 8;
-    static const int VectorBits     = 32 - SimpleTypeBits - PrecisionBits;
-
-    static const uint32_t SimpleTypeMask =
-      (~uint32_t(0) << (32 - SimpleTypeBits)) >> (32 - SimpleTypeBits);
-
-    static const uint32_t PrecisionMask =
-      ((~uint32_t(0) << VectorBits) >> (32 - PrecisionBits)) << SimpleTypeBits;
-
-    static const uint32_t VectorMask =
-      (~uint32_t(0) >> (32 - VectorBits)) << (32 - VectorBits);
-
-    static const uint32_t ElementMask =
-      (~uint32_t(0) << VectorBits) >> VectorBits;
-
-    uint32_t V;
+    union {
+      uintptr_t V;
+      SimpleValueType SimpleTy;
+      const Type *LLVMTy;
+    };
 
   public:
-
     MVT() {}
     MVT(SimpleValueType S) : V(S) {}
 
-    bool operator== (const MVT VT) const { return V == VT.V; }
-    bool operator!= (const MVT VT) const { return V != VT.V; }
+    bool operator==(const MVT VT) const {
+      return getRawBits() == VT.getRawBits();
+    }
+    bool operator!=(const MVT VT) const {
+      return getRawBits() != VT.getRawBits();
+    }
 
     /// getFloatingPointVT - Returns the MVT that represents a floating point
     /// type with the given number of bits.  There are two floating point types
@@ -179,10 +156,7 @@ namespace llvm {
       case 128:
         return i128;
       }
-      MVT VT;
-      VT.V = iAny | (((BitWidth - 1) << SimpleTypeBits) & PrecisionMask);
-      assert(VT.getSizeInBits() == BitWidth && "Bad bit width!");
-      return VT;
+      return getExtendedIntegerVT(BitWidth);
     }
 
     /// getVectorVT - Returns the MVT that represents a vector NumElements in
@@ -217,13 +191,7 @@ namespace llvm {
         if (NumElements == 2)  return v2f64;
         break;
       }
-      MVT Result;
-      Result.V = VT.V | ((NumElements + 1) << (32 - VectorBits));
-      assert(Result.getVectorElementType() == VT &&
-             "Bad vector element type!");
-      assert(Result.getVectorNumElements() == NumElements &&
-             "Bad vector length!");
-      return Result;
+      return getExtendedVectorVT(VT, NumElements);
     }
 
     /// getIntVectorWithNumElements - Return any integer vector type that has
@@ -240,11 +208,10 @@ namespace llvm {
       }
     }
 
-
     /// isSimple - Test if the given MVT is simple (as opposed to being
     /// extended).
     bool isSimple() const {
-      return V <= SimpleTypeMask;
+      return V <= LastSimpleValueType;
     }
 
     /// isExtended - Test if the given MVT is extended (as opposed to
@@ -255,34 +222,43 @@ namespace llvm {
 
     /// isFloatingPoint - Return true if this is a FP, or a vector FP type.
     bool isFloatingPoint() const {
-      uint32_t SVT = V & SimpleTypeMask;
-      return (SVT >= f32 && SVT <= ppcf128) || (SVT >= v2f32 && SVT <= v2f64);
+      return isSimple() ?
+             ((SimpleTy >= f32 && SimpleTy <= ppcf128) ||
+              (SimpleTy >= v2f32 && SimpleTy <= v2f64)) :
+             isExtendedFloatingPoint();
     }
 
     /// isInteger - Return true if this is an integer, or a vector integer type.
     bool isInteger() const {
-      uint32_t SVT = V & SimpleTypeMask;
-      return (SVT >= FIRST_INTEGER_VALUETYPE && SVT <= LAST_INTEGER_VALUETYPE) ||
-        (SVT >= v8i8 && SVT <= v2i64) || (SVT == iAny && (V & PrecisionMask));
+      return isSimple() ?
+             ((SimpleTy >= FIRST_INTEGER_VALUETYPE &&
+               SimpleTy <= LAST_INTEGER_VALUETYPE) ||
+              (SimpleTy >= v8i8 && SimpleTy <= v2i64)) :
+             isExtendedInteger();
     }
 
     /// isVector - Return true if this is a vector value type.
     bool isVector() const {
-      return (V >= FIRST_VECTOR_VALUETYPE && V <= LAST_VECTOR_VALUETYPE) ||
-             (V & VectorMask);
+      return isSimple() ?
+             (SimpleTy >= FIRST_VECTOR_VALUETYPE &&
+              SimpleTy <= LAST_VECTOR_VALUETYPE) :
+             isExtendedVector();
     }
 
     /// is64BitVector - Return true if this is a 64-bit vector type.
     bool is64BitVector() const {
-      return (V==v8i8 || V==v4i16 || V==v2i32 || V==v1i64 || V==v2f32 ||
-              (isExtended() && isVector() && getSizeInBits()==64));
+      return isSimple() ?
+             (SimpleTy==v8i8 || SimpleTy==v4i16 || SimpleTy==v2i32 ||
+              SimpleTy==v1i64 || SimpleTy==v2f32) :
+             isExtended64BitVector();
     }
 
     /// is128BitVector - Return true if this is a 128-bit vector type.
     bool is128BitVector() const {
-      return (V==v16i8 || V==v8i16 || V==v4i32 || V==v2i64 ||
-              V==v4f32 || V==v2f64 ||
-              (isExtended() && isVector() && getSizeInBits()==128));
+      return isSimple() ?
+             (SimpleTy==v16i8 || SimpleTy==v8i16 || SimpleTy==v4i32 ||
+              SimpleTy==v2i64 || SimpleTy==v4f32 || SimpleTy==v2f64) :
+             isExtended128BitVector();
     }
 
     /// isByteSized - Return true if the bit size is a multiple of 8.
@@ -321,7 +297,7 @@ namespace llvm {
     /// simple MVT.
     SimpleValueType getSimpleVT() const {
       assert(isSimple() && "Expected a SimpleValueType!");
-      return (SimpleValueType)V;
+      return SimpleTy;
     }
 
     /// getVectorElementType - Given a vector type, return the type of
@@ -329,12 +305,8 @@ namespace llvm {
     MVT getVectorElementType() const {
       assert(isVector() && "Invalid vector type!");
       switch (V) {
-      default: {
-        assert(isExtended() && "Unknown simple vector type!");
-        MVT VT;
-        VT.V = V & ElementMask;
-        return VT;
-      }
+      default:
+        return getExtendedVectorElementType();
       case v8i8 :
       case v16i8: return i8;
       case v4i16:
@@ -357,8 +329,7 @@ namespace llvm {
       assert(isVector() && "Invalid vector type!");
       switch (V) {
       default:
-        assert(isExtended() && "Unknown simple vector type!");
-        return ((V & VectorMask) >> (32 - VectorBits)) - 1;
+        return getExtendedVectorNumElements();
       case v16i8: return 16;
       case v8i8 :
       case v8i16: return 8;
@@ -379,13 +350,7 @@ namespace llvm {
     unsigned getSizeInBits() const {
       switch (V) {
       default:
-        assert(isExtended() && "MVT has no known size!");
-        if (isVector())
-          return getVectorElementType().getSizeInBits()*getVectorNumElements();
-        if (isInteger())
-          return ((V & PrecisionMask) >> SimpleTypeBits) + 1;
-        assert(false && "Unknown value type!");
-        return 0;
+        return getExtendedSizeInBits();
       case i1  :  return 1;
       case i8  :  return 8;
       case i16 :  return 16;
@@ -410,6 +375,12 @@ namespace llvm {
       case v2i64:
       case v4f32:
       case v2f64: return 128;
+      case iPTR:
+        assert(false && "Value type size is target-dependent. Ask TLI.");
+      case iPTRAny:
+      case iAny:
+      case fAny:
+        assert(false && "Value type is overloaded.");
       }
     }
 
@@ -461,7 +432,7 @@ namespace llvm {
     static MVT getMVT(const Type *Ty, bool HandleUnknown = false);
 
     /// getRawBits - Represent the type as a bunch of bits.
-    uint32_t getRawBits() const { return V; }
+    uintptr_t getRawBits() const { return V; }
 
     /// compareRawBits - A meaningless but well-behaved order, useful for
     /// constructing containers.
@@ -470,6 +441,21 @@ namespace llvm {
         return L.getRawBits() < R.getRawBits();
       }
     };
+
+  private:
+    // Methods for handling the Extended-type case in functions above.
+    // These are all out-of-line to prevent users of this header file
+    // from having a dependency on Type.h.
+    static MVT getExtendedIntegerVT(unsigned BitWidth);
+    static MVT getExtendedVectorVT(MVT VT, unsigned NumElements);
+    bool isExtendedFloatingPoint() const;
+    bool isExtendedInteger() const;
+    bool isExtendedVector() const;
+    bool isExtended64BitVector() const;
+    bool isExtended128BitVector() const;
+    MVT getExtendedVectorElementType() const;
+    unsigned getExtendedVectorNumElements() const;
+    unsigned getExtendedSizeInBits() const;
   };
 
 } // End llvm namespace
index ca23284..99dc1de 100644 (file)
 #include "llvm/DerivedTypes.h"
 using namespace llvm;
 
+MVT MVT::getExtendedIntegerVT(unsigned BitWidth) {
+  MVT VT;
+  VT.LLVMTy = IntegerType::get(BitWidth);
+  return VT;
+}
+
+MVT MVT::getExtendedVectorVT(MVT VT, unsigned NumElements) {
+  MVT ResultVT;
+  ResultVT.LLVMTy = VectorType::get(VT.getTypeForMVT(), NumElements);
+  return ResultVT;
+}
+
+bool MVT::isExtendedFloatingPoint() const {
+  assert(isExtended() && "Type is not extended!");
+  return LLVMTy->isFPOrFPVector();
+}
+
+bool MVT::isExtendedInteger() const {
+  assert(isExtended() && "Type is not extended!");
+  return LLVMTy->isIntOrIntVector();
+}
+
+bool MVT::isExtendedVector() const {
+  assert(isExtended() && "Type is not extended!");
+  return isa<VectorType>(LLVMTy);
+}
+
+bool MVT::isExtended64BitVector() const {
+  return isExtendedVector() && getSizeInBits() == 64;
+}
+
+bool MVT::isExtended128BitVector() const {
+  return isExtendedVector() && getSizeInBits() == 128;
+}
+
+MVT MVT::getExtendedVectorElementType() const {
+  assert(isExtended() && "Type is not extended!");
+  return MVT::getMVT(cast<VectorType>(LLVMTy)->getElementType());
+}
+
+unsigned MVT::getExtendedVectorNumElements() const {
+  assert(isExtended() && "Type is not extended!");
+  return cast<VectorType>(LLVMTy)->getNumElements();
+}
+
+unsigned MVT::getExtendedSizeInBits() const {
+  assert(isExtended() && "Type is not extended!");
+  if (const IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy))
+    return ITy->getBitWidth();
+  if (const VectorType *VTy = dyn_cast<VectorType>(LLVMTy))
+    return VTy->getBitWidth();
+  assert(false && "Unrecognized extended type!");
+}
+
 /// getMVTString - This function returns value type as a string, e.g. "i32".
 std::string MVT::getMVTString() const {
   switch (V) {
diff --git a/test/CodeGen/X86/i2k.ll b/test/CodeGen/X86/i2k.ll
new file mode 100644 (file)
index 0000000..712302d
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | llc -march=x86
+
+define void @foo(i2011* %x, i2011* %y, i2011* %p) nounwind {
+  %a = load i2011* %x
+  %b = load i2011* %y
+  %c = add i2011 %a, %b
+  store i2011 %c, i2011* %p
+  ret void
+}
index 8141d76..8e6a3e1 100644 (file)
@@ -15,6 +15,7 @@ add_executable(tblgen
   SubtargetEmitter.cpp
   TGLexer.cpp
   TGParser.cpp
+  TGValueTypes.cpp
   TableGen.cpp
   TableGenBackend.cpp
   FastISelEmitter.cpp
diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp
new file mode 100644 (file)
index 0000000..209e7c9
--- /dev/null
@@ -0,0 +1,123 @@
+//===- ValueTypes.cpp - Tablegen extended ValueType implementation --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// The MVT type is used by tablegen as well as in LLVM. In order to handle
+// extended types, the MVT type uses support functions that call into
+// LLVM's type system code. These aren't accessible in tablegen, so this
+// file provides simple replacements.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/Support/Streams.h"
+#include <map>
+#include <vector>
+using namespace llvm;
+
+namespace llvm {
+
+class Type {
+public:
+  virtual unsigned getSizeInBits() const = 0;
+};
+
+}
+
+class ExtendedIntegerType : public Type {
+  unsigned BitWidth;
+public:
+  explicit ExtendedIntegerType(unsigned bits)
+    : BitWidth(bits) {}
+  unsigned getSizeInBits() const {
+    return getBitWidth();
+  }
+  unsigned getBitWidth() const {
+    return BitWidth;
+  }
+};
+
+class ExtendedVectorType : public Type {
+  MVT ElementType;
+  unsigned NumElements;
+public:
+  ExtendedVectorType(MVT elty, unsigned num)
+    : ElementType(elty), NumElements(num) {}
+  unsigned getSizeInBits() const {
+    return getNumElements() * getElementType().getSizeInBits();
+  }
+  MVT getElementType() const {
+    return ElementType;
+  }
+  unsigned getNumElements() const {
+    return NumElements;
+  }
+};
+
+static std::map<unsigned, const Type *>
+  ExtendedIntegerTypeMap;
+static std::map<std::pair<uintptr_t, uintptr_t>, const Type *>
+  ExtendedVectorTypeMap;
+
+MVT MVT::getExtendedIntegerVT(unsigned BitWidth) {
+  const Type *&ET = ExtendedIntegerTypeMap[BitWidth];
+  if (!ET) ET = new ExtendedIntegerType(BitWidth);
+  MVT VT;
+  VT.LLVMTy = ET;
+  return VT;
+}
+
+MVT MVT::getExtendedVectorVT(MVT VT, unsigned NumElements) {
+  const Type *&ET = ExtendedVectorTypeMap[std::make_pair(VT.getRawBits(),
+                                                         NumElements)];
+  if (!ET) ET = new ExtendedVectorType(VT, NumElements);
+  MVT ResultVT;
+  ResultVT.LLVMTy = ET;
+  return ResultVT;
+}
+
+bool MVT::isExtendedFloatingPoint() const {
+  assert(isExtended() && "Type is not extended!");
+  // Extended floating-point types are not supported yet.
+  return false;
+}
+
+bool MVT::isExtendedInteger() const {
+  assert(isExtended() && "Type is not extended!");
+  return dynamic_cast<const ExtendedIntegerType *>(LLVMTy) != 0;
+}
+
+bool MVT::isExtendedVector() const {
+  assert(isExtended() && "Type is not extended!");
+  return dynamic_cast<const ExtendedVectorType *>(LLVMTy) != 0;
+}
+
+bool MVT::isExtended64BitVector() const {
+  assert(isExtended() && "Type is not extended!");
+  return isExtendedVector() && getSizeInBits() == 64;
+}
+
+bool MVT::isExtended128BitVector() const {
+  assert(isExtended() && "Type is not extended!");
+  return isExtendedVector() && getSizeInBits() == 128;
+}
+
+MVT MVT::getExtendedVectorElementType() const {
+  assert(isExtendedVector() && "Type is not an extended vector!");
+  return static_cast<const ExtendedVectorType *>(LLVMTy)->getElementType();
+}
+
+unsigned MVT::getExtendedVectorNumElements() const {
+  assert(isExtendedVector() && "Type is not an extended vector!");
+  return static_cast<const ExtendedVectorType *>(LLVMTy)->getNumElements();
+}
+
+unsigned MVT::getExtendedSizeInBits() const {
+  assert(isExtended() && "Type is not extended!");
+  return LLVMTy->getSizeInBits();
+}