diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 595872ad2d7..409d13ee3fc 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -114,9 +114,14 @@ class MachineFunction { /// unsigned FunctionNumber; - /// The alignment of the function. + /// Alignment - The alignment of the function. unsigned Alignment; + /// CallsSetJmp - True if the function calls setjmp or sigsetjmp. This is used + /// to limit optimizations which cannot reason about the control flow of + /// setjmp. + bool CallsSetJmp; + MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT void operator=(const MachineFunction&); // DO NOT IMPLEMENT public: @@ -181,6 +186,17 @@ public: void EnsureAlignment(unsigned A) { if (Alignment < A) Alignment = A; } + + /// callsSetJmp - Returns true if the function calls setjmp or sigsetjmp. + bool callsSetJmp() const { + return CallsSetJmp; + } + + /// setCallsSetJmp - Set a flag that indicates if there's a call to setjmp or + /// sigsetjmp. + void setCallsSetJmp(bool B) { + CallsSetJmp = B; + } /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 6d789a674cf..fc830ac2482 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -25,6 +25,7 @@ #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" +#include "llvm/Module.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/GCMetadata.h" @@ -191,6 +192,34 @@ void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } +/// FunctionCallsSetJmp - Return true if the function has a call to setjmp or +/// sigsetjmp. This is used to limit code-gen optimizations on the machine +/// function. +static bool FunctionCallsSetJmp(const Function *F) { + const Module *M = F->getParent(); + const Function *SetJmp = M->getFunction("setjmp"); + const Function *SigSetJmp = M->getFunction("sigsetjmp"); + + if (!SetJmp && !SigSetJmp) + return false; + + if (SetJmp && !SetJmp->use_empty()) + for (Value::const_use_iterator + I = SetJmp->use_begin(), E = SetJmp->use_end(); I != E; ++I) + if (const CallInst *CI = dyn_cast(I)) + if (CI->getParent()->getParent() == F) + return true; + + if (SigSetJmp && !SigSetJmp->use_empty()) + for (Value::const_use_iterator + I = SigSetJmp->use_begin(), E = SigSetJmp->use_end(); I != E; ++I) + if (const CallInst *CI = dyn_cast(I)) + if (CI->getParent()->getParent() == F) + return true; + + return false; +} + bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // Do some sanity-checking on the command-line options. assert((!EnableFastISelVerbose || EnableFastISel) && @@ -253,6 +282,9 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { done:; } + // Determine if there is a call to setjmp in the machine function. + MF->setCallsSetJmp(FunctionCallsSetJmp(&Fn)); + // Release function-specific state. SDB and CurDAG are already cleared // at this point. FuncInfo->clear(); diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp index 80435563498..7f3b452f0a5 100644 --- a/lib/CodeGen/StackSlotColoring.cpp +++ b/lib/CodeGen/StackSlotColoring.cpp @@ -162,34 +162,6 @@ namespace { }; } -/// CheckForSetJmpCall - Return true if there's a call to setjmp/sigsetjmp in -/// this function. -bool StackSlotColoring::CheckForSetJmpCall(const MachineFunction &MF) const { - const Function *F = MF.getFunction(); - const Module *M = F->getParent(); - const Function *SetJmp = M->getFunction("setjmp"); - const Function *SigSetJmp = M->getFunction("sigsetjmp"); - - if (!SetJmp && !SigSetJmp) - return false; - - if (SetJmp && !SetJmp->use_empty()) - for (Value::const_use_iterator - I = SetJmp->use_begin(), E = SetJmp->use_end(); I != E; ++I) - if (const CallInst *CI = dyn_cast(I)) - if (CI->getParent()->getParent() == F) - return true; - - if (SigSetJmp && !SigSetJmp->use_empty()) - for (Value::const_use_iterator - I = SigSetJmp->use_begin(), E = SigSetJmp->use_end(); I != E; ++I) - if (const CallInst *CI = dyn_cast(I)) - if (CI->getParent()->getParent() == F) - return true; - - return false; -} - /// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot /// references and update spill slot weights. void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) { @@ -757,10 +729,7 @@ bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { // coloring. The stack could be modified before the longjmp is executed, // resulting in the wrong value being used afterwards. (See // .) - // - // FIXME: This goes beyond the setjmp/sigsetjmp functions. Ideally, we should - // check for the GCC "returns twice" attribute. - if (CheckForSetJmpCall(MF)) + if (MF.callsSetJmp()) return false; // Gather spill slot references