llvm.org GIT mirror llvm / be22683
Dale and Evan suggested putting the "check for setjmp" much earlier in the machine code generation. That's a good idea, so I made it so. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@104655 91177308-0d34-0410-b5e6-96231b3b80d8 Bill Wendling 10 years ago
3 changed file(s) with 53 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
113113 ///
114114 unsigned FunctionNumber;
115115
116 /// The alignment of the function.
116 /// Alignment - The alignment of the function.
117117 unsigned Alignment;
118
119 /// HasReturnsTwiceCall - Returns true if there's a call with a
120 /// "returns_twice" attribute, like setjmp.
121 bool HasReturnsTwiceCall;
118122
119123 MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT
120124 void operator=(const MachineFunction&); // DO NOT IMPLEMENT
179183 /// EnsureAlignment - Make sure the function is at least 'A' bits aligned.
180184 void EnsureAlignment(unsigned A) {
181185 if (Alignment < A) Alignment = A;
186 }
187
188 /// hasReturnsTwiceCall - Returns true if there's a call with a
189 /// "returns_twice" attribute, like setjmp.
190 bool hasReturnsTwiceCall() const {
191 return HasReturnsTwiceCall;
192 }
193 void setReturnsTwiceCall(bool B) {
194 HasReturnsTwiceCall = B;
182195 }
183196
184197 /// getInfo - Keep track of various per-function pieces of information for
2424 #include "llvm/Intrinsics.h"
2525 #include "llvm/IntrinsicInst.h"
2626 #include "llvm/LLVMContext.h"
27 #include "llvm/Module.h"
2728 #include "llvm/CodeGen/FastISel.h"
2829 #include "llvm/CodeGen/GCStrategy.h"
2930 #include "llvm/CodeGen/GCMetadata.h"
250251 }
251252 }
252253 done:;
254 }
255
256 // Set a flag indicating if the machine function makes a call to setjmp /
257 // sigsetjmp (i.e., a function marked "returns_twice"). We'll use this to
258 // disable certain optimizations which cannot handle such control flows.
259 //
260 // FIXME: This goes beyond the setjmp/sigsetjmp functions. We should check for
261 // the GCC "returns twice" attribute.
262 const Module *M = Fn.getParent();
263 const Function *SetJmp = M->getFunction("setjmp");
264 const Function *SigSetJmp = M->getFunction("sigsetjmp");
265 bool HasReturnsTwiceCall = false;
266
267 if (SetJmp || SigSetJmp) {
268 if (SetJmp && !SetJmp->use_empty())
269 for (Value::const_use_iterator
270 I = SetJmp->use_begin(), E = SetJmp->use_end(); I != E; ++I)
271 if (const CallInst *CI = dyn_cast(I))
272 if (CI->getParent()->getParent() == &Fn) {
273 HasReturnsTwiceCall = true;
274 break;
275 }
276
277 if (!HasReturnsTwiceCall && SigSetJmp && !SigSetJmp->use_empty())
278 for (Value::const_use_iterator
279 I = SigSetJmp->use_begin(), E = SigSetJmp->use_end(); I != E; ++I)
280 if (const CallInst *CI = dyn_cast(I))
281 if (CI->getParent()->getParent() == &Fn) {
282 HasReturnsTwiceCall = true;
283 break;
284 }
285
286 mf.setReturnsTwiceCall(HasReturnsTwiceCall);
253287 }
254288
255289 // Release function-specific state. SDB and CurDAG are already cleared
117117
118118 private:
119119 void InitializeSlots();
120 bool CheckForSetJmpCall(const MachineFunction &MF) const;
121120 void ScanForSpillSlotRefs(MachineFunction &MF);
122121 bool OverlapWithAssignments(LiveInterval *li, int Color) const;
123122 int ColorSlot(LiveInterval *li);
159158 return LHS->weight > RHS->weight;
160159 }
161160 };
162 }
163
164 /// CheckForSetJmpCall - Return true if there's a call to setjmp/sigsetjmp in
165 /// this function.
166 bool StackSlotColoring::CheckForSetJmpCall(const MachineFunction &MF) const {
167 const Function *F = MF.getFunction();
168 const Module *M = F->getParent();
169 const Function *SetJmp = M->getFunction("setjmp");
170 const Function *SigSetJmp = M->getFunction("sigsetjmp");
171
172 if (!SetJmp && !SigSetJmp)
173 return false;
174
175 if (SetJmp && !SetJmp->use_empty())
176 for (Value::const_use_iterator
177 I = SetJmp->use_begin(), E = SetJmp->use_end(); I != E; ++I)
178 if (const CallInst *CI = dyn_cast(I))
179 if (CI->getParent()->getParent() == F)
180 return true;
181
182 if (SigSetJmp && !SigSetJmp->use_empty())
183 for (Value::const_use_iterator
184 I = SigSetJmp->use_begin(), E = SigSetJmp->use_end(); I != E; ++I)
185 if (const CallInst *CI = dyn_cast(I))
186 if (CI->getParent()->getParent() == F)
187 return true;
188
189 return false;
190161 }
191162
192163 /// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot
752723 return false;
753724 }
754725
755 // If there are calls to setjmp or sigsetjmp, don't perform stack slot
756 // coloring. The stack could be modified before the longjmp is executed,
757 // resulting in the wrong value being used afterwards. (See
758 // .)
759 //
760 // FIXME: This goes beyond the setjmp/sigsetjmp functions. Ideally, we should
761 // check for the GCC "returns twice" attribute.
762 if (CheckForSetJmpCall(MF))
726 // If there is a call to a function with the attribute "returns_twice" (like
727 // setjmp or sigsetjmp), don't perform stack slot coloring. The stack could be
728 // modified before the the second return, resulting in the wrong value being
729 // used afterwards. (See .)
730 if (MF.hasReturnsTwiceCall())
763731 return false;
764732
765733 // Gather spill slot references