aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-05-06 01:48:55 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-05-06 01:48:55 +0000
commiteaf14786ca3975266ed7041ac242122c02baf1cf (patch)
treedf9d224b2e6f54b3dc537fd7dda76ab372b77a22
parentf93b6d2ec56e56113d52f263a92ed2bcfa3acefb (diff)
Fix const merging when an alias of a const is llvm.used.
We used to disable constant merging not only if a constant is llvm.used, but also if an alias of a constant is llvm.used. This change fixes that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181175 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/IR/Value.h16
-rw-r--r--lib/IR/Value.cpp8
-rw-r--r--lib/Transforms/IPO/ConstantMerge.cpp10
-rw-r--r--test/Transforms/ConstantMerge/merge-both.ll3
4 files changed, 29 insertions, 8 deletions
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index fb61a2ac70..5fba3d5714 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -260,14 +260,24 @@ public:
/// this value.
bool hasValueHandle() const { return HasValueHandle; }
- /// stripPointerCasts - This method strips off any unneeded pointer casts and
- /// all-zero GEPs from the specified value, returning the original uncasted
- /// value. If this is called on a non-pointer value, it returns 'this'.
+ /// \brief This method strips off any unneeded pointer casts,
+ /// all-zero GEPs and aliases from the specified value, returning the original
+ /// uncasted value. If this is called on a non-pointer value, it returns
+ /// 'this'.
Value *stripPointerCasts();
const Value *stripPointerCasts() const {
return const_cast<Value*>(this)->stripPointerCasts();
}
+ /// \brief This method strips off any unneeded pointer casts and
+ /// all-zero GEPs from the specified value, returning the original
+ /// uncasted value. If this is called on a non-pointer value, it returns
+ /// 'this'.
+ Value *stripPointerCastsNoFollowAliases();
+ const Value *stripPointerCastsNoFollowAliases() const {
+ return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
+ }
+
/// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and
/// all-constant GEPs from the specified value, returning the original
/// pointer value. If this is called on a non-pointer value, it returns
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index e9eb012e6c..89a3c0578c 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -333,6 +333,7 @@ namespace {
// Various metrics for how much to strip off of pointers.
enum PointerStripKind {
PSK_ZeroIndices,
+ PSK_ZeroIndicesAndAliases,
PSK_InBoundsConstantIndices,
PSK_InBounds
};
@@ -350,6 +351,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
do {
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
switch (StripKind) {
+ case PSK_ZeroIndicesAndAliases:
case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices())
return V;
@@ -367,7 +369,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
} else if (Operator::getOpcode(V) == Instruction::BitCast) {
V = cast<Operator>(V)->getOperand(0);
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
- if (GA->mayBeOverridden())
+ if (StripKind == PSK_ZeroIndices || GA->mayBeOverridden())
return V;
V = GA->getAliasee();
} else {
@@ -381,6 +383,10 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
} // namespace
Value *Value::stripPointerCasts() {
+ return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this);
+}
+
+Value *Value::stripPointerCastsNoFollowAliases() {
return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this);
}
diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp
index b63495b968..a7bf18896b 100644
--- a/lib/Transforms/IPO/ConstantMerge.cpp
+++ b/lib/Transforms/IPO/ConstantMerge.cpp
@@ -27,6 +27,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
using namespace llvm;
@@ -68,10 +69,11 @@ static void FindUsedValues(GlobalVariable *LLVMUsed,
if (LLVMUsed == 0) return;
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
- for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
- if (GlobalValue *GV =
- dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
- UsedValues.insert(GV);
+ for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
+ Value *Operand = Inits->getOperand(i)->stripPointerCastsNoFollowAliases();
+ GlobalValue *GV = cast<GlobalValue>(Operand);
+ UsedValues.insert(GV);
+ }
}
// True if A is better than B.
diff --git a/test/Transforms/ConstantMerge/merge-both.ll b/test/Transforms/ConstantMerge/merge-both.ll
index b00345557c..316267648f 100644
--- a/test/Transforms/ConstantMerge/merge-both.ll
+++ b/test/Transforms/ConstantMerge/merge-both.ll
@@ -26,6 +26,9 @@ declare void @helper([16 x i8]*)
; CHECK-NEXT: @var6 = private constant [16 x i8] c"foo1bar2foo3bar\00", align 16
; CHECK-NEXT: @var8 = private constant [16 x i8] c"foo1bar2foo3bar\00"
+@var4a = alias %struct.foobar* @var4
+@llvm.used = appending global [1 x %struct.foobar*] [%struct.foobar* @var4a], section "llvm.metadata"
+
define i32 @main() {
entry:
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)