[llvm] abdd367 - [Bitfields][NFC] Make sure bitfields are contiguous

Guillaume Chatelet via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 7 07:35:24 PDT 2020


Author: Guillaume Chatelet
Date: 2020-07-07T14:35:13Z
New Revision: abdd367b200a0bf4176dbdaf200b23f750a35cb0

URL: https://github.com/llvm/llvm-project/commit/abdd367b200a0bf4176dbdaf200b23f750a35cb0
DIFF: https://github.com/llvm/llvm-project/commit/abdd367b200a0bf4176dbdaf200b23f750a35cb0.diff

LOG: [Bitfields][NFC] Make sure bitfields are contiguous

Differential Revision: https://reviews.llvm.org/D83202

Added: 
    

Modified: 
    llvm/include/llvm/ADT/Bitfields.h
    llvm/include/llvm/IR/InstrTypes.h
    llvm/include/llvm/IR/Instruction.h
    llvm/include/llvm/IR/Instructions.h
    llvm/unittests/ADT/BitFieldsTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/Bitfields.h b/llvm/include/llvm/ADT/Bitfields.h
index 9891b4692e80..d93f6483fa52 100644
--- a/llvm/include/llvm/ADT/Bitfields.h
+++ b/llvm/include/llvm/ADT/Bitfields.h
@@ -228,6 +228,7 @@ struct Bitfield {
     static constexpr unsigned Bits = Size;
     static constexpr unsigned FirstBit = Offset;
     static constexpr unsigned LastBit = Shift + Bits - 1;
+    static constexpr unsigned NextBit = Shift + Bits;
 
   private:
     template <typename, typename> friend struct bitfields_details::Impl;
@@ -275,6 +276,12 @@ struct Bitfield {
   template <typename A, typename B> static constexpr bool isOverlapping() {
     return A::LastBit >= B::FirstBit && B::LastBit >= A::FirstBit;
   }
+
+  template <typename A> static constexpr bool areContiguous() { return true; }
+  template <typename A, typename B, typename... Others>
+  static constexpr bool areContiguous() {
+    return A::NextBit == B::FirstBit && areContiguous<B, Others...>();
+  }
 };
 
 } // namespace llvm

diff  --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index 770d3183a909..8408c8772b22 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -758,7 +758,7 @@ class CmpInst : public Instruction {
     BAD_ICMP_PREDICATE = ICMP_SLE + 1
   };
   using PredicateField =
-      Bitfield::Element<Predicate, 0, 6, LAST_ICMP_PREDICATE>; // Next bit:6
+      Bitfield::Element<Predicate, 0, 6, LAST_ICMP_PREDICATE>;
 
 protected:
   CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred,
