; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -S -passes=dfa-jump-threading -dfa-max-out-use-blocks=5 %s | FileCheck %s declare void @use(i32) define void @max_outer_uses_by_switch(i32 %cond, ptr %p) { ; CHECK-LABEL: define void @max_outer_uses_by_switch( ; CHECK-SAME: i32 [[COND:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[SWITCH_BB:.*]] ; CHECK: [[SWITCH_BB]]: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[DETERMINE:%.*]], %[[SUB_SWITCH_BB:.*]] ], [ 2, %[[CASE2:.*]] ] ; 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 %[[CASE3:.*]] ; CHECK-NEXT: ] ; CHECK: [[CASE1]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB]] ; CHECK: [[CASE3]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB]] ; CHECK: [[SUB_SWITCH_BB]]: ; CHECK-NEXT: [[DETERMINE]] = phi i32 [ 1, %[[CASE1]] ], [ 3, %[[CASE3]] ] ; CHECK-NEXT: [[DEF:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1:.*]] ; CHECK-NEXT: i32 1, label %[[OUTER2:.*]] ; CHECK-NEXT: i32 2, label %[[OUTER3:.*]] ; CHECK-NEXT: i32 3, label %[[OUTER4:.*]] ; CHECK-NEXT: ] ; CHECK: [[CASE2]]: ; CHECK-NEXT: br label %[[SWITCH_BB]] ; CHECK: [[OUTER1]]: ; CHECK-NEXT: call void @use(i32 [[DEF]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER2]]: ; CHECK-NEXT: call void @use(i32 [[DEF]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER3]]: ; CHECK-NEXT: call void @use(i32 [[DEF]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER4]]: ; CHECK-NEXT: call void @use(i32 [[DEF]]) ; CHECK-NEXT: ret void ; CHECK: [[DEFAULT_DEST]]: ; CHECK-NEXT: ret void ; entry: br label %switch_bb switch_bb: %phi = phi i32 [ 0, %entry ], [ %determine, %sub_switch_bb ], [ 2, %case2 ] switch i32 %phi, label %default_dest [ i32 0, label %case1 i32 1, label %case2 i32 2, label %case3 ] case1: br label %sub_switch_bb case3: br label %sub_switch_bb sub_switch_bb: %determine = phi i32 [ 1, %case1 ], [ 3, %case3 ] %def = load i32, ptr %p switch i32 %cond, label %switch_bb [ i32 0, label %outer1 i32 1, label %outer2 i32 2, label %outer3 i32 3, label %outer4 ] case2: br label %switch_bb outer1: call void @use(i32 %def) ret void outer2: call void @use(i32 %def) ret void outer3: call void @use(i32 %def) ret void outer4: call void @use(i32 %def) ret void default_dest: ret void } define void @less_outer_uses_by_switch(i32 %cond, ptr %p) { ; CHECK-LABEL: define void @less_outer_uses_by_switch( ; CHECK-SAME: i32 [[COND:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[SWITCH_BB:.*]] ; CHECK: [[SWITCH_BB]]: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ poison, %[[SUB_SWITCH_BB:.*]] ] ; 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 %[[CASE3:.*]] ; CHECK-NEXT: ] ; CHECK: [[SWITCH_BB_JT2:.*]]: ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ 2, %[[CASE2]] ] ; CHECK-NEXT: br label %[[CASE3]] ; CHECK: [[SWITCH_BB_JT3:.*]]: ; CHECK-NEXT: [[PHI_JT3:%.*]] = phi i32 [ [[DETERMINE_JT3:%.*]], %[[SUB_SWITCH_BB_JT3:.*]] ] ; CHECK-NEXT: br label %[[DEFAULT_DEST]] ; CHECK: [[SWITCH_BB_JT1:.*]]: ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ [[DETERMINE_JT1:%.*]], %[[SUB_SWITCH_BB_JT1:.*]] ] ; CHECK-NEXT: br label %[[CASE2]] ; CHECK: [[CASE1]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB_JT1]] ; CHECK: [[CASE3]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB_JT3]] ; CHECK: [[SUB_SWITCH_BB]]: ; CHECK-NEXT: [[DEF:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1:.*]] ; CHECK-NEXT: ] ; CHECK: [[SUB_SWITCH_BB_JT3]]: ; CHECK-NEXT: [[DETERMINE_JT3]] = phi i32 [ 3, %[[CASE3]] ] ; CHECK-NEXT: [[DEF_JT3:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB_JT3]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1]] ; CHECK-NEXT: ] ; CHECK: [[SUB_SWITCH_BB_JT1]]: ; CHECK-NEXT: [[DETERMINE_JT1]] = phi i32 [ 1, %[[CASE1]] ] ; CHECK-NEXT: [[DEF_JT1:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB_JT1]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1]] ; CHECK-NEXT: ] ; CHECK: [[CASE2]]: ; CHECK-NEXT: br label %[[SWITCH_BB_JT2]] ; CHECK: [[OUTER1]]: ; CHECK-NEXT: [[DEF1:%.*]] = phi i32 [ [[DEF_JT3]], %[[SUB_SWITCH_BB_JT3]] ], [ [[DEF_JT1]], %[[SUB_SWITCH_BB_JT1]] ], [ [[DEF]], %[[SUB_SWITCH_BB]] ] ; CHECK-NEXT: call void @use(i32 [[DEF1]]) ; CHECK-NEXT: ret void ; CHECK: [[DEFAULT_DEST]]: ; CHECK-NEXT: ret void ; entry: br label %switch_bb switch_bb: %phi = phi i32 [ 0, %entry ], [ %determine, %sub_switch_bb ], [ 2, %case2 ] switch i32 %phi, label %default_dest [ i32 0, label %case1 i32 1, label %case2 i32 2, label %case3 ] case1: br label %sub_switch_bb case3: br label %sub_switch_bb sub_switch_bb: %determine = phi i32 [ 1, %case1 ], [ 3, %case3 ] %def = load i32, ptr %p switch i32 %cond, label %switch_bb [ i32 0, label %outer1 ] case2: br label %switch_bb outer1: call void @use(i32 %def) ret void default_dest: ret void } define void @max_outer_uses_multi_preds(i32 %cond, ptr %p) { ; CHECK-LABEL: define void @max_outer_uses_multi_preds( ; CHECK-SAME: i32 [[COND:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[SWITCH_BB:.*]] ; CHECK: [[SWITCH_BB]]: ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ poison, %[[SUB_SWITCH_BB:.*]] ] ; 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 %[[CASE3:.*]] ; CHECK-NEXT: i32 3, label %[[CASE4:.*]] ; CHECK-NEXT: ] ; CHECK: [[SWITCH_BB_JT2:.*]]: ; CHECK-NEXT: [[PHI_JT2:%.*]] = phi i32 [ 2, %[[CASE2]] ] ; CHECK-NEXT: br label %[[CASE3]] ; CHECK: [[SWITCH_BB_JT3:.*]]: ; CHECK-NEXT: [[PHI_JT3:%.*]] = phi i32 [ [[DETERMINE_JT3:%.*]], %[[SUB_SWITCH_BB_JT3:.*]] ] ; CHECK-NEXT: br label %[[CASE4]] ; CHECK: [[SWITCH_BB_JT1:.*]]: ; CHECK-NEXT: [[PHI_JT1:%.*]] = phi i32 [ [[DETERMINE_JT1:%.*]], %[[SUB_SWITCH_BB_JT1:.*]] ] ; CHECK-NEXT: br label %[[CASE2]] ; CHECK: [[CASE1]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB_JT1]] ; CHECK: [[CASE3]]: ; CHECK-NEXT: br label %[[SUB_SWITCH_BB_JT3]] ; CHECK: [[SUB_SWITCH_BB]]: ; CHECK-NEXT: [[DEF:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1:.*]] ; CHECK-NEXT: i32 1, label %[[OUTER2:.*]] ; CHECK-NEXT: i32 2, label %[[OUTER3:.*]] ; CHECK-NEXT: i32 3, label %[[OUTER4:.*]] ; CHECK-NEXT: ] ; CHECK: [[SUB_SWITCH_BB_JT3]]: ; CHECK-NEXT: [[DETERMINE_JT3]] = phi i32 [ 3, %[[CASE3]] ] ; CHECK-NEXT: [[DEF_JT3:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB_JT3]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1]] ; CHECK-NEXT: i32 1, label %[[OUTER2]] ; CHECK-NEXT: i32 2, label %[[OUTER3]] ; CHECK-NEXT: i32 3, label %[[OUTER4]] ; CHECK-NEXT: ] ; CHECK: [[SUB_SWITCH_BB_JT1]]: ; CHECK-NEXT: [[DETERMINE_JT1]] = phi i32 [ 1, %[[CASE1]] ] ; CHECK-NEXT: [[DEF_JT1:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[SWITCH_BB_JT1]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1]] ; CHECK-NEXT: i32 1, label %[[OUTER2]] ; CHECK-NEXT: i32 2, label %[[OUTER3]] ; CHECK-NEXT: i32 3, label %[[OUTER4]] ; CHECK-NEXT: ] ; CHECK: [[CASE4]]: ; CHECK-NEXT: [[DEF1:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: switch i32 [[COND]], label %[[OUTER4]] [ ; CHECK-NEXT: i32 0, label %[[OUTER1]] ; CHECK-NEXT: i32 1, label %[[OUTER2]] ; CHECK-NEXT: i32 2, label %[[OUTER3]] ; CHECK-NEXT: ] ; CHECK: [[CASE2]]: ; CHECK-NEXT: br label %[[SWITCH_BB_JT2]] ; CHECK: [[OUTER1]]: ; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[DEF]], %[[SUB_SWITCH_BB]] ], [ [[DEF1]], %[[CASE4]] ], [ [[DEF_JT1]], %[[SUB_SWITCH_BB_JT1]] ], [ [[DEF_JT3]], %[[SUB_SWITCH_BB_JT3]] ] ; CHECK-NEXT: call void @use(i32 [[PHI1]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER2]]: ; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[DEF]], %[[SUB_SWITCH_BB]] ], [ [[DEF1]], %[[CASE4]] ], [ [[DEF_JT1]], %[[SUB_SWITCH_BB_JT1]] ], [ [[DEF_JT3]], %[[SUB_SWITCH_BB_JT3]] ] ; CHECK-NEXT: call void @use(i32 [[PHI2]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER3]]: ; CHECK-NEXT: [[PHI3:%.*]] = phi i32 [ [[DEF]], %[[SUB_SWITCH_BB]] ], [ [[DEF1]], %[[CASE4]] ], [ [[DEF_JT1]], %[[SUB_SWITCH_BB_JT1]] ], [ [[DEF_JT3]], %[[SUB_SWITCH_BB_JT3]] ] ; CHECK-NEXT: call void @use(i32 [[PHI3]]) ; CHECK-NEXT: ret void ; CHECK: [[OUTER4]]: ; CHECK-NEXT: [[PHI4:%.*]] = phi i32 [ [[DEF]], %[[SUB_SWITCH_BB]] ], [ [[DEF1]], %[[CASE4]] ], [ [[DEF_JT1]], %[[SUB_SWITCH_BB_JT1]] ], [ [[DEF_JT3]], %[[SUB_SWITCH_BB_JT3]] ] ; CHECK-NEXT: call void @use(i32 [[PHI4]]) ; CHECK-NEXT: ret void ; CHECK: [[DEFAULT_DEST]]: ; CHECK-NEXT: ret void ; entry: br label %switch_bb switch_bb: %phi = phi i32 [ 0, %entry ], [ %determine, %sub_switch_bb ], [ 2, %case2 ] switch i32 %phi, label %default_dest [ i32 0, label %case1 i32 1, label %case2 i32 2, label %case3 i32 3, label %case4 ] case1: br label %sub_switch_bb case3: br label %sub_switch_bb sub_switch_bb: %determine = phi i32 [ 1, %case1 ], [ 3, %case3 ] %def = load i32, ptr %p switch i32 %cond, label %switch_bb [ i32 0, label %outer1 i32 1, label %outer2 i32 2, label %outer3 i32 3, label %outer4 ] case4: %def1 = load i32, ptr %p switch i32 %cond, label %outer4 [ i32 0, label %outer1 i32 1, label %outer2 i32 2, label %outer3 ] case2: br label %switch_bb outer1: %phi1 = phi i32 [ %def, %sub_switch_bb ], [ %def1, %case4 ] call void @use(i32 %phi1) ret void outer2: %phi2 = phi i32 [ %def, %sub_switch_bb ], [ %def1, %case4 ] call void @use(i32 %phi2) ret void outer3: %phi3 = phi i32 [ %def, %sub_switch_bb ], [ %def1, %case4 ] call void @use(i32 %phi3) ret void outer4: %phi4 = phi i32 [ %def, %sub_switch_bb ], [ %def1, %case4 ] call void @use(i32 %phi4) ret void default_dest: ret void }