Add a natural stack alignment field to TargetData, and prevent InstCombine from
authorLang Hames <lhames@gmail.com>
Mon, 10 Oct 2011 23:42:08 +0000 (23:42 +0000)
committerLang Hames <lhames@gmail.com>
Mon, 10 Oct 2011 23:42:08 +0000 (23:42 +0000)
promoting allocas to preferred alignments that exceed the natural
alignment. This avoids some potentially expensive dynamic stack realignments.

The natural stack alignment is set in target data strings via the "S<size>"
option. Size is in bits and must be a multiple of 8. The natural stack alignment
defaults to "unspecified" (represented by a zero value), and the "unspecified"
value does not prevent any alignment promotions. Target maintainers that care
about avoiding promotions should explicitly add the "S<size>" option to their
target data strings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141599 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.html
include/llvm/Target/TargetData.h
lib/Target/ARM/ARMTargetMachine.cpp
lib/Target/TargetData.cpp
lib/Target/X86/README-SSE.txt
lib/Target/X86/README.txt
lib/Target/X86/X86TargetMachine.cpp
lib/Transforms/Utils/Local.cpp

index 1392db6e60a39f576c17d80c3f5a443e4473d647..a28d92efa1a5525330a3e1201f2b033544059d8e 100644 (file)
@@ -1319,6 +1319,12 @@ target datalayout = "<i>layout specification</i>"
       the bits with the least significance have the lowest address
       location.</dd>
 
+  <dt><tt>S<i>size</i></tt></dt>
+  <dd>Specifies the natural alignment of the stack in bits. Alignment promotion
+      of stack variables is limited to the natural stack alignment to avoid
+      dynamic stack realignment. The stack alignment must be a multiple of
+      8-bits, and currently defaults to 128 bits if unspecified.</dd>
+
   <dt><tt>p:<i>size</i>:<i>abi</i>:<i>pref</i></tt></dt>
   <dd>This specifies the <i>size</i> of a pointer and its <i>abi</i> and
       <i>preferred</i> alignments. All sizes are in bits. Specifying
index 315bee96bac6ae2c2650e72ecfd23ab1aa630642..e34094ddb7b3432234b0a0a470b94ee15b3884fa 100644 (file)
@@ -70,6 +70,7 @@ private:
   unsigned      PointerMemSize;        ///< Pointer size in bytes
   unsigned      PointerABIAlign;       ///< Pointer ABI alignment
   unsigned      PointerPrefAlign;      ///< Pointer preferred alignment
+  unsigned      StackNaturalAlign;     ///< Stack natural alignment
 
   SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
   
@@ -163,6 +164,11 @@ public:
     return !isLegalInteger(Width);
   }
 
+  /// Returns true if the given alignment exceeds the natural stack alignment.
+  bool exceedsNaturalStackAlignment(unsigned Align) const {
+    return (StackNaturalAlign != 0) && (Align > StackNaturalAlign);
+  }
+
   /// fitsInLegalInteger - This function returns true if the specified type fits
   /// in a native integer type supported by the CPU.  For example, if the CPU
   /// only supports i32 as a native integer type, then i27 fits in a legal
index f779ede3e3acae58d58c8841ee610401d4786672..96b1e89b0df097cef35a84c004b74032f61bb894 100644 (file)
@@ -53,9 +53,12 @@ ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT,
   : ARMBaseTargetMachine(T, TT, CPU, FS, RM, CM), InstrInfo(Subtarget),
     DataLayout(Subtarget.isAPCS_ABI() ?
                std::string("e-p:32:32-f64:32:64-i64:32:64-"
-                           "v128:32:128-v64:32:64-n32") :
+                           "v128:32:128-v64:32:64-n32-S32") :
+               Subtarget.isAAPCS_ABI() ?
                std::string("e-p:32:32-f64:64:64-i64:64:64-"
-                           "v128:64:128-v64:64:64-n32")),
+                           "v128:64:128-v64:64:64-n32-S64") :
+               std::string("e-p:32:32-f64:64:64-i64:64:64-"
+                           "v128:64:128-v64:64:64-n32-S32")),
     ELFWriterInfo(*this),
     TLInfo(*this),
     TSInfo(*this),
@@ -75,10 +78,14 @@ ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
     DataLayout(Subtarget.isAPCS_ABI() ?
                std::string("e-p:32:32-f64:32:64-i64:32:64-"
                            "i16:16:32-i8:8:32-i1:8:32-"
-                           "v128:32:128-v64:32:64-a:0:32-n32") :
+                           "v128:32:128-v64:32:64-a:0:32-n32-S32") :
+               Subtarget.isAAPCS_ABI() ?
+               std::string("e-p:32:32-f64:64:64-i64:64:64-"
+                           "i16:16:32-i8:8:32-i1:8:32-"
+                           "v128:64:128-v64:64:64-a:0:32-n32-S64") :
                std::string("e-p:32:32-f64:64:64-i64:64:64-"
                            "i16:16:32-i8:8:32-i1:8:32-"
-                           "v128:64:128-v64:64:64-a:0:32-n32")),
+                           "v128:64:128-v64:64:64-a:0:32-n32-S32")),
     ELFWriterInfo(*this),
     TLInfo(*this),
     TSInfo(*this),
