mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 18:04:59 +00:00
Allow inlining of functions with returns_twice calls, if they have the
attribute themselve. llvm-svn: 146851
This commit is contained in:
parent
e16533eded
commit
8cf8d64d19
@ -31,8 +31,9 @@ namespace llvm {
|
|||||||
/// caller.
|
/// caller.
|
||||||
// bool NeverInline;
|
// bool NeverInline;
|
||||||
|
|
||||||
// True if this function contains a call to setjmp or _setjmp
|
// True if this function contains a call to setjmp or other functions
|
||||||
bool callsSetJmp;
|
// with attribute "returns twice" without having the attribute by itself.
|
||||||
|
bool exposesReturnsTwice;
|
||||||
|
|
||||||
// True if this function calls itself
|
// True if this function calls itself
|
||||||
bool isRecursive;
|
bool isRecursive;
|
||||||
@ -66,7 +67,7 @@ namespace llvm {
|
|||||||
/// NumRets - Keep track of how many Ret instructions the block contains.
|
/// NumRets - Keep track of how many Ret instructions the block contains.
|
||||||
unsigned NumRets;
|
unsigned NumRets;
|
||||||
|
|
||||||
CodeMetrics() : callsSetJmp(false), isRecursive(false),
|
CodeMetrics() : exposesReturnsTwice(false), isRecursive(false),
|
||||||
containsIndirectBr(false), usesDynamicAlloca(false),
|
containsIndirectBr(false), usesDynamicAlloca(false),
|
||||||
NumInsts(0), NumBlocks(0), NumCalls(0),
|
NumInsts(0), NumBlocks(0), NumCalls(0),
|
||||||
NumInlineCandidates(0), NumVectorInsts(0),
|
NumInlineCandidates(0), NumVectorInsts(0),
|
||||||
|
@ -120,10 +120,12 @@ class MachineFunction {
|
|||||||
/// Alignment - The alignment of the function.
|
/// Alignment - The alignment of the function.
|
||||||
unsigned Alignment;
|
unsigned Alignment;
|
||||||
|
|
||||||
/// CallsSetJmp - True if the function calls setjmp or sigsetjmp. This is used
|
/// ExposesReturnsTwice - True if the function calls setjmp or related
|
||||||
/// to limit optimizations which cannot reason about the control flow of
|
/// functions with attribute "returns twice", but doesn't have
|
||||||
/// setjmp.
|
/// the attribute itself.
|
||||||
bool CallsSetJmp;
|
/// This is used to limit optimizations which cannot reason
|
||||||
|
/// about the control flow of such functions.
|
||||||
|
bool ExposesReturnsTwice;
|
||||||
|
|
||||||
MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT
|
MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT
|
||||||
void operator=(const MachineFunction&); // DO NOT IMPLEMENT
|
void operator=(const MachineFunction&); // DO NOT IMPLEMENT
|
||||||
@ -192,15 +194,17 @@ public:
|
|||||||
if (Alignment < A) Alignment = A;
|
if (Alignment < A) Alignment = A;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// callsSetJmp - Returns true if the function calls setjmp or sigsetjmp.
|
/// exposesReturnsTwice - Returns true if the function calls setjmp or
|
||||||
bool callsSetJmp() const {
|
/// any other similar functions with attribute "returns twice" without
|
||||||
return CallsSetJmp;
|
/// having the attribute itself.
|
||||||
|
bool exposesReturnsTwice() const {
|
||||||
|
return ExposesReturnsTwice;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// setCallsSetJmp - Set a flag that indicates if there's a call to setjmp or
|
/// setCallsSetJmp - Set a flag that indicates if there's a call to
|
||||||
/// sigsetjmp.
|
/// a "returns twice" function.
|
||||||
void setCallsSetJmp(bool B) {
|
void setExposesReturnsTwice(bool B) {
|
||||||
CallsSetJmp = B;
|
ExposesReturnsTwice = B;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getInfo - Keep track of various per-function pieces of information for
|
/// getInfo - Keep track of various per-function pieces of information for
|
||||||
|
@ -232,10 +232,12 @@ unsigned CodeMetrics::CountCodeReductionForAlloca(Value *V) {
|
|||||||
/// from the specified function.
|
/// from the specified function.
|
||||||
void CodeMetrics::analyzeFunction(Function *F, const TargetData *TD) {
|
void CodeMetrics::analyzeFunction(Function *F, const TargetData *TD) {
|
||||||
// If this function contains a call that "returns twice" (e.g., setjmp or
|
// If this function contains a call that "returns twice" (e.g., setjmp or
|
||||||
// _setjmp), never inline it. This is a hack because we depend on the user
|
// _setjmp) and it isn't marked with "returns twice" itself, never inline it.
|
||||||
// marking their local variables as volatile if they are live across a setjmp
|
// This is a hack because we depend on the user marking their local variables
|
||||||
// call, and they probably won't do this in callers.
|
// as volatile if they are live across a setjmp call, and they probably
|
||||||
callsSetJmp = F->callsFunctionThatReturnsTwice();
|
// won't do this in callers.
|
||||||
|
exposesReturnsTwice = F->callsFunctionThatReturnsTwice() &&
|
||||||
|
!F->hasFnAttr(Attribute::ReturnsTwice);
|
||||||
|
|
||||||
// Look at the size of the callee.
|
// Look at the size of the callee.
|
||||||
for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
||||||
@ -265,7 +267,7 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F,
|
|||||||
/// NeverInline - returns true if the function should never be inlined into
|
/// NeverInline - returns true if the function should never be inlined into
|
||||||
/// any caller
|
/// any caller
|
||||||
bool InlineCostAnalyzer::FunctionInfo::NeverInline() {
|
bool InlineCostAnalyzer::FunctionInfo::NeverInline() {
|
||||||
return (Metrics.callsSetJmp || Metrics.isRecursive ||
|
return (Metrics.exposesReturnsTwice || Metrics.isRecursive ||
|
||||||
Metrics.containsIndirectBr);
|
Metrics.containsIndirectBr);
|
||||||
}
|
}
|
||||||
// getSpecializationBonus - The heuristic used to determine the per-call
|
// getSpecializationBonus - The heuristic used to determine the per-call
|
||||||
@ -634,7 +636,7 @@ InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) {
|
|||||||
|
|
||||||
// FIXME: If any of these three are true for the callee, the callee was
|
// FIXME: If any of these three are true for the callee, the callee was
|
||||||
// not inlined into the caller, so I think they're redundant here.
|
// not inlined into the caller, so I think they're redundant here.
|
||||||
CallerMetrics.callsSetJmp |= CalleeMetrics.callsSetJmp;
|
CallerMetrics.exposesReturnsTwice |= CalleeMetrics.exposesReturnsTwice;
|
||||||
CallerMetrics.isRecursive |= CalleeMetrics.isRecursive;
|
CallerMetrics.isRecursive |= CalleeMetrics.isRecursive;
|
||||||
CallerMetrics.containsIndirectBr |= CalleeMetrics.containsIndirectBr;
|
CallerMetrics.containsIndirectBr |= CalleeMetrics.containsIndirectBr;
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine if there is a call to setjmp in the machine function.
|
// Determine if there is a call to setjmp in the machine function.
|
||||||
MF->setCallsSetJmp(Fn.callsFunctionThatReturnsTwice());
|
MF->setExposesReturnsTwice(Fn.callsFunctionThatReturnsTwice());
|
||||||
|
|
||||||
// Replace forward-declared registers with the registers containing
|
// Replace forward-declared registers with the registers containing
|
||||||
// the desired value.
|
// the desired value.
|
||||||
|
@ -426,7 +426,7 @@ bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
// coloring. The stack could be modified before the longjmp is executed,
|
// coloring. The stack could be modified before the longjmp is executed,
|
||||||
// resulting in the wrong value being used afterwards. (See
|
// resulting in the wrong value being used afterwards. (See
|
||||||
// <rdar://problem/8007500>.)
|
// <rdar://problem/8007500>.)
|
||||||
if (MF.callsSetJmp())
|
if (MF.exposesReturnsTwice())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Gather spill slot references
|
// Gather spill slot references
|
||||||
|
41
test/Transforms/Inline/inline_returns_twice.ll
Normal file
41
test/Transforms/Inline/inline_returns_twice.ll
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
; RUN: opt < %s -inline -S | FileCheck %s
|
||||||
|
|
||||||
|
; Check that functions with "returns_twice" calls are only inlined,
|
||||||
|
; if they are themselve marked as such.
|
||||||
|
|
||||||
|
declare i32 @a() returns_twice
|
||||||
|
declare i32 @b() returns_twice
|
||||||
|
|
||||||
|
define i32 @f() {
|
||||||
|
entry:
|
||||||
|
%call = call i32 @a() returns_twice
|
||||||
|
%add = add nsw i32 1, %call
|
||||||
|
ret i32 %add
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @g() {
|
||||||
|
entry:
|
||||||
|
; CHECK: define i32 @g
|
||||||
|
; CHECK: call i32 @f()
|
||||||
|
; CHECK-NOT: call i32 @a()
|
||||||
|
%call = call i32 @f()
|
||||||
|
%add = add nsw i32 1, %call
|
||||||
|
ret i32 %add
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @h() returns_twice {
|
||||||
|
entry:
|
||||||
|
%call = call i32 @b() returns_twice
|
||||||
|
%add = add nsw i32 1, %call
|
||||||
|
ret i32 %add
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @i() {
|
||||||
|
entry:
|
||||||
|
; CHECK: define i32 @i
|
||||||
|
; CHECK: call i32 @b()
|
||||||
|
; CHECK-NOT: call i32 @h()
|
||||||
|
%call = call i32 @h() returns_twice
|
||||||
|
%add = add nsw i32 1, %call
|
||||||
|
ret i32 %add
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user