summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-02-11 01:23:16 +0000
committerReid Kleckner <reid@kleckner.net>2015-02-11 01:23:16 +0000
commit96d011315aa01de179897eaf4e7baeddc5de1cda (patch)
treeccced202122ff25d6362be653140bfe079ab5925 /llvm/lib
parent58e985c2db3045f1416520212108f93c8c257b18 (diff)
downloadbcm5719-llvm-96d011315aa01de179897eaf4e7baeddc5de1cda.tar.gz
bcm5719-llvm-96d011315aa01de179897eaf4e7baeddc5de1cda.zip
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. llvm-svn: 228782
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/LibCallSemantics.cpp25
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp2
-rw-r--r--llvm/lib/Transforms/IPO/PruneEH.cpp4
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp3
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp3
5 files changed, 32 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/LibCallSemantics.cpp b/llvm/lib/Analysis/LibCallSemantics.cpp
index 3a345c45d07..6c2ebdb4594 100644
--- a/llvm/lib/Analysis/LibCallSemantics.cpp
+++ b/llvm/lib/Analysis/LibCallSemantics.cpp
@@ -64,7 +64,7 @@ LibCallInfo::getFunctionInfo(const Function *F) const {
/// See if the given exception handling personality function is one that we
/// understand. If so, return a description of it; otherwise return Unknown.
-EHPersonality llvm::ClassifyEHPersonality(Value *Pers) {
+EHPersonality llvm::classifyEHPersonality(Value *Pers) {
Function *F = dyn_cast<Function>(Pers->stripPointerCasts());
if (!F)
return EHPersonality::Unknown;
@@ -73,7 +73,30 @@ EHPersonality llvm::ClassifyEHPersonality(Value *Pers) {
.Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
.Case("__gcc_personality_v0", EHPersonality::GNU_C)
.Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
+ .Case("__except_handler3", EHPersonality::MSVC_X86SEH)
+ .Case("__except_handler4", EHPersonality::MSVC_X86SEH)
.Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH)
.Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
.Default(EHPersonality::Unknown);
}
+
+bool llvm::isAsynchronousEHPersonality(EHPersonality Pers) {
+ // The two SEH personality functions can catch asynch exceptions. We assume
+ // unknown personalities don't catch asynch exceptions.
+ switch (Pers) {
+ case EHPersonality::MSVC_X86SEH:
+ case EHPersonality::MSVC_Win64SEH:
+ return true;
+ default: return false;
+ }
+ llvm_unreachable("invalid enum");
+}
+
+bool llvm::canSimplifyInvokeNoUnwind(const InvokeInst *II) {
+ const LandingPadInst *LP = II->getLandingPadInst();
+ EHPersonality Personality = classifyEHPersonality(LP->getPersonalityFn());
+ // We can't simplify any invokes to nounwind functions if the personality
+ // function wants to catch asynch exceptions. The nounwind attribute only
+ // implies that the function does not throw synchronous exceptions.
+ return !isAsynchronousEHPersonality(Personality);
+}
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index c608bb0a31e..b4019b48617 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -75,7 +75,7 @@ bool WinEHPrepare::runOnFunction(Function &Fn) {
return false;
// Classify the personality to see what kind of preparation we need.
- EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());
+ EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn());
// Delegate through to the DWARF pass if this is unrecognized.
if (!isMSVCPersonality(Pers))
diff --git a/llvm/lib/Transforms/IPO/PruneEH.cpp b/llvm/lib/Transforms/IPO/PruneEH.cpp
index 7bd4ce12860..1943b930cbf 100644
--- a/llvm/lib/Transforms/IPO/PruneEH.cpp
+++ b/llvm/lib/Transforms/IPO/PruneEH.cpp
@@ -18,8 +18,10 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
@@ -175,7 +177,7 @@ bool PruneEH::SimplifyFunction(Function *F) {
bool MadeChange = false;
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()))
- if (II->doesNotThrow()) {
+ if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) {
SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
// Insert a call instruction before the invoke.
CallInst *Call = CallInst::Create(II->getCalledValue(), Args, "", II);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 3cfcc90a8ed..ffc8ff5b16c 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2275,6 +2275,7 @@ static bool isCatchAll(EHPersonality Personality, Constant *TypeInfo) {
return false;
case EHPersonality::GNU_CXX:
case EHPersonality::GNU_ObjC:
+ case EHPersonality::MSVC_X86SEH:
case EHPersonality::MSVC_Win64SEH:
case EHPersonality::MSVC_CXX:
return TypeInfo->isNullValue();
@@ -2293,7 +2294,7 @@ Instruction *InstCombiner::visitLandingPadInst(LandingPadInst &LI) {
// The logic here should be correct for any real-world personality function.
// However if that turns out not to be true, the offending logic can always
// be conditioned on the personality function, like the catch-all logic is.
- EHPersonality Personality = ClassifyEHPersonality(LI.getPersonalityFn());
+ EHPersonality Personality = classifyEHPersonality(LI.getPersonalityFn());
// Simplify the list of clauses, eg by removing repeated catch clauses
// (these are often created by inlining).
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index b8c0a7e47b5..48305684721 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -1260,7 +1261,7 @@ static bool markAliveBlocks(BasicBlock *BB,
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
changeToUnreachable(II, true);
Changed = true;
- } else if (II->doesNotThrow()) {
+ } else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(II)) {
if (II->use_empty() && II->onlyReadsMemory()) {
// jump to the normal destination branch.
BranchInst::Create(II->getNormalDest(), II);
OpenPOWER on IntegriCloud