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
This commit is contained in:
Rafael Espindola
2013-05-06 01:48:55 +00:00
parent f93b6d2ec5
commit eaf14786ca
4 changed files with 29 additions and 8 deletions

View File

@@ -260,14 +260,24 @@ public:
/// this value. /// this value.
bool hasValueHandle() const { return HasValueHandle; } bool hasValueHandle() const { return HasValueHandle; }
/// stripPointerCasts - This method strips off any unneeded pointer casts and /// \brief This method strips off any unneeded pointer casts,
/// all-zero GEPs from the specified value, returning the original uncasted /// all-zero GEPs and aliases from the specified value, returning the original
/// value. If this is called on a non-pointer value, it returns 'this'. /// uncasted value. If this is called on a non-pointer value, it returns
/// 'this'.
Value *stripPointerCasts(); Value *stripPointerCasts();
const Value *stripPointerCasts() const { const Value *stripPointerCasts() const {
return const_cast<Value*>(this)->stripPointerCasts(); 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 /// stripInBoundsConstantOffsets - This method strips off unneeded pointer casts and
/// all-constant GEPs from the specified value, returning the original /// all-constant GEPs from the specified value, returning the original
/// pointer value. If this is called on a non-pointer value, it returns /// pointer value. If this is called on a non-pointer value, it returns

View File

@@ -333,6 +333,7 @@ namespace {
// Various metrics for how much to strip off of pointers. // Various metrics for how much to strip off of pointers.
enum PointerStripKind { enum PointerStripKind {
PSK_ZeroIndices, PSK_ZeroIndices,
PSK_ZeroIndicesAndAliases,
PSK_InBoundsConstantIndices, PSK_InBoundsConstantIndices,
PSK_InBounds PSK_InBounds
}; };
@@ -350,6 +351,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
do { do {
if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) { if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
switch (StripKind) { switch (StripKind) {
case PSK_ZeroIndicesAndAliases:
case PSK_ZeroIndices: case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices()) if (!GEP->hasAllZeroIndices())
return V; return V;
@@ -367,7 +369,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
} else if (Operator::getOpcode(V) == Instruction::BitCast) { } else if (Operator::getOpcode(V) == Instruction::BitCast) {
V = cast<Operator>(V)->getOperand(0); V = cast<Operator>(V)->getOperand(0);
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) { } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
if (GA->mayBeOverridden()) if (StripKind == PSK_ZeroIndices || GA->mayBeOverridden())
return V; return V;
V = GA->getAliasee(); V = GA->getAliasee();
} else { } else {
@@ -381,6 +383,10 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
} // namespace } // namespace
Value *Value::stripPointerCasts() { Value *Value::stripPointerCasts() {
return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this);
}
Value *Value::stripPointerCastsNoFollowAliases() {
return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this); return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this);
} }

View File

@@ -27,6 +27,7 @@
#include "llvm/IR/DataLayout.h" #include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
using namespace llvm; using namespace llvm;
@@ -68,10 +69,11 @@ static void FindUsedValues(GlobalVariable *LLVMUsed,
if (LLVMUsed == 0) return; if (LLVMUsed == 0) return;
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
if (GlobalValue *GV = Value *Operand = Inits->getOperand(i)->stripPointerCastsNoFollowAliases();
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) GlobalValue *GV = cast<GlobalValue>(Operand);
UsedValues.insert(GV); UsedValues.insert(GV);
}
} }
// True if A is better than B. // True if A is better than B.

View File

@@ -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: @var6 = private constant [16 x i8] c"foo1bar2foo3bar\00", align 16
; CHECK-NEXT: @var8 = private constant [16 x i8] c"foo1bar2foo3bar\00" ; 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() { define i32 @main() {
entry: entry:
call void @zed(%struct.foobar* @var1, %struct.foobar* @var2) call void @zed(%struct.foobar* @var1, %struct.foobar* @var2)