index 1dfd9a83dafb3d4dbf1aeecfe5607992a81f8b33..bd6a6b67beb9710d7b2265d585cc22a5675ae2dd 100644 (file)
@@ -139,6 +139,7 @@ void TargetData::init(StringRef Desc) {
   PointerMemSize = 8;
   PointerABIAlign = 8;
   PointerPrefAlign = PointerABIAlign;
+  StackNaturalAlign = 0;
 
   // Default alignments
   setAlignment(INTEGER_ALIGN,   1,  1, 1);   // i1
@@ -218,7 +219,12 @@ void TargetData::init(StringRef Desc) {
         Token = Split.second;
       } while (!Specifier.empty() || !Token.empty());
       break;
-
+    case 'S': // Stack natural alignment.
+      StackNaturalAlign = getInt(Specifier.substr(1));
+      StackNaturalAlign /= 8;
+      // FIXME: Should we really be truncating these alingments and
+      // sizes silently?
+      break;
     default:
       break;
     }
@@ -372,7 +378,9 @@ std::string TargetData::getStringRepresentation() const {
 
   OS << (LittleEndian ? "e" : "E")
      << "-p:" << PointerMemSize*8 << ':' << PointerABIAlign*8
-     << ':' << PointerPrefAlign*8;
+     << ':' << PointerPrefAlign*8
+     << "-S" << StackNaturalAlign*8;
+
   for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
     const TargetAlignElem &AI = Alignments[i];
     OS << '-' << (char)AI.AlignType << AI.TypeBitWidth << ':'
index f16ec029e96ab3da31996d9b3d13e6a5650c5e4e..7d901afae47499b401dc409f664922e6fc1da4ca 100644 (file)
@@ -862,7 +862,7 @@ define float @bar(float %x) nounwind {
 
 This IR (from PR6194):
 
-target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
 target triple = "x86_64-apple-darwin10.0.0"
 
 %0 = type { double, double }
index b98f5fbb995efe4dba3d412f3ca85c8e82aaf191..b40795506071bec75e4e472ce690dd637de857db 100644 (file)
@@ -1217,7 +1217,7 @@ Also check why xmm7 is not used at all in the function.
 
 Take the following:
 
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-S128"
 target triple = "i386-apple-darwin8"
 @in_exit.4870.b = internal global i1 false             ; <i1*> [#uses=2]
 define fastcc void @abort_gzip() noreturn nounwind  {
index 683d6aa0dd5eb117b821e4228c3990bc5e894edc..1dcad35c2e48be151a77c0fabbeba9b892bf314a 100644 (file)
@@ -34,11 +34,11 @@ X86_32TargetMachine::X86_32TargetMachine(const Target &T, StringRef TT,
                                          Reloc::Model RM, CodeModel::Model CM)
   : X86TargetMachine(T, TT, CPU, FS, RM, CM, false),
     DataLayout(getSubtargetImpl()->isTargetDarwin() ?
-               "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32" :
+               "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-f128:128:128-n8:16:32-S128" :
                (getSubtargetImpl()->isTargetCygMing() ||
                 getSubtargetImpl()->isTargetWindows()) ?
-               "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-n8:16:32" :
-               "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-n8:16:32"),
+               "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-f128:128:128-n8:16:32-S32" :
+               "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-f128:128:128-n8:16:32-S32"),
     InstrInfo(*this),
     TSInfo(*this),
     TLInfo(*this),
@@ -50,7 +50,7 @@ X86_64TargetMachine::X86_64TargetMachine(const Target &T, StringRef TT,
                                          StringRef CPU, StringRef FS,
                                          Reloc::Model RM, CodeModel::Model CM)
   : X86TargetMachine(T, TT, CPU, FS, RM, CM, true),
-    DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64"),
+    DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-f128:128:128-n8:16:32:64-S128"),
     InstrInfo(*this),
     TSInfo(*this),
     TLInfo(*this),
index be0aa82500160abd31ff692dcf88e9ee11574a84..7034feb227ad94c21c222e84515219b8a23edcc8 100644 (file)
@@ -721,10 +721,14 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) {
 /// their preferred alignment from the beginning.
 ///
 static unsigned enforceKnownAlignment(Value *V, unsigned Align,
-                                      unsigned PrefAlign) {
+                                      unsigned PrefAlign, const TargetData *TD) {
   V = V->stripPointerCasts();
 
   if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
+    // If the preferred alignment is greater than the natural stack alignment
+    // then don't round up. This avoids dynamic stack realignment.
+    if (TD && TD->exceedsNaturalStackAlignment(PrefAlign))
+      return Align;
     // If there is a requested alignment and if this is an alloca, round up.
     if (AI->getAlignment() >= PrefAlign)
       return AI->getAlignment();
@@ -775,7 +779,7 @@ unsigned llvm::getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign,
   Align = std::min(Align, +Value::MaximumAlignment);
   
   if (PrefAlign > Align)
-    Align = enforceKnownAlignment(V, Align, PrefAlign);
+    Align = enforceKnownAlignment(V, Align, PrefAlign, TD);
     
   // We don't need to make any adjustment.
   return Align;