[llvm-commits] [dragonegg] r103967 - /dragonegg/trunk/llvm-types.cpp

Duncan Sands baldrick at free.fr
Mon May 17 13:20:47 PDT 2010


Author: baldrick
Date: Mon May 17 15:20:46 2010
New Revision: 103967

URL: http://llvm.org/viewvc/llvm-project?rev=103967&view=rev
Log:
Port commit 100721 (stoklund) from llvm-gcc:
Create larger struct fields for consecutive bitfields. (Again).

When creating an LLVM struct type for a struct with bitfields, try to allocate
integer fields that are as large as possible, taking the following bitfields
into account.

For example, this struct:

  struct S {
    int a, b;
    void *c;
    unsigned d : 8;
    unsigned e : 8;
  };

used to be:

  %struct.S = type { i32, i32, i8*, i8, i8 },

but now it becomes:

  %struct.S = type { i32, i32, i8*, i16 }

This makes it easier for the code generator to shuffle register sized bitfield
groups around in fewer registers. It also means that it is harder for SROA to
isolate bit fields as scalars.

The larger struct fields are only produced when they would be properly aligned
and smaller than the natural machine word size.

This strategy is similar to what clang will be doing. We will see how it works
out.


Modified:
    dragonegg/trunk/llvm-types.cpp

Modified: dragonegg/trunk/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/llvm-types.cpp?rev=103967&r1=103966&r2=103967&view=diff
==============================================================================
--- dragonegg/trunk/llvm-types.cpp (original)
+++ dragonegg/trunk/llvm-types.cpp Mon May 17 15:20:46 2010
@@ -1507,7 +1507,8 @@
     return getFieldEndOffsetInBytes(ElementOffsetInBytes.size()-1);
   }
 
-  void addNewBitField(uint64_t Size, uint64_t FirstUnallocatedByte);
+  void addNewBitField(uint64_t Size, uint64_t Extra,
+                      uint64_t FirstUnallocatedByte);
 
   void dump() const;
 };
@@ -1515,22 +1516,43 @@
 // Add new element which is a bit field. Size is not the size of bit field,
 // but size of bits required to determine type of new Field which will be
 // used to access this bit field.
