xref: /llvm-project/llvm/test/CodeGen/RISCV/shrinkwrap.ll (revision 06246b2952d5b061e8fd75979bac9c90ccd493a4)
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