LLVM 23.0.0git
X86Subtarget.h
Go to the documentation of this file.
1//===-- X86Subtarget.h - Define Subtarget for the X86 ----------*- C++ -*--===//
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// This file declares the X86 specific subclass of TargetSubtargetInfo.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_X86_X86SUBTARGET_H
14#define LLVM_LIB_TARGET_X86_X86SUBTARGET_H
15
16#include "X86FrameLowering.h"
17#include "X86ISelLowering.h"
18#include "X86InstrInfo.h"
19#include "X86SelectionDAGInfo.h"
21#include "llvm/IR/CallingConv.h"
23#include <bitset>
24#include <climits>
25#include <memory>
26
27#define GET_SUBTARGETINFO_HEADER
28#include "X86GenSubtargetInfo.inc"
29
30namespace llvm {
31
32class CallLowering;
33class GlobalValue;
34class InstructionSelector;
35class LegalizerInfo;
36class RegisterBankInfo;
37class StringRef;
38class TargetMachine;
39
40/// The X86 backend supports a number of different styles of PIC.
41///
42namespace PICStyles {
43
44enum class Style {
45 StubPIC, // Used on i386-darwin in pic mode.
46 GOT, // Used on 32 bit elf on when in pic mode.
47 RIPRel, // Used on X86-64 when in pic mode.
48 None // Set when not in pic mode.
49};
50
51} // end namespace PICStyles
52
53class X86Subtarget final : public X86GenSubtargetInfo {
54 enum X86SSEEnum {
55 NoSSE, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, AVX, AVX2, AVX512
56 };
57
58 /// Which PIC style to use
59 PICStyles::Style PICStyle;
60
61 const TargetMachine &TM;
62
63 /// SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, or none supported.
64 X86SSEEnum X86SSELevel = NoSSE;
65
66#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
67 bool ATTRIBUTE = DEFAULT;
68#include "X86GenSubtargetInfo.inc"
69 /// ReservedRReg R#i is not available as a general purpose register.
70 std::bitset<X86::NUM_TARGET_REGS> ReservedRReg;
71
72 /// The minimum alignment known to hold of the stack frame on
73 /// entry to the function and which must be maintained by every function.
74 Align stackAlignment = Align(4);
75
76 Align TileConfigAlignment = Align(4);
77
78 /// Max. memset / memcpy size that is turned into rep/movs, rep/stos ops.
79 ///
80 // FIXME: this is a known good value for Yonah. How about others?
81 unsigned MaxInlineSizeThreshold = 128;
82
83 /// What processor and OS we're targeting.
84 Triple TargetTriple;
85
86 /// GlobalISel related APIs.
87 std::unique_ptr<CallLowering> CallLoweringInfo;
88 std::unique_ptr<LegalizerInfo> Legalizer;
89 std::unique_ptr<RegisterBankInfo> RegBankInfo;
90 std::unique_ptr<InstructionSelector> InstSelector;
91
92 /// Override the stack alignment.
93 MaybeAlign StackAlignOverride;
94
95 /// Preferred vector width from function attribute.
96 unsigned PreferVectorWidthOverride;
97
98 /// Resolved preferred vector width from function attribute and subtarget
99 /// features.
100 unsigned PreferVectorWidth = UINT32_MAX;
101
102 /// Required vector width from function attribute.
103 unsigned RequiredVectorWidth;
104
105 X86SelectionDAGInfo TSInfo;
106 // Ordering here is important. X86InstrInfo initializes X86RegisterInfo which
107 // X86TargetLowering needs.
108 X86InstrInfo InstrInfo;
109 X86TargetLowering TLInfo;
110 X86FrameLowering FrameLowering;
111
112public:
113 /// This constructor initializes the data members to match that
114 /// of the specified triple.
115 ///
116 X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
117 const X86TargetMachine &TM, MaybeAlign StackAlignOverride,
118 unsigned PreferVectorWidthOverride,
119 unsigned RequiredVectorWidth);
120 ~X86Subtarget() override;
121
122 const X86TargetLowering *getTargetLowering() const override {
123 return &TLInfo;
124 }
125
126 const X86InstrInfo *getInstrInfo() const override { return &InstrInfo; }
127
128 const X86FrameLowering *getFrameLowering() const override {
129 return &FrameLowering;
130 }
131
132 const X86SelectionDAGInfo *getSelectionDAGInfo() const override {
133 return &TSInfo;
134 }
135
136 const X86RegisterInfo *getRegisterInfo() const override {
137 return &getInstrInfo()->getRegisterInfo();
138 }
139
140 unsigned getTileConfigSize() const { return 64; }
141 Align getTileConfigAlignment() const { return TileConfigAlignment; }
142
143 /// Returns the minimum alignment known to hold of the
144 /// stack frame on entry to the function and which must be maintained by every
145 /// function for this subtarget.
146 Align getStackAlignment() const { return stackAlignment; }
147
148 /// Returns the maximum memset / memcpy size
149 /// that still makes it profitable to inline the call.
150 unsigned getMaxInlineSizeThreshold() const { return MaxInlineSizeThreshold; }
151
152 /// ParseSubtargetFeatures - Parses features string setting specified
153 /// subtarget options. Definition of function is auto generated by tblgen.
155
156 /// Methods used by Global ISel
157 const CallLowering *getCallLowering() const override;
159 const LegalizerInfo *getLegalizerInfo() const override;
160 const RegisterBankInfo *getRegBankInfo() const override;
161
162 bool isRegisterReservedByUser(Register i) const override {
163 return ReservedRReg[i.id()];
164 }
165 bool hasUserReservedRegisters() const { return ReservedRReg.any(); }
166
167private:
168 /// Initialize the full set of dependencies so we can use an initializer
169 /// list for X86Subtarget.
170 X86Subtarget &initializeSubtargetDependencies(StringRef CPU,
171 StringRef TuneCPU,
172 StringRef FS);
173 void initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
174
175public:
176
177#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
178 bool GETTER() const { return ATTRIBUTE; }
179#include "X86GenSubtargetInfo.inc"
180
181 /// Is this x86_64 with the ILP32 programming model (x32 ABI)?
182 bool isTarget64BitILP32() const { return Is64Bit && IsX32; }
183
184 /// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
185 bool isTarget64BitLP64() const { return Is64Bit && !IsX32; }
186
187 PICStyles::Style getPICStyle() const { return PICStyle; }
188 void setPICStyle(PICStyles::Style Style) { PICStyle = Style; }
189
190 bool canUseCMPXCHG8B() const { return hasCX8(); }
191 bool canUseCMPXCHG16B() const {
192 // CX16 is just the CPUID bit, instruction requires 64-bit mode too.
193 return hasCX16() && is64Bit();
194 }
195 // SSE codegen depends on cmovs, and all SSE1+ processors support them.
196 // All 64-bit processors support cmov.
197 bool canUseCMOV() const { return hasCMOV() || hasSSE1() || is64Bit(); }
198 bool hasSSE1() const { return X86SSELevel >= SSE1; }
199 bool hasSSE2() const { return X86SSELevel >= SSE2; }
200 bool hasSSE3() const { return X86SSELevel >= SSE3; }
201 bool hasSSSE3() const { return X86SSELevel >= SSSE3; }
202 bool hasSSE41() const { return X86SSELevel >= SSE41; }
203 bool hasSSE42() const { return X86SSELevel >= SSE42; }
204 bool hasAVX() const { return X86SSELevel >= AVX; }
205 bool hasAVX2() const { return X86SSELevel >= AVX2; }
206 bool hasAVX512() const { return X86SSELevel >= AVX512; }
207 bool hasInt256() const { return hasAVX2(); }
208 bool hasAnyFMA() const { return hasFMA() || hasFMA4(); }
209 bool hasPrefetchW() const {
210 // The PREFETCHW instruction was added with 3DNow but later CPUs gave it
211 // its own CPUID bit as part of deprecating 3DNow.
212 return hasPRFCHW();
213 }
214 bool hasSSEPrefetch() const {
215 // We also implicitly enable these when we have a write prefix supporting
216 // cache level OR if we have prfchw.
217 return hasSSE1() || hasPRFCHW() || hasPREFETCHI();
218 }
219 bool canUseLAHFSAHF() const { return hasLAHFSAHF64() || !is64Bit(); }
220 // These are generic getters that OR together all of the thunk types
221 // supported by the subtarget. Therefore useIndirectThunk*() will return true
222 // if any respective thunk feature is enabled.
224 return useRetpolineIndirectCalls() || useLVIControlFlowIntegrity();
225 }
227 return useRetpolineIndirectBranches() || useLVIControlFlowIntegrity();
228 }
229
230 unsigned getPreferVectorWidth() const { return PreferVectorWidth; }
231 unsigned getRequiredVectorWidth() const { return RequiredVectorWidth; }
232
233 // Helper functions to determine when we should allow widening to 512-bit
234 // during codegen.
235 // TODO: Currently we're always allowing widening on CPUs without VLX,
236 // because for many cases we don't have a better option.
237 bool canExtendTo512DQ() const {
238 return hasAVX512() && (!hasVLX() || getPreferVectorWidth() >= 512);
239 }
240 bool canExtendTo512BW() const {
241 return hasBWI() && canExtendTo512DQ();
242 }
243
244 bool hasNoDomainDelay() const { return NoDomainDelay; }
245 bool hasNoDomainDelayMov() const {
246 return hasNoDomainDelay() || NoDomainDelayMov;
247 }
249 return hasNoDomainDelay() || NoDomainDelayBlend;
250 }
252 return hasNoDomainDelay() || NoDomainDelayShuffle;
253 }
254
255 // If there are no 512-bit vectors and we prefer not to use 512-bit registers,
256 // disable them in the legalizer.
257 bool useAVX512Regs() const {
258 return hasAVX512() && (canExtendTo512DQ() || RequiredVectorWidth > 256);
259 }
260
262 return getPreferVectorWidth() >= 256 || AllowLight256Bit;
263 }
264
265 bool useBWIRegs() const {
266 return hasBWI() && useAVX512Regs();
267 }
268
269 // Returns true if the destination register of a BSF/BSR instruction is
270 // not touched if the source register is zero.
271 // NOTE: i32->i64 implicit zext isn't guaranteed by BSR/BSF pass through.
272 bool hasBitScanPassThrough() const { return is64Bit(); }
273
274 bool isXRaySupported() const override { return is64Bit(); }
275
276 /// Use clflush if we have SSE2 or we're on x86-64 (even if we asked for
277 /// no-sse2). There isn't any reason to disable it if the target processor
278 /// supports it.
279 bool hasCLFLUSH() const { return hasSSE2() || is64Bit(); }
280
281 /// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
282 /// no-sse2). There isn't any reason to disable it if the target processor
283 /// supports it.
284 bool hasMFence() const { return hasSSE2() || is64Bit(); }
285
286 /// Avoid use of `mfence` for`fence seq_cst`, and instead use `lock or`.
287 bool avoidMFence() const { return is64Bit(); }
288
289 const Triple &getTargetTriple() const { return TargetTriple; }
290
291 bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
292 bool isTargetFreeBSD() const { return TargetTriple.isOSFreeBSD(); }
293 bool isTargetDragonFly() const { return TargetTriple.isOSDragonFly(); }
294 bool isTargetSolaris() const { return TargetTriple.isOSSolaris(); }
295 bool isTargetPS() const { return TargetTriple.isPS(); }
296
297 bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
298 bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
299 bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
300
301 bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
302 bool isTargetKFreeBSD() const { return TargetTriple.isOSKFreeBSD(); }
303 bool isTargetHurd() const { return TargetTriple.isOSHurd(); }
304 bool isTargetGlibc() const { return TargetTriple.isOSGlibc(); }
305 bool isTargetMusl() const { return TargetTriple.isMusl(); }
306 bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
307 bool isTargetMCU() const { return TargetTriple.isOSIAMCU(); }
308 bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
309
310 bool isTargetWindowsMSVC() const {
311 return TargetTriple.isWindowsMSVCEnvironment();
312 }
313
315 return TargetTriple.isWindowsCoreCLREnvironment();
316 }
317
319 return TargetTriple.isWindowsCygwinEnvironment();
320 }
321
322 bool isTargetWindowsGNU() const {
323 return TargetTriple.isWindowsGNUEnvironment();
324 }
325
327 return TargetTriple.isWindowsItaniumEnvironment();
328 }
329
330 bool isTargetCygMing() const { return TargetTriple.isOSCygMing(); }
331
332 bool isUEFI() const { return TargetTriple.isUEFI(); }
333
334 bool isOSWindows() const { return TargetTriple.isOSWindows(); }
335
336 bool isTargetUEFI64() const { return Is64Bit && isUEFI(); }
337
338 bool isTargetWin64() const { return Is64Bit && isOSWindows(); }
339
340 bool isTargetWin32() const { return !Is64Bit && isOSWindows(); }
341
342 bool isPICStyleGOT() const { return PICStyle == PICStyles::Style::GOT; }
343 bool isPICStyleRIPRel() const { return PICStyle == PICStyles::Style::RIPRel; }
344
345 bool isPICStyleStubPIC() const {
346 return PICStyle == PICStyles::Style::StubPIC;
347 }
348
349 bool isPositionIndependent() const;
350
352 switch (CC) {
353 // On Win64, all these conventions just use the default convention.
354 case CallingConv::C:
357 return isTargetWin64() || isTargetUEFI64();
365 return isTargetWin64();
366 // This convention allows using the Win64 convention on other targets.
368 return true;
369 // This convention allows using the SysV convention on Windows targets.
371 return false;
372 // Otherwise, who knows what this is.
373 default:
374 return false;
375 }
376 }
377
378 /// Classify a global variable reference for the current subtarget according
379 /// to how we should reference it in a non-pcrel context.
380 unsigned char classifyLocalReference(const GlobalValue *GV) const;
381
382 unsigned char classifyGlobalReference(const GlobalValue *GV,
383 const Module &M) const;
384 unsigned char classifyGlobalReference(const GlobalValue *GV) const;
385
386 /// Classify a global function reference for the current subtarget.
387 unsigned char classifyGlobalFunctionReference(const GlobalValue *GV,
388 const Module &M) const;
389 unsigned char
390 classifyGlobalFunctionReference(const GlobalValue *GV) const override;
391
392 /// Classify a blockaddress reference for the current subtarget according to
393 /// how we should reference it in a non-pcrel context.
394 unsigned char classifyBlockAddressReference() const;
395
396 /// Return true if the subtarget allows calls to immediate address.
397 bool isLegalToCallImmediateAddr() const;
398
399 /// Return whether FrameLowering should always set the "extended frame
400 /// present" bit in FP, or set it based on a symbol in the runtime.
402 // Older OS versions (particularly system unwinders) are confused by the
403 // Swift extended frame, so when building code that might be run on them we
404 // must dynamically query the concurrency library to determine whether
405 // extended frames should be flagged as present.
406 const Triple &TT = getTargetTriple();
407
408 unsigned Major = TT.getOSVersion().getMajor();
409 switch(TT.getOS()) {
410 default:
411 return false;
412 case Triple::IOS:
413 case Triple::TvOS:
414 return Major < 15;
415 case Triple::WatchOS:
416 return Major < 8;
417 case Triple::MacOSX:
418 case Triple::Darwin:
419 return Major < 12;
420 }
421 }
422
423 /// If we are using indirect thunks, we need to expand indirectbr to avoid it
424 /// lowering to an actual indirect jump.
425 bool enableIndirectBrExpand() const override {
427 }
428
429 /// Enable the MachineScheduler pass for all X86 subtargets.
430 bool enableMachineScheduler() const override { return true; }
431
432 bool enableEarlyIfConversion() const override;
433
434 void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
435 &Mutations) const override;
436
437 AntiDepBreakMode getAntiDepBreakMode() const override {
438 return TargetSubtargetInfo::ANTIDEP_CRITICAL;
439 }
440};
441
442} // end namespace llvm
443
444#endif // LLVM_LIB_TARGET_X86_X86SUBTARGET_H
DXIL Legalizer
static bool is64Bit(const char *name)
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Holds all the information related to register banks.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr unsigned id() const
Definition Register.h:100
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Primary interface to the complete machine description for the target machine.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
const X86RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
bool canExtendTo512BW() const
bool hasAnyFMA() const
bool enableEarlyIfConversion() const override
~X86Subtarget() override
bool isOSWindows() const
bool isTargetMachO() const
unsigned getTileConfigSize() const
bool canUseLAHFSAHF() const
bool isUEFI() const
bool isTargetKFreeBSD() const
bool isXRaySupported() const override
unsigned getRequiredVectorWidth() const
bool useIndirectThunkBranches() const
bool hasSSE1() const
bool avoidMFence() const
Avoid use of mfence forfence seq_cst, and instead use lock or.
bool useLight256BitInstructions() const
bool isTargetSolaris() const
bool hasBitScanPassThrough() const
bool isPICStyleGOT() const
bool isTargetWindowsCygwin() const
bool hasSSE42() const
InstructionSelector * getInstructionSelector() const override
const X86TargetLowering * getTargetLowering() const override
bool hasMFence() const
Use mfence if we have SSE2 or we're on x86-64 (even if we asked for no-sse2).
bool hasNoDomainDelayBlend() const
Align getTileConfigAlignment() const
bool isTargetMCU() const
bool isTargetDragonFly() const
bool canUseCMOV() const
bool isPICStyleStubPIC() const
bool hasUserReservedRegisters() const
bool isLegalToCallImmediateAddr() const
Return true if the subtarget allows calls to immediate address.
bool enableMachineScheduler() const override
Enable the MachineScheduler pass for all X86 subtargets.
bool isTargetWindowsMSVC() const
bool canUseCMPXCHG8B() const
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
bool hasNoDomainDelayShuffle() const
bool isTargetDarwin() const
bool isTargetWin64() const
bool hasPrefetchW() const
bool isTarget64BitLP64() const
Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
bool swiftAsyncContextIsDynamicallySet() const
Return whether FrameLowering should always set the "extended framepresent" bit in FP,...
const Triple & getTargetTriple() const
bool isRegisterReservedByUser(Register i) const override
AntiDepBreakMode getAntiDepBreakMode() const override
bool isTargetWindowsCoreCLR() const
const X86InstrInfo * getInstrInfo() const override
const RegisterBankInfo * getRegBankInfo() const override
bool useAVX512Regs() const
bool isTargetCOFF() const
bool hasSSE3() const
bool isCallingConvWin64(CallingConv::ID CC) const
bool hasAVX512() const
bool canExtendTo512DQ() const
bool hasSSE41() const
Align getStackAlignment() const
Returns the minimum alignment known to hold of the stack frame on entry to the function and which mus...
bool isTargetELF() const
bool hasSSEPrefetch() const
bool canUseCMPXCHG16B() const
unsigned char classifyGlobalReference(const GlobalValue *GV, const Module &M) const
const LegalizerInfo * getLegalizerInfo() const override
bool isPositionIndependent() const
bool hasSSE2() const
bool isTargetFreeBSD() const
bool isTargetGlibc() const
bool isTargetFuchsia() const
bool hasSSSE3() const
bool hasInt256() const
bool isPICStyleRIPRel() const
bool isTargetCygMing() const
bool hasNoDomainDelay() const
unsigned char classifyLocalReference(const GlobalValue *GV) const
Classify a global variable reference for the current subtarget according to how we should reference i...
unsigned char classifyBlockAddressReference() const
Classify a blockaddress reference for the current subtarget according to how we should reference it i...
PICStyles::Style getPICStyle() const
bool enableIndirectBrExpand() const override
If we are using indirect thunks, we need to expand indirectbr to avoid it lowering to an actual indir...
bool hasNoDomainDelayMov() const
bool isTargetPS() const
bool isTargetUEFI64() const
const X86RegisterInfo * getRegisterInfo() const override
void setPICStyle(PICStyles::Style Style)
X86Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, const X86TargetMachine &TM, MaybeAlign StackAlignOverride, unsigned PreferVectorWidthOverride, unsigned RequiredVectorWidth)
This constructor initializes the data members to match that of the specified triple.
bool hasAVX() const
bool isTargetWindowsGNU() const
unsigned getMaxInlineSizeThreshold() const
Returns the maximum memset / memcpy size that still makes it profitable to inline the call.
unsigned getPreferVectorWidth() const
bool isTargetWindowsItanium() const
bool isTargetMusl() const
bool isTargetAndroid() const
const CallLowering * getCallLowering() const override
Methods used by Global ISel.
bool hasCLFLUSH() const
Use clflush if we have SSE2 or we're on x86-64 (even if we asked for no-sse2).
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
const X86FrameLowering * getFrameLowering() const override
void getPostRAMutations(std::vector< std::unique_ptr< ScheduleDAGMutation > > &Mutations) const override
bool isTargetHurd() const
bool useBWIRegs() const
bool isTargetWin32() const
bool useIndirectThunkCalls() const
unsigned char classifyGlobalFunctionReference(const GlobalValue *GV, const Module &M) const
Classify a global function reference for the current subtarget.
bool hasAVX2() const
const X86SelectionDAGInfo * getSelectionDAGInfo() const override
bool isTargetLinux() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ X86_64_SysV
The C convention as specified in the x86-64 supplement to the System V ABI, used on most non-Windows ...
@ Swift
Calling convention for Swift.
Definition CallingConv.h:69
@ X86_ThisCall
Similar to X86_StdCall.
@ X86_StdCall
stdcall is mostly used by the Win32 API.
Definition CallingConv.h:99
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ X86_VectorCall
MSVC calling convention that passes vectors and vector aggregates in SSE registers.
@ Intel_OCL_BI
Used for Intel OpenCL built-ins.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition CallingConv.h:76
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
Definition CallingConv.h:87
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ X86_FastCall
'fast' analog of X86_StdCall.
The X86 backend supports a number of different styles of PIC.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39