llvm.org GIT mirror llvm / 690248b
Don't promote asynch EH invokes of nounwind functions to calls If the landingpad of the invoke is using a personality function that catches asynch exceptions, then it can catch a trap. Also add some landingpads to invalid LLVM IR test cases that lack them. Over-the-shoulder reviewed by David Majnemer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228782 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
13 changed file(s) with 150 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
12351235 normally. This produces undefined behavior at runtime if the
12361236 function ever does dynamically return.
12371237 ``nounwind``
1238 This function attribute indicates that the function never returns
1239 with an unwind or exceptional control flow. If the function does
1240 unwind, its runtime behavior is undefined.
1238 This function attribute indicates that the function never raises an
1239 exception. If the function does raise an exception, its runtime
1240 behavior is undefined. However, functions marked nounwind may still
1241 trap or generate asynchronous exceptions. Exception handling schemes
1242 that are recognized by LLVM to handle asynchronous exceptions, such
1243 as SEH, will still provide their implementation defined semantics.
12411244 ``optnone``
12421245 This function attribute indicates that the function is not optimized
12431246 by any optimization or code generator passes with the
1717 #include "llvm/Analysis/AliasAnalysis.h"
1818
1919 namespace llvm {
20 class InvokeInst;
2021
2122 /// LibCallLocationInfo - This struct describes a set of memory locations that
2223 /// are accessed by libcalls. Identification of a location is doing with a
167168 GNU_C,
168169 GNU_CXX,
169170 GNU_ObjC,
171 MSVC_X86SEH,
170172 MSVC_Win64SEH,
171173 MSVC_CXX,
172174 };
173175
174 /// ClassifyEHPersonality - See if the given exception handling personality
175 /// function is one that we understand. If so, return a description of it;
176 /// otherwise return Unknown_Personality.
177 EHPersonality ClassifyEHPersonality(Value *Pers);
176 /// \brief See if the given exception handling personality function is one
177 /// that we understand. If so, return a description of it; otherwise return
178 /// Unknown.
179 EHPersonality classifyEHPersonality(Value *Pers);
180
181 /// \brief Returns true if this personality function catches asynchronous
182 /// exceptions.
183 bool isAsynchronousEHPersonality(EHPersonality Pers);
184
185 bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
178186
179187 } // end namespace llvm
180188
6363
6464 /// See if the given exception handling personality function is one that we
6565 /// understand. If so, return a description of it; otherwise return Unknown.
66 EHPersonality llvm::ClassifyEHPersonality(Value *Pers) {
66 EHPersonality llvm::classifyEHPersonality(Value *Pers) {
6767 Function *F = dyn_cast(Pers->stripPointerCasts());
6868 if (!F)
6969 return EHPersonality::Unknown;
7272 .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
7373 .Case("__gcc_personality_v0", EHPersonality::GNU_C)
7474 .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
75 .Case("__except_handler3", EHPersonality::MSVC_X86SEH)
76 .Case("__except_handler4", EHPersonality::MSVC_X86SEH)
7577 .Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH)
7678 .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
7779 .Default(EHPersonality::Unknown);
7880 }
81
82 bool llvm::isAsynchronousEHPersonality(EHPersonality Pers) {
83 // The two SEH personality functions can catch asynch exceptions. We assume
84 // unknown personalities don't catch asynch exceptions.
85 switch (Pers) {
86 case EHPersonality::MSVC_X86SEH:
87 case EHPersonality::MSVC_Win64SEH:
88 return true;
89 default: return false;
90 }
91 llvm_unreachable("invalid enum");
92 }
93
94 bool llvm::canSimplifyInvokeNoUnwind(const InvokeInst *II) {
95 const LandingPadInst *LP = II->getLandingPadInst();
96 EHPersonality Personality = classifyEHPersonality(LP->getPersonalityFn());
97 // We can't simplify any invokes to nounwind functions if the personality
98 // function wants to catch asynch exceptions. The nounwind attribute only
99 // implies that the function does not throw synchronous exceptions.
100 return !isAsynchronousEHPersonality(Personality);
101 }
7474 return false;
7575
7676 // Classify the personality to see what kind of preparation we need.
77 EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());
77 EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn());
7878
7979 // Delegate through to the DWARF pass if this is unrecognized.
8080 if (!isMSVCPersonality(Pers))
1717 #include "llvm/ADT/SmallPtrSet.h"
1818 #include "llvm/ADT/SmallVector.h"
1919 #include "llvm/ADT/Statistic.h"
20 #include "llvm/Support/raw_ostream.h"
2021 #include "llvm/Analysis/CallGraph.h"
2122 #include "llvm/Analysis/CallGraphSCCPass.h"
23 #include "llvm/Analysis/LibCallSemantics.h"
2224 #include "llvm/IR/CFG.h"
2325 #include "llvm/IR/Constants.h"
2426 #include "llvm/IR/Function.h"
174176 bool MadeChange = false;
175177 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
176178 if (InvokeInst *II = dyn_cast(BB->getTerminator()))
177 if (II->doesNotThrow()) {
179 if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) {
178180 SmallVector Args(II->op_begin(), II->op_end() - 3);
179181 // Insert a call instruction before the invoke.
180182 CallInst *Call = CallInst::Create(II->getCalledValue(), Args, "", II);
22742274 return false;
22752275 case EHPersonality::GNU_CXX:
22762276 case EHPersonality::GNU_ObjC:
2277 case EHPersonality::MSVC_X86SEH:
22772278 case EHPersonality::MSVC_Win64SEH:
22782279 case EHPersonality::MSVC_CXX:
22792280 return TypeInfo->isNullValue();
22922293 // The logic here should be correct for any real-world personality function.
22932294 // However if that turns out not to be true, the offending logic can always
22942295 // be conditioned on the personality function, like the catch-all logic is.
2295 EHPersonality Personality = ClassifyEHPersonality(LI.getPersonalityFn());
2296 EHPersonality Personality = classifyEHPersonality(LI.getPersonalityFn());
22962297
22972298 // Simplify the list of clauses, eg by removing repeated catch clauses
22982299 // (these are often created by inlining).
1616 #include "llvm/ADT/STLExtras.h"
1717 #include "llvm/ADT/SmallPtrSet.h"
1818 #include "llvm/ADT/Statistic.h"
19 #include "llvm/Analysis/LibCallSemantics.h"
1920 #include "llvm/Analysis/InstructionSimplify.h"
2021 #include "llvm/Analysis/MemoryBuiltins.h"
2122 #include "llvm/Analysis/ValueTracking.h"
12591260 if (isa(Callee) || isa(Callee)) {
12601261 changeToUnreachable(II, true);
12611262 Changed = true;
1262 } else if (II->doesNotThrow()) {
1263 } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) {
12631264 if (II->use_empty() && II->onlyReadsMemory()) {
12641265 // jump to the normal destination branch.
12651266 BranchInst::Create(II->getNormalDest(), II);
0 ; RUN: opt -S -O2 < %s | FileCheck %s
1
2 ; Feature test that verifies that all optimizations leave asynch personality
3 ; invokes of nounwind functions alone.
4 ; The @div function in this test can fault, even though it can't
5 ; throw a synchronous exception.
6
7 define i32 @div(i32 %n, i32 %d) nounwind noinline {
8 entry:
9 %div = sdiv i32 %n, %d
10 ret i32 %div
11 }
12
13 define i32 @main() nounwind {
14 entry:
15 %call = invoke i32 @div(i32 10, i32 0)
16 to label %__try.cont unwind label %lpad
17
18 lpad:
19 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
20 catch i8* null
21 br label %__try.cont
22
23 __try.cont:
24 %retval.0 = phi i32 [ %call, %entry ], [ 0, %lpad ]
25 ret i32 %retval.0
26 }
27
28 ; CHECK-LABEL: define i32 @main()
29 ; CHECK: invoke i32 @div(i32 10, i32 0)
30
31 declare i32 @__C_specific_handler(...)
66 ret void
77
88 lpad1:
9 landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
10 cleanup
911 invoke void @f4()
1012 to label %ok2 unwind label %lpad2
1113
+0
-15
test/Transforms/PruneEH/2003-11-21-PHIUpdate.ll less more
None ; RUN: opt < %s -prune-eh -disable-output
1
2 define internal void @callee() {
3 ret void
4 }
5
6 define i32 @caller() {
7 ;
8 invoke void @callee( )
9 to label %E unwind label %E
10 E: ; preds = %0, %0
11 %X = phi i32 [ 0, %0 ], [ 0, %0 ] ; [#uses=1]
12 ret i32 %X
13 }
14
0 ; RUN: opt -S -prune-eh < %s | FileCheck %s
1
2 ; Don't remove invokes of nounwind functions if the personality handles async
3 ; exceptions. The @div function in this test can fault, even though it can't
4 ; throw a synchronous exception.
5
6 define i32 @div(i32 %n, i32 %d) nounwind {
7 entry:
8 %div = sdiv i32 %n, %d
9 ret i32 %div
10 }
11
12 define i32 @main() nounwind {
13 entry:
14 %call = invoke i32 @div(i32 10, i32 0)
15 to label %__try.cont unwind label %lpad
16
17 lpad:
18 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
19 catch i8* null
20 br label %__try.cont
21
22 __try.cont:
23 %retval.0 = phi i32 [ %call, %entry ], [ 0, %lpad ]
24 ret i32 %retval.0
25 }
26
27 ; CHECK-LABEL: define i32 @main()
28 ; CHECK: invoke i32 @div(i32 10, i32 0)
29
30 declare i32 @__C_specific_handler(...)
1111 ret i32 0
1212
1313 Other: ; preds = %0
14 landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
15 catch i8* null
1416 ret i32 1
1517 }
18
19 declare i32 @__gxx_personality_v0(...)
0 ; RUN: opt -S -simplifycfg < %s | FileCheck %s
1
2 ; Don't remove invokes of nounwind functions if the personality handles async
3 ; exceptions. The @div function in this test can fault, even though it can't
4 ; throw a synchronous exception.
5
6 define i32 @div(i32 %n, i32 %d) nounwind {
7 entry:
8 %div = sdiv i32 %n, %d
9 ret i32 %div
10 }
11
12 define i32 @main() nounwind {
13 entry:
14 %call = invoke i32 @div(i32 10, i32 0)
15 to label %__try.cont unwind label %lpad
16
17 lpad:
18 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
19 catch i8* null
20 br label %__try.cont
21
22 __try.cont:
23 %retval.0 = phi i32 [ %call, %entry ], [ 0, %lpad ]
24 ret i32 %retval.0
25 }
26
27 ; CHECK-LABEL: define i32 @main()
28 ; CHECK: invoke i32 @div(i32 10, i32 0)
29
30 declare i32 @__C_specific_handler(...)