]> granicus.if.org Git - clang/commitdiff
Allow targets to define minimum alignment for global variables
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 6 May 2013 16:23:57 +0000 (16:23 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 6 May 2013 16:23:57 +0000 (16:23 +0000)
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

include/clang/AST/ASTContext.h
include/clang/Basic/TargetInfo.h
lib/AST/ASTContext.cpp
lib/Basic/TargetInfo.cpp
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h

index 902ded55f867ba41ee2f6e7e293e72fe0f5a118b..c5d3337fd22d36882cac8f7a40763b7472f20c4d 100644 (file)
@@ -1593,6 +1593,14 @@ public:
   /// beneficial for performance to overalign a data type.
   unsigned getPreferredTypeAlign(const Type *T) const;
 
+  /// \brief Return the alignment in bits that should be given to a
+  /// global variable with type \p T.
+  unsigned getAlignOfGlobalVar(QualType T) const;
+
+  /// \brief Return the alignment in characters that should be given to a
+  /// global variable with type \p T.
+  CharUnits getAlignOfGlobalVarInChars(QualType T) const;
+
   /// \brief Return a conservative estimate of the alignment of the specified
   /// decl \p D.
   ///
index c05f062aee95d8c50d9a2addc6c6fa82b45049c2..21325fac361f9853e886f4e01bf066eab3c68142 100644 (file)
@@ -66,6 +66,7 @@ protected:
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
   unsigned char SuitableAlign;
+  unsigned char MinGlobalAlign;
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
   unsigned short MaxVectorAlign;
   const char *DescriptionString;
@@ -266,6 +267,10 @@ public:
   /// object with a fundamental alignment requirement.
   unsigned getSuitableAlign() const { return SuitableAlign; }
 
+  /// getMinGlobalAlign - Return the minimum alignment of a global variable,
+  /// unless its alignment is explicitly reduced via attributes.
+  unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
+
   /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
   /// bits.
   unsigned getWCharWidth() const { return getTypeWidth(WCharType); }
index e6dfd445adf29b2eaf51044dce2bf21a398342b8..8d40a6a299d6ff2806ed9fed285f5677691c8caf 100644 (file)
@@ -1283,6 +1283,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
         T = getBaseElementType(arrayType);
       }
       Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
+      if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+        if (VD->hasGlobalStorage())
+          Align = std::max(Align, getTargetInfo().getMinGlobalAlign());
+      }
     }
 
     // Fields can be subject to extra alignment constraints, like if
@@ -1725,6 +1729,18 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
   return ABIAlign;
 }
 
+/// getAlignOfGlobalVar - Return the alignment in bits that should be given
+/// to a global variable of the specified type.
+unsigned ASTContext::getAlignOfGlobalVar(QualType T) const {
+  return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign());
+}
+
+/// getAlignOfGlobalVarInChars - Return the alignment in characters that
+/// should be given to a global variable of the specified type.
+CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const {
+  return toCharUnitsFromBits(getAlignOfGlobalVar(T));
+}
+
 /// DeepCollectObjCIvars -
 /// This routine first collects all declared, but not synthesized, ivars in
 /// super class and then collects all ivars, including those synthesized for
index ff72f495c8ba1ff06075808f689ec8554c18e713..0d44dc010e1a78960c5fe47efd17514489396ba7 100644 (file)
@@ -37,6 +37,7 @@ TargetInfo::TargetInfo(const std::string &T) : TargetOpts(), Triple(T)
   LongWidth = LongAlign = 32;
   LongLongWidth = LongLongAlign = 64;
   SuitableAlign = 64;
+  MinGlobalAlign = 0;
   HalfWidth = 16;
   HalfAlign = 16;
   FloatWidth = 32;
index ff183c96e0c8b115276f21fc8c12b0cfa0a1ada8..0b03a3c4b67dbb53e45c5557e0e26d1731bed825 100644 (file)
@@ -2339,6 +2339,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {
     new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true,
                              Linkage, C, ".str");
   GV->setUnnamedAddr(true);
+  // Don't enforce the target's minimum global alignment, since the only use
+  // of the string is via this class initializer.
   if (isUTF16) {
     CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy);
     GV->setAlignment(Align.getQuantity());
@@ -2472,6 +2474,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) {
   new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C,
                            ".str");
   GV->setUnnamedAddr(true);
+  // Don't enforce the target's minimum global alignment, since the only use
+  // of the string is via this class initializer.
   CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
   GV->setAlignment(Align.getQuantity());
   Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros);
@@ -2576,7 +2580,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) {
 /// constant array for the given string literal.
 llvm::Constant *
 CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
-  CharUnits Align = getContext().getTypeAlignInChars(S->getType());
+  CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType());
   if (S->isAscii() || S->isUTF8()) {
     SmallString<64> Str(S->getString());
     
@@ -2645,6 +2649,10 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str,
   if (!GlobalName)
     GlobalName = ".str";
 
+  if (Alignment == 0)
+    Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy)
+      .getQuantity();
+
   // Don't share any string literals if strings aren't constant.
   if (LangOpts.WritableStrings)
     return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment);
index 7bbca80bf4d784ecec835aaa94f905560b40037a..91138c607c36bc55763582553aad3f857cea6ee8 100644 (file)
@@ -713,7 +713,7 @@ public:
   /// (if one is created).
   llvm::Constant *GetAddrOfConstantString(StringRef Str,
                                           const char *GlobalName=0,
-                                          unsigned Alignment=1);
+                                          unsigned Alignment=0);
 
   /// GetAddrOfConstantCString - Returns a pointer to a character array
   /// containing the literal and a terminating '\0' character. The result has
@@ -723,7 +723,7 @@ public:
   /// created).
   llvm::Constant *GetAddrOfConstantCString(const std::string &str,
                                            const char *GlobalName=0,
-                                           unsigned Alignment=1);
+                                           unsigned Alignment=0);
 
   /// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global
   /// variable for the given file-scope compound literal expression.