mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-26 20:26:07 +00:00
Teach DAE to look for functions whose arguments are unused, and change all callers to pass in an undefvalue instead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123596 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -39,7 +39,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
STATISTIC(NumArgumentsEliminated, "Number of unread args removed");
|
STATISTIC(NumArgumentsEliminated, "Number of unread args removed");
|
||||||
STATISTIC(NumRetValsEliminated , "Number of unused return values removed");
|
STATISTIC(NumRetValsEliminated , "Number of unused return values removed");
|
||||||
|
STATISTIC(NumArgumentsReplacedWithUndef,
|
||||||
|
"Number of unread args replaced with undef");
|
||||||
namespace {
|
namespace {
|
||||||
/// DAE - The dead argument elimination pass.
|
/// DAE - The dead argument elimination pass.
|
||||||
///
|
///
|
||||||
@@ -148,6 +149,7 @@ namespace {
|
|||||||
void PropagateLiveness(const RetOrArg &RA);
|
void PropagateLiveness(const RetOrArg &RA);
|
||||||
bool RemoveDeadStuffFromFunction(Function *F);
|
bool RemoveDeadStuffFromFunction(Function *F);
|
||||||
bool DeleteDeadVarargs(Function &Fn);
|
bool DeleteDeadVarargs(Function &Fn);
|
||||||
|
bool RemoveDeadArgumentsFromCallers(Function &Fn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,6 +289,55 @@ bool DAE::DeleteDeadVarargs(Function &Fn) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RemoveDeadArgumentsFromCallers - Checks if the given function has any
|
||||||
|
/// arguments that are unused, and changes the caller parameters to be undefined
|
||||||
|
/// instead.
|
||||||
|
bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn)
|
||||||
|
{
|
||||||
|
if (Fn.isDeclaration())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Functions with local linkage should already have been handled.
|
||||||
|
if (Fn.hasLocalLinkage())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Fn.use_empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
llvm::SmallVector<unsigned, 8> UnusedArgs;
|
||||||
|
for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
Argument *Arg = I;
|
||||||
|
|
||||||
|
if (Arg->use_empty() && !Arg->hasByValAttr())
|
||||||
|
UnusedArgs.push_back(Arg->getArgNo());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnusedArgs.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool Changed = false;
|
||||||
|
|
||||||
|
for (Function::use_iterator I = Fn.use_begin(), E = Fn.use_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
CallSite CS(*I);
|
||||||
|
if (!CS || !CS.isCallee(I))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Now go through all unused args and replace them with "undef".
|
||||||
|
for (unsigned I = 0, E = UnusedArgs.size(); I != E; ++I) {
|
||||||
|
unsigned ArgNo = UnusedArgs[I];
|
||||||
|
|
||||||
|
Value *Arg = CS.getArgument(ArgNo);
|
||||||
|
CS.setArgument(ArgNo, UndefValue::get(Arg->getType()));
|
||||||
|
++NumArgumentsReplacedWithUndef;
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Changed;
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience function that returns the number of return values. It returns 0
|
/// Convenience function that returns the number of return values. It returns 0
|
||||||
/// for void functions and 1 for functions not returning a struct. It returns
|
/// for void functions and 1 for functions not returning a struct. It returns
|
||||||
/// the number of struct elements for functions returning a struct.
|
/// the number of struct elements for functions returning a struct.
|
||||||
@@ -939,5 +990,14 @@ bool DAE::runOnModule(Module &M) {
|
|||||||
Function *F = I++;
|
Function *F = I++;
|
||||||
Changed |= RemoveDeadStuffFromFunction(F);
|
Changed |= RemoveDeadStuffFromFunction(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, look for any unused parameters in functions with non-local
|
||||||
|
// linkage and replace the passed in parameters with undef.
|
||||||
|
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
|
||||||
|
Function& F = *I;
|
||||||
|
|
||||||
|
Changed |= RemoveDeadArgumentsFromCallers(F);
|
||||||
|
}
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
; RUN: opt -deadargelim -S %s | FileCheck %s
|
; RUN: opt -deadargelim -S %s | FileCheck %s
|
||||||
; XFAIL: *
|
|
||||||
|
|
||||||
define void @test(i32) {
|
define void @test(i32) {
|
||||||
ret void
|
ret void
|
||||||
@@ -11,3 +10,30 @@ define void @foo() {
|
|||||||
; CHECK: @foo
|
; CHECK: @foo
|
||||||
; CHECK: i32 undef
|
; CHECK: i32 undef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @f(i32 %X) {
|
||||||
|
entry:
|
||||||
|
tail call void @sideeffect() nounwind
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @sideeffect()
|
||||||
|
|
||||||
|
define void @g(i32 %n) {
|
||||||
|
entry:
|
||||||
|
%add = add nsw i32 %n, 1
|
||||||
|
; CHECK: tail call void @f(i32 undef)
|
||||||
|
tail call void @f(i32 %add)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @h() {
|
||||||
|
entry:
|
||||||
|
%i = alloca i32, align 4
|
||||||
|
volatile store i32 10, i32* %i, align 4
|
||||||
|
; CHECK: %tmp = volatile load i32* %i, align 4
|
||||||
|
; CHECK-next: call void @f(i32 undef)
|
||||||
|
%tmp = volatile load i32* %i, align 4
|
||||||
|
call void @f(i32 %tmp)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user