mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[Bitfields][NFC] Make sure bitfields are contiguous
Differential Revision: https://reviews.llvm.org/D83202
This commit is contained in:
parent
b9d820cbde
commit
a3a41cd01b
@ -228,6 +228,7 @@ struct Bitfield {
|
|||||||
static constexpr unsigned Bits = Size;
|
static constexpr unsigned Bits = Size;
|
||||||
static constexpr unsigned FirstBit = Offset;
|
static constexpr unsigned FirstBit = Offset;
|
||||||
static constexpr unsigned LastBit = Shift + Bits - 1;
|
static constexpr unsigned LastBit = Shift + Bits - 1;
|
||||||
|
static constexpr unsigned NextBit = Shift + Bits;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename, typename> friend struct bitfields_details::Impl;
|
template <typename, typename> friend struct bitfields_details::Impl;
|
||||||
@ -275,6 +276,12 @@ struct Bitfield {
|
|||||||
template <typename A, typename B> static constexpr bool isOverlapping() {
|
template <typename A, typename B> static constexpr bool isOverlapping() {
|
||||||
return A::LastBit >= B::FirstBit && B::LastBit >= A::FirstBit;
|
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
|
} // namespace llvm
|
||||||
|
@ -758,7 +758,7 @@ public:
|
|||||||
BAD_ICMP_PREDICATE = ICMP_SLE + 1
|
BAD_ICMP_PREDICATE = ICMP_SLE + 1
|
||||||
};
|
};
|
||||||
using PredicateField =
|
using PredicateField =
|
||||||
Bitfield::Element<Predicate, 0, 6, LAST_ICMP_PREDICATE>; // Next bit:6
|
Bitfield::Element<Predicate, 0, 6, LAST_ICMP_PREDICATE>;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CmpInst(Type *ty, Instruction::OtherOps op, Predicate pred,
|
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
|
/// subclass requires. Note that accessing the end of the argument list isn't
|
||||||
/// as cheap as most other operations on the base class.
|
/// as cheap as most other operations on the base class.
|
||||||
class CallBase : public Instruction {
|
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:
|
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.
|
/// The last operand is the called operand.
|
||||||
static constexpr int CalledOperandOpEndIdx = -1;
|
static constexpr int CalledOperandOpEndIdx = -1;
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "llvm/IR/SymbolTableListTraits.h"
|
#include "llvm/IR/SymbolTableListTraits.h"
|
||||||
#include "llvm/IR/User.h"
|
#include "llvm/IR/User.h"
|
||||||
#include "llvm/IR/Value.h"
|
#include "llvm/IR/Value.h"
|
||||||
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -53,7 +54,7 @@ class Instruction : public User,
|
|||||||
protected:
|
protected:
|
||||||
// The 15 first bits of `Value::SubclassData` are available for subclasses of
|
// The 15 first bits of `Value::SubclassData` are available for subclasses of
|
||||||
// `Instruction` to use.
|
// `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
|
// Template alias so that all Instruction storing alignment use the same
|
||||||
// definiton.
|
// definiton.
|
||||||
@ -61,10 +62,18 @@ protected:
|
|||||||
// 2^29. We store them as Log2(Alignment), so we need 5 bits to encode the 30
|
// 2^29. We store them as Log2(Alignment), so we need 5 bits to encode the 30
|
||||||
// possible values.
|
// possible values.
|
||||||
template <unsigned Offset>
|
template <unsigned Offset>
|
||||||
using AlignmentBitfieldElement =
|
using AlignmentBitfieldElementT =
|
||||||
typename Bitfield::Element<unsigned, Offset, 5,
|
typename Bitfield::Element<unsigned, Offset, 5,
|
||||||
Value::MaxAlignmentExponent>;
|
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:
|
private:
|
||||||
// The last bit is used to store whether the instruction has metadata attached
|
// The last bit is used to store whether the instruction has metadata attached
|
||||||
// or not.
|
// or not.
|
||||||
|
@ -60,9 +60,12 @@ class LLVMContext;
|
|||||||
class AllocaInst : public UnaryInstruction {
|
class AllocaInst : public UnaryInstruction {
|
||||||
Type *AllocatedType;
|
Type *AllocatedType;
|
||||||
|
|
||||||
using AlignmentField = AlignmentBitfieldElement<0>; // Next bit:5
|
using AlignmentField = AlignmentBitfieldElementT<0>;
|
||||||
using UsedWithInAllocaField = Bitfield::Element<bool, 5, 1>; // Next bit:6
|
using UsedWithInAllocaField = BoolBitfieldElementT<AlignmentField::NextBit>;
|
||||||
using SwiftErrorField = Bitfield::Element<bool, 6, 1>; // Next bit:7
|
using SwiftErrorField = BoolBitfieldElementT<UsedWithInAllocaField::NextBit>;
|
||||||
|
static_assert(Bitfield::areContiguous<AlignmentField, UsedWithInAllocaField,
|
||||||
|
SwiftErrorField>(),
|
||||||
|
"Bitfields must be contiguous");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Note: Instruction needs to be a friend here to call cloneImpl.
|
// Note: Instruction needs to be a friend here to call cloneImpl.
|
||||||
@ -168,10 +171,12 @@ private:
|
|||||||
/// An instruction for reading from memory. This uses the SubclassData field in
|
/// An instruction for reading from memory. This uses the SubclassData field in
|
||||||
/// Value to store whether or not the load is volatile.
|
/// Value to store whether or not the load is volatile.
|
||||||
class LoadInst : public UnaryInstruction {
|
class LoadInst : public UnaryInstruction {
|
||||||
using VolatileField = Bitfield::Element<bool, 0, 1>; // Next bit:1
|
using VolatileField = BoolBitfieldElementT<0>;
|
||||||
using AlignmentField = AlignmentBitfieldElement<1>; // Next bit:6
|
using AlignmentField = AlignmentBitfieldElementT<VolatileField::NextBit>;
|
||||||
using OrderingField = Bitfield::Element<AtomicOrdering, 6, 3,
|
using OrderingField = AtomicOrderingBitfieldElementT<AlignmentField::NextBit>;
|
||||||
AtomicOrdering::LAST>; // Next bit:9
|
static_assert(
|
||||||
|
Bitfield::areContiguous<VolatileField, AlignmentField, OrderingField>(),
|
||||||
|
"Bitfields must be contiguous");
|
||||||
|
|
||||||
void AssertOK();
|
void AssertOK();
|
||||||
|
|
||||||
@ -295,10 +300,12 @@ private:
|
|||||||
|
|
||||||
/// An instruction for storing to memory.
|
/// An instruction for storing to memory.
|
||||||
class StoreInst : public Instruction {
|
class StoreInst : public Instruction {
|
||||||
using VolatileField = Bitfield::Element<bool, 0, 1>; // Next bit:1
|
using VolatileField = BoolBitfieldElementT<0>;
|
||||||
using AlignmentField = AlignmentBitfieldElement<1>; // Next bit:6
|
using AlignmentField = AlignmentBitfieldElementT<VolatileField::NextBit>;
|
||||||
using OrderingField = Bitfield::Element<AtomicOrdering, 6, 3,
|
using OrderingField = AtomicOrderingBitfieldElementT<AlignmentField::NextBit>;
|
||||||
AtomicOrdering::LAST>; // Next bit:9
|
static_assert(
|
||||||
|
Bitfield::areContiguous<VolatileField, AlignmentField, OrderingField>(),
|
||||||
|
"Bitfields must be contiguous");
|
||||||
|
|
||||||
void AssertOK();
|
void AssertOK();
|
||||||
|
|
||||||
@ -434,8 +441,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
|
|||||||
|
|
||||||
/// An instruction for ordering other memory operations.
|
/// An instruction for ordering other memory operations.
|
||||||
class FenceInst : public Instruction {
|
class FenceInst : public Instruction {
|
||||||
using OrderingField = Bitfield::Element<AtomicOrdering, 1, 3,
|
using OrderingField = AtomicOrderingBitfieldElementT<0>;
|
||||||
AtomicOrdering::LAST>; // Next bit:4
|
|
||||||
|
|
||||||
void Init(AtomicOrdering Ordering, SyncScope::ID SSID);
|
void Init(AtomicOrdering Ordering, SyncScope::ID SSID);
|
||||||
|
|
||||||
@ -543,11 +549,18 @@ public:
|
|||||||
return User::operator new(s, 3);
|
return User::operator new(s, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
using VolatileField = Bitfield::Element<bool, 0, 1>; // Next bit:1
|
using VolatileField = BoolBitfieldElementT<0>;
|
||||||
using WeakField = Bitfield::Element<bool, 1, 1>; // Next bit:2
|
using WeakField = BoolBitfieldElementT<VolatileField::NextBit>;
|
||||||
using SuccessOrderingField = AtomicOrderingBitfieldElement<2>; // Next bit:5
|
using SuccessOrderingField =
|
||||||
using FailureOrderingField = AtomicOrderingBitfieldElement<5>; // Next bit:8
|
AtomicOrderingBitfieldElementT<WeakField::NextBit>;
|
||||||
using AlignmentField = AlignmentBitfieldElement<8>; // Next bit:13
|
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
|
/// Return the alignment of the memory that is being allocated by the
|
||||||
/// instruction.
|
/// instruction.
|
||||||
@ -755,10 +768,14 @@ public:
|
|||||||
return User::operator new(s, 2);
|
return User::operator new(s, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
using VolatileField = Bitfield::Element<bool, 0, 1>; // Next bit:1
|
using VolatileField = BoolBitfieldElementT<0>;
|
||||||
using AtomicOrderingField = AtomicOrderingBitfieldElement<1>; // Next bit:4
|
using AtomicOrderingField =
|
||||||
using OperationField = BinOpBitfieldElement<4>; // Next bit:8
|
AtomicOrderingBitfieldElementT<VolatileField::NextBit>;
|
||||||
using AlignmentField = AlignmentBitfieldElement<8>; // Next bit:13
|
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>(); }
|
BinOp getOperation() const { return getSubclassData<OperationField>(); }
|
||||||
|
|
||||||
@ -1591,6 +1608,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
using TailCallKindField = Bitfield::Element<TailCallKind, 0, 2, TCK_LAST>;
|
using TailCallKindField = Bitfield::Element<TailCallKind, 0, 2, TCK_LAST>;
|
||||||
|
static_assert(
|
||||||
|
Bitfield::areContiguous<TailCallKindField, CallBase::CallingConvField>(),
|
||||||
|
"Bitfields must be contiguous");
|
||||||
|
|
||||||
TailCallKind getTailCallKind() const {
|
TailCallKind getTailCallKind() const {
|
||||||
return getSubclassData<TailCallKindField>();
|
return getSubclassData<TailCallKindField>();
|
||||||
@ -2754,7 +2774,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value)
|
|||||||
/// cleanup.
|
/// cleanup.
|
||||||
///
|
///
|
||||||
class LandingPadInst : public Instruction {
|
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 of operands actually allocated. NumOperands is
|
||||||
/// the number actually in use.
|
/// the number actually in use.
|
||||||
@ -4125,7 +4145,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value)
|
|||||||
// CatchSwitchInst Class
|
// CatchSwitchInst Class
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
class CatchSwitchInst : public Instruction {
|
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 of operands actually allocated. NumOperands is
|
||||||
/// the number actually in use.
|
/// the number actually in use.
|
||||||
@ -4474,7 +4494,8 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value)
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
class CleanupReturnInst : public Instruction {
|
class CleanupReturnInst : public Instruction {
|
||||||
using UnwindDestField = Bitfield::Element<unsigned, 0, 1>; // Next bit:1
|
using UnwindDestField = BoolBitfieldElementT<0>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CleanupReturnInst(const CleanupReturnInst &RI);
|
CleanupReturnInst(const CleanupReturnInst &RI);
|
||||||
CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
|
CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values,
|
||||||
|
@ -192,6 +192,18 @@ TEST(BitfieldsTest, isOverlapping) {
|
|||||||
EXPECT_FALSE((Bitfield::isOverlapping<C, D>()));
|
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) {
|
TEST(BitfieldsTest, FullUint64) {
|
||||||
uint64_t Storage = 0;
|
uint64_t Storage = 0;
|
||||||
using Value = Bitfield::Element<uint64_t, 0, 64>;
|
using Value = Bitfield::Element<uint64_t, 0, 64>;
|
||||||
|
Loading…
Reference in New Issue
Block a user