1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -two-entry-phi-node-folding-threshold=0 -phi-node-folding-threshold=4 < %s | FileCheck %s 3 4declare void @sideeffect0() 5declare void @sideeffect1() 6declare void @sideeffect2() 7 8define i32 @unknown(i1 %c, i32 %a, i32 %b) { 9; CHECK-LABEL: @unknown( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: call void @sideeffect0() 12; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 13; CHECK: dispatch: 14; CHECK-NEXT: call void @sideeffect1() 15; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 16; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 17; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0 18; CHECK-NEXT: br label [[END]] 19; CHECK: end: 20; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 21; CHECK-NEXT: call void @sideeffect2() 22; CHECK-NEXT: ret i32 [[RES]] 23; 24entry: 25 call void @sideeffect0() 26 br i1 %c, label %dispatch, label %end 27 28dispatch: 29 call void @sideeffect1() 30 %cmp = icmp eq i32 %a, %b 31 br i1 %cmp, label %cond.true, label %end 32 33cond.true: 34 %val = add i32 %a, %b 35 br label %end 36 37end: 38 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 39 call void @sideeffect2() 40 ret i32 %res 41} 42 43define i32 @predictably_taken(i1 %c, i32 %a, i32 %b) { 44; CHECK-LABEL: @predictably_taken( 45; CHECK-NEXT: entry: 46; CHECK-NEXT: call void @sideeffect0() 47; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 48; CHECK: dispatch: 49; CHECK-NEXT: call void @sideeffect1() 50; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 51; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 52; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !prof [[PROF0:![0-9]+]] 53; CHECK-NEXT: br label [[END]] 54; CHECK: end: 55; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 56; CHECK-NEXT: call void @sideeffect2() 57; CHECK-NEXT: ret i32 [[RES]] 58; 59entry: 60 call void @sideeffect0() 61 br i1 %c, label %dispatch, label %end 62 63dispatch: 64 call void @sideeffect1() 65 %cmp = icmp eq i32 %a, %b 66 br i1 %cmp, label %cond.true, label %end, !prof !0 ; likely branches to %cond.true 67 68cond.true: 69 %val = add i32 %a, %b 70 br label %end 71 72end: 73 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 74 call void @sideeffect2() 75 ret i32 %res 76} 77 78define i32 @predictably_nontaken(i1 %c, i32 %a, i32 %b) { 79; CHECK-LABEL: @predictably_nontaken( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: call void @sideeffect0() 82; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 83; CHECK: dispatch: 84; CHECK-NEXT: call void @sideeffect1() 85; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 86; CHECK-NEXT: br i1 [[CMP]], label [[END]], label [[COND_TRUE:%.*]], !prof [[PROF0]] 87; CHECK: cond.true: 88; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 89; CHECK-NEXT: br label [[END]] 90; CHECK: end: 91; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ 0, [[DISPATCH]] ], [ [[VAL]], [[COND_TRUE]] ] 92; CHECK-NEXT: call void @sideeffect2() 93; CHECK-NEXT: ret i32 [[RES]] 94; 95entry: 96 call void @sideeffect0() 97 br i1 %c, label %dispatch, label %end 98 99dispatch: 100 call void @sideeffect1() 101 %cmp = icmp eq i32 %a, %b 102 br i1 %cmp, label %end, label %cond.true, !prof !0 ; likely branches to %end 103 104cond.true: 105 %val = add i32 %a, %b 106 br label %end 107 108end: 109 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 110 call void @sideeffect2() 111 ret i32 %res 112} 113 114define i32 @almost_predictably_nontaken(i1 %c, i32 %a, i32 %b) { 115; CHECK-LABEL: @almost_predictably_nontaken( 116; CHECK-NEXT: entry: 117; CHECK-NEXT: call void @sideeffect0() 118; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 119; CHECK: dispatch: 120; CHECK-NEXT: call void @sideeffect1() 121; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 122; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 123; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 0, i32 [[VAL]], !prof [[PROF1:![0-9]+]] 124; CHECK-NEXT: br label [[END]] 125; CHECK: end: 126; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 127; CHECK-NEXT: call void @sideeffect2() 128; CHECK-NEXT: ret i32 [[RES]] 129; 130entry: 131 call void @sideeffect0() 132 br i1 %c, label %dispatch, label %end 133 134dispatch: 135 call void @sideeffect1() 136 %cmp = icmp eq i32 %a, %b 137 br i1 %cmp, label %end, label %cond.true, !prof !1 ; almost likely branches to %end 138 139cond.true: 140 %val = add i32 %a, %b 141 br label %end 142 143end: 144 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 145 call void @sideeffect2() 146 ret i32 %res 147} 148 149define i32 @unpredictable(i1 %c, i32 %a, i32 %b) { 150; CHECK-LABEL: @unpredictable( 151; CHECK-NEXT: entry: 152; CHECK-NEXT: call void @sideeffect0() 153; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 154; CHECK: dispatch: 155; CHECK-NEXT: call void @sideeffect1() 156; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 157; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 158; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !unpredictable [[META2:![0-9]+]] 159; CHECK-NEXT: br label [[END]] 160; CHECK: end: 161; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 162; CHECK-NEXT: call void @sideeffect2() 163; CHECK-NEXT: ret i32 [[RES]] 164; 165entry: 166 call void @sideeffect0() 167 br i1 %c, label %dispatch, label %end 168 169dispatch: 170 call void @sideeffect1() 171 %cmp = icmp eq i32 %a, %b 172 br i1 %cmp, label %cond.true, label %end, !unpredictable !2 ; unpredictable 173 174cond.true: 175 %val = add i32 %a, %b 176 br label %end 177 178end: 179 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 180 call void @sideeffect2() 181 ret i32 %res 182} 183 184define i32 @unpredictable_yet_taken(i1 %c, i32 %a, i32 %b) { 185; CHECK-LABEL: @unpredictable_yet_taken( 186; CHECK-NEXT: entry: 187; CHECK-NEXT: call void @sideeffect0() 188; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 189; CHECK: dispatch: 190; CHECK-NEXT: call void @sideeffect1() 191; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 192; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 193; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 [[VAL]], i32 0, !prof [[PROF0]], !unpredictable [[META2]] 194; CHECK-NEXT: br label [[END]] 195; CHECK: end: 196; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 197; CHECK-NEXT: call void @sideeffect2() 198; CHECK-NEXT: ret i32 [[RES]] 199; 200entry: 201 call void @sideeffect0() 202 br i1 %c, label %dispatch, label %end 203 204dispatch: 205 call void @sideeffect1() 206 %cmp = icmp eq i32 %a, %b 207 br i1 %cmp, label %cond.true, label %end, !prof !0, !unpredictable !2 ; likely branches to %cond.true, yet unpredictable 208 209cond.true: 210 %val = add i32 %a, %b 211 br label %end 212 213end: 214 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 215 call void @sideeffect2() 216 ret i32 %res 217} 218 219define i32 @unpredictable_yet_nontaken(i1 %c, i32 %a, i32 %b) { 220; CHECK-LABEL: @unpredictable_yet_nontaken( 221; CHECK-NEXT: entry: 222; CHECK-NEXT: call void @sideeffect0() 223; CHECK-NEXT: br i1 [[C:%.*]], label [[DISPATCH:%.*]], label [[END:%.*]] 224; CHECK: dispatch: 225; CHECK-NEXT: call void @sideeffect1() 226; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 227; CHECK-NEXT: [[VAL:%.*]] = add i32 [[A]], [[B]] 228; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP]], i32 0, i32 [[VAL]], !prof [[PROF0]], !unpredictable [[META2]] 229; CHECK-NEXT: br label [[END]] 230; CHECK: end: 231; CHECK-NEXT: [[RES:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[DISPATCH]] ] 232; CHECK-NEXT: call void @sideeffect2() 233; CHECK-NEXT: ret i32 [[RES]] 234; 235entry: 236 call void @sideeffect0() 237 br i1 %c, label %dispatch, label %end 238 239dispatch: 240 call void @sideeffect1() 241 %cmp = icmp eq i32 %a, %b 242 br i1 %cmp, label %end, label %cond.true, !prof !0, !unpredictable !2 ; likely branches to %end, yet unpredictable 243 244cond.true: 245 %val = add i32 %a, %b 246 br label %end 247 248end: 249 %res = phi i32 [ -1, %entry ], [ 0, %dispatch ], [ %val, %cond.true ] 250 call void @sideeffect2() 251 ret i32 %res 252} 253 254!0 = !{!"branch_weights", i32 99, i32 1} 255!1 = !{!"branch_weights", i32 70, i32 1} 256!2 = !{} 257 258; CHECK: !0 = !{!"branch_weights", i32 99, i32 1} 259; CHECK: !1 = !{!"branch_weights", i32 70, i32 1} 260; CHECK: !2 = !{} 261