[IR] Optimize bitfield layout of Value for MSVC
authorReid Kleckner <rnk@google.com>
Fri, 26 Feb 2016 18:08:59 +0000 (18:08 +0000)
committerReid Kleckner <rnk@google.com>
Fri, 26 Feb 2016 18:08:59 +0000 (18:08 +0000)
This should save a pointer of padding from all MSVC Value subclasses.

Recall that MSVC will not pack the following bitfields together:
  unsigned Bits : 29;
  unsigned Flag1 : 1;
  unsigned Flag2 : 1;
  unsigned Flag3 : 1;

Add a static_assert because LLVM developers always trip over this
behavior. This regressed in June.

llvm-svn: 262045

llvm/include/llvm/IR/DataLayout.h
llvm/include/llvm/IR/GlobalValue.h
llvm/include/llvm/IR/Value.h
llvm/lib/IR/Value.cpp

index 65a0706..585580c 100644 (file)
@@ -476,7 +476,7 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) {
 class StructLayout {
   uint64_t StructSize;
   unsigned StructAlignment;
-  bool IsPadded : 1;
+  unsigned IsPadded : 1;
   unsigned NumElements : 31;
   uint64_t MemberOffsets[1]; // variable sized array!
 public:
index 38d2290..03abf9a 100644 (file)
@@ -75,9 +75,9 @@ protected:
   }
 
   Type *ValueType;
-  // Note: VC++ treats enums as signed, so an extra bit is required to prevent
-  // Linkage and Visibility from turning into negative values.
-  LinkageTypes Linkage : 5;   // The linkage of this global
+  // All bitfields use unsigned as the underlying type so that MSVC will pack
+  // them.
+  unsigned Linkage : 4;       // The linkage of this global
   unsigned Visibility : 2;    // The visibility style of this global
   unsigned UnnamedAddr : 1;   // This value's address is not significant
   unsigned DllStorageClass : 2; // DLL storage class
@@ -259,44 +259,40 @@ public:
            Linkage == CommonLinkage || Linkage == ExternalWeakLinkage;
   }
 
-  bool hasExternalLinkage() const { return isExternalLinkage(Linkage); }
+  bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); }
   bool hasAvailableExternallyLinkage() const {
-    return isAvailableExternallyLinkage(Linkage);
+    return isAvailableExternallyLinkage(getLinkage());
   }
-  bool hasLinkOnceLinkage() const {
-    return isLinkOnceLinkage(Linkage);
+  bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); }
+  bool hasLinkOnceODRLinkage() const {
+    return isLinkOnceODRLinkage(getLinkage());
   }
-  bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); }
-  bool hasWeakLinkage() const {
-    return isWeakLinkage(Linkage);
+  bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); }
+  bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); }
+  bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); }
+  bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); }
+  bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); }
+  bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); }
+  bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); }
+  bool hasExternalWeakLinkage() const {
+    return isExternalWeakLinkage(getLinkage());
   }
-  bool hasWeakAnyLinkage() const {
-    return isWeakAnyLinkage(Linkage);
-  }
-  bool hasWeakODRLinkage() const {
-    return isWeakODRLinkage(Linkage);
-  }
-  bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); }
-  bool hasInternalLinkage() const { return isInternalLinkage(Linkage); }
-  bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); }
-  bool hasLocalLinkage() const { return isLocalLinkage(Linkage); }
-  bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); }
-  bool hasCommonLinkage() const { return isCommonLinkage(Linkage); }
+  bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); }
 
   void setLinkage(LinkageTypes LT) {
     if (isLocalLinkage(LT))
       Visibility = DefaultVisibility;
     Linkage = LT;
   }
-  LinkageTypes getLinkage() const { return Linkage; }
+  LinkageTypes getLinkage() const { return LinkageTypes(Linkage); }
 
   bool isDiscardableIfUnused() const {
-    return isDiscardableIfUnused(Linkage);
+    return isDiscardableIfUnused(getLinkage());
   }
 
-  bool mayBeOverridden() const { return mayBeOverridden(Linkage); }
+  bool mayBeOverridden() const { return mayBeOverridden(getLinkage()); }
 
-  bool isWeakForLinker() const { return isWeakForLinker(Linkage); }
+  bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); }
 
   /// Copy all additional attributes (those not needed to create a GlobalValue)
   /// from the GlobalValue Src to this one.
index 70bbe25..6d5694a 100644 (file)
@@ -107,10 +107,11 @@ protected:
   enum : unsigned { NumUserOperandsBits = 28 };
   unsigned NumUserOperands : NumUserOperandsBits;
 
-  bool IsUsedByMD : 1;
-  bool HasName : 1;
-  bool HasHungOffUses : 1;
-  bool HasDescriptor : 1;
+  // Use the same type as the bitfield above so that MSVC will pack them.
+  unsigned IsUsedByMD : 1;
+  unsigned HasName : 1;
+  unsigned HasHungOffUses : 1;
+  unsigned HasDescriptor : 1;
 
 private:
   template <typename UseT> // UseT == 'Use' or 'const Use'
index f02c8fd..19fb4f8 100644 (file)
@@ -59,6 +59,8 @@ Value::Value(Type *ty, unsigned scid)
            (SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal))
     assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&
            "Cannot create non-first-class values except for constants!");
+  static_assert(sizeof(Value) == 3 * sizeof(void *) + 2 * sizeof(unsigned),
+                "Value too big");
 }
 
 Value::~Value() {