From bb5b3f33594cfa40e9f53bf9a71af359b080a697 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 10 Oct 2011 23:42:08 +0000 Subject: [PATCH] Add a natural stack alignment field to TargetData, and prevent InstCombine from 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" 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" 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 | 6 ++++++ include/llvm/Target/TargetData.h | 6 ++++++ lib/Target/ARM/ARMTargetMachine.cpp | 15 +++++++++++---- lib/Target/TargetData.cpp | 12 ++++++++++-- lib/Target/X86/README-SSE.txt | 2 +- lib/Target/X86/README.txt | 2 +- lib/Target/X86/X86TargetMachine.cpp | 8 ++++---- lib/Transforms/Utils/Local.cpp | 8 ++++++-- 8 files changed, 45 insertions(+), 14 deletions(-) diff --git a/docs/LangRef.html b/docs/LangRef.html index 1392db6e60a..a28d92efa1a 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -1319,6 +1319,12 @@ target datalayout = "layout specification" the bits with the least significance have the lowest address location. +
Ssize
+
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.
+
p:size:abi:pref
This specifies the size of a pointer and its abi and preferred alignments. All sizes are in bits. Specifying diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h index 315bee96bac..e34094ddb7b 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/Target/TargetData.h @@ -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 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 diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index f779ede3e3a..96b1e89b0df 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -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")), + "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-S32")), ELFWriterInfo(*this), TLInfo(*this), TSInfo(*this), diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp index 1dfd9a83daf..bd6a6b67beb 100644 --- a/lib/Target/TargetData.cpp +++ b/lib/Target/TargetData.cpp @@ -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 << ':' diff --git a/lib/Target/X86/README-SSE.txt b/lib/Target/X86/README-SSE.txt index f16ec029e96..7d901afae47 100644 --- a/lib/Target/X86/README-SSE.txt +++ b/lib/Target/X86/README-SSE.txt @@ -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 } diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt index b98f5fbb995..b4079550607 100644 --- a/lib/Target/X86/README.txt +++ b/lib/Target/X86/README.txt @@ -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 ; [#uses=2] define fastcc void @abort_gzip() noreturn nounwind { diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 683d6aa0dd5..1dcad35c2e4 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -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), diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index be0aa825001..7034feb227a 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -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(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;