1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=lanai | FileCheck %s
3
4define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp {
5; CHECK-LABEL: f:
6; CHECK:       ! %bb.0:
7; CHECK-NEXT:    st %fp, [--%sp]
8; CHECK-NEXT:    add %sp, 0x8, %fp
9; CHECK-NEXT:    sub %sp, 0x8, %sp
10; CHECK-NEXT:    sub.f %r6, %r7, %r3
11; CHECK-NEXT:    sel.gt %r3, %r0, %rv
12; CHECK-NEXT:    ld -4[%fp], %pc ! return
13; CHECK-NEXT:    add %fp, 0x0, %sp
14; CHECK-NEXT:    ld -8[%fp], %fp
15  %cmp = icmp sgt i32 %a, %b
16  %sub = sub nsw i32 %a, %b
17  %sub. = select i1 %cmp, i32 %sub, i32 0
18  ret i32 %sub.
19}
20
21define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp {
22; CHECK-LABEL: g:
23; CHECK:       ! %bb.0:
24; CHECK-NEXT:    st %fp, [--%sp]
25; CHECK-NEXT:    add %sp, 0x8, %fp
26; CHECK-NEXT:    sub %sp, 0x8, %sp
27; CHECK-NEXT:    sub.f %r7, %r6, %r3
28; CHECK-NEXT:    sel.gt %r3, %r0, %rv
29; CHECK-NEXT:    ld -4[%fp], %pc ! return
30; CHECK-NEXT:    add %fp, 0x0, %sp
31; CHECK-NEXT:    ld -8[%fp], %fp
32  %cmp = icmp slt i32 %a, %b
33  %sub = sub nsw i32 %b, %a
34  %sub. = select i1 %cmp, i32 %sub, i32 0
35  ret i32 %sub.
36}
37
38define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp {
39; CHECK-LABEL: h:
40; CHECK:       ! %bb.0:
41; CHECK-NEXT:    st %fp, [--%sp]
42; CHECK-NEXT:    add %sp, 0x8, %fp
43; CHECK-NEXT:    sub %sp, 0x8, %sp
44; CHECK-NEXT:    sub.f %r6, 0x3, %r3
45; CHECK-NEXT:    sel.gt %r3, %r7, %rv
46; CHECK-NEXT:    ld -4[%fp], %pc ! return
47; CHECK-NEXT:    add %fp, 0x0, %sp
48; CHECK-NEXT:    ld -8[%fp], %fp
49  %cmp = icmp sgt i32 %a, 3
50  %sub = sub nsw i32 %a, 3
51  %sub. = select i1 %cmp, i32 %sub, i32 %b
52  ret i32 %sub.
53}
54
55define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp {
56; CHECK-LABEL: i:
57; CHECK:       ! %bb.0:
58; CHECK-NEXT:    st %fp, [--%sp]
59; CHECK-NEXT:    add %sp, 0x8, %fp
60; CHECK-NEXT:    sub %sp, 0x8, %sp
61; CHECK-NEXT:    sub.f %r7, %r6, %r3
62; CHECK-NEXT:    sel.ugt %r3, %r0, %rv
63; CHECK-NEXT:    ld -4[%fp], %pc ! return
64; CHECK-NEXT:    add %fp, 0x0, %sp
65; CHECK-NEXT:    ld -8[%fp], %fp
66  %cmp = icmp ult i32 %a, %b
67  %sub = sub i32 %b, %a
68  %sub. = select i1 %cmp, i32 %sub, i32 0
69  ret i32 %sub.
70}
71
72; If SR is live-out, we can't remove cmp if there exists a swapped sub.
73define i32 @j(i32 inreg %a, i32 inreg %b) nounwind {
74; CHECK-LABEL: j:
75; CHECK:       ! %bb.0: ! %entry
76; CHECK-NEXT:    st %fp, [--%sp]
77; CHECK-NEXT:    add %sp, 0x8, %fp
78; CHECK-NEXT:    sub.f %r6, %r7, %rv
79; CHECK-NEXT:    bne .LBB4_2
80; CHECK-NEXT:    sub %sp, 0x8, %sp
81; CHECK-NEXT:  .LBB4_1: ! %if.then
82; CHECK-NEXT:    sub.f %r7, %r6, %r0
83; CHECK-NEXT:    sel.gt %rv, %r6, %rv
84; CHECK-NEXT:  .LBB4_2: ! %if.else
85; CHECK-NEXT:    ld -4[%fp], %pc ! return
86; CHECK-NEXT:    add %fp, 0x0, %sp
87; CHECK-NEXT:    ld -8[%fp], %fp
88entry:
89  %cmp = icmp eq i32 %b, %a
90  %sub = sub nsw i32 %a, %b
91  br i1 %cmp, label %if.then, label %if.else
92
93if.then:
94  %cmp2 = icmp sgt i32 %b, %a
95  %sel = select i1 %cmp2, i32 %sub, i32 %a
96  ret i32 %sel
97
98if.else:
99  ret i32 %sub
100}
101
102declare void @abort()
103declare void @exit(i32)
104@t = common global i32 0
105
106; If the comparison uses the C bit (signed overflow/underflow), we can't
107; omit the comparison.
108define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
109; CHECK-LABEL: cmp_ult0:
110; CHECK:       ! %bb.0: ! %entry
111; CHECK-NEXT:    st %fp, [--%sp]
112; CHECK-NEXT:    add %sp, 0x8, %fp
113; CHECK-NEXT:    mov hi(t), %r3
114; CHECK-NEXT:    or %r3, lo(t), %r3
115; CHECK-NEXT:    ld 0[%r3], %r3
116; CHECK-NEXT:    sub %r3, 0x11, %r3
117; CHECK-NEXT:    sub.f %r3, 0x0, %r0
118; CHECK-NEXT:    buge .LBB5_2
119; CHECK-NEXT:    sub %sp, 0x10, %sp
120; CHECK-NEXT:  .LBB5_1: ! %if.then
121; CHECK-NEXT:    add %pc, 0x10, %rca
122; CHECK-NEXT:    st %rca, [--%sp]
123; CHECK-NEXT:    bt abort
124; CHECK-NEXT:    nop
125; CHECK-NEXT:  .LBB5_2: ! %if.else
126; CHECK-NEXT:    st %r0, 0[%sp]
127; CHECK-NEXT:    add %pc, 0x10, %rca
128; CHECK-NEXT:    st %rca, [--%sp]
129; CHECK-NEXT:    bt exit
130; CHECK-NEXT:    nop
131entry:
132  %load = load i32, i32* @t, align 4
133  %sub = sub i32 %load, 17
134  %cmp = icmp ult i32 %sub, 0
135  br i1 %cmp, label %if.then, label %if.else
136
137if.then:
138  call void @abort()
139  unreachable
140
141if.else:
142  call void @exit(i32 0)
143  unreachable
144}
145
146; Same for the V bit.
147; TODO: add test that exercises V bit individually (VC/VS).
148define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
149; CHECK-LABEL: cmp_gt0:
150; CHECK:       ! %bb.0: ! %entry
151; CHECK-NEXT:    st %fp, [--%sp]
152; CHECK-NEXT:    add %sp, 0x8, %fp
153; CHECK-NEXT:    mov hi(t), %r3
154; CHECK-NEXT:    or %r3, lo(t), %r3
155; CHECK-NEXT:    ld 0[%r3], %r3
156; CHECK-NEXT:    sub %r3, 0x11, %r3
157; CHECK-NEXT:    sub.f %r3, 0x1, %r0
158; CHECK-NEXT:    blt .LBB6_2
159; CHECK-NEXT:    sub %sp, 0x10, %sp
160; CHECK-NEXT:  .LBB6_1: ! %if.then
161; CHECK-NEXT:    add %pc, 0x10, %rca
162; CHECK-NEXT:    st %rca, [--%sp]
163; CHECK-NEXT:    bt abort
164; CHECK-NEXT:    nop
165; CHECK-NEXT:  .LBB6_2: ! %if.else
166; CHECK-NEXT:    st %r0, 0[%sp]
167; CHECK-NEXT:    add %pc, 0x10, %rca
168; CHECK-NEXT:    st %rca, [--%sp]
169; CHECK-NEXT:    bt exit
170; CHECK-NEXT:    nop
171entry:
172  %load = load i32, i32* @t, align 4
173  %sub = sub i32 %load, 17
174  %cmp = icmp sgt i32 %sub, 0
175  br i1 %cmp, label %if.then, label %if.else
176
177if.then:
178  call void @abort()
179  unreachable
180
181if.else:
182  call void @exit(i32 0)
183  unreachable
184}
185