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