Index: llvm/trunk/include/llvm/Analysis/LibCallSemantics.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LibCallSemantics.h +++ llvm/trunk/include/llvm/Analysis/LibCallSemantics.h @@ -162,6 +162,21 @@ virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; }; + enum class EHPersonality { + Unknown, + GNU_Ada, + GNU_C, + GNU_CXX, + GNU_ObjC, + MSVC_Win64SEH, + MSVC_CXX, + }; + + /// ClassifyEHPersonality - See if the given exception handling personality + /// function is one that we understand. If so, return a description of it; + /// otherwise return Unknown_Personality. + EHPersonality ClassifyEHPersonality(Value *Pers); + } // end namespace llvm #endif Index: llvm/trunk/lib/Analysis/LibCallSemantics.cpp =================================================================== --- llvm/trunk/lib/Analysis/LibCallSemantics.cpp +++ llvm/trunk/lib/Analysis/LibCallSemantics.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/LibCallSemantics.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/IR/Function.h" using namespace llvm; @@ -61,3 +62,18 @@ return Map->lookup(F->getName()); } +/// 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) { + Function *F = dyn_cast(Pers->stripPointerCasts()); + if (!F) + return EHPersonality::Unknown; + return StringSwitch(F->getName()) + .Case("__gnat_eh_personality", EHPersonality::GNU_Ada) + .Case("__gxx_personality_v0", EHPersonality::GNU_CXX) + .Case("__gcc_personality_v0", EHPersonality::GNU_C) + .Case("__objc_personality_v0", EHPersonality::GNU_ObjC) + .Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH) + .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX) + .Default(EHPersonality::Unknown); +} Index: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -43,6 +43,7 @@ #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -2259,41 +2260,26 @@ return nullptr; } -enum Personality_Type { - Unknown_Personality, - GNU_Ada_Personality, - GNU_CXX_Personality, - GNU_ObjC_Personality -}; - -/// RecognizePersonality - See if the given exception handling personality -/// function is one that we understand. If so, return a description of it; -/// otherwise return Unknown_Personality. -static Personality_Type RecognizePersonality(Value *Pers) { - Function *F = dyn_cast(Pers->stripPointerCasts()); - if (!F) - return Unknown_Personality; - return StringSwitch(F->getName()) - .Case("__gnat_eh_personality", GNU_Ada_Personality) - .Case("__gxx_personality_v0", GNU_CXX_Personality) - .Case("__objc_personality_v0", GNU_ObjC_Personality) - .Default(Unknown_Personality); -} - /// isCatchAll - Return 'true' if the given typeinfo will match anything. -static bool isCatchAll(Personality_Type Personality, Constant *TypeInfo) { +static bool isCatchAll(EHPersonality Personality, Constant *TypeInfo) { switch (Personality) { - case Unknown_Personality: + case EHPersonality::GNU_C: + // The GCC C EH personality only exists to support cleanups, so it's not + // clear what the semantics of catch clauses are. + return false; + case EHPersonality::Unknown: return false; - case GNU_Ada_Personality: + case EHPersonality::GNU_Ada: // While __gnat_all_others_value will match any Ada exception, it doesn't // match foreign exceptions (or didn't, before gcc-4.7). return false; - case GNU_CXX_Personality: - case GNU_ObjC_Personality: + case EHPersonality::GNU_CXX: + case EHPersonality::GNU_ObjC: + case EHPersonality::MSVC_Win64SEH: + case EHPersonality::MSVC_CXX: return TypeInfo->isNullValue(); } - llvm_unreachable("Unknown personality!"); + llvm_unreachable("invalid enum"); } static bool shorter_filter(const Value *LHS, const Value *RHS) { @@ -2307,7 +2293,7 @@ // 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. - Personality_Type Personality = RecognizePersonality(LI.getPersonalityFn()); + EHPersonality Personality = ClassifyEHPersonality(LI.getPersonalityFn()); // Simplify the list of clauses, eg by removing repeated catch clauses // (these are often created by inlining). Index: llvm/trunk/test/Transforms/InstCombine/LandingPadClauses.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/LandingPadClauses.ll +++ llvm/trunk/test/Transforms/InstCombine/LandingPadClauses.ll @@ -7,6 +7,7 @@ declare i32 @generic_personality(i32, i64, i8*, i8*) declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*) declare i32 @__objc_personality_v0(i32, i64, i8*, i8*) +declare i32 @__C_specific_handler(...) declare void @bar() @@ -231,3 +232,54 @@ ; CHECK-NEXT: null ; CHECK-NEXT: unreachable } + +define void @foo_seh() { +; CHECK-LABEL: @foo_seh( + invoke void @bar() + to label %cont.a unwind label %lpad.a +cont.a: + invoke void @bar() + to label %cont.b unwind label %lpad.b +cont.b: + invoke void @bar() + to label %cont.c unwind label %lpad.c +cont.c: + invoke void @bar() + to label %cont.d unwind label %lpad.d +cont.d: + ret void + +lpad.a: + %a = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler + catch i32* null + catch i32* @T1 + unreachable +; CHECK: %a = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable + +lpad.b: + %b = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler + filter [1 x i32*] zeroinitializer + unreachable +; CHECK: %b = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.c: + %c = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler + filter [2 x i32*] [i32* @T1, i32* null] + unreachable +; CHECK: %c = landingpad +; CHECK-NEXT: cleanup +; CHECK-NEXT: unreachable + +lpad.d: + %d = landingpad { i8*, i32 } personality i32 (...)* @__C_specific_handler + cleanup + catch i32* null + unreachable +; CHECK: %d = landingpad +; CHECK-NEXT: null +; CHECK-NEXT: unreachable +}