<div dir="ltr">Thanks!<div><br></div><div>I was recently playing around with a test case where this insertion of llvm.trap would inhibit optimization for some pass configurations.</div><div><br></div><div>For reference, it was a binary search routine that returned null in the "not found" case; but the result was unconditionally dereferenced so after inlining we could remove the `lo <= hi` check every time through the loop since that leads to "return NULL". Interestingly, this causes the actual behavior when the UB occurs to be an infloop instead of a segfault.</div><div>That's what happened in the original customer test case, but while reducing this I noticed that simplifycfg could ruin the optimization if run at the wrong time.<br></div><div><br></div><div>-- Sean Silva</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jun 25, 2016 at 1:04 AM, David Majnemer via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: majnemer<br>
Date: Sat Jun 25 03:04:19 2016<br>
New Revision: 273778<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=273778&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=273778&view=rev</a><br>
Log:<br>
[SimplifyCFG] Stop inserting calls to llvm.trap for UB<br>
<br>
SimplifyCFG had logic to insert calls to llvm.trap for two very<br>
particular IR patterns: stores and invokes of undef/null.<br>
<br>
While InstCombine canonicalizes certain undefined behavior IR patterns<br>
to stores of undef, phase ordering means that this cannot be relied upon<br>
in general.<br>
<br>
There are much better tools than llvm.trap: UBSan and ASan.<br>
<br>
N.B. I could be argued into reverting this change if a clear argument as<br>
to why it is important that we synthesize llvm.trap for stores, I'd be<br>
hard pressed to see why it'd be useful for invokes...<br>
<br>
Removed:<br>
llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll<br>
Modified:<br>
llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
llvm/trunk/lib/CodeGen/WinEHPrepare.cpp<br>
llvm/trunk/lib/Transforms/IPO/PruneEH.cpp<br>
llvm/trunk/lib/Transforms/Scalar/SCCP.cpp<br>
llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp<br>
llvm/trunk/lib/Transforms/Utils/Local.cpp<br>
llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp<br>
llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll<br>
llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/Local.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/Local.h?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/Local.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/Local.h Sat Jun 25 03:04:19 2016<br>
@@ -296,7 +296,7 @@ unsigned removeAllNonTerminatorAndEHPadI<br>
<br>
/// Insert an unreachable instruction before the specified<br>
/// instruction, making it and the rest of the code in the block dead.<br>
-unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap);<br>
+unsigned changeToUnreachable(Instruction *I);<br>
<br>
/// Replace 'BB's terminator with one that does not have an unwind successor<br>
/// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind<br>
<br>
Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Sat Jun 25 03:04:19 2016<br>
@@ -963,9 +963,9 @@ void WinEHPrepare::removeImplausibleInst<br>
BasicBlock::iterator CallI =<br>
std::prev(BB->getTerminator()->getIterator());<br>
auto *CI = cast<CallInst>(&*CallI);<br>
- changeToUnreachable(CI, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(CI);<br>
} else {<br>
- changeToUnreachable(&I, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(&I);<br>
}<br>
<br>
// There are no more instructions in the block (except for unreachable),<br>
@@ -986,7 +986,7 @@ void WinEHPrepare::removeImplausibleInst<br>
IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;<br>
if (IsUnreachableRet || IsUnreachableCatchret ||<br>
IsUnreachableCleanupret) {<br>
- changeToUnreachable(TI, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(TI);<br>
} else if (isa<InvokeInst>(TI)) {<br>
if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {<br>
// Invokes within a cleanuppad for the MSVC++ personality never<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/PruneEH.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PruneEH.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PruneEH.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/PruneEH.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/PruneEH.cpp Sat Jun 25 03:04:19 2016<br>
@@ -258,7 +258,7 @@ void PruneEH::DeleteBasicBlock(BasicBloc<br>
<br>
if (TokenInst) {<br>
if (!isa<TerminatorInst>(TokenInst))<br>
- changeToUnreachable(TokenInst->getNextNode(), /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(TokenInst->getNextNode());<br>
} else {<br>
// Get the list of successors of this block.<br>
std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Sat Jun 25 03:04:19 2016<br>
@@ -1802,8 +1802,7 @@ static bool runIPSCCP(Module &M, const D<br>
DEBUG(dbgs() << " BasicBlock Dead:" << *BB);<br>
<br>
++NumDeadBlocks;<br>
- NumInstRemoved +=<br>
- changeToUnreachable(BB->getFirstNonPHI(), /*UseLLVMTrap=*/false);<br>
+ NumInstRemoved += changeToUnreachable(BB->getFirstNonPHI());<br>
<br>
MadeChanges = true;<br>
<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sat Jun 25 03:04:19 2016<br>
@@ -1833,7 +1833,7 @@ bool llvm::InlineFunction(CallSite CS, I<br>
// As such, we replace the cleanupret with unreachable.<br>
if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(BB->getTerminator()))<br>
if (CleanupRet->unwindsToCaller() && EHPadForCallUnwindsLocally)<br>
- changeToUnreachable(CleanupRet, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(CleanupRet);<br>
<br>
Instruction *I = BB->getFirstNonPHI();<br>
if (!I->isEHPad())<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Sat Jun 25 03:04:19 2016<br>
@@ -42,11 +42,13 @@<br>
#include "llvm/IR/MDBuilder.h"<br>
#include "llvm/IR/Metadata.h"<br>
#include "llvm/IR/Operator.h"<br>
+#include "llvm/IR/PatternMatch.h"<br>
#include "llvm/IR/ValueHandle.h"<br>
#include "llvm/Support/Debug.h"<br>
#include "llvm/Support/MathExtras.h"<br>
#include "llvm/Support/raw_ostream.h"<br>
using namespace llvm;<br>
+using namespace llvm::PatternMatch;<br>
<br>
#define DEBUG_TYPE "local"<br>
<br>
@@ -1310,21 +1312,13 @@ unsigned llvm::removeAllNonTerminatorAnd<br>
return NumDeadInst;<br>
}<br>
<br>
-unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {<br>
+unsigned llvm::changeToUnreachable(Instruction *I) {<br>
BasicBlock *BB = I->getParent();<br>
// Loop over all of the successors, removing BB's entry from any PHI<br>
// nodes.<br>
- for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)<br>
- (*SI)->removePredecessor(BB);<br>
+ for (BasicBlock *Succ : successors(BB))<br>
+ Succ->removePredecessor(BB);<br>
<br>
- // Insert a call to llvm.trap right before this. This turns the undefined<br>
- // behavior into a hard fail instead of falling through into random code.<br>
- if (UseLLVMTrap) {<br>
- Function *TrapFn =<br>
- Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);<br>
- CallInst *CallTrap = CallInst::Create(TrapFn, "", I);<br>
- CallTrap->setDebugLoc(I->getDebugLoc());<br>
- }<br>
new UnreachableInst(I->getContext(), I);<br>
<br>
// All instructions after this are dead.<br>
@@ -1374,22 +1368,14 @@ static bool markAliveBlocks(Function &F,<br>
// Do a quick scan of the basic block, turning any obviously unreachable<br>
// instructions into LLVM unreachable insts. The instruction combining pass<br>
// canonicalizes unreachable insts into stores to null or undef.<br>
- for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){<br>
+ for (Instruction &I : *BB) {<br>
// Assumptions that are known to be false are equivalent to unreachable.<br>
// Also, if the condition is undefined, then we make the choice most<br>
// beneficial to the optimizer, and choose that to also be unreachable.<br>
- if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI)) {<br>
+ if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {<br>
if (II->getIntrinsicID() == Intrinsic::assume) {<br>
- bool MakeUnreachable = false;<br>
- if (isa<UndefValue>(II->getArgOperand(0)))<br>
- MakeUnreachable = true;<br>
- else if (ConstantInt *Cond =<br>
- dyn_cast<ConstantInt>(II->getArgOperand(0)))<br>
- MakeUnreachable = Cond->isZero();<br>
-<br>
- if (MakeUnreachable) {<br>
- // Don't insert a call to llvm.trap right before the unreachable.<br>
- changeToUnreachable(&*BBI, false);<br>
+ if (match(II->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) {<br>
+ changeToUnreachable(II);<br>
Changed = true;<br>
break;<br>
}<br>
@@ -1404,19 +1390,19 @@ static bool markAliveBlocks(Function &F,<br>
// Note: unlike in llvm.assume, it is not "obviously profitable" for<br>
// guards to treat `undef` as `false` since a guard on `undef` can<br>
// still be useful for widening.<br>
- if (auto *CI = dyn_cast<ConstantInt>(II->getArgOperand(0)))<br>
- if (CI->isZero() && !isa<UnreachableInst>(II->getNextNode())) {<br>
- changeToUnreachable(II->getNextNode(), /*UseLLVMTrap=*/ false);<br>
+ if (match(II->getArgOperand(0), m_Zero()))<br>
+ if (!isa<UnreachableInst>(II->getNextNode())) {<br>
+ changeToUnreachable(II->getNextNode());<br>
Changed = true;<br>
break;<br>
}<br>
}<br>
}<br>
<br>
- if (CallInst *CI = dyn_cast<CallInst>(BBI)) {<br>
+ if (auto *CI = dyn_cast<CallInst>(&I)) {<br>
Value *Callee = CI->getCalledValue();<br>
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {<br>
- changeToUnreachable(CI, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(CI);<br>
Changed = true;<br>
break;<br>
}<br>
@@ -1424,10 +1410,8 @@ static bool markAliveBlocks(Function &F,<br>
// If we found a call to a no-return function, insert an unreachable<br>
// instruction after it. Make sure there isn't *already* one there<br>
// though.<br>
- ++BBI;<br>
- if (!isa<UnreachableInst>(BBI)) {<br>
- // Don't insert a call to llvm.trap right before the unreachable.<br>
- changeToUnreachable(&*BBI, false);<br>
+ if (!isa<UnreachableInst>(CI->getNextNode())) {<br>
+ changeToUnreachable(CI->getNextNode());<br>
Changed = true;<br>
}<br>
break;<br>
@@ -1437,7 +1421,7 @@ static bool markAliveBlocks(Function &F,<br>
// Store to undef and store to null are undefined and used to signal that<br>
// they should be changed to unreachable by passes that can't modify the<br>
// CFG.<br>
- if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {<br>
+ if (auto *SI = dyn_cast<StoreInst>(&I)) {<br>
// Don't touch volatile stores.<br>
if (SI->isVolatile()) continue;<br>
<br>
@@ -1446,7 +1430,7 @@ static bool markAliveBlocks(Function &F,<br>
if (isa<UndefValue>(Ptr) ||<br>
(isa<ConstantPointerNull>(Ptr) &&<br>
SI->getPointerAddressSpace() == 0)) {<br>
- changeToUnreachable(SI, true);<br>
+ changeToUnreachable(SI);<br>
Changed = true;<br>
break;<br>
}<br>
@@ -1458,7 +1442,7 @@ static bool markAliveBlocks(Function &F,<br>
// Turn invokes that call 'nounwind' functions into ordinary calls.<br>
Value *Callee = II->getCalledValue();<br>
if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {<br>
- changeToUnreachable(II, true);<br>
+ changeToUnreachable(II);<br>
Changed = true;<br>
} else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {<br>
if (II->use_empty() && II->onlyReadsMemory()) {<br>
@@ -1511,9 +1495,9 @@ static bool markAliveBlocks(Function &F,<br>
}<br>
<br>
Changed |= ConstantFoldTerminator(BB, true);<br>
- for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)<br>
- if (Reachable.insert(*SI).second)<br>
- Worklist.push_back(*SI);<br>
+ for (BasicBlock *Succ : successors(BB))<br>
+ if (Reachable.insert(Succ).second)<br>
+ Worklist.push_back(Succ);<br>
} while (!Worklist.empty());<br>
return Changed;<br>
}<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Sat Jun 25 03:04:19 2016<br>
@@ -491,7 +491,7 @@ ReprocessLoop:<br>
<br>
// Zap the dead pred's terminator and replace it with unreachable.<br>
TerminatorInst *TI = P->getTerminator();<br>
- changeToUnreachable(TI, /*UseLLVMTrap=*/false);<br>
+ changeToUnreachable(TI);<br>
Changed = true;<br>
}<br>
}<br>
<br>
Modified: llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/invoke.ll Sat Jun 25 03:04:19 2016<br>
@@ -12,7 +12,6 @@ declare i32 @fn()<br>
; CHECK-LABEL: @f1(<br>
define i8* @f1() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
entry:<br>
-; CHECK: call void @llvm.trap()<br>
; CHECK: unreachable<br>
%call = invoke noalias i8* undef()<br>
to label %invoke.cont unwind label %lpad<br>
@@ -31,7 +30,6 @@ lpad:<br>
; CHECK-LABEL: @f2(<br>
define i8* @f2() nounwind uwtable ssp personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
entry:<br>
-; CHECK: call void @llvm.trap()<br>
; CHECK: unreachable<br>
%call = invoke noalias i8* null()<br>
to label %invoke.cont unwind label %lpad<br>
<br>
Removed: llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll?rev=273777&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll?rev=273777&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/trap-debugloc.ll (removed)<br>
@@ -1,22 +0,0 @@<br>
-; RUN: opt -S -simplifycfg < %s | FileCheck %s<br>
-; Radar 9342286<br>
-; Assign DebugLoc to trap instruction.<br>
-define void @foo() nounwind ssp !dbg !0 {<br>
-; CHECK: call void @llvm.trap(), !dbg<br>
- store i32 42, i32* null, !dbg !5<br>
- ret void, !dbg !7<br>
-}<br>
-<br>
-!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!2}<br>
-!llvm.module.flags = !{!10}<br>
-<br>
-!0 = distinct !DISubprogram(name: "foo", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: false, unit: !2, file: !8, scope: !1, type: !3)<br>
-!1 = !DIFile(filename: "foo.c", directory: "/private/tmp")<br>
-!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "Apple clang version 3.0 (tags/Apple/clang-206.1) (based on LLVM 3.0svn)", isOptimized: true, emissionKind: FullDebug, file: !8, enums: !{}, retainedTypes: !{})<br>
-!3 = !DISubroutineType(types: !4)<br>
-!4 = !{null}<br>
-!5 = !DILocation(line: 4, column: 2, scope: !6)<br>
-!6 = distinct !DILexicalBlock(line: 3, column: 12, file: !8, scope: !0)<br>
-!7 = !DILocation(line: 5, column: 1, scope: !6)<br>
-!8 = !DIFile(filename: "foo.c", directory: "/private/tmp")<br>
-!10 = !{i32 1, !"Debug Info Version", i32 3}<br>
<br>
Modified: llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll?rev=273778&r1=273777&r2=273778&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll?rev=273778&r1=273777&r2=273778&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll Sat Jun 25 03:04:19 2016<br>
@@ -28,7 +28,6 @@ entry:<br>
ret void<br>
<br>
; CHECK-LABEL: @test2(<br>
-; CHECK: call void @llvm.trap<br>
; CHECK: unreachable<br>
}<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>