-void StructTypeConversionInfo::addNewBitField(uint64_t Size,
+// If possible, allocate a field with room for Size+Extra bits.
+void StructTypeConversionInfo::addNewBitField(uint64_t Size, uint64_t Extra,
                                               uint64_t FirstUnallocatedByte) {
 
   // Figure out the LLVM type that we will use for the new field.
   // Note, Size is not necessarily size of the new field. It indicates
   // additional bits required after FirstunallocatedByte to cover new field.
-  const Type *NewFieldTy;
-  if (Size <= 8)
-    NewFieldTy = Type::getInt8Ty(Context);
-  else if (Size <= 16)
-    NewFieldTy = Type::getInt16Ty(Context);
-  else if (Size <= 32)
-    NewFieldTy = Type::getInt32Ty(Context);
-  else {
-    assert(Size <= 64 && "Bitfield too large!");
-    NewFieldTy = Type::getInt64Ty(Context);
+  const Type *NewFieldTy = 0;
+
+  // First try an ABI-aligned field including (some of) the Extra bits.
+  // This field must satisfy Size <= w && w <= XSize.
+  uint64_t XSize = Size + Extra;
+  for (unsigned w = NextPowerOf2(std::min(UINT64_C(64), XSize))/2;
+       w >= Size && w >= 8; w /= 2) {
+    if (TD.isIllegalInteger(w))
+      continue;
+    // Would a w-sized integer field be aligned here?
+    const unsigned a = TD.getABIIntegerTypeAlignment(w);
+    if (FirstUnallocatedByte & (a-1) || a > getGCCStructAlignmentInBytes())
+      continue;
+    // OK, use w-sized integer.
+    NewFieldTy = IntegerType::get(Context, w);
+    break;
+  }
+
+  // Try an integer field that holds Size bits.
+  if (!NewFieldTy) {
+    if (Size <= 8)
+      NewFieldTy = Type::getInt8Ty(Context);
+    else if (Size <= 16)
+      NewFieldTy = Type::getInt16Ty(Context);
+    else if (Size <= 32)
+      NewFieldTy = Type::getInt32Ty(Context);
+    else {
+      assert(Size <= 64 && "Bitfield too large!");
+      NewFieldTy = Type::getInt64Ty(Context);
+    }
   }
 
   // Check that the alignment of NewFieldTy won't cause a gap in the structure!
@@ -1707,7 +1729,34 @@
   // LLVM struct such that there are no holes in the struct where the bitfield
   // is: these holes would make it impossible to statically initialize a global
   // of this type that has an initializer for the bitfield.
-  
+
+  // We want the integer-typed fields as large as possible up to the machine
+  // word size. If there are more bitfields following this one, try to include
+  // them in the same field.
+
+  // Calculate the total number of bits in the continuous group of bitfields
+  // following this one. This is the number of bits that addNewBitField should
+  // try to include.
+  unsigned ExtraSizeInBits = 0;
+  tree LastBitField = 0;
+  for (tree f = TREE_CHAIN(Field); f; f = TREE_CHAIN(f)) {
+    if (TREE_CODE(f) != FIELD_DECL ||
+        TREE_CODE(DECL_FIELD_OFFSET(f)) != INTEGER_CST)
+      break;
+    if (isBitfield(f))
+      LastBitField = f;
+    else {
+      // We can use all this bits up to the next non-bitfield.
+      LastBitField = 0;
+      ExtraSizeInBits = getFieldOffsetInBits(f) - EndBitOffset;
+      break;
+    }
+  }
+  // Record ended in a bitfield? Use all of the last byte.
+  if (LastBitField)
+    ExtraSizeInBits = RoundUpToAlignment(getFieldOffsetInBits(LastBitField) +
+      TREE_INT_CST_LOW(DECL_SIZE(LastBitField)), 8) - EndBitOffset;
+
   // Compute the number of bits that we need to add to this struct to cover
   // this field.
   uint64_t FirstUnallocatedByte = Info.getEndUnallocatedByte();
@@ -1721,7 +1770,7 @@
       // This field starts at byte boundry. Need to allocate space
       // for additional bytes not yet allocated.
       unsigned NumBitsToAdd = FieldSizeInBits - AvailableBits;
-      Info.addNewBitField(NumBitsToAdd, FirstUnallocatedByte);
+      Info.addNewBitField(NumBitsToAdd, ExtraSizeInBits, FirstUnallocatedByte);
       return;
     }
 
@@ -1745,7 +1794,7 @@
       for (unsigned idx = 0; idx < (prevFieldTypeSizeInBits/8); ++idx)
 	FirstUnallocatedByte--;
     }
-    Info.addNewBitField(NumBitsRequired, FirstUnallocatedByte);
+    Info.addNewBitField(NumBitsRequired, ExtraSizeInBits, FirstUnallocatedByte);
     // Do this after adding Field.
     Info.lastFieldStartsAtNonByteBoundry(true);
     return;
@@ -1779,7 +1828,7 @@
   }
 
   // Now, Field starts at FirstUnallocatedByte and everything is aligned.
-  Info.addNewBitField(FieldSizeInBits, FirstUnallocatedByte);
+  Info.addNewBitField(FieldSizeInBits, ExtraSizeInBits, FirstUnallocatedByte);
 }
 
 /// UnionHasOnlyZeroOffsets - Check if a union type has only members with
@@ -1857,7 +1906,7 @@
 
     if (isBitfield(UnionField)) {
       unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(UnionField));
-      Info.addNewBitField(FieldSizeInBits, 0);
+      Info.addNewBitField(FieldSizeInBits, 0, 0);
     } else {
       Info.allFieldsAreNotBitFields();
       Info.addElement(UnionTy, 0, Info.getTypeSize(UnionTy));





More information about the llvm-commits mailing list