diff options
-rw-r--r-- | lib/Transforms/Utils/SimplifyCFG.cpp | 36 | ||||
-rw-r--r-- | test/Transforms/SimplifyCFG/trapping-load-unreachable.ll | 43 |
2 files changed, 69 insertions, 10 deletions
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 52145b9..850ee49 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -2244,18 +2244,34 @@ bool SimplifyCFGOpt::SimplifyUnreachable(UnreachableInst *UI) { while (UI != BB->begin()) { BasicBlock::iterator BBI = UI; --BBI; - // Do not delete instructions that can have side effects, like calls - // (which may never return) and volatile loads and stores. + // Do not delete instructions that can have side effects which might cause + // the unreachable to not be reachable; specifically, calls and volatile + // operations may have this effect. if (isa<CallInst>(BBI) && !isa<DbgInfoIntrinsic>(BBI)) break; - - if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) - if (SI->isVolatile()) - break; - - if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) - if (LI->isVolatile()) + + if (BBI->mayHaveSideEffects()) { + if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) { + if (SI->isVolatile()) + break; + } else if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) { + if (LI->isVolatile()) + break; + } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(BBI)) { + if (RMWI->isVolatile()) + break; + } else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(BBI)) { + if (CXI->isVolatile()) + break; + } else if (!isa<FenceInst>(BBI) && !isa<VAArgInst>(BBI) && + !isa<LandingPadInst>(BBI)) { break; - + } + // Note that deleting LandingPad's here is in fact okay, although it + // involves a bit of subtle reasoning. If this inst is a LandingPad, + // all the predecessors of this block will be the unwind edges of Invokes, + // and we can therefore guaranteed this block will be erased. + } + // Delete this instruction (any uses are guaranteed to be dead) if (!BBI->use_empty()) BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); diff --git a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll index ebf4f17..10d6981 100644 --- a/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll +++ b/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll @@ -42,3 +42,46 @@ entry: ; CHECK: store volatile i32 4, i32* null ; CHECK: ret } + +; Check store before unreachable. +define void @test4(i1 %C, i32* %P) { +; CHECK: @test4 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + store volatile i32 0, i32* %P + unreachable +F: + ret void +} + +; Check cmpxchg before unreachable. +define void @test5(i1 %C, i32* %P) { +; CHECK: @test5 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + cmpxchg volatile i32* %P, i32 0, i32 1 seq_cst + unreachable +F: + ret void +} + +; Check atomicrmw before unreachable. +define void @test6(i1 %C, i32* %P) { +; CHECK: @test6 +; CHECK: entry: +; CHECK-NEXT: br i1 %C +entry: + br i1 %C, label %T, label %F +T: + atomicrmw volatile xchg i32* %P, i32 0 seq_cst + unreachable +F: + ret void +} + |