@@ -1096,12 +1096,16 @@ using ConstOperandBundleDef = OperandBundleDefT<const Value *>;
 /// subclass requires. Note that accessing the end of the argument list isn't
 /// as cheap as most other operations on the base class.
 class CallBase : public Instruction {
-  // The first two bits are reserved by CallInst for fast retrieving,
-  using CallInstReservedField = Bitfield::Element<unsigned, 0, 2>; // Next bit:2
-  using CallingConvField = Bitfield::Element<CallingConv::ID, 2, 10,
-                                             CallingConv::MaxID>; // Next bit:12
-
 protected:
+  // The first two bits are reserved by CallInst for fast retrieval,
+  using CallInstReservedField = Bitfield::Element<unsigned, 0, 2>;
+  using CallingConvField =
+      Bitfield::Element<CallingConv::ID, CallInstReservedField::NextBit, 10,
+                        CallingConv::MaxID>;
+  static_assert(
+      Bitfield::areContiguous<CallInstReservedField, CallingConvField>(),
+      "Bitfields must be contiguous");
+
   /// The last operand is the called operand.
   static constexpr int CalledOperandOpEndIdx = -1;
 

diff  --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index a85353ff9027..a03eac0ad40d 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -23,6 +23,7 @@
 #include "llvm/IR/SymbolTableListTraits.h"
 #include "llvm/IR/User.h"
 #include "llvm/IR/Value.h"
+#include "llvm/Support/AtomicOrdering.h"
 #include "llvm/Support/Casting.h"
 #include <algorithm>
 #include <cassert>
@@ -53,7 +54,7 @@ class Instruction : public User,
 protected:
   // The 15 first bits of `Value::SubclassData` are available for subclasses of
   // `Instruction` to use.
-  using OpaqueField = Bitfield::Element<uint16_t, 0, 15>; // Next bit:15
+  using OpaqueField = Bitfield::Element<uint16_t, 0, 15>;
 
   // Template alias so that all Instruction storing alignment use the same
   // definiton.
@@ -61,10 +62,18 @@ class Instruction : public User,
   // 2^29. We store them as Log2(Alignment), so we need 5 bits to encode the 30
   // possible values.
   template <unsigned Offset>
-  using AlignmentBitfieldElement =
+  using AlignmentBitfieldElementT =
       typename Bitfield::Element<unsigned, Offset, 5,
                                  Value::MaxAlignmentExponent>;
 
+  template <unsigned Offset>
+  using BoolBitfieldElementT = typename Bitfield::Element<bool, Offset, 1>;
+
+  template <unsigned Offset>
+  using AtomicOrderingBitfieldElementT =
+      typename Bitfield::Element<AtomicOrdering, Offset, 3,
+                                 AtomicOrdering::LAST>;
+
 private:
   // The last bit is used to store whether the instruction has metadata attached
   // or not.

diff  --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 7119b1392d2d..0afc585dfbe5 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -60,9 +60,12 @@ class LLVMContext;
 class AllocaInst : public UnaryInstruction {
   Type *AllocatedType;
 
-  using AlignmentField = AlignmentBitfieldElement<0>;          // Next bit:5
-  using UsedWithInAllocaField = Bitfield::Element<bool, 5, 1>; // Next bit:6
-  using SwiftErrorField = Bitfield::Element<bool, 6, 1>;       // Next bit:7
+  using AlignmentField = AlignmentBitfieldElementT<0>;
+  using UsedWithInAllocaField = BoolBitfieldElementT<AlignmentField::NextBit>;
+  using SwiftErrorField = BoolBitfieldElementT<UsedWithInAllocaField::NextBit>;
+  static_assert(Bitfield::areContiguous<AlignmentField, UsedWithInAllocaField,
+                                        SwiftErrorField>(),
+                "Bitfields must be contiguous");
 
 protected:
   // Note: Instruction needs to be a friend here to call cloneImpl.
@@ -168,10 +171,12 @@ class AllocaInst : public UnaryInstruction {
 /// An instruction for reading from memory. This uses the SubclassData field in
 /// Value to store whether or not the load is volatile.
 class LoadInst : public UnaryInstruction {
-  using VolatileField = Bitfield::Element<bool, 0, 1>;      // Next bit:1
-  using AlignmentField = AlignmentBitfieldElement<1>;       // Next bit:6
-  using OrderingField = Bitfield::Element<AtomicOrdering, 6, 3,
-                                          AtomicOrdering::LAST>; // Next bit:9
+  using VolatileField = BoolBitfieldElementT<0>;
+  using AlignmentField = AlignmentBitfieldElementT<VolatileField::NextBit>;
+  using OrderingField = AtomicOrderingBitfieldElementT<AlignmentField::NextBit>;
+  static_assert(
+      Bitfield::areContiguous<VolatileField, AlignmentField, OrderingField>(),
+      "Bitfields must be contiguous");
 
   void AssertOK();
 
@@ -295,10 +300,12 @@ class LoadInst : public UnaryInstruction {
 
 /// An instruction for storing to memory.
 class StoreInst : public Instruction {
-  using VolatileField = Bitfield::Element<bool, 0, 1>;      // Next bit:1
-  using AlignmentField = AlignmentBitfieldElement<1>;       // Next bit:6
-  using OrderingField = Bitfield::Element<AtomicOrdering, 6, 3,
-                                          AtomicOrdering::LAST>; // Next bit:9
+  using VolatileField = BoolBitfieldElementT<0>;
+  using AlignmentField = AlignmentBitfieldElementT<VolatileField::NextBit>;
+  using OrderingField = AtomicOrderingBitfieldElementT<AlignmentField::NextBit>;
+  static_assert(
+      Bitfield::areContiguous<VolatileField, AlignmentField, OrderingField>(),
+      "Bitfields must be contiguous");
 
   void AssertOK();
 
@@ -434,8 +441,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
 
 /// An instruction for ordering other memory operations.
 class FenceInst : public Instruction {
-  using OrderingField = Bitfield::Element<AtomicOrdering, 1, 3,
-                                          AtomicOrdering::LAST>; // Next bit:4
+  using OrderingField = AtomicOrderingBitfieldElementT<0>;
 
   void Init(AtomicOrdering Ordering, SyncScope::ID SSID);
 
@@ -543,11 +549,18 @@ class AtomicCmpXchgInst : public Instruction {
     return User::operator new(s, 3);
   }
 
-  using VolatileField = Bitfield::Element<bool, 0, 1>;           // Next bit:1
-  using WeakField = Bitfield::Element<bool, 1, 1>;               // Next bit:2
-  using SuccessOrderingField = AtomicOrderingBitfieldElement<2>; // Next bit:5
-  using FailureOrderingField = AtomicOrderingBitfieldElement<5>; // Next bit:8
-  using AlignmentField = AlignmentBitfieldElement<8>;            // Next bit:13
+  using VolatileField = BoolBitfieldElementT<0>;
+  using WeakField = BoolBitfieldElementT<VolatileField::NextBit>;
+  using SuccessOrderingField =
+      AtomicOrderingBitfieldElementT<WeakField::NextBit>;
+  using FailureOrderingField =
+      AtomicOrderingBitfieldElementT<SuccessOrderingField::NextBit>;
+  using AlignmentField =
+      AlignmentBitfieldElementT<FailureOrderingField::NextBit>;
+  static_assert(
+      Bitfield::areContiguous<VolatileField, WeakField, SuccessOrderingField,
+                              FailureOrderingField, AlignmentField>(),
+      "Bitfields must be contiguous");
 
   /// Return the alignment of the memory that is being allocated by the
   /// instruction.
@@ -755,10 +768,14 @@ class AtomicRMWInst : public Instruction {
     return User::operator new(s, 2);
   }
 
-  using VolatileField = Bitfield::Element<bool, 0, 1>;          // Next bit:1
-  using AtomicOrderingField = AtomicOrderingBitfieldElement<1>; // Next bit:4
-  using OperationField = BinOpBitfieldElement<4>;               // Next bit:8
-  using AlignmentField = AlignmentBitfieldElement<8>;           // Next bit:13
+  using VolatileField = BoolBitfieldElementT<0>;
+  using AtomicOrderingField =
+      AtomicOrderingBitfieldElementT<VolatileField::NextBit>;
+  using OperationField = BinOpBitfieldElement<AtomicOrderingField::NextBit>;
+  using AlignmentField = AlignmentBitfieldElementT<OperationField::NextBit>;
+  static_assert(Bitfield::areContiguous<VolatileField, AtomicOrderingField,
+                                        OperationField, AlignmentField>(),
+                "Bitfields must be contiguous");
 
   BinOp getOperation() const { return getSubclassData<OperationField>(); }
 
@@ -1591,6 +1608,9 @@ class CallInst : public CallBase {
   };
 
   using TailCallKindField = Bitfield::Element<TailCallKind, 0, 2, TCK_LAST>;
+  static_assert(
+      Bitfield::areContiguous<TailCallKindField, CallBase::CallingConvField>(),
+      "Bitfields must be contiguous");
 
   TailCallKind getTailCallKind() const {
     return getSubclassData<TailCallKindField>();
@@ -2754,7 +2774,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value)
 /// cleanup.
 ///
 class LandingPadInst : public Instruction {
-  using CleanupField = Bitfield::Element<bool, 0, 1>;
+  using CleanupField = BoolBitfieldElementT<0>;
 
   /// The number of operands actually allocated.  NumOperands is
   /// the number actually in use.
@@ -4125,7 +4145,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
 //                         CatchSwitchInst Class
 //===----------------------------------------------------------------------===//
 class CatchSwitchInst : public Instruction {
-  using UnwindDestField = Bitfield::Element<unsigned, 0, 1>; // Next bit:1
+  using UnwindDestField = BoolBitfieldElementT<0>;
 
   /// The number of operands actually allocated.  NumOperands is
   /// the number actually in use.
@@ -4474,7 +4494,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
 //===----------------------------------------------------------------------===//
 
 class CleanupReturnInst : public Instruction {
-  using UnwindDestField = Bitfield::Element<unsigned, 0, 1>; // Next bit:1
+  using UnwindDestField = BoolBitfieldElementT<0>;
+
 private:
   CleanupReturnInst(const CleanupReturnInst &RI);
   CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,

diff  --git a/llvm/unittests/ADT/BitFieldsTest.cpp b/llvm/unittests/ADT/BitFieldsTest.cpp
index 759c18394995..3062d5d7f293 100644
--- a/llvm/unittests/ADT/BitFieldsTest.cpp
+++ b/llvm/unittests/ADT/BitFieldsTest.cpp
@@ -192,6 +192,18 @@ TEST(BitfieldsTest, isOverlapping) {
   EXPECT_FALSE((Bitfield::isOverlapping<C, D>()));
 }
 
+TEST(BitfieldsTest, areContiguous) {
+  using A = Bitfield::Element<unsigned, 0, 1>; // Next Bit:1
+  using B = Bitfield::Element<unsigned, 1, 4>; // Next Bit:5
+  using C = Bitfield::Element<unsigned, 5, 3>; // Next Bit:8
+  EXPECT_TRUE((Bitfield::areContiguous<A, B>()));
+  EXPECT_TRUE((Bitfield::areContiguous<A, B, C>()));
+
+  EXPECT_FALSE((Bitfield::areContiguous<A, C>()));
+  EXPECT_FALSE((Bitfield::areContiguous<A, A>()));
+  EXPECT_FALSE((Bitfield::areContiguous<B, A>()));
+}
+
 TEST(BitfieldsTest, FullUint64) {
   uint64_t Storage = 0;
   using Value = Bitfield::Element<uint64_t, 0, 64>;


        


More information about the llvm-commits mailing list