1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 2; RUN: llc -mtriple=riscv64 < %s | FileCheck %s 3 4define i1 @sink_li(ptr %text, ptr %text.addr.0) nounwind { 5; CHECK-LABEL: sink_li: 6; CHECK: # %bb.0: # %entry 7; CHECK-NEXT: addi sp, sp, -32 8; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 9; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 10; CHECK-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 11; CHECK-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 12; CHECK-NEXT: mv s1, a1 13; CHECK-NEXT: mv s0, a0 14; CHECK-NEXT: call toupper 15; CHECK-NEXT: li a1, 0 16; CHECK-NEXT: beqz s0, .LBB0_26 17; CHECK-NEXT: # %bb.1: # %while.body.preheader 18; CHECK-NEXT: li a2, 1 19; CHECK-NEXT: li a3, 9 20; CHECK-NEXT: li a4, 32 21; CHECK-NEXT: .LBB0_2: # %while.body 22; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 23; CHECK-NEXT: bnez a2, .LBB0_4 24; CHECK-NEXT: # %bb.3: # %while.body 25; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 26; CHECK-NEXT: bne a2, a3, .LBB0_16 27; CHECK-NEXT: .LBB0_4: # %while.body.1 28; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 29; CHECK-NEXT: bnez a2, .LBB0_6 30; CHECK-NEXT: # %bb.5: # %while.body.1 31; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 32; CHECK-NEXT: bne a2, a3, .LBB0_17 33; CHECK-NEXT: .LBB0_6: # %while.body.3 34; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 35; CHECK-NEXT: bnez a2, .LBB0_8 36; CHECK-NEXT: # %bb.7: # %while.body.3 37; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 38; CHECK-NEXT: bne a2, a4, .LBB0_19 39; CHECK-NEXT: .LBB0_8: # %while.body.4 40; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 41; CHECK-NEXT: bnez a2, .LBB0_10 42; CHECK-NEXT: # %bb.9: # %while.body.4 43; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 44; CHECK-NEXT: bne a2, a4, .LBB0_21 45; CHECK-NEXT: .LBB0_10: # %while.body.5 46; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 47; CHECK-NEXT: bnez a2, .LBB0_12 48; CHECK-NEXT: # %bb.11: # %while.body.5 49; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 50; CHECK-NEXT: bne a2, a3, .LBB0_23 51; CHECK-NEXT: .LBB0_12: # %while.body.6 52; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 53; CHECK-NEXT: bnez a2, .LBB0_2 54; CHECK-NEXT: # %bb.13: # %while.body.6 55; CHECK-NEXT: # in Loop: Header=BB0_2 Depth=1 56; CHECK-NEXT: beq a2, a3, .LBB0_2 57; CHECK-NEXT: # %bb.14: # %while.body.6 58; CHECK-NEXT: beqz a2, .LBB0_24 59; CHECK-NEXT: # %bb.15: # %strdup.exit.split.loop.exit126 60; CHECK-NEXT: addi s0, s1, 7 61; CHECK-NEXT: j .LBB0_25 62; CHECK-NEXT: .LBB0_16: # %while.body 63; CHECK-NEXT: beqz a2, .LBB0_26 64; CHECK-NEXT: j .LBB0_18 65; CHECK-NEXT: .LBB0_17: # %while.body.1 66; CHECK-NEXT: beqz a2, .LBB0_24 67; CHECK-NEXT: .LBB0_18: # %strdup.exit.loopexit 68; CHECK-NEXT: li s0, 0 69; CHECK-NEXT: j .LBB0_25 70; CHECK-NEXT: .LBB0_19: # %while.body.3 71; CHECK-NEXT: beqz a2, .LBB0_24 72; CHECK-NEXT: # %bb.20: # %strdup.exit.split.loop.exit120 73; CHECK-NEXT: addi s0, s1, 4 74; CHECK-NEXT: j .LBB0_25 75; CHECK-NEXT: .LBB0_21: # %while.body.4 76; CHECK-NEXT: beqz a2, .LBB0_24 77; CHECK-NEXT: # %bb.22: # %strdup.exit.split.loop.exit122 78; CHECK-NEXT: addi s0, s1, 5 79; CHECK-NEXT: j .LBB0_25 80; CHECK-NEXT: .LBB0_23: # %while.body.5 81; CHECK-NEXT: bnez a2, .LBB0_25 82; CHECK-NEXT: .LBB0_24: 83; CHECK-NEXT: li a1, 0 84; CHECK-NEXT: j .LBB0_26 85; CHECK-NEXT: .LBB0_25: # %strdup.exit 86; CHECK-NEXT: li s1, 0 87; CHECK-NEXT: mv s2, a0 88; CHECK-NEXT: li a0, 0 89; CHECK-NEXT: mv a1, s0 90; CHECK-NEXT: jalr s1 91; CHECK-NEXT: li a0, 0 92; CHECK-NEXT: mv a1, s2 93; CHECK-NEXT: li a2, 0 94; CHECK-NEXT: jalr s1 95; CHECK-NEXT: li a1, 1 96; CHECK-NEXT: .LBB0_26: # %return 97; CHECK-NEXT: mv a0, a1 98; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 99; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 100; CHECK-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 101; CHECK-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 102; CHECK-NEXT: addi sp, sp, 32 103; CHECK-NEXT: ret 104entry: 105 %call = call i32 @toupper() 106 %tobool.not = icmp eq ptr %text, null 107 br i1 %tobool.not, label %return, label %while.body 108 109while.body: ; preds = %while.body.6, %while.body.6, %entry 110 switch i8 1, label %strdup.exit.split.loop.exit114 [ 111 i8 1, label %while.body.1 112 i8 9, label %while.body.1 113 i8 0, label %return 114 ] 115 116while.body.1: ; preds = %while.body, %while.body 117 switch i8 1, label %strdup.exit [ 118 i8 1, label %while.body.3 119 i8 9, label %while.body.3 120 i8 0, label %return 121 ] 122 123while.body.3: ; preds = %while.body.1, %while.body.1 124 switch i8 1, label %strdup.exit.split.loop.exit120 [ 125 i8 32, label %while.body.4 126 i8 1, label %while.body.4 127 i8 0, label %return 128 ] 129 130while.body.4: ; preds = %while.body.3, %while.body.3 131 switch i8 1, label %strdup.exit.split.loop.exit122 [ 132 i8 32, label %while.body.5 133 i8 1, label %while.body.5 134 i8 0, label %return 135 ] 136 137while.body.5: ; preds = %while.body.4, %while.body.4 138 switch i8 1, label %strdup.exit.split.loop.exit124 [ 139 i8 1, label %while.body.6 140 i8 9, label %while.body.6 141 i8 0, label %return 142 ] 143 144while.body.6: ; preds = %while.body.5, %while.body.5 145 switch i8 1, label %strdup.exit.split.loop.exit126 [ 146 i8 1, label %while.body 147 i8 9, label %while.body 148 i8 0, label %return 149 ] 150 151strdup.exit.split.loop.exit114: ; preds = %while.body 152 br label %strdup.exit 153 154strdup.exit.split.loop.exit120: ; preds = %while.body.3 155 %incdec.ptr.3.le = getelementptr i8, ptr %text.addr.0, i64 4 156 br label %strdup.exit 157 158strdup.exit.split.loop.exit122: ; preds = %while.body.4 159 %incdec.ptr.4.le = getelementptr i8, ptr %text.addr.0, i64 5 160 br label %strdup.exit 161 162strdup.exit.split.loop.exit124: ; preds = %while.body.5 163 br label %strdup.exit 164 165strdup.exit.split.loop.exit126: ; preds = %while.body.6 166 %incdec.ptr.6.le = getelementptr i8, ptr %text.addr.0, i64 7 167 br label %strdup.exit 168 169strdup.exit: ; preds = %strdup.exit.split.loop.exit126, %strdup.exit.split.loop.exit124, %strdup.exit.split.loop.exit122, %strdup.exit.split.loop.exit120, %strdup.exit.split.loop.exit114, %while.body.1 170 %text.addr.0.lcssa = phi ptr [ null, %strdup.exit.split.loop.exit114 ], [ %incdec.ptr.3.le, %strdup.exit.split.loop.exit120 ], [ %incdec.ptr.4.le, %strdup.exit.split.loop.exit122 ], [ %text, %strdup.exit.split.loop.exit124 ], [ %incdec.ptr.6.le, %strdup.exit.split.loop.exit126 ], [ null, %while.body.1 ] 171 %call5.i = tail call ptr null(ptr null, ptr %text.addr.0.lcssa) 172 %memchr64 = tail call ptr null(ptr null, i32 %call, i64 0) 173 br label %return 174 175return: ; preds = %strdup.exit, %while.body.6, %while.body.5, %while.body.4, %while.body.3, %while.body.1, %while.body, %entry 176 %retval.1 = phi i1 [ false, %entry ], [ true, %strdup.exit ], [ false, %while.body ], [ false, %while.body.1 ], [ false, %while.body.3 ], [ false, %while.body.4 ], [ false, %while.body.5 ], [ false, %while.body.6 ] 177 ret i1 %retval.1 178} 179 180declare i32 @toupper() 181 182; In this example, %arg and the return value (13) have overlapping live 183; intervals because the ABI mandidates they both be placed in a0. 184define signext i32 @overlap_live_ranges(ptr %arg, i32 signext %arg1) { 185; CHECK-LABEL: overlap_live_ranges: 186; CHECK: # %bb.0: # %bb 187; CHECK-NEXT: li a2, 1 188; CHECK-NEXT: bne a1, a2, .LBB1_2 189; CHECK-NEXT: # %bb.1: # %bb2 190; CHECK-NEXT: lw a0, 4(a0) 191; CHECK-NEXT: ret 192; CHECK-NEXT: .LBB1_2: 193; CHECK-NEXT: li a0, 13 194; CHECK-NEXT: ret 195bb: 196 %i = icmp eq i32 %arg1, 1 197 br i1 %i, label %bb2, label %bb5 198 199bb2: ; preds = %bb 200 %i3 = getelementptr inbounds nuw i8, ptr %arg, i64 4 201 %i4 = load i32, ptr %i3, align 4 202 br label %bb5 203 204bb5: ; preds = %bb2, %bb 205 %i6 = phi i32 [ %i4, %bb2 ], [ 13, %bb ] 206 ret i32 %i6 207} 208 209 210; For switches, the values feeding the phi are always sunk into the 211; target blocks as the IR syntax requires the intermediate block and 212; DAG lowers it in the immediate predecessor of the phi. 213define signext i32 @switch_dispatch(i8 %a) { 214; CHECK-LABEL: switch_dispatch: 215; CHECK: # %bb.0: # %bb 216; CHECK-NEXT: addi sp, sp, -16 217; CHECK-NEXT: .cfi_def_cfa_offset 16 218; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 219; CHECK-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 220; CHECK-NEXT: .cfi_offset ra, -8 221; CHECK-NEXT: .cfi_offset s0, -16 222; CHECK-NEXT: andi a0, a0, 255 223; CHECK-NEXT: li a1, 31 224; CHECK-NEXT: blt a1, a0, .LBB2_5 225; CHECK-NEXT: # %bb.1: # %bb 226; CHECK-NEXT: beqz a0, .LBB2_10 227; CHECK-NEXT: # %bb.2: # %bb 228; CHECK-NEXT: li a1, 12 229; CHECK-NEXT: beq a0, a1, .LBB2_11 230; CHECK-NEXT: # %bb.3: # %bb 231; CHECK-NEXT: li a1, 13 232; CHECK-NEXT: bne a0, a1, .LBB2_9 233; CHECK-NEXT: # %bb.4: # %case.4 234; CHECK-NEXT: li s0, 644 235; CHECK-NEXT: j .LBB2_13 236; CHECK-NEXT: .LBB2_5: # %bb 237; CHECK-NEXT: li a1, 234 238; CHECK-NEXT: beq a0, a1, .LBB2_9 239; CHECK-NEXT: # %bb.6: # %bb 240; CHECK-NEXT: li a1, 70 241; CHECK-NEXT: beq a0, a1, .LBB2_12 242; CHECK-NEXT: # %bb.7: # %bb 243; CHECK-NEXT: li a1, 32 244; CHECK-NEXT: bne a0, a1, .LBB2_9 245; CHECK-NEXT: # %bb.8: # %case.0 246; CHECK-NEXT: li s0, 13 247; CHECK-NEXT: j .LBB2_13 248; CHECK-NEXT: .LBB2_9: # %case.default 249; CHECK-NEXT: li s0, 23 250; CHECK-NEXT: j .LBB2_13 251; CHECK-NEXT: .LBB2_10: # %case.5 252; CHECK-NEXT: li s0, 54 253; CHECK-NEXT: j .LBB2_13 254; CHECK-NEXT: .LBB2_11: # %case.1 255; CHECK-NEXT: li s0, 53 256; CHECK-NEXT: j .LBB2_13 257; CHECK-NEXT: .LBB2_12: # %case.2 258; CHECK-NEXT: li s0, 33 259; CHECK-NEXT: .LBB2_13: # %merge 260; CHECK-NEXT: mv a0, s0 261; CHECK-NEXT: call use 262; CHECK-NEXT: mv a0, s0 263; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 264; CHECK-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 265; CHECK-NEXT: .cfi_restore ra 266; CHECK-NEXT: .cfi_restore s0 267; CHECK-NEXT: addi sp, sp, 16 268; CHECK-NEXT: .cfi_def_cfa_offset 0 269; CHECK-NEXT: ret 270bb: 271 switch i8 %a, label %case.default [ 272 i8 32, label %case.0 273 i8 12, label %case.1 274 i8 70, label %case.2 275 i8 -22, label %case.3 276 i8 13, label %case.4 277 i8 0, label %case.5 278 ] 279 280case.0: 281 br label %merge 282case.1: 283 br label %merge 284case.2: 285 br label %merge 286case.3: 287 br label %merge 288case.4: 289 br label %merge 290case.5: 291 br label %merge 292case.default: 293 br label %merge 294 295merge: 296 %res = phi i32 [ 23, %case.default ], [ 13, %case.0 ], [ 53, %case.1 ], [ 33, %case.2 ], [ 23, %case.3 ], [ 644, %case.4 ], [ 54, %case.5 ] 297 call void @use(i32 %res) 298 ret i32 %res 299} 300 301; Same as for the switch, but written via manual branching. 302define signext i32 @branch_dispatch(i8 %a) { 303; CHECK-LABEL: branch_dispatch: 304; CHECK: # %bb.0: # %case.0 305; CHECK-NEXT: addi sp, sp, -16 306; CHECK-NEXT: .cfi_def_cfa_offset 16 307; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 308; CHECK-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 309; CHECK-NEXT: .cfi_offset ra, -8 310; CHECK-NEXT: .cfi_offset s0, -16 311; CHECK-NEXT: .cfi_remember_state 312; CHECK-NEXT: andi a0, a0, 255 313; CHECK-NEXT: li a1, 32 314; CHECK-NEXT: beq a0, a1, .LBB3_7 315; CHECK-NEXT: # %bb.1: # %case.1 316; CHECK-NEXT: li a1, 12 317; CHECK-NEXT: beq a0, a1, .LBB3_8 318; CHECK-NEXT: # %bb.2: # %case.2 319; CHECK-NEXT: li a1, 70 320; CHECK-NEXT: beq a0, a1, .LBB3_9 321; CHECK-NEXT: # %bb.3: # %case.3 322; CHECK-NEXT: li a1, 234 323; CHECK-NEXT: li s0, 23 324; CHECK-NEXT: beq a0, a1, .LBB3_10 325; CHECK-NEXT: # %bb.4: # %case.4 326; CHECK-NEXT: beqz a0, .LBB3_11 327; CHECK-NEXT: # %bb.5: # %case.5 328; CHECK-NEXT: li a1, 5 329; CHECK-NEXT: bne a0, a1, .LBB3_10 330; CHECK-NEXT: # %bb.6: 331; CHECK-NEXT: li s0, 54 332; CHECK-NEXT: j .LBB3_10 333; CHECK-NEXT: .LBB3_7: 334; CHECK-NEXT: li s0, 13 335; CHECK-NEXT: j .LBB3_10 336; CHECK-NEXT: .LBB3_8: 337; CHECK-NEXT: li s0, 53 338; CHECK-NEXT: j .LBB3_10 339; CHECK-NEXT: .LBB3_9: 340; CHECK-NEXT: li s0, 33 341; CHECK-NEXT: .LBB3_10: # %merge 342; CHECK-NEXT: mv a0, s0 343; CHECK-NEXT: call use 344; CHECK-NEXT: mv a0, s0 345; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 346; CHECK-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 347; CHECK-NEXT: .cfi_restore ra 348; CHECK-NEXT: .cfi_restore s0 349; CHECK-NEXT: addi sp, sp, 16 350; CHECK-NEXT: .cfi_def_cfa_offset 0 351; CHECK-NEXT: ret 352; CHECK-NEXT: .LBB3_11: 353; CHECK-NEXT: .cfi_restore_state 354; CHECK-NEXT: li s0, 644 355; CHECK-NEXT: j .LBB3_10 356case.0: 357 %c0 = icmp ne i8 %a, 32 358 br i1 %c0, label %case.1, label %merge 359case.1: 360 %c1 = icmp ne i8 %a, 12 361 br i1 %c1, label %case.2, label %merge 362case.2: 363 %c2 = icmp ne i8 %a, 70 364 br i1 %c2, label %case.3, label %merge 365case.3: 366 %c3 = icmp ne i8 %a, -22 367 br i1 %c3, label %case.4, label %merge 368case.4: 369 %c4 = icmp ne i8 %a, 0 370 br i1 %c4, label %case.5, label %merge 371case.5: 372 %c5 = icmp ne i8 %a, 5 373 br i1 %c5, label %case.default, label %merge 374case.default: 375 br label %merge 376 377merge: 378 %res = phi i32 [ 23, %case.default ], [ 13, %case.0 ], [ 53, %case.1 ], [ 33, %case.2 ], [ 23, %case.3 ], [ 644, %case.4 ], [ 54, %case.5 ] 379 call void @use(i32 %res) 380 ret i32 %res 381} 382 383 384declare void @use(i32) 385 386