| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=dse -S %s | FileCheck %s |
| |
| target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" |
| |
| ; Make sure we do not crash when we encounter unreachable blocks while checking |
| ; if all paths to DomAccess go through a killing block. |
| define void @test(ptr %ptr, i1 %c.1, i1 %c.2, i1 %c.3) { |
| ; CHECK-LABEL: @test( |
| ; CHECK-NEXT: bb: |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[BB27:%.*]], label [[BB53:%.*]] |
| ; CHECK: bb10: |
| ; CHECK-NEXT: br label [[BB43:%.*]] |
| ; CHECK: bb22: |
| ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[BB22:%.*]], label [[BB53]] |
| ; CHECK: bb27: |
| ; CHECK-NEXT: br i1 [[C_3:%.*]], label [[BB38:%.*]], label [[BB39:%.*]] |
| ; CHECK: bb38: |
| ; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR:%.*]], align 4 |
| ; CHECK-NEXT: br label [[BB38]] |
| ; CHECK: bb39: |
| ; CHECK-NEXT: br i1 [[C_2]], label [[BB43]], label [[BB38]] |
| ; CHECK: bb43: |
| ; CHECK-NEXT: store float 0.000000e+00, ptr [[PTR]], align 4 |
| ; CHECK-NEXT: br label [[BB50:%.*]] |
| ; CHECK: bb50: |
| ; CHECK-NEXT: br i1 [[C_3]], label [[BB27]], label [[BB53]] |
| ; CHECK: bb53: |
| ; CHECK-NEXT: br label [[BB53]] |
| ; |
| bb: |
| br i1 %c.1, label %bb27, label %bb53 |
| |
| bb10: ; No predecessors! |
| br label %bb43 |
| |
| bb22: ; preds = %bb22 |
| br i1 %c.2, label %bb22, label %bb53 |
| |
| bb27: ; preds = %bb50, %bb |
| br i1 %c.3, label %bb38, label %bb39 |
| |
| bb38: ; preds = %bb39, %bb38, %bb27 |
| store float 0.000000e+00, ptr %ptr, align 4 |
| br label %bb38 |
| |
| bb39: ; preds = %bb27 |
| br i1 %c.2, label %bb43, label %bb38 |
| |
| bb43: ; preds = %bb39, %bb10 |
| store float 0.000000e+00, ptr %ptr, align 4 |
| br label %bb50 |
| |
| bb50: ; preds = %bb43 |
| br i1 %c.3, label %bb27, label %bb53 |
| |
| bb53: ; preds = %bb53, %bb50, %bb22, %bb |
| br label %bb53 |
| } |
| |
| declare void @exit() |
| |
| define void @unreachable_exit_with_no_call(ptr noalias %ptr, i1 %c.1) { |
| ; CHECK-LABEL: @unreachable_exit_with_no_call( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: unreachable |
| ; CHECK: if.end: |
| ; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| store i64 1, ptr %ptr, align 8 |
| br i1 %c.1, label %if.then, label %if.end |
| |
| if.then: |
| unreachable |
| |
| if.end: |
| store i64 0, ptr %ptr, align 8 |
| ret void |
| } |
| |
| ; Test for PR53800. |
| define void @unreachable_exit_with_nounwind_call_pr53800(ptr noalias %ptr, i1 %c.1) { |
| ; CHECK-LABEL: @unreachable_exit_with_nounwind_call_pr53800( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: tail call void @exit() #[[ATTR0:[0-9]+]] |
| ; CHECK-NEXT: unreachable |
| ; CHECK: if.end: |
| ; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| store i64 1, ptr %ptr, align 8 |
| br i1 %c.1, label %if.then, label %if.end |
| |
| if.then: |
| tail call void @exit() nounwind |
| unreachable |
| |
| if.end: |
| store i64 0, ptr %ptr, align 8 |
| ret void |
| } |
| |
| ; The call @exit may read %ptr as it is not marked as noalias |
| define void @unreachable_exit_and_call_may_read(ptr %ptr, i1 %c.1) { |
| ; CHECK-LABEL: @unreachable_exit_and_call_may_read( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: store i64 1, ptr [[PTR:%.*]], align 8 |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: tail call void @exit() #[[ATTR0]] |
| ; CHECK-NEXT: unreachable |
| ; CHECK: if.end: |
| ; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| store i64 1, ptr %ptr, align 8 |
| br i1 %c.1, label %if.then, label %if.end |
| |
| if.then: |
| tail call void @exit() nounwind |
| unreachable |
| |
| if.end: |
| store i64 0, ptr %ptr, align 8 |
| ret void |
| } |
| |
| define void @unreachable_exit_with_may_unwind_call(ptr noalias %ptr, i1 %c.1) { |
| ; CHECK-LABEL: @unreachable_exit_with_may_unwind_call( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: store i64 1, ptr [[PTR:%.*]], align 8 |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: tail call void @exit() |
| ; CHECK-NEXT: unreachable |
| ; CHECK: if.end: |
| ; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| store i64 1, ptr %ptr, align 8 |
| br i1 %c.1, label %if.then, label %if.end |
| |
| if.then: |
| tail call void @exit() |
| unreachable |
| |
| if.end: |
| store i64 0, ptr %ptr, align 8 |
| ret void |
| } |
| |
| ; Cannot remove the store in entry, because it is not dead on the path to e.1 |
| define void @unreachable_exit_but_another_exit(ptr noalias %ptr, i1 %c.1, i32 %s, i1 %c.2) { |
| ; CHECK-LABEL: @unreachable_exit_but_another_exit( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: store i64 1, ptr [[PTR:%.*]], align 8 |
| ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] |
| ; CHECK: if.then: |
| ; CHECK-NEXT: br i1 [[C_2:%.*]], label [[E_0:%.*]], label [[E_1:%.*]] |
| ; CHECK: e.0: |
| ; CHECK-NEXT: tail call void @exit() #[[ATTR0]] |
| ; CHECK-NEXT: unreachable |
| ; CHECK: e.1: |
| ; CHECK-NEXT: ret void |
| ; CHECK: if.end: |
| ; CHECK-NEXT: store i64 0, ptr [[PTR]], align 8 |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| store i64 1, ptr %ptr, align 8 |
| br i1 %c.1, label %if.then, label %if.end |
| |
| if.then: |
| br i1 %c.2, label %e.0, label %e.1 |
| |
| e.0: |
| tail call void @exit() nounwind |
| unreachable |
| |
| e.1: |
| ret void |
| |
| if.end: |
| store i64 0, ptr %ptr, align 8 |
| ret void |
| } |