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()));
; 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
+}
+