1; Test LOCFH.  See comments in asm-18.ll about testing high-word operations.
2;
3; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z13 \
4; RUN:   -no-integrated-as | FileCheck -allow-deprecated-dag-overlap %s
5
6declare void @foo(i32 *)
7
8; Test the simple case.
9define void @f1(i32 *%ptr, i32 %limit) {
10; CHECK-LABEL: f1:
11; CHECK-DAG: stepa [[REG:%r[0-5]]]
12; CHECK-DAG: clfi %r3, 42
13; CHECK: locfhhe [[REG]], 0(%r2)
14; CHECK: br %r14
15  %easy = call i32 asm "stepa $0", "=h"()
16  %cond = icmp ult i32 %limit, 42
17  %other = load i32, i32 *%ptr
18  %res = select i1 %cond, i32 %easy, i32 %other
19  call void asm sideeffect "stepb $0", "h"(i32 %res)
20  ret void
21}
22
23; ...and again with the operands swapped.
24define void @f2(i32 *%ptr, i32 %limit) {
25; CHECK-LABEL: f2:
26; CHECK-DAG: stepa [[REG:%r[0-5]]]
27; CHECK-DAG: clfi %r3, 42
28; CHECK: locfhl [[REG]], 0(%r2)
29; CHECK: br %r14
30  %easy = call i32 asm "stepa $0", "=h"()
31  %cond = icmp ult i32 %limit, 42
32  %other = load i32, i32 *%ptr
33  %res = select i1 %cond, i32 %other, i32 %easy
34  call void asm sideeffect "stepb $0", "h"(i32 %res)
35  ret void
36}
37
38; Check the high end of the aligned LOC range.
39define void @f3(i32 *%base, i32 %limit) {
40; CHECK-LABEL: f3:
41; CHECK-DAG: stepa [[REG:%r[0-5]]]
42; CHECK-DAG: clfi %r3, 42
43; CHECK: locfhhe [[REG]], 524284(%r2)
44; CHECK: br %r14
45  %easy = call i32 asm "stepa $0", "=h"()
46  %ptr = getelementptr i32, i32 *%base, i64 131071
47  %cond = icmp ult i32 %limit, 42
48  %other = load i32, i32 *%ptr
49  %res = select i1 %cond, i32 %easy, i32 %other
50  call void asm sideeffect "stepb $0", "h"(i32 %res)
51  ret void
52}
53
54; Check the next word up.  Other sequences besides this one would be OK.
55define void @f4(i32 *%base, i32 %limit) {
56; CHECK-LABEL: f4:
57; CHECK-DAG: stepa [[REG:%r[0-5]]]
58; CHECK-DAG: agfi %r2, 524288
59; CHECK-DAG: clfi %r3, 42
60; CHECK: locfhhe [[REG]], 0(%r2)
61; CHECK: br %r14
62  %easy = call i32 asm "stepa $0", "=h"()
63  %ptr = getelementptr i32, i32 *%base, i64 131072
64  %cond = icmp ult i32 %limit, 42
65  %other = load i32, i32 *%ptr
66  %res = select i1 %cond, i32 %easy, i32 %other
67  call void asm sideeffect "stepb $0", "h"(i32 %res)
68  ret void
69}
70
71; Check the low end of the LOC range.
72define void @f5(i32 *%base, i32 %limit) {
73; CHECK-LABEL: f5:
74; CHECK-DAG: stepa [[REG:%r[0-5]]]
75; CHECK-DAG: clfi %r3, 42
76; CHECK: locfhhe [[REG]], -524288(%r2)
77; CHECK: br %r14
78  %easy = call i32 asm "stepa $0", "=h"()
79  %ptr = getelementptr i32, i32 *%base, i64 -131072
80  %cond = icmp ult i32 %limit, 42
81  %other = load i32, i32 *%ptr
82  %res = select i1 %cond, i32 %easy, i32 %other
83  call void asm sideeffect "stepb $0", "h"(i32 %res)
84  ret void
85}
86
87; Check the next word down, with the same comments as f4.
88define void @f6(i32 *%base, i32 %limit) {
89; CHECK-LABEL: f6:
90; CHECK-DAG: stepa [[REG:%r[0-5]]]
91; CHECK-DAG: clfi %r3, 42
92; CHECK-DAG: agfi %r2, -524292
93; CHECK-DAG: clfi %r3, 42
94; CHECK: locfhhe [[REG]], 0(%r2)
95; CHECK: br %r14
96  %easy = call i32 asm "stepa $0", "=h"()
97  %ptr = getelementptr i32, i32 *%base, i64 -131073
98  %cond = icmp ult i32 %limit, 42
99  %other = load i32, i32 *%ptr
100  %res = select i1 %cond, i32 %easy, i32 %other
101  call void asm sideeffect "stepb $0", "h"(i32 %res)
102  ret void
103}
104
105; Try a frame index base.
106define void @f7(i32 %alt, i32 %limit) {
107; CHECK-LABEL: f7:
108; CHECK: brasl %r14, foo@PLT
109; CHECK: stepa [[REG:%r[0-5]]]
110; CHECK: locfhhe [[REG]], {{[0-9]+}}(%r15)
111; CHECK: br %r14
112  %ptr = alloca i32
113  call void @foo(i32 *%ptr)
114  %easy = call i32 asm "stepa $0", "=h"()
115  %cond = icmp ult i32 %limit, 42
116  %other = load i32, i32 *%ptr
117  %res = select i1 %cond, i32 %easy, i32 %other
118  call void asm sideeffect "stepb $0", "h"(i32 %res)
119  ret void
120}
121
122; Try a case when an index is involved.
123define void @f8(i32 %limit, i64 %base, i64 %index) {
124; CHECK-LABEL: f8:
125; CHECK-DAG: stepa [[REG:%r[0-5]]]
126; CHECK-DAG: clfi %r2, 42
127; CHECK: locfhhe [[REG]], 0({{%r[1-5]}})
128; CHECK: br %r14
129  %easy = call i32 asm "stepa $0", "=h"()
130  %add = add i64 %base, %index
131  %ptr = inttoptr i64 %add to i32 *
132  %cond = icmp ult i32 %limit, 42
133  %other = load i32, i32 *%ptr
134  %res = select i1 %cond, i32 %easy, i32 %other
135  call void asm sideeffect "stepb $0", "h"(i32 %res)
136  ret void
137}
138
139; Test that conditionally-executed loads do not use LOC, since it is allowed
140; to trap even when the condition is false.
141define void @f9(i32 %limit, i32 *%ptr) {
142; CHECK-LABEL: f9:
143; CHECK-NOT: loc
144; CHECK: lfh
145; CHECK: br %r14
146entry:
147  %easy = call i32 asm "stepa $0", "=h"()
148  %cmp = icmp ule i32 %easy, %limit
149  br i1 %cmp, label %load, label %exit
150
151load:
152  %other = load i32, i32 *%ptr
153  br label %exit
154
155exit:
156  %res = phi i32 [ %easy, %entry ], [ %other, %load ]
157  call void asm sideeffect "stepb $0", "h"(i32 %res)
158  ret void
159}
160