1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -switch-range-to-icmp -S | FileCheck %s 3 4declare i32 @f(i32) 5 6define i32 @basic(i32 %x) { 7; CHECK-LABEL: @basic( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 10; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 11; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[DEFAULT:%.*]] 12; CHECK: common.ret: 13; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[DEFAULT]] ], [ [[TMP1:%.*]], [[A]] ] 14; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] 15; CHECK: default: 16; CHECK-NEXT: [[TMP0]] = call i32 @f(i32 0) 17; CHECK-NEXT: br label [[COMMON_RET:%.*]] 18; CHECK: a: 19; CHECK-NEXT: [[TMP1]] = call i32 @f(i32 1) 20; CHECK-NEXT: br label [[COMMON_RET]] 21; 22 23entry: 24 switch i32 %x, label %default [ 25 i32 5, label %a 26 i32 6, label %a 27 i32 7, label %a 28 ] 29default: 30 %0 = call i32 @f(i32 0) 31 ret i32 %0 32a: 33 %1 = call i32 @f(i32 1) 34 ret i32 %1 35} 36 37 38define i32 @unreachable(i32 %x) { 39; CHECK-LABEL: @unreachable( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 42; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 43; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] 44; CHECK: common.ret: 45; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[A]] ], [ [[TMP1:%.*]], [[B]] ] 46; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] 47; CHECK: a: 48; CHECK-NEXT: [[TMP0]] = call i32 @f(i32 0) 49; CHECK-NEXT: br label [[COMMON_RET:%.*]] 50; CHECK: b: 51; CHECK-NEXT: [[TMP1]] = call i32 @f(i32 1) 52; CHECK-NEXT: br label [[COMMON_RET]] 53; 54 55entry: 56 switch i32 %x, label %unreachable [ 57 i32 5, label %a 58 i32 6, label %a 59 i32 7, label %a 60 i32 10, label %b 61 i32 20, label %b 62 i32 30, label %b 63 i32 40, label %b 64 ] 65unreachable: 66 unreachable 67a: 68 %0 = call i32 @f(i32 0) 69 ret i32 %0 70b: 71 %1 = call i32 @f(i32 1) 72 ret i32 %1 73} 74 75 76define i32 @unreachable2(i32 %x) { 77; CHECK-LABEL: @unreachable2( 78; CHECK-NEXT: entry: 79; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X:%.*]], -5 80; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i32 [[X_OFF]], 3 81; CHECK-NEXT: br i1 [[SWITCH]], label [[A:%.*]], label [[B:%.*]] 82; CHECK: common.ret: 83; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[TMP0:%.*]], [[A]] ], [ [[TMP1:%.*]], [[B]] ] 84; CHECK-NEXT: ret i32 [[COMMON_RET_OP]] 85; CHECK: a: 86; CHECK-NEXT: [[TMP0]] = call i32 @f(i32 0) 87; CHECK-NEXT: br label [[COMMON_RET:%.*]] 88; CHECK: b: 89; CHECK-NEXT: [[TMP1]] = call i32 @f(i32 1) 90; CHECK-NEXT: br label [[COMMON_RET]] 91; 92 93entry: 94 ; Note: folding the most popular case destination into the default 95 ; would prevent switch-to-icmp here. 96 switch i32 %x, label %unreachable [ 97 i32 5, label %a 98 i32 6, label %a 99 i32 7, label %a 100 i32 10, label %b 101 i32 20, label %b 102 ] 103unreachable: 104 unreachable 105a: 106 %0 = call i32 @f(i32 0) 107 ret i32 %0 108b: 109 %1 = call i32 @f(i32 1) 110 ret i32 %1 111} 112 113; This would crash because we did not clean up the 114; default block of the switch before removing the switch. 115 116define void @PR42737(ptr %a, i1 %c) { 117; CHECK-LABEL: @PR42737( 118; CHECK-NEXT: entry: 119; CHECK-NEXT: unreachable 120; 121entry: 122 br i1 %c, label %switch, label %else 123 124else: 125 store i32 2, ptr %a 126 br label %switch 127 128switch: 129 %cleanup.dest1 = phi i32 [ 0, %else ], [ 3, %entry ] 130 switch i32 %cleanup.dest1, label %unreach1 [ 131 i32 0, label %cleanup1 132 i32 3, label %cleanup2 133 ] 134 135cleanup1: 136 br label %unreach2 137 138cleanup2: 139 br label %unreach2 140 141unreach1: 142 %phi2 = phi i32 [ %cleanup.dest1, %switch ] 143 unreachable 144 145unreach2: 146 unreachable 147} 148 149 150define void @pr53208_single_reachable_dest(i8 %sw, ptr %p0) { 151; CHECK-LABEL: @pr53208_single_reachable_dest( 152; CHECK-NEXT: group2: 153; CHECK-NEXT: call void @bar(ptr [[P0:%.*]]) 154; CHECK-NEXT: ret void 155; 156 switch i8 %sw, label %group3 [ 157 i8 0, label %group1 158 i8 1, label %group1 159 i8 2, label %group1 160 i8 3, label %group1 161 i8 11, label %group1 162 i8 12, label %group1 163 i8 13, label %group1 164 i8 7, label %group1 165 i8 17, label %group1 166 i8 14, label %group1 167 i8 15, label %group1 168 i8 4, label %group2 169 i8 5, label %group2 170 i8 6, label %group2 171 i8 8, label %group2 172 i8 9, label %group2 173 i8 10, label %group2 174 ] 175 176group1: 177 br label %exit 178 179group2: 180 br label %exit 181 182group3: 183 br label %exit 184 185exit: 186 %phi = phi ptr [ null, %group3 ], [ %p0, %group2 ], [ null, %group1 ] 187 call void @bar(ptr %phi) 188 ret void 189} 190 191declare void @bar(ptr nonnull dereferenceable(4)) 192