Commit 9577ee84 authored by Tim Northover's avatar Tim Northover
Browse files

NeonEmitter: switch to enum for internal Type representation.

Previously we had a handful of bools (Signed, Floating, ...) that could
easily end up in an inconsistent state. This adds an enum Kind which
holds the mutually exclusive states a type might be in, retaining some
of the bools that modified an underlying type.

https://reviews.llvm.org/D69715
parent 58fa50f4
Loading
Loading
Loading
Loading
+90 −101
Original line number Diff line number Diff line
@@ -140,7 +140,15 @@ class Type {
private:
  TypeSpec TS;

  bool Float, Signed, Immediate, Void, Poly, Constant, Pointer;
  enum TypeKind {
    Void,
    Float,
    SInt,
    UInt,
    Poly,
  };
  TypeKind Kind;
  bool Immediate, Constant, Pointer;
  // ScalarForMangling and NoManglingQ are really not suited to live here as
  // they are not related to the type. But they live in the TypeSpec (not the
  // prototype), so this is really the only place to store them.
@@ -149,15 +157,14 @@ private:

public:
  Type()
      : Float(false), Signed(false), Immediate(false), Void(true), Poly(false),
        Constant(false), Pointer(false), ScalarForMangling(false),
        NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {}
      : Kind(Void), Immediate(false), Constant(false),
        Pointer(false), ScalarForMangling(false), NoManglingQ(false),
        Bitwidth(0), ElementBitwidth(0), NumVectors(0) {}

  Type(TypeSpec TS, char CharMod)
      : TS(std::move(TS)), Float(false), Signed(false), Immediate(false),
        Void(false), Poly(false), Constant(false), Pointer(false),
        ScalarForMangling(false), NoManglingQ(false), Bitwidth(0),
        ElementBitwidth(0), NumVectors(0) {
      : TS(std::move(TS)), Kind(Void), Immediate(false),
        Constant(false), Pointer(false), ScalarForMangling(false),
        NoManglingQ(false), Bitwidth(0), ElementBitwidth(0), NumVectors(0) {
    applyModifier(CharMod);
  }

@@ -174,21 +181,21 @@ public:
  bool noManglingQ() const { return NoManglingQ; }

  bool isPointer() const { return Pointer; }
  bool isFloating() const { return Float; }
  bool isInteger() const { return !Float && !Poly; }
  bool isSigned() const { return Signed; }
  bool isFloating() const { return Kind == Float; }
  bool isInteger() const { return Kind == SInt || Kind == UInt; }
  bool isPoly() const { return Kind == Poly; }
  bool isSigned() const { return Kind == SInt; }
  bool isImmediate() const { return Immediate; }
  bool isScalar() const { return NumVectors == 0; }
  bool isVector() const { return NumVectors > 0; }
  bool isFloat() const { return Float && ElementBitwidth == 32; }
  bool isDouble() const { return Float && ElementBitwidth == 64; }
  bool isHalf() const { return Float && ElementBitwidth == 16; }
  bool isPoly() const { return Poly; }
  bool isFloat() const { return isFloating() && ElementBitwidth == 32; }
  bool isDouble() const { return isFloating() && ElementBitwidth == 64; }
  bool isHalf() const { return isFloating() && ElementBitwidth == 16; }
  bool isChar() const { return ElementBitwidth == 8; }
  bool isShort() const { return !Float && ElementBitwidth == 16; }
  bool isInt() const { return !Float && ElementBitwidth == 32; }
  bool isLong() const { return !Float && ElementBitwidth == 64; }
  bool isVoid() const { return Void; }
  bool isShort() const { return isInteger() && ElementBitwidth == 16; }
  bool isInt() const { return isInteger() && ElementBitwidth == 32; }
  bool isLong() const { return isInteger() && ElementBitwidth == 64; }
  bool isVoid() const { return Kind == Void; }
  unsigned getNumElements() const { return Bitwidth / ElementBitwidth; }
  unsigned getSizeInBits() const { return Bitwidth; }
  unsigned getElementSizeInBits() const { return ElementBitwidth; }
@@ -197,21 +204,24 @@ public:
  //
  // Mutator functions
  //
  void makeUnsigned() { Signed = false; }
  void makeSigned() { Signed = true; }
  void makeUnsigned() {
    assert(isInteger() && "not a potentially signed type");
    Kind = UInt;
  }
  void makeSigned() {
    assert(isInteger() && "not a potentially signed type");
    Kind = SInt;
  }

  void makeInteger(unsigned ElemWidth, bool Sign) {
    Float = false;
    Poly = false;
    Signed = Sign;
    assert(!isVoid() && "converting void to int probably not useful");
    Kind = Sign ? SInt : UInt;
    Immediate = false;
    ElementBitwidth = ElemWidth;
  }

  void makeImmediate(unsigned ElemWidth) {
    Float = false;
    Poly = false;
    Signed = true;
    Kind = SInt;
    Immediate = true;
    ElementBitwidth = ElemWidth;
  }
@@ -257,7 +267,7 @@ private:
  /// seen. This is needed by applyModifier as some modifiers
  /// only take effect if the type size was changed by "Q" or "H".
  void applyTypespec(bool &Quad);
  /// Applies a prototype modifier to the type.
  /// Applies a prototype modifiers to the type.
  void applyModifier(char Mod);
};

@@ -582,16 +592,16 @@ public:
//===----------------------------------------------------------------------===//

std::string Type::str() const {
  if (Void)
  if (isVoid())
    return "void";
  std::string S;

  if (!Signed && isInteger())
  if (isInteger() && !isSigned())
    S += "u";

  if (Poly)
  if (isPoly())
    S += "poly";
  else if (Float)
  else if (isFloating())
    S += "float";
  else
    S += "int";
@@ -636,10 +646,10 @@ std::string Type::builtin_str() const {
    default: llvm_unreachable("Unhandled case!");
    }

  if (isChar() && !Pointer && Signed)
  if (isChar() && !isPointer() && isSigned())
    // Make chars explicitly signed.
    S = "S" + S;
  else if (isInteger() && !Pointer && !Signed)
  else if (!isPointer() && isInteger() && !isSigned())
    S = "U" + S;

  // Constant indices are "int", but have the "constant expression" modifier.
@@ -673,20 +683,20 @@ unsigned Type::getNeonEnum() const {
  }

  unsigned Base = (unsigned)NeonTypeFlags::Int8 + Addend;
  if (Poly) {
  if (isPoly()) {
    // Adjustment needed because Poly32 doesn't exist.
    if (Addend >= 2)
      --Addend;
    Base = (unsigned)NeonTypeFlags::Poly8 + Addend;
  }
  if (Float) {
  if (isFloating()) {
    assert(Addend != 0 && "Float8 doesn't exist!");
    Base = (unsigned)NeonTypeFlags::Float16 + (Addend - 1);
  }

  if (Bitwidth == 128)
    Base |= (unsigned)NeonTypeFlags::QuadFlag;
  if (isInteger() && !Signed)
  if (isInteger() && !isSigned())
    Base |= (unsigned)NeonTypeFlags::UnsignedFlag;

  return Base;
@@ -694,22 +704,18 @@ unsigned Type::getNeonEnum() const {

Type Type::fromTypedefName(StringRef Name) {
  Type T;
  T.Void = false;
  T.Float = false;
  T.Poly = false;
  T.Kind = SInt;

  if (Name.front() == 'u') {
    T.Signed = false;
    T.Kind = UInt;
    Name = Name.drop_front();
  } else {
    T.Signed = true;
  }

  if (Name.startswith("float")) {
    T.Float = true;
    T.Kind = Float;
    Name = Name.drop_front(5);
  } else if (Name.startswith("poly")) {
    T.Poly = true;
    T.Kind = Poly;
    Name = Name.drop_front(4);
  } else {
    assert(Name.startswith("int"));
@@ -760,10 +766,8 @@ Type Type::fromTypedefName(StringRef Name) {
void Type::applyTypespec(bool &Quad) {
  std::string S = TS;
  ScalarForMangling = false;
  Void = false;
  Poly = Float = false;
  Kind = SInt;
  ElementBitwidth = ~0U;
  Signed = true;
  NumVectors = 1;

  for (char I : S) {
@@ -779,28 +783,28 @@ void Type::applyTypespec(bool &Quad) {
      Quad = true;
      break;
    case 'P':
      Poly = true;
      Kind = Poly;
      break;
    case 'U':
      Signed = false;
      Kind = UInt;
      break;
    case 'c':
      ElementBitwidth = 8;
      break;
    case 'h':
      Float = true;
      Kind = Float;
      LLVM_FALLTHROUGH;
    case 's':
      ElementBitwidth = 16;
      break;
    case 'f':
      Float = true;
      Kind = Float;
      LLVM_FALLTHROUGH;
    case 'i':
      ElementBitwidth = 32;
      break;
    case 'd':
      Float = true;
      Kind = Float;
      LLVM_FALLTHROUGH;
    case 'l':
      ElementBitwidth = 64;
@@ -808,7 +812,7 @@ void Type::applyTypespec(bool &Quad) {
    case 'k':
      ElementBitwidth = 128;
      // Poly doesn't have a 128x1 type.
      if (Poly)
      if (isPoly())
        NumVectors = 0;
      break;
    default:
@@ -826,97 +830,84 @@ void Type::applyModifier(char Mod) {

  switch (Mod) {
  case 'v':
    Void = true;
    Kind = Void;
    break;
  case 't':
    if (Poly) {
      Poly = false;
      Signed = false;
    }
    if (isPoly())
      Kind = UInt;
    break;
  case 'b':
    Signed = false;
    Float = false;
    Poly = false;
    Kind = UInt;
    NumVectors = 0;
    Bitwidth = ElementBitwidth;
    break;
  case '$':
    Signed = true;
    Float = false;
    Poly = false;
    Kind = SInt;
    NumVectors = 0;
    Bitwidth = ElementBitwidth;
    break;
  case 'u':
    Signed = false;
    Poly = false;
    Float = false;
    Kind = UInt;
    break;
  case 'x':
    Signed = true;
    assert(!Poly && "'u' can't be used with poly types!");
    Float = false;
    assert(!isPoly() && "'u' can't be used with poly types!");
    Kind = SInt;
    break;
  case 'o':
    Bitwidth = ElementBitwidth = 64;
    NumVectors = 0;
    Float = true;
    Kind = Float;
    break;
  case 'y':
    Bitwidth = ElementBitwidth = 32;
    NumVectors = 0;
    Float = true;
    Kind = Float;
    break;
  case 'Y':
    Bitwidth = ElementBitwidth = 16;
    NumVectors = 0;
    Float = true;
    Kind = Float;
    break;
  case 'I':
    Bitwidth = ElementBitwidth = 32;
    NumVectors = 0;
    Float = false;
    Signed = true;
    Kind = SInt;
    break;
  case 'L':
    Bitwidth = ElementBitwidth = 64;
    NumVectors = 0;
    Float = false;
    Signed = true;
    Kind = SInt;
    break;
  case 'U':
    Bitwidth = ElementBitwidth = 32;
    NumVectors = 0;
    Float = false;
    Signed = false;
    Kind = UInt;
    break;
  case 'O':
    Bitwidth = ElementBitwidth = 64;
    NumVectors = 0;
    Float = false;
    Signed = false;
    Kind = UInt;
    break;
  case 'f':
    Float = true;
    Kind = Float;
    ElementBitwidth = 32;
    break;
  case 'F':
    Float = true;
    Kind = Float;
    ElementBitwidth = 64;
    break;
  case 'H':
    Float = true;
    Kind = Float;
    ElementBitwidth = 16;
    break;
  case '0':
    Float = true;
    Kind = Float;
    if (AppliedQuad)
      Bitwidth /= 2;
    ElementBitwidth = 16;
    break;
  case '1':
    Float = true;
    Kind = Float;
    if (!AppliedQuad)
      Bitwidth *= 2;
    ElementBitwidth = 16;
@@ -937,19 +928,15 @@ void Type::applyModifier(char Mod) {
    ElementBitwidth *= 2;
    break;
  case 'i':
    Float = false;
    Poly = false;
    Kind = SInt;
    ElementBitwidth = Bitwidth = 32;
    NumVectors = 0;
    Signed = true;
    Immediate = true;
    break;
  case 'l':
    Float = false;
    Poly = false;
    Kind = UInt;
    ElementBitwidth = Bitwidth = 64;
    NumVectors = 0;
    Signed = false;
    Immediate = true;
    break;
  case 'z':
@@ -987,7 +974,7 @@ void Type::applyModifier(char Mod) {
    break;
  case 'e':
    ElementBitwidth /= 2;
    Signed = false;
    Kind = UInt;
    break;
  case 'm':
    ElementBitwidth /= 2;
@@ -1089,7 +1076,7 @@ std::string Intrinsic::getBuiltinTypeStr() {

  Type RetT = getReturnType();
  if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() &&
      !RetT.isFloating())
      !RetT.isFloating() && !RetT.isVoid())
    RetT.makeInteger(RetT.getElementSizeInBits(), false);

  // Since the return value must be one type, return a vector type of the
@@ -1101,11 +1088,12 @@ std::string Intrinsic::getBuiltinTypeStr() {
  } else {
    if (RetT.isPoly())
      RetT.makeInteger(RetT.getElementSizeInBits(), false);
    if (!RetT.isScalar() && !RetT.isSigned())
    if (!RetT.isScalar() && RetT.isInteger() && !RetT.isSigned())
      RetT.makeSigned();

    bool ForcedVectorFloatingType = isFloatingPointProtoModifier(Proto[0]);
    if (LocalCK == ClassB && !RetT.isScalar() && !ForcedVectorFloatingType)
    if (LocalCK == ClassB && !RetT.isVoid() && !RetT.isScalar() &&
        !ForcedVectorFloatingType)
      // Cast to vector of 8-bit elements.
      RetT.makeInteger(8, true);

@@ -1124,7 +1112,7 @@ std::string Intrinsic::getBuiltinTypeStr() {
    if (T.isHalf() && T.isVector() && !T.isScalarForMangling())
      T.makeInteger(8, true);

    if (LocalCK == ClassI)
    if (LocalCK == ClassI && T.isInteger())
      T.makeSigned();

    if (hasImmediate() && getImmediateIdx() == I)
@@ -1447,6 +1435,7 @@ void Intrinsic::emitBodyAsBuiltinCall() {
      CastToType.makeInteger(8, true);
      Arg = "(" + CastToType.str() + ")" + Arg;
    } else if (CastToType.isVector() && LocalCK == ClassI) {
      if (CastToType.isInteger())
        CastToType.makeSigned();
      Arg = "(" + CastToType.str() + ")" + Arg;
    }
@@ -2410,7 +2399,7 @@ void NeonEmitter::run(raw_ostream &OS) {
  for (auto &TS : TDTypeVec) {
    bool IsA64 = false;
    Type T(TS, 'd');
    if (T.isDouble() || (T.isPoly() && T.isLong()))
    if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64))
      IsA64 = true;

    if (InIfdef && !IsA64) {
@@ -2443,7 +2432,7 @@ void NeonEmitter::run(raw_ostream &OS) {
    for (auto &TS : TDTypeVec) {
      bool IsA64 = false;
      Type T(TS, 'd');
      if (T.isDouble() || (T.isPoly() && T.isLong()))
      if (T.isDouble() || (T.isPoly() && T.getElementSizeInBits() == 64))
        IsA64 = true;

      if (InIfdef && !IsA64) {