1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S -o - < %s | FileCheck %s 3 4declare void @func2(i32) 5declare void @func4(i32) 6declare void @func6(i32) 7declare void @func8(i32) 8 9;; test1 - create a switch with case 2 and case 4 from two branches: N == 2 10;; and N == 4. 11define void @test1(i32 %N) nounwind uwtable { 12; CHECK-LABEL: @test1( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: switch i32 [[N:%.*]], label [[IF_ELSE8:%.*]] [ 15; CHECK-NEXT: i32 2, label [[IF_THEN:%.*]] 16; CHECK-NEXT: i32 4, label [[IF_THEN7:%.*]] 17; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]] 18; CHECK: if.then: 19; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1:[0-9]+]] 20; CHECK-NEXT: br label [[IF_END9:%.*]] 21; CHECK: if.then7: 22; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]] 23; CHECK-NEXT: br label [[IF_END9]] 24; CHECK: if.else8: 25; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]] 26; CHECK-NEXT: br label [[IF_END9]] 27; CHECK: if.end9: 28; CHECK-NEXT: ret void 29; 30entry: 31 %cmp = icmp eq i32 %N, 2 32 br i1 %cmp, label %if.then, label %if.else, !prof !0 33 34if.then: 35 call void @func2(i32 %N) nounwind 36 br label %if.end9 37 38if.else: 39 %cmp2 = icmp eq i32 %N, 4 40 br i1 %cmp2, label %if.then7, label %if.else8, !prof !1 41 42if.then7: 43 call void @func4(i32 %N) nounwind 44 br label %if.end 45 46if.else8: 47 call void @func8(i32 %N) nounwind 48 br label %if.end 49 50if.end: 51 br label %if.end9 52 53if.end9: 54 ret void 55} 56 57;; test2 - Merge two switches where PredDefault == BB. 58define void @test2(i32 %M, i32 %N) nounwind uwtable { 59; CHECK-LABEL: @test2( 60; CHECK-NEXT: entry: 61; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[M:%.*]], 2 62; CHECK-NEXT: br i1 [[CMP]], label [[SW1:%.*]], label [[SW2:%.*]] 63; CHECK: sw1: 64; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_EPILOG:%.*]] [ 65; CHECK-NEXT: i32 2, label [[SW_BB:%.*]] 66; CHECK-NEXT: i32 3, label [[SW_BB1:%.*]] 67; CHECK-NEXT: i32 4, label [[SW_BB5:%.*]] 68; CHECK-NEXT: ], !prof [[PROF1:![0-9]+]] 69; CHECK: sw.bb: 70; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1]] 71; CHECK-NEXT: br label [[SW_EPILOG]] 72; CHECK: sw.bb1: 73; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]] 74; CHECK-NEXT: br label [[SW_EPILOG]] 75; CHECK: sw2: 76; CHECK-NEXT: switch i32 [[N]], label [[SW_EPILOG]] [ 77; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 78; CHECK-NEXT: i32 4, label [[SW_BB5]] 79; CHECK-NEXT: ], !prof [[PROF2:![0-9]+]] 80; CHECK: sw.bb4: 81; CHECK-NEXT: call void @func6(i32 [[N]]) #[[ATTR1]] 82; CHECK-NEXT: br label [[SW_EPILOG]] 83; CHECK: sw.bb5: 84; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]] 85; CHECK-NEXT: br label [[SW_EPILOG]] 86; CHECK: sw.epilog: 87; CHECK-NEXT: ret void 88; 89entry: 90 %cmp = icmp sgt i32 %M, 2 91 br i1 %cmp, label %sw1, label %sw2 92 93sw1: 94 switch i32 %N, label %sw2 [ 95 i32 2, label %sw.bb 96 i32 3, label %sw.bb1 97 ], !prof !2 98 99sw.bb: 100 call void @func2(i32 %N) nounwind 101 br label %sw.epilog 102 103sw.bb1: 104 call void @func4(i32 %N) nounwind 105 br label %sw.epilog 106 107sw2: 108;; Here "case 2" is invalidated if control is transferred through default case 109;; of the first switch. 110 switch i32 %N, label %sw.epilog [ 111 i32 2, label %sw.bb4 112 i32 4, label %sw.bb5 113 ], !prof !3 114 115sw.bb4: 116 call void @func6(i32 %N) nounwind 117 br label %sw.epilog 118 119sw.bb5: 120 call void @func8(i32 %N) nounwind 121 br label %sw.epilog 122 123sw.epilog: 124 ret void 125} 126 127;; test3 - Merge two switches where PredDefault != BB. 128define void @test3(i32 %M, i32 %N) nounwind uwtable { 129; CHECK-LABEL: @test3( 130; CHECK-NEXT: entry: 131; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[M:%.*]], 2 132; CHECK-NEXT: br i1 [[CMP]], label [[SW1:%.*]], label [[SW2:%.*]] 133; CHECK: sw1: 134; CHECK-NEXT: switch i32 [[N:%.*]], label [[SW_BB:%.*]] [ 135; CHECK-NEXT: i32 1, label [[SW_BB1:%.*]] 136; CHECK-NEXT: i32 3, label [[SW_BB4:%.*]] 137; CHECK-NEXT: i32 2, label [[SW_EPILOG:%.*]] 138; CHECK-NEXT: ], !prof [[PROF3:![0-9]+]] 139; CHECK: sw.bb: 140; CHECK-NEXT: call void @func2(i32 [[N]]) #[[ATTR1]] 141; CHECK-NEXT: br label [[SW_EPILOG]] 142; CHECK: sw.bb1: 143; CHECK-NEXT: call void @func4(i32 [[N]]) #[[ATTR1]] 144; CHECK-NEXT: br label [[SW_EPILOG]] 145; CHECK: sw2: 146; CHECK-NEXT: switch i32 [[N]], label [[SW_EPILOG]] [ 147; CHECK-NEXT: i32 3, label [[SW_BB4]] 148; CHECK-NEXT: i32 4, label [[SW_BB5:%.*]] 149; CHECK-NEXT: ], !prof [[PROF4:![0-9]+]] 150; CHECK: sw.bb4: 151; CHECK-NEXT: call void @func6(i32 [[N]]) #[[ATTR1]] 152; CHECK-NEXT: br label [[SW_EPILOG]] 153; CHECK: sw.bb5: 154; CHECK-NEXT: call void @func8(i32 [[N]]) #[[ATTR1]] 155; CHECK-NEXT: br label [[SW_EPILOG]] 156; CHECK: sw.epilog: 157; CHECK-NEXT: ret void 158; 159entry: 160 %cmp = icmp sgt i32 %M, 2 161 br i1 %cmp, label %sw1, label %sw2 162 163sw1: 164 switch i32 %N, label %sw.bb [ 165 i32 2, label %sw2 166 i32 3, label %sw2 167 i32 1, label %sw.bb1 168 ], !prof !4 169 170sw.bb: 171 call void @func2(i32 %N) nounwind 172 br label %sw.epilog 173 174sw.bb1: 175 call void @func4(i32 %N) nounwind 176 br label %sw.epilog 177 178sw2: 179 switch i32 %N, label %sw.epilog [ 180 i32 3, label %sw.bb4 181 i32 4, label %sw.bb5 182 ], !prof !5 183 184sw.bb4: 185 call void @func6(i32 %N) nounwind 186 br label %sw.epilog 187 188sw.bb5: 189 call void @func8(i32 %N) nounwind 190 br label %sw.epilog 191 192sw.epilog: 193 ret void 194} 195 196!0 = !{!"branch_weights", i32 64, i32 4} 197!1 = !{!"branch_weights", i32 4, i32 64} 198; CHECK: !0 = !{!"branch_weights", i32 256, i32 4352, i32 16} 199!2 = !{!"branch_weights", i32 4, i32 4, i32 8} 200!3 = !{!"branch_weights", i32 8, i32 8, i32 4} 201; CHECK: !1 = !{!"branch_weights", i32 32, i32 48, i32 96, i32 16} 202!4 = !{!"branch_weights", i32 7, i32 6, i32 4, i32 3} 203!5 = !{!"branch_weights", i32 17, i32 13, i32 9} 204; CHECK: !3 = !{!"branch_weights", i32 7, i32 3, i32 4, i32 6} 205