Add basic generic CodeGen support for half.
authorDan Gohman <gohman@apple.com>
Tue, 20 Dec 2011 00:02:33 +0000 (00:02 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 20 Dec 2011 00:02:33 +0000 (00:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146927 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/ValueTypes.h
include/llvm/CodeGen/ValueTypes.td
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/TargetData.cpp
lib/VMCore/ValueTypes.cpp
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/IntrinsicEmitter.cpp

index 7a7080f28faba6bf2232390d90789e464bbc6362..de9aacd2a59b845ec78e93ad404c4e79bc2a6fa4 100644 (file)
@@ -45,49 +45,50 @@ namespace llvm {
       FIRST_INTEGER_VALUETYPE = i1,
       LAST_INTEGER_VALUETYPE  = i128,
 
-      f32            =   7,   // This is a 32 bit floating point value
-      f64            =   8,   // This is a 64 bit floating point value
-      f80            =   9,   // This is a 80 bit floating point value
-      f128           =  10,   // This is a 128 bit floating point value
-      ppcf128        =  11,   // This is a PPC 128-bit floating point value
-
-      v2i8           =  12,   //  2 x i8
-      v4i8           =  13,   //  4 x i8
-      v8i8           =  14,   //  8 x i8
-      v16i8          =  15,   // 16 x i8
-      v32i8          =  16,   // 32 x i8
-      v2i16          =  17,   //  2 x i16
-      v4i16          =  18,   //  4 x i16
-      v8i16          =  19,   //  8 x i16
-      v16i16         =  20,   // 16 x i16
-      v2i32          =  21,   //  2 x i32
-      v4i32          =  22,   //  4 x i32
-      v8i32          =  23,   //  8 x i32
-      v1i64          =  24,   //  1 x i64
-      v2i64          =  25,   //  2 x i64
-      v4i64          =  26,   //  4 x i64
-      v8i64          =  27,   //  8 x i64
-
-      v2f32          =  28,   //  2 x f32
-      v4f32          =  29,   //  4 x f32
-      v8f32          =  30,   //  8 x f32
-      v2f64          =  31,   //  2 x f64
-      v4f64          =  32,   //  4 x f64
+      f16            =   7,   // This is a 16 bit floating point value
+      f32            =   8,   // This is a 32 bit floating point value
+      f64            =   9,   // This is a 64 bit floating point value
+      f80            =  10,   // This is a 80 bit floating point value
+      f128           =  11,   // This is a 128 bit floating point value
+      ppcf128        =  12,   // This is a PPC 128-bit floating point value
+
+      v2i8           =  13,   //  2 x i8
+      v4i8           =  14,   //  4 x i8
+      v8i8           =  15,   //  8 x i8
+      v16i8          =  16,   // 16 x i8
+      v32i8          =  17,   // 32 x i8
+      v2i16          =  18,   //  2 x i16
+      v4i16          =  19,   //  4 x i16
+      v8i16          =  20,   //  8 x i16
+      v16i16         =  21,   // 16 x i16
+      v2i32          =  22,   //  2 x i32
+      v4i32          =  23,   //  4 x i32
+      v8i32          =  24,   //  8 x i32
+      v1i64          =  25,   //  1 x i64
+      v2i64          =  26,   //  2 x i64
+      v4i64          =  27,   //  4 x i64
+      v8i64          =  28,   //  8 x i64
+
+      v2f32          =  29,   //  2 x f32
+      v4f32          =  30,   //  4 x f32
+      v8f32          =  31,   //  8 x f32
+      v2f64          =  32,   //  2 x f64
+      v4f64          =  33,   //  4 x f64
 
       FIRST_VECTOR_VALUETYPE = v2i8,
       LAST_VECTOR_VALUETYPE  = v4f64,
 
-      x86mmx         =  33,   // This is an X86 MMX value
+      x86mmx         =  34,   // This is an X86 MMX value
 
-      Glue           =  34,   // This glues nodes together during pre-RA sched
+      Glue           =  35,   // This glues nodes together during pre-RA sched
 
-      isVoid         =  35,   // This has no value
+      isVoid         =  36,   // This has no value
 
-      Untyped        =  36,   // This value takes a register, but has
+      Untyped        =  37,   // This value takes a register, but has
                               // unspecified type.  The register class
                               // will be determined by the opcode.
 
-      LAST_VALUETYPE =  37,   // This always remains at the end of the list.
+      LAST_VALUETYPE =  38,   // This always remains at the end of the list.
 
       // This is the current maximum for LAST_VALUETYPE.
       // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -143,7 +144,7 @@ namespace llvm {
 
     /// isFloatingPoint - Return true if this is a FP, or a vector FP type.
     bool isFloatingPoint() const {
-      return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) ||
+      return ((SimpleTy >= MVT::f16 && SimpleTy <= MVT::ppcf128) ||
              (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64));
     }
 
@@ -252,6 +253,7 @@ namespace llvm {
       case i1  :  return 1;
       case i8  :  return 8;
       case i16 :
+      case f16:
       case v2i8:  return 16;
       case f32 :
       case i32 :
@@ -301,6 +303,8 @@ namespace llvm {
       switch (BitWidth) {
       default:
         assert(false && "Bad bit width!");
+      case 16:
+        return MVT::f16;
       case 32:
         return MVT::f32;
       case 64:
index 0cfb634ead79e5c75150b292a898531d6d8b9d83..482f84771c9c53f4eff4e8b2934ca1d168809969 100644 (file)
@@ -26,39 +26,40 @@ def i16    : ValueType<16 ,  3>;   // 16-bit integer value
 def i32    : ValueType<32 ,  4>;   // 32-bit integer value
 def i64    : ValueType<64 ,  5>;   // 64-bit integer value
 def i128   : ValueType<128,  6>;   // 128-bit integer value
-def f32    : ValueType<32 ,  7>;   // 32-bit floating point value
-def f64    : ValueType<64 ,  8>;   // 64-bit floating point value
-def f80    : ValueType<80 ,  9>;   // 80-bit floating point value
-def f128   : ValueType<128, 10>;   // 128-bit floating point value
-def ppcf128: ValueType<128, 11>;   // PPC 128-bit floating point value
+def f16    : ValueType<16 ,  7>;   // 32-bit floating point value
+def f32    : ValueType<32 ,  8>;   // 32-bit floating point value
+def f64    : ValueType<64 ,  9>;   // 64-bit floating point value
+def f80    : ValueType<80 , 10>;   // 80-bit floating point value
+def f128   : ValueType<128, 11>;   // 128-bit floating point value
+def ppcf128: ValueType<128, 12>;   // PPC 128-bit floating point value
 
-def v2i8   : ValueType<16 , 12>;   //  2 x i8  vector value
-def v4i8   : ValueType<32 , 13>;   //  4 x i8  vector value
-def v8i8   : ValueType<64 , 14>;   //  8 x i8  vector value
-def v16i8  : ValueType<128, 15>;   // 16 x i8  vector value
-def v32i8  : ValueType<256, 16>;   // 32 x i8 vector value
-def v2i16  : ValueType<32 , 17>;   //  2 x i16 vector value
-def v4i16  : ValueType<64 , 18>;   //  4 x i16 vector value
-def v8i16  : ValueType<128, 19>;   //  8 x i16 vector value
-def v16i16 : ValueType<256, 20>;   // 16 x i16 vector value
-def v2i32  : ValueType<64 , 21>;   //  2 x i32 vector value
-def v4i32  : ValueType<128, 22>;   //  4 x i32 vector value
-def v8i32  : ValueType<256, 23>;   //  8 x i32 vector value
-def v1i64  : ValueType<64 , 24>;   //  1 x i64 vector value
-def v2i64  : ValueType<128, 25>;   //  2 x i64 vector value
-def v4i64  : ValueType<256, 26>;   //  4 x i64 vector value
-def v8i64  : ValueType<512, 27>;   //  8 x i64 vector value
+def v2i8   : ValueType<16 , 13>;   //  2 x i8  vector value
+def v4i8   : ValueType<32 , 14>;   //  4 x i8  vector value
+def v8i8   : ValueType<64 , 15>;   //  8 x i8  vector value
+def v16i8  : ValueType<128, 16>;   // 16 x i8  vector value
+def v32i8  : ValueType<256, 17>;   // 32 x i8 vector value
+def v2i16  : ValueType<32 , 18>;   //  2 x i16 vector value
+def v4i16  : ValueType<64 , 19>;   //  4 x i16 vector value
+def v8i16  : ValueType<128, 20>;   //  8 x i16 vector value
+def v16i16 : ValueType<256, 21>;   // 16 x i16 vector value
+def v2i32  : ValueType<64 , 22>;   //  2 x i32 vector value
+def v4i32  : ValueType<128, 23>;   //  4 x i32 vector value
+def v8i32  : ValueType<256, 24>;   //  8 x i32 vector value
+def v1i64  : ValueType<64 , 25>;   //  1 x i64 vector value
+def v2i64  : ValueType<128, 26>;   //  2 x i64 vector value
+def v4i64  : ValueType<256, 27>;   //  4 x i64 vector value
+def v8i64  : ValueType<512, 28>;   //  8 x i64 vector value
 
-def v2f32  : ValueType<64 , 28>;   //  2 x f32 vector value
-def v4f32  : ValueType<128, 29>;   //  4 x f32 vector value
-def v8f32  : ValueType<256, 30>;   //  8 x f32 vector value
-def v2f64  : ValueType<128, 31>;   //  2 x f64 vector value
-def v4f64  : ValueType<256, 32>;   //  4 x f64 vector value
+def v2f32  : ValueType<64 , 29>;   //  2 x f32 vector value
+def v4f32  : ValueType<128, 30>;   //  4 x f32 vector value
+def v8f32  : ValueType<256, 31>;   //  8 x f32 vector value
+def v2f64  : ValueType<128, 32>;   //  2 x f64 vector value
+def v4f64  : ValueType<256, 33>;   //  4 x f64 vector value
 
-def x86mmx : ValueType<64 , 33>;   // X86 MMX value
-def FlagVT : ValueType<0  , 34>;   // Pre-RA sched glue
-def isVoid : ValueType<0  , 35>;   // Produces no value
-def untyped: ValueType<8  , 36>;   // Produces an untyped value
+def x86mmx : ValueType<64 , 34>;   // X86 MMX value
+def FlagVT : ValueType<0  , 35>;   // Pre-RA sched glue
+def isVoid : ValueType<0  , 36>;   // Produces no value
+def untyped: ValueType<8  , 37>;   // Produces an untyped value
 
 def MetadataVT: ValueType<0, 250>; // Metadata
 
index d13eae098f4c7a1cfd8701c7a8bfd8dc801dcd32..82860c265744b19ff4146d893dbe543277a83098 100644 (file)
@@ -1694,16 +1694,14 @@ static void EmitGlobalConstantStruct(const ConstantStruct *CS,
 
 static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
                                  AsmPrinter &AP) {
-  // FP Constants are printed as integer constants to avoid losing
-  // precision.
-  if (CFP->getType()->isDoubleTy()) {
+  if (CFP->getType()->isHalfTy()) {
     if (AP.isVerbose()) {
-      double Val = CFP->getValueAPF().convertToDouble();
-      AP.OutStreamer.GetCommentOS() << "double " << Val << '\n';
+      SmallString<10> Str;
+      CFP->getValueAPF().toString(Str);
+      AP.OutStreamer.GetCommentOS() << "half " << Str << '\n';
     }
-
     uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
-    AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
+    AP.OutStreamer.EmitIntValue(Val, 2, AddrSpace);
     return;
   }
 
@@ -1717,6 +1715,19 @@ static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
     return;
   }
 
+  // FP Constants are printed as integer constants to avoid losing
+  // precision.
+  if (CFP->getType()->isDoubleTy()) {
+    if (AP.isVerbose()) {
+      double Val = CFP->getValueAPF().convertToDouble();
+      AP.OutStreamer.GetCommentOS() << "double " << Val << '\n';
+    }
+
+    uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
+    AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
+    return;
+  }
+
   if (CFP->getType()->isX86_FP80Ty()) {
     // all long double variants are printed as hex
     // API needed to prevent premature destruction
index 9ced1ac24394d398cdb4f70b9bc73cfff9c114d2..9d7a41d014424053c2eb8bbff57bd4a52b10a069 100644 (file)
@@ -572,21 +572,22 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
   // ConstantFP nodes default to expand.  Targets can either change this to
   // Legal, in which case all fp constants are legal, or use isFPImmLegal()
   // to optimize expansions for certain constants.
+  setOperationAction(ISD::ConstantFP, MVT::f16, Expand);
   setOperationAction(ISD::ConstantFP, MVT::f32, Expand);
   setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
   setOperationAction(ISD::ConstantFP, MVT::f80, Expand);
 
   // These library functions default to expand.
-  setOperationAction(ISD::FLOG ,  MVT::f64, Expand);
-  setOperationAction(ISD::FLOG2,  MVT::f64, Expand);
-  setOperationAction(ISD::FLOG10, MVT::f64, Expand);
-  setOperationAction(ISD::FEXP ,  MVT::f64, Expand);
-  setOperationAction(ISD::FEXP2,  MVT::f64, Expand);
-  setOperationAction(ISD::FFLOOR, MVT::f64, Expand);
-  setOperationAction(ISD::FNEARBYINT, MVT::f64, Expand);
-  setOperationAction(ISD::FCEIL,  MVT::f64, Expand);
-  setOperationAction(ISD::FRINT,  MVT::f64, Expand);
-  setOperationAction(ISD::FTRUNC, MVT::f64, Expand);
+  setOperationAction(ISD::FLOG ,  MVT::f16, Expand);
+  setOperationAction(ISD::FLOG2,  MVT::f16, Expand);
+  setOperationAction(ISD::FLOG10, MVT::f16, Expand);
+  setOperationAction(ISD::FEXP ,  MVT::f16, Expand);
+  setOperationAction(ISD::FEXP2,  MVT::f16, Expand);
+  setOperationAction(ISD::FFLOOR, MVT::f16, Expand);
+  setOperationAction(ISD::FNEARBYINT, MVT::f16, Expand);
+  setOperationAction(ISD::FCEIL,  MVT::f16, Expand);
+  setOperationAction(ISD::FRINT,  MVT::f16, Expand);
+  setOperationAction(ISD::FTRUNC, MVT::f16, Expand);
   setOperationAction(ISD::FLOG ,  MVT::f32, Expand);
   setOperationAction(ISD::FLOG2,  MVT::f32, Expand);
   setOperationAction(ISD::FLOG10, MVT::f32, Expand);
@@ -597,6 +598,16 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
   setOperationAction(ISD::FCEIL,  MVT::f32, Expand);
   setOperationAction(ISD::FRINT,  MVT::f32, Expand);
   setOperationAction(ISD::FTRUNC, MVT::f32, Expand);
+  setOperationAction(ISD::FLOG ,  MVT::f64, Expand);
+  setOperationAction(ISD::FLOG2,  MVT::f64, Expand);
+  setOperationAction(ISD::FLOG10, MVT::f64, Expand);
+  setOperationAction(ISD::FEXP ,  MVT::f64, Expand);
+  setOperationAction(ISD::FEXP2,  MVT::f64, Expand);
+  setOperationAction(ISD::FFLOOR, MVT::f64, Expand);
+  setOperationAction(ISD::FNEARBYINT, MVT::f64, Expand);
+  setOperationAction(ISD::FCEIL,  MVT::f64, Expand);
+  setOperationAction(ISD::FRINT,  MVT::f64, Expand);
+  setOperationAction(ISD::FTRUNC, MVT::f64, Expand);
 
   // Default ISD::TRAP to expand (which turns it into abort).
   setOperationAction(ISD::TRAP, MVT::Other, Expand);
index ff60e0b29c74d3c19dc89b9fdace0b3814acdff2..2b39f1308b7a9cfd039c00123c12f1c9c967bf65 100644 (file)
@@ -147,6 +147,7 @@ void TargetData::init() {
   setAlignment(INTEGER_ALIGN,   2,  2, 16);  // i16
   setAlignment(INTEGER_ALIGN,   4,  4, 32);  // i32
   setAlignment(INTEGER_ALIGN,   4,  8, 64);  // i64
+  setAlignment(FLOAT_ALIGN,     2,  2, 16);  // half
   setAlignment(FLOAT_ALIGN,     4,  4, 32);  // float
   setAlignment(FLOAT_ALIGN,     8,  8, 64);  // double
   setAlignment(VECTOR_ALIGN,    8,  8, 64);  // v2i32, v1i64, ...
@@ -477,6 +478,8 @@ uint64_t TargetData::getTypeSizeInBits(Type *Ty) const {
     return cast<IntegerType>(Ty)->getBitWidth();
   case Type::VoidTyID:
     return 8;
+  case Type::HalfTyID:
+    return 16;
   case Type::FloatTyID:
     return 32;
   case Type::DoubleTyID:
@@ -534,6 +537,7 @@ unsigned TargetData::getAlignment(Type *Ty, bool abi_or_pref) const {
   case Type::VoidTyID:
     AlignType = INTEGER_ALIGN;
     break;
+  case Type::HalfTyID:
   case Type::FloatTyID:
   case Type::DoubleTyID:
   // PPC_FP128TyID and FP128TyID have different data contents, but the
index 089c2594cbea3e392c6a13f48186628f5fc17d0a..3b4ec3299530e46b9303f1b177925accc8e77fae 100644 (file)
@@ -108,6 +108,7 @@ std::string EVT::getEVTString() const {
   case MVT::i32:     return "i32";
   case MVT::i64:     return "i64";
   case MVT::i128:    return "i128";
+  case MVT::f16:     return "f16";
   case MVT::f32:     return "f32";
   case MVT::f64:     return "f64";
   case MVT::f80:     return "f80";
@@ -158,6 +159,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
   case MVT::i32:     return Type::getInt32Ty(Context);
   case MVT::i64:     return Type::getInt64Ty(Context);
   case MVT::i128:    return IntegerType::get(Context, 128);
+  case MVT::f16:     return Type::getHalfTy(Context);
   case MVT::f32:     return Type::getFloatTy(Context);
   case MVT::f64:     return Type::getDoubleTy(Context);
   case MVT::f80:     return Type::getX86_FP80Ty(Context);
@@ -202,6 +204,7 @@ EVT EVT::getEVT(Type *Ty, bool HandleUnknown){
     return MVT::isVoid;
   case Type::IntegerTyID:
     return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth());
+  case Type::HalfTyID:      return MVT(MVT::f16);
   case Type::FloatTyID:     return MVT(MVT::f32);
   case Type::DoubleTyID:    return MVT(MVT::f64);
   case Type::X86_FP80TyID:  return MVT(MVT::f80);
index c8d2b00a82e0799e94df1353d8375462bd839272..cb9851841e357426201533c5dc0e5e217d4c0fe4 100644 (file)
@@ -58,6 +58,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
   case MVT::iAny:     return "MVT::iAny";
   case MVT::fAny:     return "MVT::fAny";
   case MVT::vAny:     return "MVT::vAny";
+  case MVT::f16:      return "MVT::f16";
   case MVT::f32:      return "MVT::f32";
   case MVT::f64:      return "MVT::f64";
   case MVT::f80:      return "MVT::f80";
index 782b89ede2e7d6697324c4e72a9c5c6606eb7278..657988b3f82372d8d3998d2fba256dd62164955d 100644 (file)
@@ -181,6 +181,8 @@ static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
   } else if (VT == MVT::Other) {
     // MVT::OtherVT is used to mean the empty struct type here.
     OS << "StructType::get(Context)";
+  } else if (VT == MVT::f16) {
+    OS << "Type::getHalfTy(Context)";
   } else if (VT == MVT::f32) {
     OS << "Type::getFloatTy(Context)";
   } else if (VT == MVT::f64) {