1; RUN: llc < %s -mtriple=lanai | FileCheck %s
2
3define i32 @f(i32 inreg %a, i32 inreg %b) nounwind ssp {
4entry:
5; CHECK-LABEL: f:
6; CHECK: sub.f %r6, %r7, [[IN:%.*]]
7; CHECK: sel.gt [[IN]], %r0, %rv
8  %cmp = icmp sgt i32 %a, %b
9  %sub = sub nsw i32 %a, %b
10  %sub. = select i1 %cmp, i32 %sub, i32 0
11  ret i32 %sub.
12}
13
14define i32 @g(i32 inreg %a, i32 inreg %b) nounwind ssp {
15entry:
16; CHECK-LABEL: g:
17; CHECK: sub.f %r7, %r6, [[IN:%.*]]
18; CHECK: sel.lt [[IN]], %r0, %rv
19  %cmp = icmp slt i32 %a, %b
20  %sub = sub nsw i32 %b, %a
21  %sub. = select i1 %cmp, i32 %sub, i32 0
22  ret i32 %sub.
23}
24
25define i32 @h(i32 inreg %a, i32 inreg %b) nounwind ssp {
26entry:
27; CHECK-LABEL: h:
28; CHECK: sub.f %r6, 0x3, [[IN:%.*]]
29; CHECK: sel.gt [[IN]], %r7, %rv
30  %cmp = icmp sgt i32 %a, 3
31  %sub = sub nsw i32 %a, 3
32  %sub. = select i1 %cmp, i32 %sub, i32 %b
33  ret i32 %sub.
34}
35
36define i32 @i(i32 inreg %a, i32 inreg %b) nounwind readnone ssp {
37entry:
38; CHECK-LABEL: i:
39; CHECK: sub.f %r7, %r6, [[IN:%.*]]
40; CHECK: sel.ult [[IN]], %r0, %rv
41  %cmp = icmp ult i32 %a, %b
42  %sub = sub i32 %b, %a
43  %sub. = select i1 %cmp, i32 %sub, i32 0
44  ret i32 %sub.
45}
46; If SR is live-out, we can't remove cmp if there exists a swapped sub.
47define i32 @j(i32 inreg %a, i32 inreg %b) nounwind {
48entry:
49; CHECK-LABEL: j:
50; CHECK: sub.f %r7, %r6, %r0
51; CHECK: sub %r6, %r7, %rv
52  %cmp = icmp eq i32 %b, %a
53  %sub = sub nsw i32 %a, %b
54  br i1 %cmp, label %if.then, label %if.else
55
56if.then:
57  %cmp2 = icmp sgt i32 %b, %a
58  %sel = select i1 %cmp2, i32 %sub, i32 %a
59  ret i32 %sel
60
61if.else:
62  ret i32 %sub
63}
64
65declare void @abort()
66declare void @exit(i32)
67@t = common global i32 0
68
69; If the comparison uses the C bit (signed overflow/underflow), we can't
70; omit the comparison.
71define i32 @cmp_ult0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
72entry:
73; CHECK-LABEL: cmp_ult0
74; CHECK: sub {{.*}}, 0x11, [[IN:%.*]]
75; CHECK: sub.f [[IN]], 0x0, %r0
76  %load = load i32, i32* @t, align 4
77  %sub = sub i32 %load, 17
78  %cmp = icmp ult i32 %sub, 0
79  br i1 %cmp, label %if.then, label %if.else
80
81if.then:
82  call void @abort()
83  unreachable
84
85if.else:
86  call void @exit(i32 0)
87  unreachable
88}
89
90; Same for the V bit.
91; TODO: add test that exercises V bit individually (VC/VS).
92define i32 @cmp_gt0(i32 inreg %a, i32 inreg %b, i32 inreg %x, i32 inreg %y) {
93entry:
94; CHECK-LABEL: cmp_gt0
95; CHECK: sub {{.*}}, 0x11, [[IN:%.*]]
96; CHECK: sub.f [[IN]], 0x1, %r0
97  %load = load i32, i32* @t, align 4
98  %sub = sub i32 %load, 17
99  %cmp = icmp sgt i32 %sub, 0
100  br i1 %cmp, label %if.then, label %if.else
101
102if.then:
103  call void @abort()
104  unreachable
105
106if.else:
107  call void @exit(i32 0)
108  unreachable
109}
110