| ; 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 | |
| } |