summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2016-04-25 10:48:29 +0000
committerJames Molloy <james.molloy@arm.com>2016-04-25 10:48:29 +0000
commiteb040cc55f670fbb9087a5d5bf2bd1b3aa1dd403 (patch)
tree33515323433f51772ccaaba0c11b75addfeb9f5c
parent3c924653c1e9cf0c6d86af11e4c88d3349da3936 (diff)
downloadbcm5719-llvm-eb040cc55f670fbb9087a5d5bf2bd1b3aa1dd403.tar.gz
bcm5719-llvm-eb040cc55f670fbb9087a5d5bf2bd1b3aa1dd403.zip
[GlobalOpt] Allow constant globals to be SRA'd
The current logic assumes that any constant global will never be SRA'd. I presume this is because normally constant globals can be pushed into their uses and deleted. However, that sometimes can't happen (which is where you really want SRA, so the elements that can be eliminated, are!). There seems to be no reason why we can't SRA constants too, so let's do it. llvm-svn: 267393
-rw-r--r--llvm/lib/Transforms/IPO/GlobalOpt.cpp14
-rw-r--r--llvm/test/Transforms/GlobalOpt/globalsra.ll21
2 files changed, 30 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index a9c2a95a479..558e9774367 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -474,7 +474,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const DataLayout &DL) {
if (!GlobalUsersSafeToSRA(GV))
return nullptr;
- assert(GV->hasLocalLinkage() && !GV->isConstant());
+ assert(GV->hasLocalLinkage());
Constant *Init = GV->getInitializer();
Type *Ty = Init->getType();
@@ -1928,7 +1928,8 @@ bool GlobalOpt::processInternalGlobal(GlobalVariable *GV,
}
return Changed;
- } else if (GS.StoredType <= GlobalStatus::InitializerStored) {
+ }
+ if (GS.StoredType <= GlobalStatus::InitializerStored) {
DEBUG(dbgs() << "MARKING CONSTANT: " << *GV << "\n");
GV->setConstant(true);
@@ -1941,15 +1942,18 @@ bool GlobalOpt::processInternalGlobal(GlobalVariable *GV,
<< "all users and delete global!\n");
GV->eraseFromParent();
++NumDeleted;
+ return true;
}
+ // Fall through to the next check; see if we can optimize further.
++NumMarked;
- return true;
- } else if (!GV->getInitializer()->getType()->isSingleValueType()) {
+ }
+ if (!GV->getInitializer()->getType()->isSingleValueType()) {
const DataLayout &DL = GV->getParent()->getDataLayout();
if (SRAGlobal(GV, DL))
return true;
- } else if (GS.StoredType == GlobalStatus::StoredOnce && GS.StoredOnceValue) {
+ }
+ if (GS.StoredType == GlobalStatus::StoredOnce && GS.StoredOnceValue) {
// If the initial value for the global was an undef value, and if only
// one other value was stored into it, we can just change the
// initializer to be the stored value, then delete all stores to the
diff --git a/llvm/test/Transforms/GlobalOpt/globalsra.ll b/llvm/test/Transforms/GlobalOpt/globalsra.ll
index d593fcd9e15..7d43c382d9e 100644
--- a/llvm/test/Transforms/GlobalOpt/globalsra.ll
+++ b/llvm/test/Transforms/GlobalOpt/globalsra.ll
@@ -22,3 +22,24 @@ define double @constantize() {
ret double %X
}
+@G2 = internal constant { i32, float, { double } } {
+ i32 1,
+ float 1.000000e+00,
+ { double } { double 1.727000e+01 } } ; <{ i32, float, { double } }*> [#uses=3]
+
+define void @onlystore2() {
+ store i32 123, i32* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 0)
+ ret void
+}
+
+define float @storeinit2() {
+ store float 1.000000e+00, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 1)
+ %X = load float, float* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 1) ; <float> [#uses=1]
+ ret float %X
+}
+
+define double @constantize2() {
+ %X = load double, double* getelementptr ({ i32, float, { double } }, { i32, float, { double } }* @G2, i32 0, i32 2, i32 0) ; <double> [#uses=1]
+ ret double %X
+}
+
OpenPOWER on IntegriCloud