Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 6b20351

Browse files
committed
Allow targets to define minimum alignment for global variables This patch adds a new common code feature that allows platform code to request minimum alignment of global symbols. The background for this is that on SystemZ, the most efficient way to load addresses of global symbol is the LOAD ADDRESS RELATIVE LONG (LARL) instruction. This instruction provides PC-relative addressing, but only to *even* addresses. For this reason, existing compilers will guarantee that global symbols are always aligned to at least 2. [ Since symbols would otherwise already use a default alignment based on their type, this will usually only affect global objects of character type or character arrays. ] GCC also allows creating symbols without that extra alignment by using explicit "aligned" attributes (which then need to be used on both definition and each use of the symbol). To enable support for this with Clang, this patch adds a TargetInfo::MinGlobalAlign variable that provides a global minimum for the alignment of every global object (unless overridden via explicit alignment attribute), and adds code to respect this setting. Within this patch, no platform actually sets the value to anything but the default 1, resulting in no change in behaviour on any existing target. This version of the patch incorporates feedback from reviews by Eric Christopher and John McCall. Thanks to all reviewers! Patch by Richard Sandiford. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181210 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent fd4aa4b commit 6b20351

File tree

6 files changed

+41
-3
lines changed

6 files changed

+41
-3
lines changed

include/clang/AST/ASTContext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
15931593
/// beneficial for performance to overalign a data type.
15941594
unsigned getPreferredTypeAlign(const Type *T) const;
15951595

1596+
/// \brief Return the alignment in bits that should be given to a
1597+
/// global variable with type \p T.
1598+
unsigned getAlignOfGlobalVar(QualType T) const;
1599+
1600+
/// \brief Return the alignment in characters that should be given to a
1601+
/// global variable with type \p T.
1602+
CharUnits getAlignOfGlobalVarInChars(QualType T) const;
1603+
15961604
/// \brief Return a conservative estimate of the alignment of the specified
15971605
/// decl \p D.
15981606
///

include/clang/Basic/TargetInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
6666
unsigned char LongWidth, LongAlign;
6767
unsigned char LongLongWidth, LongLongAlign;
6868
unsigned char SuitableAlign;
69+
unsigned char MinGlobalAlign;
6970
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
7071
unsigned short MaxVectorAlign;
7172
const char *DescriptionString;
@@ -266,6 +267,10 @@ class TargetInfo : public RefCountedBase<TargetInfo> {
266267
/// object with a fundamental alignment requirement.
267268
unsigned getSuitableAlign() const { return SuitableAlign; }
268269

270+
/// getMinGlobalAlign - Return the minimum alignment of a global variable,
271+
/// unless its alignment is explicitly reduced via attributes.
272+
unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
273+
269274
/// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
270275
/// bits.
271276
unsigned getWCharWidth() const { return getTypeWidth(WCharType); }

lib/AST/ASTContext.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
12831283
T = getBaseElementType(arrayType);
12841284
}
12851285
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
1286+
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1287+
if (VD->hasGlobalStorage())
1288+
Align = std::max(Align, getTargetInfo().getMinGlobalAlign());
1289+
}
12861290
}
12871291

12881292
// Fields can be subject to extra alignment constraints, like if
@@ -1725,6 +1729,18 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
17251729
return ABIAlign;
17261730
}
17271731

1732+
/// getAlignOfGlobalVar - Return the alignment in bits that should be given
1733+
/// to a global variable of the specified type.
1734+
unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
1735+
return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign());
1736+
}
1737+
1738+
/// getAlignOfGlobalVarInChars - Return the alignment in characters that
1739+
/// should be given to a global variable of the specified type.
1740+
CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const {
1741+
return toCharUnitsFromBits(getAlignOfGlobalVar(T));
1742+
}
1743+
17281744
/// DeepCollectObjCIvars -
17291745
/// This routine first collects all declared, but not synthesized, ivars in
17301746
/// super class and then collects all ivars, including those synthesized for

lib/Basic/TargetInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ TargetInfo::TargetInfo(const std::string &T) : TargetOpts(), Triple(T)
3737
LongWidth = LongAlign = 32;
3838
LongLongWidth = LongLongAlign = 64;
3939
SuitableAlign = 64;
40+
MinGlobalAlign = 0;
4041
HalfWidth = 16;
4142
HalfAlign = 16;
4243
FloatWidth = 32;

lib/CodeGen/CodeGenModule.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2339,6 +2339,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
23392339
new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true,
23402340
Linkage, C, ".str");
23412341
GV->setUnnamedAddr(true);
2342+
// Don't enforce the target's minimum global alignment, since the only use
2343+
// of the string is via this class initializer.
23422344
if (isUTF16) {
23432345
CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy);
23442346
GV->setAlignment(Align.getQuantity());
@@ -2472,6 +2474,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
24722474
new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C,
24732475
".str");
24742476
GV->setUnnamedAddr(true);
2477+
// Don't enforce the target's minimum global alignment, since the only use
2478+
// of the string is via this class initializer.
24752479
CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
24762480
GV->setAlignment(Align.getQuantity());
24772481
Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
@@ -2576,7 +2580,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
25762580
/// constant array for the given string literal.
25772581
llvm::Constant *
25782582
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
2579-
CharUnits Align = getContext().getTypeAlignInChars(S->getType());
2583+
CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType());
25802584
if (S->isAscii() || S->isUTF8()) {
25812585
SmallString<64> Str(S->getString());
25822586

@@ -2645,6 +2649,10 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
26452649
if (!GlobalName)
26462650
GlobalName = ".str";
26472651

2652+
if (Alignment == 0)
2653+
Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy)
2654+
.getQuantity();
2655+
26482656
// Don't share any string literals if strings aren't constant.
26492657
if (LangOpts.WritableStrings)
26502658
return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);

lib/CodeGen/CodeGenModule.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class CodeGenModule : public CodeGenTypeCache {
713713
/// (if one is created).
714714
llvm::Constant *GetAddrOfConstantString(StringRef Str,
715715
const char *GlobalName=0,
716-
unsigned Alignment=1);
716+
unsigned Alignment=0);
717717

718718
/// GetAddrOfConstantCString - Returns a pointer to a character array
719719
/// containing the literal and a terminating '\0' character. The result has
@@ -723,7 +723,7 @@ class CodeGenModule : public CodeGenTypeCache {
723723
/// created).
724724
llvm::Constant *GetAddrOfConstantCString(const std::string &str,
725725
const char *GlobalName=0,
726-
unsigned Alignment=1);
726+
unsigned Alignment=0);
727727

728728
/// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global
729729
/// variable for the given file-scope compound literal expression.

0 commit comments

Comments
 (0)