summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/llvm/include/llvm/IR/GlobalValue.h4
-rw-r--r--contrib/llvm/lib/CodeGen/CodeGenPrepare.cpp4
-rw-r--r--contrib/llvm/lib/IR/Globals.cpp44
-rw-r--r--contrib/llvm/lib/Transforms/Utils/Local.cpp33
4 files changed, 69 insertions, 16 deletions
diff --git a/contrib/llvm/include/llvm/IR/GlobalValue.h b/contrib/llvm/include/llvm/IR/GlobalValue.h
index 4fa4e7d..fa6469a 100644
--- a/contrib/llvm/include/llvm/IR/GlobalValue.h
+++ b/contrib/llvm/include/llvm/IR/GlobalValue.h
@@ -346,6 +346,10 @@ public:
return !(isDeclarationForLinker() || isWeakForLinker());
}
+ // Returns true if the alignment of the value can be unilaterally
+ // increased.
+ bool canIncreaseAlignment() const;
+
/// This method unlinks 'this' from the containing module, but does not delete
/// it.
virtual void removeFromParent() = 0;
diff --git a/contrib/llvm/lib/CodeGen/CodeGenPrepare.cpp b/contrib/llvm/lib/CodeGen/CodeGenPrepare.cpp
index 03e5778..fd4ee46 100644
--- a/contrib/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/contrib/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1742,8 +1742,8 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, bool& ModifiedDT) {
// over-aligning global variables that have an explicit section is
// forbidden.
GlobalVariable *GV;
- if ((GV = dyn_cast<GlobalVariable>(Val)) && GV->hasUniqueInitializer() &&
- !GV->hasSection() && GV->getAlignment() < PrefAlign &&
+ if ((GV = dyn_cast<GlobalVariable>(Val)) && GV->canIncreaseAlignment() &&
+ GV->getAlignment() < PrefAlign &&
DL->getTypeAllocSize(GV->getType()->getElementType()) >=
MinSize + Offset2)
GV->setAlignment(PrefAlign);
diff --git a/contrib/llvm/lib/IR/Globals.cpp b/contrib/llvm/lib/IR/Globals.cpp
index 6159f93..a61b62b 100644
--- a/contrib/llvm/lib/IR/Globals.cpp
+++ b/contrib/llvm/lib/IR/Globals.cpp
@@ -12,11 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/GlobalValue.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
@@ -134,6 +135,47 @@ bool GlobalValue::isDeclaration() const {
return false;
}
+bool GlobalValue::canIncreaseAlignment() const {
+ // Firstly, can only increase the alignment of a global if it
+ // is a strong definition.
+ if (!isStrongDefinitionForLinker())
+ return false;
+
+ // It also has to either not have a section defined, or, not have
+ // alignment specified. (If it is assigned a section, the global
+ // could be densely packed with other objects in the section, and
+ // increasing the alignment could cause padding issues.)
+ if (hasSection() && getAlignment() > 0)
+ return false;
+
+ // On ELF platforms, we're further restricted in that we can't
+ // increase the alignment of any variable which might be emitted
+ // into a shared library, and which is exported. If the main
+ // executable accesses a variable found in a shared-lib, the main
+ // exe actually allocates memory for and exports the symbol ITSELF,
+ // overriding the symbol found in the library. That is, at link
+ // time, the observed alignment of the variable is copied into the
+ // executable binary. (A COPY relocation is also generated, to copy
+ // the initial data from the shadowed variable in the shared-lib
+ // into the location in the main binary, before running code.)
+ //
+ // And thus, even though you might think you are defining the
+ // global, and allocating the memory for the global in your object
+ // file, and thus should be able to set the alignment arbitrarily,
+ // that's not actually true. Doing so can cause an ABI breakage; an
+ // executable might have already been built with the previous
+ // alignment of the variable, and then assuming an increased
+ // alignment will be incorrect.
+
+ // Conservatively assume ELF if there's no parent pointer.
+ bool isELF =
+ (!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatELF());
+ if (isELF && hasDefaultVisibility() && !hasLocalLinkage())
+ return false;
+
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/Transforms/Utils/Local.cpp b/contrib/llvm/lib/Transforms/Utils/Local.cpp
index d2793e5..1cb65fc 100644
--- a/contrib/llvm/lib/Transforms/Utils/Local.cpp
+++ b/contrib/llvm/lib/Transforms/Utils/Local.cpp
@@ -944,37 +944,44 @@ bool llvm::EliminateDuplicatePHINodes(BasicBlock *BB) {
static unsigned enforceKnownAlignment(Value *V, unsigned Align,
unsigned PrefAlign,
const DataLayout &DL) {
+ assert(PrefAlign > Align);
+
V = V->stripPointerCasts();
if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
+ // TODO: ideally, computeKnownBits ought to have used
+ // AllocaInst::getAlignment() in its computation already, making
+ // the below max redundant. But, as it turns out,
+ // stripPointerCasts recurses through infinite layers of bitcasts,
+ // while computeKnownBits is not allowed to traverse more than 6
+ // levels.
+ Align = std::max(AI->getAlignment(), Align);
+ if (PrefAlign <= Align)
+ return Align;
+
// If the preferred alignment is greater than the natural stack alignment
// then don't round up. This avoids dynamic stack realignment.
if (DL.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();
AI->setAlignment(PrefAlign);
return PrefAlign;
}
if (auto *GO = dyn_cast<GlobalObject>(V)) {
+ // TODO: as above, this shouldn't be necessary.
+ Align = std::max(GO->getAlignment(), Align);
+ if (PrefAlign <= Align)
+ return Align;
+
// If there is a large requested alignment and we can, bump up the alignment
// of the global. If the memory we set aside for the global may not be the
// memory used by the final program then it is impossible for us to reliably
// enforce the preferred alignment.
- if (!GO->isStrongDefinitionForLinker())
+ if (!GO->canIncreaseAlignment())
return Align;
- if (GO->getAlignment() >= PrefAlign)
- return GO->getAlignment();
- // We can only increase the alignment of the global if it has no alignment
- // specified or if it is not assigned a section. If it is assigned a
- // section, the global could be densely packed with other objects in the
- // section, increasing the alignment could cause padding issues.
- if (!GO->hasSection() || GO->getAlignment() == 0)
- GO->setAlignment(PrefAlign);
- return GO->getAlignment();
+ GO->setAlignment(PrefAlign);
+ return PrefAlign;
}
return Align;
OpenPOWER on IntegriCloud