Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
     18 #define ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
     19 
     20 #include <iosfwd>
     21 
     22 #include <android-base/logging.h>
     23 
     24 #include "base/bit_utils.h"
     25 
     26 namespace art {
     27 
     28 class DataType {
     29  public:
     30   enum class Type : uint8_t {
     31     kReference = 0,
     32     kBool,
     33     kUint8,
     34     kInt8,
     35     kUint16,
     36     kInt16,
     37     kUint32,
     38     kInt32,
     39     kUint64,
     40     kInt64,
     41     kFloat32,
     42     kFloat64,
     43     kVoid,
     44     kLast = kVoid
     45   };
     46 
     47   static constexpr Type FromShorty(char type);
     48   static constexpr char TypeId(DataType::Type type);
     49 
     50   static constexpr size_t SizeShift(Type type) {
     51     switch (type) {
     52       case Type::kVoid:
     53       case Type::kBool:
     54       case Type::kUint8:
     55       case Type::kInt8:
     56         return 0;
     57       case Type::kUint16:
     58       case Type::kInt16:
     59         return 1;
     60       case Type::kUint32:
     61       case Type::kInt32:
     62       case Type::kFloat32:
     63         return 2;
     64       case Type::kUint64:
     65       case Type::kInt64:
     66       case Type::kFloat64:
     67         return 3;
     68       case Type::kReference:
     69         return WhichPowerOf2(kObjectReferenceSize);
     70       default:
     71         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
     72         return 0;
     73     }
     74   }
     75 
     76   static constexpr size_t Size(Type type) {
     77     switch (type) {
     78       case Type::kVoid:
     79         return 0;
     80       case Type::kBool:
     81       case Type::kUint8:
     82       case Type::kInt8:
     83         return 1;
     84       case Type::kUint16:
     85       case Type::kInt16:
     86         return 2;
     87       case Type::kUint32:
     88       case Type::kInt32:
     89       case Type::kFloat32:
     90         return 4;
     91       case Type::kUint64:
     92       case Type::kInt64:
     93       case Type::kFloat64:
     94         return 8;
     95       case Type::kReference:
     96         return kObjectReferenceSize;
     97       default:
     98         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
     99         return 0;
    100     }
    101   }
    102 
    103   static bool IsFloatingPointType(Type type) {
    104     return type == Type::kFloat32 || type == Type::kFloat64;
    105   }
    106 
    107   static bool IsIntegralType(Type type) {
    108     // The Java language does not allow treating boolean as an integral type but
    109     // our bit representation makes it safe.
    110     switch (type) {
    111       case Type::kBool:
    112       case Type::kUint8:
    113       case Type::kInt8:
    114       case Type::kUint16:
    115       case Type::kInt16:
    116       case Type::kUint32:
    117       case Type::kInt32:
    118       case Type::kUint64:
    119       case Type::kInt64:
    120         return true;
    121       default:
    122         return false;
    123     }
    124   }
    125 
    126   static bool IsIntOrLongType(Type type) {
    127     return type == Type::kInt32 || type == Type::kInt64;
    128   }
    129 
    130   static bool Is64BitType(Type type) {
    131     return type == Type::kUint64 || type == Type::kInt64 || type == Type::kFloat64;
    132   }
    133 
    134   static bool IsUnsignedType(Type type) {
    135     return type == Type::kBool || type == Type::kUint8 || type == Type::kUint16 ||
    136         type == Type::kUint32 || type == Type::kUint64;
    137   }
    138 
    139   // Return the general kind of `type`, fusing integer-like types as Type::kInt.
    140   static Type Kind(Type type) {
    141     switch (type) {
    142       case Type::kBool:
    143       case Type::kUint8:
    144       case Type::kInt8:
    145       case Type::kUint16:
    146       case Type::kInt16:
    147       case Type::kUint32:
    148       case Type::kInt32:
    149         return Type::kInt32;
    150       case Type::kUint64:
    151       case Type::kInt64:
    152         return Type::kInt64;
    153       default:
    154         return type;
    155     }
    156   }
    157 
    158   static int64_t MinValueOfIntegralType(Type type) {
    159     switch (type) {
    160       case Type::kBool:
    161         return std::numeric_limits<bool>::min();
    162       case Type::kUint8:
    163         return std::numeric_limits<uint8_t>::min();
    164       case Type::kInt8:
    165         return std::numeric_limits<int8_t>::min();
    166       case Type::kUint16:
    167         return std::numeric_limits<uint16_t>::min();
    168       case Type::kInt16:
    169         return std::numeric_limits<int16_t>::min();
    170       case Type::kUint32:
    171         return std::numeric_limits<uint32_t>::min();
    172       case Type::kInt32:
    173         return std::numeric_limits<int32_t>::min();
    174       case Type::kUint64:
    175         return std::numeric_limits<uint64_t>::min();
    176       case Type::kInt64:
    177         return std::numeric_limits<int64_t>::min();
    178       default:
    179         LOG(FATAL) << "non integral type";
    180     }
    181     return 0;
    182   }
    183 
    184   static int64_t MaxValueOfIntegralType(Type type) {
    185     switch (type) {
    186       case Type::kBool:
    187         return std::numeric_limits<bool>::max();
    188       case Type::kUint8:
    189         return std::numeric_limits<uint8_t>::max();
    190       case Type::kInt8:
    191         return std::numeric_limits<int8_t>::max();
    192       case Type::kUint16:
    193         return std::numeric_limits<uint16_t>::max();
    194       case Type::kInt16:
    195         return std::numeric_limits<int16_t>::max();
    196       case Type::kUint32:
    197         return std::numeric_limits<uint32_t>::max();
    198       case Type::kInt32:
    199         return std::numeric_limits<int32_t>::max();
    200       case Type::kUint64:
    201         return std::numeric_limits<uint64_t>::max();
    202       case Type::kInt64:
    203         return std::numeric_limits<int64_t>::max();
    204       default:
    205         LOG(FATAL) << "non integral type";
    206     }
    207     return 0;
    208   }
    209 
    210   static bool IsTypeConversionImplicit(Type input_type, Type result_type);
    211   static bool IsTypeConversionImplicit(int64_t value, Type result_type);
    212 
    213   static const char* PrettyDescriptor(Type type);
    214 
    215  private:
    216   static constexpr size_t kObjectReferenceSize = 4u;
    217 };
    218 std::ostream& operator<<(std::ostream& os, DataType::Type data_type);
    219 
    220 // Defined outside DataType to have the operator<< available for DCHECK_NE().
    221 inline bool DataType::IsTypeConversionImplicit(Type input_type, Type result_type) {
    222   DCHECK_NE(DataType::Type::kVoid, result_type);
    223   DCHECK_NE(DataType::Type::kVoid, input_type);
    224 
    225   // Invariant: We should never generate a conversion to a Boolean value.
    226   DCHECK_NE(DataType::Type::kBool, result_type);
    227 
    228   // Besides conversion to the same type, integral conversions to non-Int64 types
    229   // are implicit if the result value range covers the input value range, i.e.
    230   // widening conversions that do not need to trim the sign bits.
    231   return result_type == input_type ||
    232          (result_type != Type::kInt64 &&
    233           IsIntegralType(input_type) &&
    234           IsIntegralType(result_type) &&
    235           MinValueOfIntegralType(input_type) >= MinValueOfIntegralType(result_type) &&
    236           MaxValueOfIntegralType(input_type) <= MaxValueOfIntegralType(result_type));
    237 }
    238 
    239 inline bool DataType::IsTypeConversionImplicit(int64_t value, Type result_type) {
    240   if (IsIntegralType(result_type) && result_type != Type::kInt64) {
    241     // If the constant value falls in the range of the result_type, type
    242     // conversion isn't needed.
    243     return value >= MinValueOfIntegralType(result_type) &&
    244            value <= MaxValueOfIntegralType(result_type);
    245   }
    246   // Conversion isn't implicit if it's into non-integer types, or 64-bit int
    247   // which may have different number of registers.
    248   return false;
    249 }
    250 
    251 }  // namespace art
    252 
    253 #endif  // ART_COMPILER_OPTIMIZING_DATA_TYPE_H_
    254