| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 |
| ; RUN: opt -S -passes=dfa-jump-threading -verify-dom-info=1 %s | FileCheck %s |
| |
| declare void @do_something() |
| declare void @user(i32) |
| |
| define void @equivalent_on_default(i1 %c1) { |
| ; CHECK-LABEL: define void @equivalent_on_default( |
| ; CHECK-SAME: i1 [[C1:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[SWITCH_BB:%.*]] |
| ; CHECK: switch_bb: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ poison, [[CASE2END:%.*]] ] |
| ; CHECK-NEXT: switch i32 [[PHI]], label [[DEFAULT_DEST:%.*]] [ |
| ; CHECK-NEXT: i32 0, label [[CASE1:%.*]] |
| ; CHECK-NEXT: i32 1, label [[CASE2:%.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: switch_bb.jt2: |
| ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ [[PHI_CASE2_JT2:%.*]], [[CASE2END_JT2:%.*]] ] |
| ; CHECK-NEXT: br label [[DEFAULT_DEST]] |
| ; CHECK: switch_bb.jt1: |
| ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ 1, [[CASE1]] ] |
| ; CHECK-NEXT: br label [[CASE2]] |
| ; CHECK: case1: |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT1:%.*]] |
| ; CHECK: case2: |
| ; CHECK-NEXT: br i1 [[C1]], label [[CASE2THEN:%.*]], label [[CASE2END_JT2]] |
| ; CHECK: case2then: |
| ; CHECK-NEXT: br label [[CASE2END_JT2]] |
| ; CHECK: case2end: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB]] |
| ; CHECK: case2end.jt2: |
| ; CHECK-NEXT: [[PHI_CASE2_JT2]] = phi i32 [ 2, [[CASE2]] ], [ 3, [[CASE2THEN]] ] |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT2:%.*]] |
| ; CHECK: default_dest: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %switch_bb |
| |
| switch_bb: |
| %phi = phi i32 [ 0, %entry ], [ 1, %case1 ], [ %phi_case2, %case2end ] |
| switch i32 %phi, label %default_dest [ |
| i32 0, label %case1 |
| i32 1, label %case2 |
| ] |
| |
| case1: |
| br label %switch_bb |
| |
| case2: |
| br i1 %c1, label %case2then, label %case2end |
| |
| case2then: |
| br label %case2end |
| |
| case2end: |
| %phi_case2 = phi i32 [ 2, %case2 ] , [ 3, %case2then ] |
| call void @do_something() |
| br label %switch_bb |
| |
| default_dest: |
| ret void |
| } |
| |
| define void @equivalent_on_default_user(i1 %c1) { |
| ; CHECK-LABEL: define void @equivalent_on_default_user( |
| ; CHECK-SAME: i1 [[C1:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[SWITCH_BB:%.*]] |
| ; CHECK: switch_bb: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ poison, [[CASE2END:%.*]] ] |
| ; CHECK-NEXT: switch i32 [[PHI]], label [[DEFAULT_DEST:%.*]] [ |
| ; CHECK-NEXT: i32 0, label [[CASE1:%.*]] |
| ; CHECK-NEXT: i32 1, label [[CASE2:%.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: switch_bb.jt2: |
| ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ [[PHI_CASE2_JT2:%.*]], [[CASE2END_JT2:%.*]] ] |
| ; CHECK-NEXT: br label [[DEFAULT_DEST]] |
| ; CHECK: switch_bb.jt1: |
| ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ 1, [[CASE1]] ] |
| ; CHECK-NEXT: br label [[CASE2]] |
| ; CHECK: case1: |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT1:%.*]] |
| ; CHECK: case2: |
| ; CHECK-NEXT: br i1 [[C1]], label [[CASE2THEN:%.*]], label [[CASE2END_JT2]] |
| ; CHECK: case2then: |
| ; CHECK-NEXT: br label [[CASE2END_JT2]] |
| ; CHECK: case2end: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: call void @user(i32 poison) |
| ; CHECK-NEXT: br label [[SWITCH_BB]] |
| ; CHECK: case2end.jt2: |
| ; CHECK-NEXT: [[PHI_CASE2_JT2]] = phi i32 [ 2, [[CASE2]] ], [ 3, [[CASE2THEN]] ] |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: call void @user(i32 [[PHI_CASE2_JT2]]) |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT2:%.*]] |
| ; CHECK: default_dest: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %switch_bb |
| |
| switch_bb: |
| %phi = phi i32 [ 0, %entry ], [ 1, %case1 ], [ %phi_case2, %case2end ] |
| switch i32 %phi, label %default_dest [ |
| i32 0, label %case1 |
| i32 1, label %case2 |
| ] |
| |
| case1: |
| br label %switch_bb |
| |
| case2: |
| br i1 %c1, label %case2then, label %case2end |
| |
| case2then: |
| br label %case2end |
| |
| case2end: |
| %phi_case2 = phi i32 [ 2, %case2 ] , [ 3, %case2then ] |
| call void @do_something() |
| call void @user(i32 %phi_case2) |
| br label %switch_bb |
| |
| default_dest: |
| ret void |
| } |
| |
| define void @equivalent_only_cases(i1 %c1) { |
| ; CHECK-LABEL: define void @equivalent_only_cases( |
| ; CHECK-SAME: i1 [[C1:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[SWITCH_BB:%.*]] |
| ; CHECK: switch_bb: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ poison, [[CASE2END:%.*]] ] |
| ; CHECK-NEXT: switch i32 [[PHI]], label [[DEFAULT_DEST:%.*]] [ |
| ; CHECK-NEXT: i32 0, label [[CASE1:%.*]] |
| ; CHECK-NEXT: i32 1, label [[CASE2:%.*]] |
| ; CHECK-NEXT: i32 2, label [[CASE1]] |
| ; CHECK-NEXT: i32 3, label [[CASE1]] |
| ; CHECK-NEXT: ] |
| ; CHECK: switch_bb.jt2: |
| ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ [[PHI_CASE2_JT2:%.*]], [[CASE2END_JT2:%.*]] ] |
| ; CHECK-NEXT: br label [[CASE1]] |
| ; CHECK: switch_bb.jt1: |
| ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ 1, [[CASE1]] ] |
| ; CHECK-NEXT: br label [[CASE2]] |
| ; CHECK: case1: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT1:%.*]] |
| ; CHECK: case2: |
| ; CHECK-NEXT: br i1 [[C1]], label [[CASE2THEN:%.*]], label [[CASE2END_JT2]] |
| ; CHECK: case2then: |
| ; CHECK-NEXT: br label [[CASE2END_JT2]] |
| ; CHECK: case2end: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB]] |
| ; CHECK: case2end.jt2: |
| ; CHECK-NEXT: [[PHI_CASE2_JT2]] = phi i32 [ 2, [[CASE2]] ], [ 3, [[CASE2THEN]] ] |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT2:%.*]] |
| ; CHECK: default_dest: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %switch_bb |
| |
| switch_bb: |
| %phi = phi i32 [ 0, %entry ], [ 1, %case1 ], [ %phi_case2, %case2end ] |
| switch i32 %phi, label %default_dest [ |
| i32 0, label %case1 |
| i32 1, label %case2 |
| i32 2, label %case1 |
| i32 3, label %case1 |
| ] |
| |
| case1: |
| call void @do_something() |
| br label %switch_bb |
| |
| case2: |
| br i1 %c1, label %case2then, label %case2end |
| |
| case2then: |
| br label %case2end |
| |
| case2end: |
| %phi_case2 = phi i32 [ 2, %case2 ] , [ 3, %case2then ] |
| call void @do_something() |
| br label %switch_bb |
| |
| default_dest: |
| ret void |
| } |
| |
| define void @equivalent_both_case_and_default(i1 %c1, i1 %c2) { |
| ; CHECK-LABEL: define void @equivalent_both_case_and_default( |
| ; CHECK-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]]) { |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: br label [[SWITCH_BB:%.*]] |
| ; CHECK: switch_bb: |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ poison, [[CASE2END:%.*]] ] |
| ; CHECK-NEXT: switch i32 [[PHI]], label [[DEFAULT_DEST:%.*]] [ |
| ; CHECK-NEXT: i32 0, label [[CASE1:%.*]] |
| ; CHECK-NEXT: i32 1, label [[CASE2:%.*]] |
| ; CHECK-NEXT: i32 2, label [[CASE1]] |
| ; CHECK-NEXT: i32 3, label [[CASE1]] |
| ; CHECK-NEXT: ] |
| ; CHECK: switch_bb.jt4: |
| ; CHECK-NEXT: [[PHI_JT3:%.*]] = phi i32 [ [[PHI_CASE2_JT3:%.*]], [[CASE2END_JT3:%.*]] ] |
| ; CHECK-NEXT: br label [[DEFAULT_DEST]] |
| ; CHECK: switch_bb.jt2: |
| ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ [[PHI_CASE2_JT2:%.*]], [[CASE2END_JT2:%.*]] ] |
| ; CHECK-NEXT: br label [[CASE1]] |
| ; CHECK: switch_bb.jt1: |
| ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ 1, [[CASE1]] ] |
| ; CHECK-NEXT: br label [[CASE2]] |
| ; CHECK: case1: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT1:%.*]] |
| ; CHECK: case2: |
| ; CHECK-NEXT: br i1 [[C1]], label [[CASE2THEN:%.*]], label [[CASE2END_JT2]] |
| ; CHECK: case2then: |
| ; CHECK-NEXT: br i1 [[C2]], label [[CASE2THEN2:%.*]], label [[CASE2END_JT2]] |
| ; CHECK: case2then2: |
| ; CHECK-NEXT: br i1 [[C2]], label [[CASE2THEN3:%.*]], label [[CASE2END_JT3]] |
| ; CHECK: case2then3: |
| ; CHECK-NEXT: br label [[CASE2END_JT3]] |
| ; CHECK: case2end: |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB]] |
| ; CHECK: case2end.jt4: |
| ; CHECK-NEXT: [[PHI_CASE2_JT3]] = phi i32 [ 4, [[CASE2THEN2]] ], [ 5, [[CASE2THEN3]] ] |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT3:%.*]] |
| ; CHECK: case2end.jt2: |
| ; CHECK-NEXT: [[PHI_CASE2_JT2]] = phi i32 [ 2, [[CASE2]] ], [ 3, [[CASE2THEN]] ] |
| ; CHECK-NEXT: call void @do_something() |
| ; CHECK-NEXT: br label [[SWITCH_BB_JT2:%.*]] |
| ; CHECK: default_dest: |
| ; CHECK-NEXT: ret void |
| ; |
| entry: |
| br label %switch_bb |
| |
| switch_bb: |
| %phi = phi i32 [ 0, %entry ], [ 1, %case1 ], [ %phi_case2, %case2end ] |
| switch i32 %phi, label %default_dest [ |
| i32 0, label %case1 |
| i32 1, label %case2 |
| i32 2, label %case1 |
| i32 3, label %case1 |
| ] |
| |
| case1: |
| call void @do_something() |
| br label %switch_bb |
| |
| case2: |
| br i1 %c1, label %case2then, label %case2end |
| |
| case2then: |
| br i1 %c2, label %case2then2, label %case2end |
| |
| case2then2: |
| br i1 %c2, label %case2then3, label %case2end |
| |
| case2then3: |
| br label %case2end |
| |
| case2end: |
| %phi_case2 = phi i32 [ 2, %case2 ], [ 3, %case2then ], [ 4, %case2then2 ], [ 5, %case2then3 ] |
| call void @do_something() |
| br label %switch_bb |
| |
| default_dest: |
| ret void |
| } |