1; Test STOCGs that are presented as selects.
2;
3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s
4
5declare void @foo(i64 *)
6
7; Test with the loaded value first.
8define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
9; CHECK-LABEL: f1:
10; CHECK: clfi %r4, 42
11; CHECK: stocghe %r3, 0(%r2)
12; CHECK: br %r14
13  %cond = icmp ult i32 %limit, 42
14  %orig = load i64 *%ptr
15  %res = select i1 %cond, i64 %orig, i64 %alt
16  store i64 %res, i64 *%ptr
17  ret void
18}
19
20; ...and with the loaded value second
21define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
22; CHECK-LABEL: f2:
23; CHECK: clfi %r4, 42
24; CHECK: stocgl %r3, 0(%r2)
25; CHECK: br %r14
26  %cond = icmp ult i32 %limit, 42
27  %orig = load i64 *%ptr
28  %res = select i1 %cond, i64 %alt, i64 %orig
29  store i64 %res, i64 *%ptr
30  ret void
31}
32
33; Check the high end of the aligned STOCG range.
34define void @f3(i64 *%base, i64 %alt, i32 %limit) {
35; CHECK-LABEL: f3:
36; CHECK: clfi %r4, 42
37; CHECK: stocghe %r3, 524280(%r2)
38; CHECK: br %r14
39  %ptr = getelementptr i64 *%base, i64 65535
40  %cond = icmp ult i32 %limit, 42
41  %orig = load i64 *%ptr
42  %res = select i1 %cond, i64 %orig, i64 %alt
43  store i64 %res, i64 *%ptr
44  ret void
45}
46
47; Check the next doubleword up.  Other sequences besides this one would be OK.
48define void @f4(i64 *%base, i64 %alt, i32 %limit) {
49; CHECK-LABEL: f4:
50; CHECK: agfi %r2, 524288
51; CHECK: clfi %r4, 42
52; CHECK: stocghe %r3, 0(%r2)
53; CHECK: br %r14
54  %ptr = getelementptr i64 *%base, i64 65536
55  %cond = icmp ult i32 %limit, 42
56  %orig = load i64 *%ptr
57  %res = select i1 %cond, i64 %orig, i64 %alt
58  store i64 %res, i64 *%ptr
59  ret void
60}
61
62; Check the low end of the STOCG range.
63define void @f5(i64 *%base, i64 %alt, i32 %limit) {
64; CHECK-LABEL: f5:
65; CHECK: clfi %r4, 42
66; CHECK: stocghe %r3, -524288(%r2)
67; CHECK: br %r14
68  %ptr = getelementptr i64 *%base, i64 -65536
69  %cond = icmp ult i32 %limit, 42
70  %orig = load i64 *%ptr
71  %res = select i1 %cond, i64 %orig, i64 %alt
72  store i64 %res, i64 *%ptr
73  ret void
74}
75
76; Check the next doubleword down, with the same comments as f4.
77define void @f6(i64 *%base, i64 %alt, i32 %limit) {
78; CHECK-LABEL: f6:
79; CHECK: agfi %r2, -524296
80; CHECK: clfi %r4, 42
81; CHECK: stocghe %r3, 0(%r2)
82; CHECK: br %r14
83  %ptr = getelementptr i64 *%base, i64 -65537
84  %cond = icmp ult i32 %limit, 42
85  %orig = load i64 *%ptr
86  %res = select i1 %cond, i64 %orig, i64 %alt
87  store i64 %res, i64 *%ptr
88  ret void
89}
90
91; Try a frame index base.
92define void @f7(i64 %alt, i32 %limit) {
93; CHECK-LABEL: f7:
94; CHECK: brasl %r14, foo@PLT
95; CHECK: stocghe {{%r[0-9]+}}, {{[0-9]+}}(%r15)
96; CHECK: brasl %r14, foo@PLT
97; CHECK: br %r14
98  %ptr = alloca i64
99  call void @foo(i64 *%ptr)
100  %cond = icmp ult i32 %limit, 42
101  %orig = load i64 *%ptr
102  %res = select i1 %cond, i64 %orig, i64 %alt
103  store i64 %res, i64 *%ptr
104  call void @foo(i64 *%ptr)
105  ret void
106}
107
108; Test that conditionally-executed stores do not use STOC, since STOC
109; is allowed to trap even when the condition is false.
110define void @f8(i64 %a, i64 %b, i64 *%dest) {
111; CHECK-LABEL: f8:
112; CHECK-NOT: stocg %r3, 0(%r4)
113; CHECK: br %r14
114entry:
115  %cmp = icmp ule i64 %a, %b
116  br i1 %cmp, label %store, label %exit
117
118store:
119  store i64 %b, i64 *%dest
120  br label %exit
121
122exit:
123  ret void
124}
125