mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 17:56:53 +00:00
Add unnamed_addr when we can show that address of a global is not used.
llvm-svn: 123834
This commit is contained in:
parent
8a1c4fd8ce
commit
ce499efe1d
@ -40,6 +40,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumMarked , "Number of globals marked constant");
|
||||
STATISTIC(NumUnnamed , "Number of globals marked unnamed_addr");
|
||||
STATISTIC(NumSRA , "Number of aggregate globals broken into scalars");
|
||||
STATISTIC(NumHeapSRA , "Number of heap objects SRA'd");
|
||||
STATISTIC(NumSubstitute,"Number of globals with initializers stored into them");
|
||||
@ -55,6 +56,7 @@ STATISTIC(NumAliasesResolved, "Number of global aliases resolved");
|
||||
STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");
|
||||
|
||||
namespace {
|
||||
struct GlobalStatus;
|
||||
struct GlobalOpt : public ModulePass {
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
}
|
||||
@ -71,7 +73,10 @@ namespace {
|
||||
bool OptimizeGlobalVars(Module &M);
|
||||
bool OptimizeGlobalAliases(Module &M);
|
||||
bool OptimizeGlobalCtorsList(GlobalVariable *&GCL);
|
||||
bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI);
|
||||
bool ProcessGlobal(GlobalVariable *GV,Module::global_iterator &GVI);
|
||||
bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI,
|
||||
const SmallPtrSet<const PHINode*, 16> &PHIUsers,
|
||||
const GlobalStatus &GS);
|
||||
};
|
||||
}
|
||||
|
||||
@ -87,6 +92,9 @@ namespace {
|
||||
/// about it. If we find out that the address of the global is taken, none of
|
||||
/// this info will be accurate.
|
||||
struct GlobalStatus {
|
||||
/// isCompared - True if the global's address is used in a comparison.
|
||||
bool isCompared;
|
||||
|
||||
/// isLoaded - True if the global is ever loaded. If the global isn't ever
|
||||
/// loaded it can be deleted.
|
||||
bool isLoaded;
|
||||
@ -132,9 +140,10 @@ struct GlobalStatus {
|
||||
/// HasPHIUser - Set to true if this global has a user that is a PHI node.
|
||||
bool HasPHIUser;
|
||||
|
||||
GlobalStatus() : isLoaded(false), StoredType(NotStored), StoredOnceValue(0),
|
||||
AccessingFunction(0), HasMultipleAccessingFunctions(false),
|
||||
HasNonInstructionUser(false), HasPHIUser(false) {}
|
||||
GlobalStatus() : isCompared(false), isLoaded(false), StoredType(NotStored),
|
||||
StoredOnceValue(0), AccessingFunction(0),
|
||||
HasMultipleAccessingFunctions(false), HasNonInstructionUser(false),
|
||||
HasPHIUser(false) {}
|
||||
};
|
||||
|
||||
}
|
||||
@ -228,7 +237,7 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS,
|
||||
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
|
||||
GS.HasPHIUser = true;
|
||||
} else if (isa<CmpInst>(I)) {
|
||||
// Nothing to analyse.
|
||||
GS.isCompared = true;
|
||||
} else if (isa<MemTransferInst>(I)) {
|
||||
const MemTransferInst *MTI = cast<MemTransferInst>(I);
|
||||
if (MTI->getArgOperand(0) == V)
|
||||
@ -1691,10 +1700,12 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
|
||||
|
||||
/// ProcessInternalGlobal - Analyze the specified global variable and optimize
|
||||
/// it if possible. If we make a change, return true.
|
||||
bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
|
||||
Module::global_iterator &GVI) {
|
||||
SmallPtrSet<const PHINode*, 16> PHIUsers;
|
||||
GlobalStatus GS;
|
||||
bool GlobalOpt::ProcessGlobal(GlobalVariable *GV,
|
||||
Module::global_iterator &GVI) {
|
||||
if (!GV->hasLocalLinkage())
|
||||
return false;
|
||||
|
||||
// Do more involved optimizations if the global is internal.
|
||||
GV->removeDeadConstantUsers();
|
||||
|
||||
if (GV->use_empty()) {
|
||||
@ -1704,9 +1715,29 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
|
||||
return true;
|
||||
}
|
||||
|
||||
SmallPtrSet<const PHINode*, 16> PHIUsers;
|
||||
GlobalStatus GS;
|
||||
|
||||
if (AnalyzeGlobal(GV, GS, PHIUsers))
|
||||
return false;
|
||||
|
||||
if (!GS.isCompared && !GV->hasUnnamedAddr()) {
|
||||
GV->setUnnamedAddr(true);
|
||||
NumUnnamed++;
|
||||
}
|
||||
|
||||
if (GV->isConstant() || !GV->hasInitializer())
|
||||
return false;
|
||||
|
||||
return ProcessInternalGlobal(GV, GVI, PHIUsers, GS);
|
||||
}
|
||||
|
||||
/// ProcessInternalGlobal - Analyze the specified global variable and optimize
|
||||
/// it if possible. If we make a change, return true.
|
||||
bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
|
||||
Module::global_iterator &GVI,
|
||||
const SmallPtrSet<const PHINode*, 16> &PHIUsers,
|
||||
const GlobalStatus &GS) {
|
||||
// If this is a first class global and has only one accessing function
|
||||
// and this function is main (which we know is not recursive we can make
|
||||
// this global a local variable) we replace the global with a local alloca
|
||||
@ -1903,10 +1934,8 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) {
|
||||
if (New && New != CE)
|
||||
GV->setInitializer(New);
|
||||
}
|
||||
// Do more involved optimizations if the global is internal.
|
||||
if (!GV->isConstant() && GV->hasLocalLinkage() &&
|
||||
GV->hasInitializer())
|
||||
Changed |= ProcessInternalGlobal(GV, GVI);
|
||||
|
||||
Changed |= ProcessGlobal(GV, GVI);
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
; alignments. Elements 0 and 2 must be 16-byte aligned, and element
|
||||
; 1 must be at least 8 byte aligned (but could be more).
|
||||
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.0 = internal global .*align 16}
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.1 = internal global .*align 8}
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.2 = internal global .*align 16}
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.0 = internal unnamed_addr global .*align 16}
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.1 = internal unnamed_addr global .*align 8}
|
||||
; RUN: opt < %s -globalopt -S | grep {@G.2 = internal unnamed_addr global .*align 16}
|
||||
; rdar://5891920
|
||||
|
||||
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:32:32-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt < %s -globalopt -S | grep {@X = internal global i32}
|
||||
; RUN: opt < %s -globalopt -S | grep {@X = internal unnamed_addr global i32}
|
||||
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 triple = "i386-apple-darwin7"
|
||||
@X = internal global i32* null ; <i32**> [#uses=2]
|
||||
|
@ -8,7 +8,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
||||
target triple = "x86_64-apple-darwin10.0"
|
||||
|
||||
@TOP = internal global i64* null ; <i64**> [#uses=2]
|
||||
; CHECK: @TOP = internal global i64* null
|
||||
; CHECK: @TOP = internal unnamed_addr global i64* null
|
||||
@channelColumns = internal global i64 0 ; <i64*> [#uses=2]
|
||||
|
||||
; Derived from @DescribeChannel() in yacr2
|
||||
|
@ -1,5 +1,5 @@
|
||||
; RUN: opt < %s -globalopt -S > %t
|
||||
; RUN: grep {@Y = internal global \\\[3 x \[%\]struct.X\\\] zeroinitializer} %t
|
||||
; RUN: grep {@Y = internal unnamed_addr global \\\[3 x \[%\]struct.X\\\] zeroinitializer} %t
|
||||
; RUN: grep load %t | count 6
|
||||
; RUN: grep {add i32 \[%\]a, \[%\]b} %t | count 3
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
; RUN: opt < %s -globalopt -S | \
|
||||
; RUN: grep {G1 = internal constant}
|
||||
; RUN: grep {G1 = internal unnamed_addr constant}
|
||||
|
||||
@G1 = internal global [58 x i8] c"asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd\00" ; <[58 x i8]*> [#uses=1]
|
||||
|
||||
|
54
test/Transforms/GlobalOpt/unnamed-addr.ll
Normal file
54
test/Transforms/GlobalOpt/unnamed-addr.ll
Normal file
@ -0,0 +1,54 @@
|
||||
; RUN: opt %s -globalopt -S | FileCheck %s
|
||||
|
||||
@a = internal global i32 0, align 4
|
||||
@b = internal global i32 0, align 4
|
||||
@c = internal global i32 0, align 4
|
||||
@d = internal constant [4 x i8] c"foo\00", align 1
|
||||
|
||||
; CHECK: @a = internal global i32 0, align 4
|
||||
; CHECK: @b = internal global i32 0, align 4
|
||||
; CHECK: @c = internal unnamed_addr global i32 0, align 4
|
||||
; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1
|
||||
|
||||
define i1 @bah(i64 %i) nounwind readonly optsize ssp {
|
||||
entry:
|
||||
%arrayidx4 = getelementptr inbounds [4 x i8]* @d, i64 0, i64 %i
|
||||
%tmp5 = load i8* %arrayidx4, align 1
|
||||
%cmp = icmp eq i8 %tmp5, 42
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define void @baz(i32 %x) {
|
||||
entry:
|
||||
store i32 %x, i32* @a, align 4
|
||||
store i32 %x, i32* @b, align 4
|
||||
store i32 %x, i32* @c, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @foo(i32* %x) nounwind readnone optsize ssp {
|
||||
entry:
|
||||
%cmp = icmp eq i32* %x, @a
|
||||
%conv = zext i1 %cmp to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i32 @bar() {
|
||||
entry:
|
||||
switch i64 ptrtoint (i32* @b to i64), label %sw.epilog [
|
||||
i64 1, label %return
|
||||
i64 0, label %return
|
||||
]
|
||||
|
||||
sw.epilog:
|
||||
ret i32 0
|
||||
|
||||
return:
|
||||
ret i32 1
|
||||
}
|
||||
|
||||
define i32 @zed() {
|
||||
entry:
|
||||
%tmp1 = load i32* @c, align 4
|
||||
ret i32 %tmp1
|
||||
}
|
Loading…
Reference in New Issue
Block a user