1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple riscv32 -enable-shrink-wrap=false < %s \ 3; RUN: | FileCheck %s -check-prefix=RV32I-SW-NO 4; RUN: llc -mtriple riscv32 < %s \ 5; RUN: | FileCheck %s -check-prefix=RV32I-SW 6; RUN: llc -mtriple riscv32 -mattr=+save-restore < %s \ 7; RUN: | FileCheck %s -check-prefix=RV32I-SW-SR 8; RUN: llc -mtriple riscv64 < %s \ 9; RUN: | FileCheck %s -check-prefix=RV64I-SW 10 11declare void @abort() 12 13define void @eliminate_restore(i32 %n) nounwind { 14; RV32I-SW-NO-LABEL: eliminate_restore: 15; RV32I-SW-NO: # %bb.0: 16; RV32I-SW-NO-NEXT: addi sp, sp, -16 17; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 18; RV32I-SW-NO-NEXT: li a1, 32 19; RV32I-SW-NO-NEXT: bgeu a1, a0, .LBB0_2 20; RV32I-SW-NO-NEXT: # %bb.1: # %if.end 21; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 22; RV32I-SW-NO-NEXT: addi sp, sp, 16 23; RV32I-SW-NO-NEXT: ret 24; RV32I-SW-NO-NEXT: .LBB0_2: # %if.then 25; RV32I-SW-NO-NEXT: call abort 26; 27; RV32I-SW-LABEL: eliminate_restore: 28; RV32I-SW: # %bb.0: 29; RV32I-SW-NEXT: li a1, 32 30; RV32I-SW-NEXT: bgeu a1, a0, .LBB0_2 31; RV32I-SW-NEXT: # %bb.1: # %if.end 32; RV32I-SW-NEXT: ret 33; RV32I-SW-NEXT: .LBB0_2: # %if.then 34; RV32I-SW-NEXT: addi sp, sp, -16 35; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 36; RV32I-SW-NEXT: call abort 37; 38; RV32I-SW-SR-LABEL: eliminate_restore: 39; RV32I-SW-SR: # %bb.0: 40; RV32I-SW-SR-NEXT: li a1, 32 41; RV32I-SW-SR-NEXT: bgeu a1, a0, .LBB0_2 42; RV32I-SW-SR-NEXT: # %bb.1: # %if.end 43; RV32I-SW-SR-NEXT: ret 44; RV32I-SW-SR-NEXT: .LBB0_2: # %if.then 45; RV32I-SW-SR-NEXT: call t0, __riscv_save_0 46; RV32I-SW-SR-NEXT: call abort 47; 48; RV64I-SW-LABEL: eliminate_restore: 49; RV64I-SW: # %bb.0: 50; RV64I-SW-NEXT: sext.w a0, a0 51; RV64I-SW-NEXT: li a1, 32 52; RV64I-SW-NEXT: bgeu a1, a0, .LBB0_2 53; RV64I-SW-NEXT: # %bb.1: # %if.end 54; RV64I-SW-NEXT: ret 55; RV64I-SW-NEXT: .LBB0_2: # %if.then 56; RV64I-SW-NEXT: addi sp, sp, -16 57; RV64I-SW-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 58; RV64I-SW-NEXT: call abort 59 %cmp = icmp ule i32 %n, 32 60 br i1 %cmp, label %if.then, label %if.end 61 62if.then: 63 call void @abort() 64 unreachable 65 66if.end: 67 ret void 68} 69 70declare void @notdead(ptr) 71 72define void @conditional_alloca(i32 %n) nounwind { 73; RV32I-SW-NO-LABEL: conditional_alloca: 74; RV32I-SW-NO: # %bb.0: 75; RV32I-SW-NO-NEXT: addi sp, sp, -16 76; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 77; RV32I-SW-NO-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 78; RV32I-SW-NO-NEXT: addi s0, sp, 16 79; RV32I-SW-NO-NEXT: li a1, 32 80; RV32I-SW-NO-NEXT: bltu a1, a0, .LBB1_2 81; RV32I-SW-NO-NEXT: # %bb.1: # %if.then 82; RV32I-SW-NO-NEXT: addi a0, a0, 15 83; RV32I-SW-NO-NEXT: andi a0, a0, -16 84; RV32I-SW-NO-NEXT: sub a0, sp, a0 85; RV32I-SW-NO-NEXT: mv sp, a0 86; RV32I-SW-NO-NEXT: call notdead 87; RV32I-SW-NO-NEXT: .LBB1_2: # %if.end 88; RV32I-SW-NO-NEXT: addi sp, s0, -16 89; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 90; RV32I-SW-NO-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 91; RV32I-SW-NO-NEXT: addi sp, sp, 16 92; RV32I-SW-NO-NEXT: ret 93; 94; RV32I-SW-LABEL: conditional_alloca: 95; RV32I-SW: # %bb.0: 96; RV32I-SW-NEXT: li a1, 32 97; RV32I-SW-NEXT: bltu a1, a0, .LBB1_2 98; RV32I-SW-NEXT: # %bb.1: # %if.then 99; RV32I-SW-NEXT: addi sp, sp, -16 100; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 101; RV32I-SW-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 102; RV32I-SW-NEXT: addi s0, sp, 16 103; RV32I-SW-NEXT: addi a0, a0, 15 104; RV32I-SW-NEXT: andi a0, a0, -16 105; RV32I-SW-NEXT: sub a0, sp, a0 106; RV32I-SW-NEXT: mv sp, a0 107; RV32I-SW-NEXT: call notdead 108; RV32I-SW-NEXT: addi sp, s0, -16 109; RV32I-SW-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 110; RV32I-SW-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 111; RV32I-SW-NEXT: addi sp, sp, 16 112; RV32I-SW-NEXT: .LBB1_2: # %if.end 113; RV32I-SW-NEXT: ret 114; 115; RV32I-SW-SR-LABEL: conditional_alloca: 116; RV32I-SW-SR: # %bb.0: 117; RV32I-SW-SR-NEXT: li a1, 32 118; RV32I-SW-SR-NEXT: bltu a1, a0, .LBB1_2 119; RV32I-SW-SR-NEXT: # %bb.1: # %if.then 120; RV32I-SW-SR-NEXT: call t0, __riscv_save_1 121; RV32I-SW-SR-NEXT: addi s0, sp, 16 122; RV32I-SW-SR-NEXT: addi a0, a0, 15 123; RV32I-SW-SR-NEXT: andi a0, a0, -16 124; RV32I-SW-SR-NEXT: sub a0, sp, a0 125; RV32I-SW-SR-NEXT: mv sp, a0 126; RV32I-SW-SR-NEXT: call notdead 127; RV32I-SW-SR-NEXT: addi sp, s0, -16 128; RV32I-SW-SR-NEXT: tail __riscv_restore_1 129; RV32I-SW-SR-NEXT: .LBB1_2: # %if.end 130; RV32I-SW-SR-NEXT: ret 131; 132; RV64I-SW-LABEL: conditional_alloca: 133; RV64I-SW: # %bb.0: 134; RV64I-SW-NEXT: sext.w a1, a0 135; RV64I-SW-NEXT: li a2, 32 136; RV64I-SW-NEXT: bltu a2, a1, .LBB1_2 137; RV64I-SW-NEXT: # %bb.1: # %if.then 138; RV64I-SW-NEXT: addi sp, sp, -16 139; RV64I-SW-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 140; RV64I-SW-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 141; RV64I-SW-NEXT: addi s0, sp, 16 142; RV64I-SW-NEXT: slli a0, a0, 32 143; RV64I-SW-NEXT: srli a0, a0, 32 144; RV64I-SW-NEXT: addi a0, a0, 15 145; RV64I-SW-NEXT: andi a0, a0, -16 146; RV64I-SW-NEXT: sub a0, sp, a0 147; RV64I-SW-NEXT: mv sp, a0 148; RV64I-SW-NEXT: call notdead 149; RV64I-SW-NEXT: addi sp, s0, -16 150; RV64I-SW-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 151; RV64I-SW-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 152; RV64I-SW-NEXT: addi sp, sp, 16 153; RV64I-SW-NEXT: .LBB1_2: # %if.end 154; RV64I-SW-NEXT: ret 155 %cmp = icmp ule i32 %n, 32 156 br i1 %cmp, label %if.then, label %if.end 157 158if.then: 159 %addr = alloca i8, i32 %n 160 call void @notdead(ptr %addr) 161 br label %if.end 162 163if.end: 164 ret void 165} 166 167; FIXME: Rematerialize "li s1, 57" for the second use instead of spilling s1, 168; and then shrink wrap the result avoiding frame setup on the %bb.0 -> %exit 169; edge. 170define void @li_straightline_a(i32 zeroext %a, i32 zeroext %b) { 171; RV32I-SW-NO-LABEL: li_straightline_a: 172; RV32I-SW-NO: # %bb.0: 173; RV32I-SW-NO-NEXT: addi sp, sp, -16 174; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 16 175; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 176; RV32I-SW-NO-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 177; RV32I-SW-NO-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 178; RV32I-SW-NO-NEXT: .cfi_offset ra, -4 179; RV32I-SW-NO-NEXT: .cfi_offset s0, -8 180; RV32I-SW-NO-NEXT: .cfi_offset s1, -12 181; RV32I-SW-NO-NEXT: li s1, 57 182; RV32I-SW-NO-NEXT: beq a0, s1, .LBB2_3 183; RV32I-SW-NO-NEXT: # %bb.1: # %do_call 184; RV32I-SW-NO-NEXT: mv s0, a1 185; RV32I-SW-NO-NEXT: call foo 186; RV32I-SW-NO-NEXT: beq s0, s1, .LBB2_3 187; RV32I-SW-NO-NEXT: # %bb.2: # %do_call2 188; RV32I-SW-NO-NEXT: call foo 189; RV32I-SW-NO-NEXT: .LBB2_3: # %exit 190; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 191; RV32I-SW-NO-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 192; RV32I-SW-NO-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 193; RV32I-SW-NO-NEXT: .cfi_restore ra 194; RV32I-SW-NO-NEXT: .cfi_restore s0 195; RV32I-SW-NO-NEXT: .cfi_restore s1 196; RV32I-SW-NO-NEXT: addi sp, sp, 16 197; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 0 198; RV32I-SW-NO-NEXT: ret 199; 200; RV32I-SW-LABEL: li_straightline_a: 201; RV32I-SW: # %bb.0: 202; RV32I-SW-NEXT: addi sp, sp, -16 203; RV32I-SW-NEXT: .cfi_def_cfa_offset 16 204; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 205; RV32I-SW-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 206; RV32I-SW-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 207; RV32I-SW-NEXT: .cfi_offset ra, -4 208; RV32I-SW-NEXT: .cfi_offset s0, -8 209; RV32I-SW-NEXT: .cfi_offset s1, -12 210; RV32I-SW-NEXT: li s1, 57 211; RV32I-SW-NEXT: beq a0, s1, .LBB2_3 212; RV32I-SW-NEXT: # %bb.1: # %do_call 213; RV32I-SW-NEXT: mv s0, a1 214; RV32I-SW-NEXT: call foo 215; RV32I-SW-NEXT: beq s0, s1, .LBB2_3 216; RV32I-SW-NEXT: # %bb.2: # %do_call2 217; RV32I-SW-NEXT: call foo 218; RV32I-SW-NEXT: .LBB2_3: # %exit 219; RV32I-SW-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 220; RV32I-SW-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 221; RV32I-SW-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 222; RV32I-SW-NEXT: .cfi_restore ra 223; RV32I-SW-NEXT: .cfi_restore s0 224; RV32I-SW-NEXT: .cfi_restore s1 225; RV32I-SW-NEXT: addi sp, sp, 16 226; RV32I-SW-NEXT: .cfi_def_cfa_offset 0 227; RV32I-SW-NEXT: ret 228; 229; RV32I-SW-SR-LABEL: li_straightline_a: 230; RV32I-SW-SR: # %bb.0: 231; RV32I-SW-SR-NEXT: call t0, __riscv_save_2 232; RV32I-SW-SR-NEXT: .cfi_def_cfa_offset 16 233; RV32I-SW-SR-NEXT: .cfi_offset ra, -4 234; RV32I-SW-SR-NEXT: .cfi_offset s0, -8 235; RV32I-SW-SR-NEXT: .cfi_offset s1, -12 236; RV32I-SW-SR-NEXT: li s1, 57 237; RV32I-SW-SR-NEXT: beq a0, s1, .LBB2_3 238; RV32I-SW-SR-NEXT: # %bb.1: # %do_call 239; RV32I-SW-SR-NEXT: mv s0, a1 240; RV32I-SW-SR-NEXT: call foo 241; RV32I-SW-SR-NEXT: beq s0, s1, .LBB2_3 242; RV32I-SW-SR-NEXT: # %bb.2: # %do_call2 243; RV32I-SW-SR-NEXT: call foo 244; RV32I-SW-SR-NEXT: .LBB2_3: # %exit 245; RV32I-SW-SR-NEXT: tail __riscv_restore_2 246; 247; RV64I-SW-LABEL: li_straightline_a: 248; RV64I-SW: # %bb.0: 249; RV64I-SW-NEXT: addi sp, sp, -32 250; RV64I-SW-NEXT: .cfi_def_cfa_offset 32 251; RV64I-SW-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 252; RV64I-SW-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 253; RV64I-SW-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 254; RV64I-SW-NEXT: .cfi_offset ra, -8 255; RV64I-SW-NEXT: .cfi_offset s0, -16 256; RV64I-SW-NEXT: .cfi_offset s1, -24 257; RV64I-SW-NEXT: li s1, 57 258; RV64I-SW-NEXT: beq a0, s1, .LBB2_3 259; RV64I-SW-NEXT: # %bb.1: # %do_call 260; RV64I-SW-NEXT: mv s0, a1 261; RV64I-SW-NEXT: call foo 262; RV64I-SW-NEXT: beq s0, s1, .LBB2_3 263; RV64I-SW-NEXT: # %bb.2: # %do_call2 264; RV64I-SW-NEXT: call foo 265; RV64I-SW-NEXT: .LBB2_3: # %exit 266; RV64I-SW-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 267; RV64I-SW-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 268; RV64I-SW-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 269; RV64I-SW-NEXT: .cfi_restore ra 270; RV64I-SW-NEXT: .cfi_restore s0 271; RV64I-SW-NEXT: .cfi_restore s1 272; RV64I-SW-NEXT: addi sp, sp, 32 273; RV64I-SW-NEXT: .cfi_def_cfa_offset 0 274; RV64I-SW-NEXT: ret 275 %cmp0 = icmp eq i32 %a, 57 276 br i1 %cmp0, label %exit, label %do_call 277do_call: 278 call i32 @foo() 279 %cmp1 = icmp eq i32 %b, 57 280 br i1 %cmp1, label %exit, label %do_call2 281do_call2: 282 call i32 @foo() 283 br label %exit 284exit: 285 ret void 286} 287 288; FIXME: The "mv s0, a1" is only required along the do_call path, and can 289; be sunk there. We can also shrink wrap to avoid the frame setup along 290; the %bb.0 -> %exit edge. 291define void @li_straightline_b(i32 zeroext %a, i32 zeroext %b) { 292; RV32I-SW-NO-LABEL: li_straightline_b: 293; RV32I-SW-NO: # %bb.0: 294; RV32I-SW-NO-NEXT: addi sp, sp, -16 295; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 16 296; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 297; RV32I-SW-NO-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 298; RV32I-SW-NO-NEXT: .cfi_offset ra, -4 299; RV32I-SW-NO-NEXT: .cfi_offset s0, -8 300; RV32I-SW-NO-NEXT: mv s0, a1 301; RV32I-SW-NO-NEXT: li a1, 57 302; RV32I-SW-NO-NEXT: beq a0, a1, .LBB3_3 303; RV32I-SW-NO-NEXT: # %bb.1: # %do_call 304; RV32I-SW-NO-NEXT: call foo 305; RV32I-SW-NO-NEXT: li a0, 57 306; RV32I-SW-NO-NEXT: beq s0, a0, .LBB3_3 307; RV32I-SW-NO-NEXT: # %bb.2: # %do_call2 308; RV32I-SW-NO-NEXT: call foo 309; RV32I-SW-NO-NEXT: .LBB3_3: # %exit 310; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 311; RV32I-SW-NO-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 312; RV32I-SW-NO-NEXT: .cfi_restore ra 313; RV32I-SW-NO-NEXT: .cfi_restore s0 314; RV32I-SW-NO-NEXT: addi sp, sp, 16 315; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 0 316; RV32I-SW-NO-NEXT: ret 317; 318; RV32I-SW-LABEL: li_straightline_b: 319; RV32I-SW: # %bb.0: 320; RV32I-SW-NEXT: addi sp, sp, -16 321; RV32I-SW-NEXT: .cfi_def_cfa_offset 16 322; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 323; RV32I-SW-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 324; RV32I-SW-NEXT: .cfi_offset ra, -4 325; RV32I-SW-NEXT: .cfi_offset s0, -8 326; RV32I-SW-NEXT: mv s0, a1 327; RV32I-SW-NEXT: li a1, 57 328; RV32I-SW-NEXT: beq a0, a1, .LBB3_3 329; RV32I-SW-NEXT: # %bb.1: # %do_call 330; RV32I-SW-NEXT: call foo 331; RV32I-SW-NEXT: li a0, 57 332; RV32I-SW-NEXT: beq s0, a0, .LBB3_3 333; RV32I-SW-NEXT: # %bb.2: # %do_call2 334; RV32I-SW-NEXT: call foo 335; RV32I-SW-NEXT: .LBB3_3: # %exit 336; RV32I-SW-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 337; RV32I-SW-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 338; RV32I-SW-NEXT: .cfi_restore ra 339; RV32I-SW-NEXT: .cfi_restore s0 340; RV32I-SW-NEXT: addi sp, sp, 16 341; RV32I-SW-NEXT: .cfi_def_cfa_offset 0 342; RV32I-SW-NEXT: ret 343; 344; RV32I-SW-SR-LABEL: li_straightline_b: 345; RV32I-SW-SR: # %bb.0: 346; RV32I-SW-SR-NEXT: call t0, __riscv_save_1 347; RV32I-SW-SR-NEXT: .cfi_def_cfa_offset 16 348; RV32I-SW-SR-NEXT: .cfi_offset ra, -4 349; RV32I-SW-SR-NEXT: .cfi_offset s0, -8 350; RV32I-SW-SR-NEXT: mv s0, a1 351; RV32I-SW-SR-NEXT: li a1, 57 352; RV32I-SW-SR-NEXT: beq a0, a1, .LBB3_3 353; RV32I-SW-SR-NEXT: # %bb.1: # %do_call 354; RV32I-SW-SR-NEXT: call foo 355; RV32I-SW-SR-NEXT: li a0, 57 356; RV32I-SW-SR-NEXT: beq s0, a0, .LBB3_3 357; RV32I-SW-SR-NEXT: # %bb.2: # %do_call2 358; RV32I-SW-SR-NEXT: call foo 359; RV32I-SW-SR-NEXT: .LBB3_3: # %exit 360; RV32I-SW-SR-NEXT: tail __riscv_restore_1 361; 362; RV64I-SW-LABEL: li_straightline_b: 363; RV64I-SW: # %bb.0: 364; RV64I-SW-NEXT: addi sp, sp, -16 365; RV64I-SW-NEXT: .cfi_def_cfa_offset 16 366; RV64I-SW-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 367; RV64I-SW-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 368; RV64I-SW-NEXT: .cfi_offset ra, -8 369; RV64I-SW-NEXT: .cfi_offset s0, -16 370; RV64I-SW-NEXT: mv s0, a1 371; RV64I-SW-NEXT: li a1, 57 372; RV64I-SW-NEXT: beq a0, a1, .LBB3_3 373; RV64I-SW-NEXT: # %bb.1: # %do_call 374; RV64I-SW-NEXT: call foo 375; RV64I-SW-NEXT: li a0, 57 376; RV64I-SW-NEXT: beq s0, a0, .LBB3_3 377; RV64I-SW-NEXT: # %bb.2: # %do_call2 378; RV64I-SW-NEXT: call foo 379; RV64I-SW-NEXT: .LBB3_3: # %exit 380; RV64I-SW-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 381; RV64I-SW-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 382; RV64I-SW-NEXT: .cfi_restore ra 383; RV64I-SW-NEXT: .cfi_restore s0 384; RV64I-SW-NEXT: addi sp, sp, 16 385; RV64I-SW-NEXT: .cfi_def_cfa_offset 0 386; RV64I-SW-NEXT: ret 387 %cmp0 = icmp eq i32 %a, 57 388 br i1 %cmp0, label %exit, label %do_call 389do_call: 390 call i32 @foo() 391 br label %next 392next: 393 %cmp1 = icmp eq i32 %b, 57 394 br i1 %cmp1, label %exit, label %do_call2 395do_call2: 396 call i32 @foo() 397 br label %exit 398exit: 399 ret void 400} 401 402; A further variant of "b" to show that we can shrink wrap this case 403; if the second use of 57 is remat, and we eliminate the second live 404; argument. 405define void @li_straightline_c(i32 zeroext %a) { 406; RV32I-SW-NO-LABEL: li_straightline_c: 407; RV32I-SW-NO: # %bb.0: 408; RV32I-SW-NO-NEXT: addi sp, sp, -16 409; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 16 410; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 411; RV32I-SW-NO-NEXT: .cfi_offset ra, -4 412; RV32I-SW-NO-NEXT: li a1, 57 413; RV32I-SW-NO-NEXT: beq a0, a1, .LBB4_3 414; RV32I-SW-NO-NEXT: # %bb.1: # %do_call 415; RV32I-SW-NO-NEXT: call foo 416; RV32I-SW-NO-NEXT: li a1, 57 417; RV32I-SW-NO-NEXT: beq a0, a1, .LBB4_3 418; RV32I-SW-NO-NEXT: # %bb.2: # %do_call2 419; RV32I-SW-NO-NEXT: call foo 420; RV32I-SW-NO-NEXT: .LBB4_3: # %exit 421; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 422; RV32I-SW-NO-NEXT: .cfi_restore ra 423; RV32I-SW-NO-NEXT: addi sp, sp, 16 424; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 0 425; RV32I-SW-NO-NEXT: ret 426; 427; RV32I-SW-LABEL: li_straightline_c: 428; RV32I-SW: # %bb.0: 429; RV32I-SW-NEXT: li a1, 57 430; RV32I-SW-NEXT: beq a0, a1, .LBB4_4 431; RV32I-SW-NEXT: # %bb.1: # %do_call 432; RV32I-SW-NEXT: addi sp, sp, -16 433; RV32I-SW-NEXT: .cfi_def_cfa_offset 16 434; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 435; RV32I-SW-NEXT: .cfi_offset ra, -4 436; RV32I-SW-NEXT: call foo 437; RV32I-SW-NEXT: li a1, 57 438; RV32I-SW-NEXT: beq a0, a1, .LBB4_3 439; RV32I-SW-NEXT: # %bb.2: # %do_call2 440; RV32I-SW-NEXT: call foo 441; RV32I-SW-NEXT: .LBB4_3: 442; RV32I-SW-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 443; RV32I-SW-NEXT: .cfi_restore ra 444; RV32I-SW-NEXT: addi sp, sp, 16 445; RV32I-SW-NEXT: .cfi_def_cfa_offset 0 446; RV32I-SW-NEXT: .LBB4_4: # %exit 447; RV32I-SW-NEXT: ret 448; 449; RV32I-SW-SR-LABEL: li_straightline_c: 450; RV32I-SW-SR: # %bb.0: 451; RV32I-SW-SR-NEXT: li a1, 57 452; RV32I-SW-SR-NEXT: beq a0, a1, .LBB4_4 453; RV32I-SW-SR-NEXT: # %bb.1: # %do_call 454; RV32I-SW-SR-NEXT: call t0, __riscv_save_0 455; RV32I-SW-SR-NEXT: .cfi_def_cfa_offset 16 456; RV32I-SW-SR-NEXT: .cfi_offset ra, -4 457; RV32I-SW-SR-NEXT: call foo 458; RV32I-SW-SR-NEXT: li a1, 57 459; RV32I-SW-SR-NEXT: beq a0, a1, .LBB4_3 460; RV32I-SW-SR-NEXT: # %bb.2: # %do_call2 461; RV32I-SW-SR-NEXT: call foo 462; RV32I-SW-SR-NEXT: .LBB4_3: 463; RV32I-SW-SR-NEXT: tail __riscv_restore_0 464; RV32I-SW-SR-NEXT: j .LBB4_4 465; RV32I-SW-SR-NEXT: .LBB4_4: # %exit 466; RV32I-SW-SR-NEXT: ret 467; 468; RV64I-SW-LABEL: li_straightline_c: 469; RV64I-SW: # %bb.0: 470; RV64I-SW-NEXT: li a1, 57 471; RV64I-SW-NEXT: beq a0, a1, .LBB4_4 472; RV64I-SW-NEXT: # %bb.1: # %do_call 473; RV64I-SW-NEXT: addi sp, sp, -16 474; RV64I-SW-NEXT: .cfi_def_cfa_offset 16 475; RV64I-SW-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 476; RV64I-SW-NEXT: .cfi_offset ra, -8 477; RV64I-SW-NEXT: call foo 478; RV64I-SW-NEXT: li a1, 57 479; RV64I-SW-NEXT: beq a0, a1, .LBB4_3 480; RV64I-SW-NEXT: # %bb.2: # %do_call2 481; RV64I-SW-NEXT: call foo 482; RV64I-SW-NEXT: .LBB4_3: 483; RV64I-SW-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 484; RV64I-SW-NEXT: .cfi_restore ra 485; RV64I-SW-NEXT: addi sp, sp, 16 486; RV64I-SW-NEXT: .cfi_def_cfa_offset 0 487; RV64I-SW-NEXT: .LBB4_4: # %exit 488; RV64I-SW-NEXT: ret 489 %cmp0 = icmp eq i32 %a, 57 490 br i1 %cmp0, label %exit, label %do_call 491do_call: 492 %b = call i32 @foo() 493 br label %next 494next: 495 %cmp1 = icmp eq i32 %b, 57 496 br i1 %cmp1, label %exit, label %do_call2 497do_call2: 498 call i32 @foo() 499 br label %exit 500exit: 501 ret void 502} 503 504 505; In this case, the second use is in a loop, so using a callee 506; saved register to avoid a remat is the profitable choice. 507; FIXME: We can shrink wrap the frame setup around the loop 508; and avoid it along the %bb.0 -> %exit edge 509define void @li_loop(i32 zeroext %a, i32 zeroext %b) { 510; RV32I-SW-NO-LABEL: li_loop: 511; RV32I-SW-NO: # %bb.0: 512; RV32I-SW-NO-NEXT: addi sp, sp, -16 513; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 16 514; RV32I-SW-NO-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 515; RV32I-SW-NO-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 516; RV32I-SW-NO-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 517; RV32I-SW-NO-NEXT: .cfi_offset ra, -4 518; RV32I-SW-NO-NEXT: .cfi_offset s0, -8 519; RV32I-SW-NO-NEXT: .cfi_offset s1, -12 520; RV32I-SW-NO-NEXT: li s1, 57 521; RV32I-SW-NO-NEXT: beq a0, s1, .LBB5_3 522; RV32I-SW-NO-NEXT: # %bb.1: # %do_call.preheader 523; RV32I-SW-NO-NEXT: mv s0, a1 524; RV32I-SW-NO-NEXT: .LBB5_2: # %do_call 525; RV32I-SW-NO-NEXT: # =>This Inner Loop Header: Depth=1 526; RV32I-SW-NO-NEXT: call foo 527; RV32I-SW-NO-NEXT: bne s0, s1, .LBB5_2 528; RV32I-SW-NO-NEXT: .LBB5_3: # %exit 529; RV32I-SW-NO-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 530; RV32I-SW-NO-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 531; RV32I-SW-NO-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 532; RV32I-SW-NO-NEXT: .cfi_restore ra 533; RV32I-SW-NO-NEXT: .cfi_restore s0 534; RV32I-SW-NO-NEXT: .cfi_restore s1 535; RV32I-SW-NO-NEXT: addi sp, sp, 16 536; RV32I-SW-NO-NEXT: .cfi_def_cfa_offset 0 537; RV32I-SW-NO-NEXT: ret 538; 539; RV32I-SW-LABEL: li_loop: 540; RV32I-SW: # %bb.0: 541; RV32I-SW-NEXT: addi sp, sp, -16 542; RV32I-SW-NEXT: .cfi_def_cfa_offset 16 543; RV32I-SW-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 544; RV32I-SW-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 545; RV32I-SW-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 546; RV32I-SW-NEXT: .cfi_offset ra, -4 547; RV32I-SW-NEXT: .cfi_offset s0, -8 548; RV32I-SW-NEXT: .cfi_offset s1, -12 549; RV32I-SW-NEXT: li s1, 57 550; RV32I-SW-NEXT: beq a0, s1, .LBB5_3 551; RV32I-SW-NEXT: # %bb.1: # %do_call.preheader 552; RV32I-SW-NEXT: mv s0, a1 553; RV32I-SW-NEXT: .LBB5_2: # %do_call 554; RV32I-SW-NEXT: # =>This Inner Loop Header: Depth=1 555; RV32I-SW-NEXT: call foo 556; RV32I-SW-NEXT: bne s0, s1, .LBB5_2 557; RV32I-SW-NEXT: .LBB5_3: # %exit 558; RV32I-SW-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 559; RV32I-SW-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 560; RV32I-SW-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 561; RV32I-SW-NEXT: .cfi_restore ra 562; RV32I-SW-NEXT: .cfi_restore s0 563; RV32I-SW-NEXT: .cfi_restore s1 564; RV32I-SW-NEXT: addi sp, sp, 16 565; RV32I-SW-NEXT: .cfi_def_cfa_offset 0 566; RV32I-SW-NEXT: ret 567; 568; RV32I-SW-SR-LABEL: li_loop: 569; RV32I-SW-SR: # %bb.0: 570; RV32I-SW-SR-NEXT: call t0, __riscv_save_2 571; RV32I-SW-SR-NEXT: .cfi_def_cfa_offset 16 572; RV32I-SW-SR-NEXT: .cfi_offset ra, -4 573; RV32I-SW-SR-NEXT: .cfi_offset s0, -8 574; RV32I-SW-SR-NEXT: .cfi_offset s1, -12 575; RV32I-SW-SR-NEXT: li s1, 57 576; RV32I-SW-SR-NEXT: beq a0, s1, .LBB5_3 577; RV32I-SW-SR-NEXT: # %bb.1: # %do_call.preheader 578; RV32I-SW-SR-NEXT: mv s0, a1 579; RV32I-SW-SR-NEXT: .LBB5_2: # %do_call 580; RV32I-SW-SR-NEXT: # =>This Inner Loop Header: Depth=1 581; RV32I-SW-SR-NEXT: call foo 582; RV32I-SW-SR-NEXT: bne s0, s1, .LBB5_2 583; RV32I-SW-SR-NEXT: .LBB5_3: # %exit 584; RV32I-SW-SR-NEXT: tail __riscv_restore_2 585; 586; RV64I-SW-LABEL: li_loop: 587; RV64I-SW: # %bb.0: 588; RV64I-SW-NEXT: addi sp, sp, -32 589; RV64I-SW-NEXT: .cfi_def_cfa_offset 32 590; RV64I-SW-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 591; RV64I-SW-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 592; RV64I-SW-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 593; RV64I-SW-NEXT: .cfi_offset ra, -8 594; RV64I-SW-NEXT: .cfi_offset s0, -16 595; RV64I-SW-NEXT: .cfi_offset s1, -24 596; RV64I-SW-NEXT: li s1, 57 597; RV64I-SW-NEXT: beq a0, s1, .LBB5_3 598; RV64I-SW-NEXT: # %bb.1: # %do_call.preheader 599; RV64I-SW-NEXT: mv s0, a1 600; RV64I-SW-NEXT: .LBB5_2: # %do_call 601; RV64I-SW-NEXT: # =>This Inner Loop Header: Depth=1 602; RV64I-SW-NEXT: call foo 603; RV64I-SW-NEXT: bne s0, s1, .LBB5_2 604; RV64I-SW-NEXT: .LBB5_3: # %exit 605; RV64I-SW-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 606; RV64I-SW-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 607; RV64I-SW-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 608; RV64I-SW-NEXT: .cfi_restore ra 609; RV64I-SW-NEXT: .cfi_restore s0 610; RV64I-SW-NEXT: .cfi_restore s1 611; RV64I-SW-NEXT: addi sp, sp, 32 612; RV64I-SW-NEXT: .cfi_def_cfa_offset 0 613; RV64I-SW-NEXT: ret 614 %cmp0 = icmp eq i32 %a, 57 615 br i1 %cmp0, label %exit, label %do_call 616do_call: 617 call i32 @foo() 618 %cmp1 = icmp eq i32 %b, 57 619 br i1 %cmp1, label %exit, label %do_call 620exit: 621 ret void 622} 623 624declare zeroext i32 @foo() 625