[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