1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2 3; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -keep-loops=false -S < %s | FileCheck %s 4; RUN: opt -passes='simplifycfg<no-keep-loops>' -S < %s | FileCheck %s 5 6; It's not worthwhile to if-convert one of the phi nodes and leave 7; the other behind, because that still requires a branch. If 8; SimplifyCFG if-converts one of the phis, it should do both. 9 10define i32 @upper_bound(ptr %r, i32 %high, i32 %k) nounwind { 11; CHECK-LABEL: define i32 @upper_bound 12; CHECK-SAME: (ptr [[R:%.*]], i32 [[HIGH:%.*]], i32 [[K:%.*]]) #[[ATTR0:[0-9]+]] { 13; CHECK-NEXT: entry: 14; CHECK-NEXT: br label [[WHILE_COND:%.*]] 15; CHECK: while.cond: 16; CHECK-NEXT: [[HIGH_ADDR_0:%.*]] = phi i32 [ [[HIGH]], [[ENTRY:%.*]] ], [ [[SPEC_SELECT:%.*]], [[WHILE_BODY:%.*]] ] 17; CHECK-NEXT: [[LOW_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SPEC_SELECT1:%.*]], [[WHILE_BODY]] ] 18; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[LOW_0]], [[HIGH_ADDR_0]] 19; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]] 20; CHECK: while.body: 21; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOW_0]], [[HIGH_ADDR_0]] 22; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[ADD]], 2 23; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[DIV]] to i64 24; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[R]], i64 [[IDXPROM]] 25; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 26; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[K]], [[TMP0]] 27; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[DIV]], 1 28; CHECK-NEXT: [[SPEC_SELECT]] = select i1 [[CMP1]], i32 [[DIV]], i32 [[HIGH_ADDR_0]] 29; CHECK-NEXT: [[SPEC_SELECT1]] = select i1 [[CMP1]], i32 [[LOW_0]], i32 [[ADD2]] 30; CHECK-NEXT: br label [[WHILE_COND]] 31; CHECK: while.end: 32; CHECK-NEXT: ret i32 [[LOW_0]] 33; 34entry: 35 br label %while.cond 36 37while.cond: ; preds = %if.then, %if.else, %entry 38 %high.addr.0 = phi i32 [ %high, %entry ], [ %div, %if.then ], [ %high.addr.0, %if.else ] 39 %low.0 = phi i32 [ 0, %entry ], [ %low.0, %if.then ], [ %add2, %if.else ] 40 %cmp = icmp ult i32 %low.0, %high.addr.0 41 br i1 %cmp, label %while.body, label %while.end 42 43while.body: ; preds = %while.cond 44 %add = add i32 %low.0, %high.addr.0 45 %div = udiv i32 %add, 2 46 %idxprom = zext i32 %div to i64 47 %arrayidx = getelementptr inbounds i32, ptr %r, i64 %idxprom 48 %0 = load i32, ptr %arrayidx 49 %cmp1 = icmp ult i32 %k, %0 50 br i1 %cmp1, label %if.then, label %if.else 51 52if.then: ; preds = %while.body 53 br label %while.cond 54 55if.else: ; preds = %while.body 56 %add2 = add i32 %div, 1 57 br label %while.cond 58 59while.end: ; preds = %while.cond 60 ret i32 %low.0 61} 62 63define i32 @merge0(i1 %c1, i1 %c2, i1 %c3) { 64; CHECK-LABEL: define i32 @merge0 65; CHECK-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) { 66; CHECK-NEXT: j2: 67; CHECK-NEXT: [[DOT:%.*]] = select i1 [[C2]], i32 0, i32 1 68; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C3]], i32 2, i32 3 69; CHECK-NEXT: [[PHI2:%.*]] = select i1 [[C1]], i32 [[DOT]], i32 [[SPEC_SELECT]] 70; CHECK-NEXT: ret i32 [[PHI2]] 71; 72 br i1 %c1, label %if1, label %else1 73 74if1: 75 br i1 %c2, label %if2, label %else2 76 77if2: 78 br label %j1 else2: 79 br label %j1 80 81else1: 82 br i1 %c3, label %j1, label %j2 83 84j1: 85 %phi1 = phi i32 [ 0, %if2 ], [ 1, %else2 ], [ 2, %else1 ] 86 br label %j2 87 88j2: 89 %phi2 = phi i32 [ %phi1, %j1 ], [ 3, %else1 ] 90 ret i32 %phi2 91} 92 93define i8 @merge1(i8 noundef %arg, i1 %c1, i1 %c2) { 94; CHECK-LABEL: define i8 @merge1 95; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) { 96; CHECK-NEXT: entry: 97; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 98; CHECK-NEXT: i8 -123, label [[CASE0:%.*]] 99; CHECK-NEXT: i8 66, label [[SUCC:%.*]] 100; CHECK-NEXT: i8 123, label [[CASE2:%.*]] 101; CHECK-NEXT: ] 102; CHECK: unreachable: 103; CHECK-NEXT: unreachable 104; CHECK: case0: 105; CHECK-NEXT: [[C1_NOT:%.*]] = xor i1 [[C1]], true 106; CHECK-NEXT: [[C2_NOT:%.*]] = xor i1 [[C2]], true 107; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]] 108; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3 109; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4 110; CHECK-NEXT: br label [[SUCC]] 111; CHECK: case2: 112; CHECK-NEXT: br label [[SUCC]] 113; CHECK: Succ: 114; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 2, [[CASE2]] ], [ 1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ] 115; CHECK-NEXT: ret i8 [[PHI2]] 116; 117entry: 118 switch i8 %arg, label %unreachable [ 119 i8 -123, label %case0 120 i8 66, label %case1 121 i8 123, label %case2 122 ] 123 124unreachable: 125 unreachable 126 127case0: 128 br i1 %c1, label %CommonPred, label %BB 129 130case1: 131 br label %BB 132 133case2: 134 br label %BB 135 136CommonPred: 137 br i1 %c2, label %Succ, label %BB 138 139BB: 140 %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred] 141 br label %Succ 142 143Succ: 144 %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ] 145 ret i8 %phi2 146} 147 148define i8 @merge1_unfoldable_one_block(i8 noundef %arg, i1 %c1, i1 %c2) { 149; CHECK-LABEL: define i8 @merge1_unfoldable_one_block 150; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) { 151; CHECK-NEXT: entry: 152; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 153; CHECK-NEXT: i8 -123, label [[CASE0:%.*]] 154; CHECK-NEXT: i8 66, label [[SUCC:%.*]] 155; CHECK-NEXT: i8 123, label [[CASE2:%.*]] 156; CHECK-NEXT: ] 157; CHECK: unreachable: 158; CHECK-NEXT: unreachable 159; CHECK: case0: 160; CHECK-NEXT: call void @dummy() 161; CHECK-NEXT: [[C1_NOT:%.*]] = xor i1 [[C1]], true 162; CHECK-NEXT: [[C2_NOT:%.*]] = xor i1 [[C2]], true 163; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]] 164; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3 165; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4 166; CHECK-NEXT: br label [[SUCC]] 167; CHECK: case2: 168; CHECK-NEXT: br label [[SUCC]] 169; CHECK: Succ: 170; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 2, [[CASE2]] ], [ 1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ] 171; CHECK-NEXT: ret i8 [[PHI2]] 172; 173entry: 174 switch i8 %arg, label %unreachable [ 175 i8 -123, label %case0 176 i8 66, label %case1 177 i8 123, label %case2 178 ] 179 180unreachable: 181 unreachable 182 183case0: 184 call void @dummy() 185 br i1 %c1, label %CommonPred, label %BB 186 187case1: 188 br label %BB 189 190case2: 191 br label %BB 192 193CommonPred: 194 br i1 %c2, label %Succ, label %BB 195 196BB: 197 %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred] 198 br label %Succ 199 200Succ: 201 %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ] 202 ret i8 %phi2 203} 204 205define i8 @merge1_unfoldable_two_block(i8 noundef %arg, i1 %c1, i1 %c2) { 206; CHECK-LABEL: define i8 @merge1_unfoldable_two_block 207; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) { 208; CHECK-NEXT: entry: 209; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 210; CHECK-NEXT: i8 -123, label [[CASE0:%.*]] 211; CHECK-NEXT: i8 66, label [[CASE1:%.*]] 212; CHECK-NEXT: i8 123, label [[SUCC:%.*]] 213; CHECK-NEXT: ] 214; CHECK: unreachable: 215; CHECK-NEXT: unreachable 216; CHECK: case0: 217; CHECK-NEXT: call void @dummy() 218; CHECK-NEXT: [[C1_NOT:%.*]] = xor i1 [[C1]], true 219; CHECK-NEXT: [[C2_NOT:%.*]] = xor i1 [[C2]], true 220; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]] 221; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3 222; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4 223; CHECK-NEXT: br label [[SUCC]] 224; CHECK: case1: 225; CHECK-NEXT: call void @dummy() 226; CHECK-NEXT: br label [[SUCC]] 227; CHECK: Succ: 228; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 1, [[CASE1]] ], [ 2, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ] 229; CHECK-NEXT: ret i8 [[PHI2]] 230; 231entry: 232 switch i8 %arg, label %unreachable [ 233 i8 -123, label %case0 234 i8 66, label %case1 235 i8 123, label %case2 236 ] 237 238unreachable: 239 unreachable 240 241case0: 242call void @dummy() 243 br i1 %c1, label %CommonPred, label %BB 244 245case1: 246call void @dummy() 247 br label %BB 248 249case2: 250 br label %BB 251 252CommonPred: 253 br i1 %c2, label %Succ, label %BB 254 255BB: 256 %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred] 257 br label %Succ 258 259Succ: 260 %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ] 261 ret i8 %phi2 262} 263 264define i8 @merge1_unfoldable_all_block(i8 noundef %arg, i1 %c1, i1 %c2) { 265; CHECK-LABEL: define i8 @merge1_unfoldable_all_block 266; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) { 267; CHECK-NEXT: entry: 268; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 269; CHECK-NEXT: i8 -123, label [[CASE0:%.*]] 270; CHECK-NEXT: i8 66, label [[CASE1:%.*]] 271; CHECK-NEXT: i8 123, label [[CASE2:%.*]] 272; CHECK-NEXT: ] 273; CHECK: unreachable: 274; CHECK-NEXT: unreachable 275; CHECK: case0: 276; CHECK-NEXT: call void @dummy() 277; CHECK-NEXT: br i1 [[C1]], label [[COMMONPRED:%.*]], label [[SUCC:%.*]] 278; CHECK: case1: 279; CHECK-NEXT: call void @dummy() 280; CHECK-NEXT: br label [[SUCC]] 281; CHECK: case2: 282; CHECK-NEXT: call void @dummy() 283; CHECK-NEXT: br label [[SUCC]] 284; CHECK: CommonPred: 285; CHECK-NEXT: call void @dummy() 286; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C2]], i8 4, i8 3 287; CHECK-NEXT: br label [[SUCC]] 288; CHECK: Succ: 289; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 0, [[CASE0]] ], [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ [[SPEC_SELECT]], [[COMMONPRED]] ] 290; CHECK-NEXT: ret i8 [[PHI2]] 291; 292entry: 293 switch i8 %arg, label %unreachable [ 294 i8 -123, label %case0 295 i8 66, label %case1 296 i8 123, label %case2 297 ] 298 299unreachable: 300 unreachable 301 302case0: 303call void @dummy() 304 br i1 %c1, label %CommonPred, label %BB 305 306case1: 307call void @dummy() 308 br label %BB 309 310case2: 311call void @dummy() 312 br label %BB 313 314CommonPred: 315call void @dummy() 316 br i1 %c2, label %Succ, label %BB 317 318BB: 319 %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred] 320 br label %Succ 321 322Succ: 323 %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ] 324 ret i8 %phi2 325} 326 327declare void @dummy() 328 329