LLVM 20.0.0git
CBufferDataLayout.cpp
Go to the documentation of this file.
1//===- Target/DirectX/CBufferDataLayout.cpp - Cbuffer layout helper -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Utils to help cbuffer layout.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CBufferDataLayout.h"
14
16#include "llvm/IR/IRBuilder.h"
17
18namespace llvm {
19namespace dxil {
20
21// Implement cbuffer layout in
22// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
24 struct LegacyStructLayout {
25 StructType *ST;
27 TypeSize Size = {0, false};
28 std::pair<uint32_t, uint32_t> getElementLegacyOffset(unsigned Idx) const {
29 assert(Idx < Offsets.size() && "Invalid element idx!");
30 uint32_t Offset = Offsets[Idx];
31 uint32_t Ch = Offset & (RowAlign - 1);
32 return std::make_pair((Offset - Ch) / RowAlign, Ch);
33 }
34 };
35
36public:
39
40private:
41 TypeSize applyRowAlign(TypeSize Offset, Type *EltTy);
42 TypeSize getTypeAllocSize(Type *Ty);
43 LegacyStructLayout &getStructLayout(StructType *ST);
44 const DataLayout &DL;
46 // 4 Dwords align.
47 static const uint32_t RowAlign = 16;
48 static TypeSize alignTo4Dwords(TypeSize Offset) {
49 return alignTo(Offset, RowAlign);
50 }
51};
52
54 return getTypeAllocSize(Ty);
55}
56
57TypeSize LegacyCBufferLayout::applyRowAlign(TypeSize Offset, Type *EltTy) {
58 TypeSize AlignedOffset = alignTo4Dwords(Offset);
59
60 if (AlignedOffset == Offset)
61 return Offset;
62
63 if (isa<StructType>(EltTy) || isa<ArrayType>(EltTy))
64 return AlignedOffset;
65 TypeSize Size = DL.getTypeStoreSize(EltTy);
66 if ((Offset + Size) > AlignedOffset)
67 return AlignedOffset;
68 else
69 return Offset;
70}
71
72TypeSize LegacyCBufferLayout::getTypeAllocSize(Type *Ty) {
73 if (auto *ST = dyn_cast<StructType>(Ty)) {
74 LegacyStructLayout &Layout = getStructLayout(ST);
75 return Layout.Size;
76 } else if (auto *AT = dyn_cast<ArrayType>(Ty)) {
77 unsigned NumElts = AT->getNumElements();
78 if (NumElts == 0)
79 return TypeSize::getFixed(0);
80
81 TypeSize EltSize = getTypeAllocSize(AT->getElementType());
82 TypeSize AlignedEltSize = alignTo4Dwords(EltSize);
83 // Each new element start 4 dwords aligned.
84 return TypeSize::getFixed(AlignedEltSize * (NumElts - 1) + EltSize);
85 } else {
86 // NOTE: Use type store size, not align to ABI on basic types for legacy
87 // layout.
88 return DL.getTypeStoreSize(Ty);
89 }
90}
91
92LegacyCBufferLayout::LegacyStructLayout &
93LegacyCBufferLayout::getStructLayout(StructType *ST) {
94 auto it = StructLayouts.find(ST);
95 if (it != StructLayouts.end())
96 return it->second;
97
98 TypeSize Offset = TypeSize::getFixed(0);
99 LegacyStructLayout Layout;
100 Layout.ST = ST;
101 for (Type *EltTy : ST->elements()) {
102 TypeSize EltSize = getTypeAllocSize(EltTy);
103 if (TypeSize ScalarSize = EltTy->getScalarType()->getPrimitiveSizeInBits())
104 Offset = alignTo(Offset, ScalarSize >> 3);
105 Offset = applyRowAlign(Offset, EltTy);
106 Layout.Offsets.emplace_back(Offset);
107 Offset = Offset.getWithIncrement(EltSize);
108 }
109 Layout.Size = Offset;
110 StructLayouts[ST] = Layout;
111 return StructLayouts[ST];
112}
113
115 : DL(DL), IsLegacyLayout(IsLegacy),
116 LegacyDL(IsLegacy ? std::make_unique<LegacyCBufferLayout>(DL) : nullptr) {
117}
118
120
122 if (IsLegacyLayout)
123 return LegacyDL->getTypeAllocSizeInBytes(Ty);
124 else
125 return DL.getTypeAllocSize(Ty);
126}
127
128} // namespace dxil
129} // namespace llvm
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:457
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Definition: DataLayout.h:421
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
Class to represent struct types.
Definition: DerivedTypes.h:218
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition: TypeSize.h:345
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition: Type.h:355
CBufferDataLayout(const DataLayout &DL, const bool IsLegacy)
llvm::TypeSize getTypeAllocSizeInBytes(Type *Ty)
LegacyCBufferLayout(const DataLayout &DL)
TypeSize getTypeAllocSizeInBytes(Type *Ty)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858