1; RUN: llc -march=amdgcn -show-mc-encoding -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=GCN -check-prefix=SIVI %s
2; RUN: llc -march=amdgcn -mcpu=bonaire -show-mc-encoding -verify-machineinstrs < %s | FileCheck -check-prefix=CI -check-prefix=GCN  %s
3; RUN: llc -march=amdgcn -mcpu=tonga -show-mc-encoding -verify-machineinstrs < %s | FileCheck -check-prefix=VI -check-prefix=GCN -check-prefix=SIVI %s
4
5; SMRD load with an immediate offset.
6; GCN-LABEL: {{^}}smrd0:
7; SICI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x1 ; encoding: [0x01
8; VI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x4
9define amdgpu_kernel void @smrd0(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
10entry:
11  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 1
12  %tmp1 = load i32, i32 addrspace(2)* %tmp
13  store i32 %tmp1, i32 addrspace(1)* %out
14  ret void
15}
16
17; SMRD load with the largest possible immediate offset.
18; GCN-LABEL: {{^}}smrd1:
19; SICI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0xff ; encoding: [0xff,0x{{[0-9]+[137]}}
20; VI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x3fc
21define amdgpu_kernel void @smrd1(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
22entry:
23  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 255
24  %tmp1 = load i32, i32 addrspace(2)* %tmp
25  store i32 %tmp1, i32 addrspace(1)* %out
26  ret void
27}
28
29; SMRD load with an offset greater than the largest possible immediate.
30; GCN-LABEL: {{^}}smrd2:
31; SI: s_movk_i32 s[[OFFSET:[0-9]]], 0x400
32; SI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], s[[OFFSET]] ; encoding: [0x0[[OFFSET]]
33; CI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x100
34; VI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x400
35; GCN: s_endpgm
36define amdgpu_kernel void @smrd2(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
37entry:
38  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 256
39  %tmp1 = load i32, i32 addrspace(2)* %tmp
40  store i32 %tmp1, i32 addrspace(1)* %out
41  ret void
42}
43
44; SMRD load with a 64-bit offset
45; GCN-LABEL: {{^}}smrd3:
46; FIXME: There are too many copies here because we don't fold immediates
47;        through REG_SEQUENCE
48; SI: s_load_dwordx2 s[{{[0-9]:[0-9]}}], s[{{[0-9]:[0-9]}}], 0xb ; encoding: [0x0b
49; TODO: Add VI checks
50; GCN: s_endpgm
51define amdgpu_kernel void @smrd3(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
52entry:
53  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 4294967296
54  %tmp1 = load i32, i32 addrspace(2)* %tmp
55  store i32 %tmp1, i32 addrspace(1)* %out
56  ret void
57}
58
59; SMRD load with the largest possible immediate offset on VI
60; GCN-LABEL: {{^}}smrd4:
61; SI: s_mov_b32 [[OFFSET:s[0-9]+]], 0xffffc
62; SI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], [[OFFSET]]
63; CI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x3ffff
64; VI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0xffffc
65define amdgpu_kernel void @smrd4(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
66entry:
67  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 262143
68  %tmp1 = load i32, i32 addrspace(2)* %tmp
69  store i32 %tmp1, i32 addrspace(1)* %out
70  ret void
71}
72
73; SMRD load with an offset greater than the largest possible immediate on VI
74; GCN-LABEL: {{^}}smrd5:
75; SIVI: s_mov_b32 [[OFFSET:s[0-9]+]], 0x100000
76; SIVI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], [[OFFSET]]
77; CI: s_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x40000
78; GCN: s_endpgm
79define amdgpu_kernel void @smrd5(i32 addrspace(1)* %out, i32 addrspace(2)* %ptr) #0 {
80entry:
81  %tmp = getelementptr i32, i32 addrspace(2)* %ptr, i64 262144
82  %tmp1 = load i32, i32 addrspace(2)* %tmp
83  store i32 %tmp1, i32 addrspace(1)* %out
84  ret void
85}
86
87; GCN-LABEL: {{^}}smrd_hazard:
88; GCN-DAG: s_mov_b32 s3, 3
89; GCN-DAG: s_mov_b32 s2, 2
90; GCN-DAG: s_mov_b32 s1, 1
91; GCN-DAG: s_mov_b32 s0, 0
92; SI-NEXT: nop 3
93; GCN-NEXT: s_buffer_load_dword s0, s[0:3], 0x0
94define amdgpu_ps float @smrd_hazard(<4 x i32> inreg %desc) #0 {
95main_body:
96  %d0 = insertelement <4 x i32> undef, i32 0, i32 0
97  %d1 = insertelement <4 x i32> %d0, i32 1, i32 1
98  %d2 = insertelement <4 x i32> %d1, i32 2, i32 2
99  %d3 = insertelement <4 x i32> %d2, i32 3, i32 3
100  %r = call float @llvm.SI.load.const.v4i32(<4 x i32> %d3, i32 0)
101  ret float %r
102}
103
104; SMRD load using the load.const.v4i32 intrinsic with an immediate offset
105; GCN-LABEL: {{^}}smrd_load_const0:
106; SICI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x4 ; encoding: [0x04
107; VI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x10
108define amdgpu_ps void @smrd_load_const0(<4 x i32> addrspace(2)* inreg %arg, <4 x i32> addrspace(2)* inreg %arg1, <32 x i8> addrspace(2)* inreg %arg2, i32 inreg %arg3, <2 x i32> %arg4, <2 x i32> %arg5, <2 x i32> %arg6, <3 x i32> %arg7, <2 x i32> %arg8, <2 x i32> %arg9, <2 x i32> %arg10, float %arg11, float %arg12, float %arg13, float %arg14, float %arg15, float %arg16, float %arg17, float %arg18, float %arg19) #0 {
109main_body:
110  %tmp = getelementptr <4 x i32>, <4 x i32> addrspace(2)* %arg, i32 0
111  %tmp20 = load <4 x i32>, <4 x i32> addrspace(2)* %tmp
112  %tmp21 = call float @llvm.SI.load.const.v4i32(<4 x i32> %tmp20, i32 16)
113  call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tmp21, float %tmp21, float %tmp21, float %tmp21, i1 true, i1 true) #0
114  ret void
115}
116
117; SMRD load using the load.const.v4i32 intrinsic with the largest possible immediate
118; offset.
119; GCN-LABEL: {{^}}smrd_load_const1:
120; SICI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0xff ; encoding: [0xff
121; VI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x3fc
122define amdgpu_ps void @smrd_load_const1(<4 x i32> addrspace(2)* inreg %arg, <4 x i32> addrspace(2)* inreg %arg1, <32 x i8> addrspace(2)* inreg %arg2, i32 inreg %arg3, <2 x i32> %arg4, <2 x i32> %arg5, <2 x i32> %arg6, <3 x i32> %arg7, <2 x i32> %arg8, <2 x i32> %arg9, <2 x i32> %arg10, float %arg11, float %arg12, float %arg13, float %arg14, float %arg15, float %arg16, float %arg17, float %arg18, float %arg19) #0 {
123main_body:
124  %tmp = getelementptr <4 x i32>, <4 x i32> addrspace(2)* %arg, i32 0
125  %tmp20 = load <4 x i32>, <4 x i32> addrspace(2)* %tmp
126  %tmp21 = call float @llvm.SI.load.const.v4i32(<4 x i32> %tmp20, i32 1020)
127  call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tmp21, float %tmp21, float %tmp21, float %tmp21, i1 true, i1 true) #0
128  ret void
129}
130
131; SMRD load using the load.const.v4i32 intrinsic with an offset greater than the
132; largets possible immediate.
133; immediate offset.
134; GCN-LABEL: {{^}}smrd_load_const2:
135; SI: s_movk_i32 s[[OFFSET:[0-9]]], 0x400
136; SI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], s[[OFFSET]] ; encoding: [0x0[[OFFSET]]
137; CI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x100
138; VI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x400
139define amdgpu_ps void @smrd_load_const2(<4 x i32> addrspace(2)* inreg %arg, <4 x i32> addrspace(2)* inreg %arg1, <32 x i8> addrspace(2)* inreg %arg2, i32 inreg %arg3, <2 x i32> %arg4, <2 x i32> %arg5, <2 x i32> %arg6, <3 x i32> %arg7, <2 x i32> %arg8, <2 x i32> %arg9, <2 x i32> %arg10, float %arg11, float %arg12, float %arg13, float %arg14, float %arg15, float %arg16, float %arg17, float %arg18, float %arg19) #0 {
140main_body:
141  %tmp = getelementptr <4 x i32>, <4 x i32> addrspace(2)* %arg, i32 0
142  %tmp20 = load <4 x i32>, <4 x i32> addrspace(2)* %tmp
143  %tmp21 = call float @llvm.SI.load.const.v4i32(<4 x i32> %tmp20, i32 1024)
144  call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tmp21, float %tmp21, float %tmp21, float %tmp21, i1 true, i1 true) #0
145  ret void
146}
147
148; SMRD load with the largest possible immediate offset on VI
149; GCN-LABEL: {{^}}smrd_load_const3:
150; SI: s_mov_b32 [[OFFSET:s[0-9]+]], 0xffffc
151; SI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], [[OFFSET]]
152; CI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x3ffff
153; VI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0xffffc
154define amdgpu_ps void @smrd_load_const3(<4 x i32> addrspace(2)* inreg %arg, <4 x i32> addrspace(2)* inreg %arg1, <32 x i8> addrspace(2)* inreg %arg2, i32 inreg %arg3, <2 x i32> %arg4, <2 x i32> %arg5, <2 x i32> %arg6, <3 x i32> %arg7, <2 x i32> %arg8, <2 x i32> %arg9, <2 x i32> %arg10, float %arg11, float %arg12, float %arg13, float %arg14, float %arg15, float %arg16, float %arg17, float %arg18, float %arg19) #0 {
155main_body:
156  %tmp = getelementptr <4 x i32>, <4 x i32> addrspace(2)* %arg, i32 0
157  %tmp20 = load <4 x i32>, <4 x i32> addrspace(2)* %tmp
158  %tmp21 = call float @llvm.SI.load.const.v4i32(<4 x i32> %tmp20, i32 1048572)
159  call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tmp21, float %tmp21, float %tmp21, float %tmp21, i1 true, i1 true) #0
160  ret void
161}
162
163; SMRD load with an offset greater than the largest possible immediate on VI
164; GCN-LABEL: {{^}}smrd_load_const4:
165; SIVI: s_mov_b32 [[OFFSET:s[0-9]+]], 0x100000
166; SIVI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], [[OFFSET]]
167; CI: s_buffer_load_dword s{{[0-9]}}, s[{{[0-9]:[0-9]}}], 0x40000
168; GCN: s_endpgm
169define amdgpu_ps void @smrd_load_const4(<4 x i32> addrspace(2)* inreg %arg, <4 x i32> addrspace(2)* inreg %arg1, <32 x i8> addrspace(2)* inreg %arg2, i32 inreg %arg3, <2 x i32> %arg4, <2 x i32> %arg5, <2 x i32> %arg6, <3 x i32> %arg7, <2 x i32> %arg8, <2 x i32> %arg9, <2 x i32> %arg10, float %arg11, float %arg12, float %arg13, float %arg14, float %arg15, float %arg16, float %arg17, float %arg18, float %arg19) #0 {
170main_body:
171  %tmp = getelementptr <4 x i32>, <4 x i32> addrspace(2)* %arg, i32 0
172  %tmp20 = load <4 x i32>, <4 x i32> addrspace(2)* %tmp
173  %tmp21 = call float @llvm.SI.load.const.v4i32(<4 x i32> %tmp20, i32 1048576)
174  call void @llvm.amdgcn.exp.f32(i32 0, i32 15, float %tmp21, float %tmp21, float %tmp21, float %tmp21, i1 true, i1 true) #0
175  ret void
176}
177
178; GCN-LABEL: {{^}}smrd_sgpr_offset:
179; GCN: s_buffer_load_dword s{{[0-9]}}, s[0:3], s4
180define amdgpu_ps float @smrd_sgpr_offset(<4 x i32> inreg %desc, i32 inreg %offset) #0 {
181main_body:
182  %r = call float @llvm.SI.load.const.v4i32(<4 x i32> %desc, i32 %offset)
183  ret float %r
184}
185
186; GCN-LABEL: {{^}}smrd_vgpr_offset:
187; GCN: buffer_load_dword v{{[0-9]}}, v0, s[0:3], 0 offen ;
188define amdgpu_ps float @smrd_vgpr_offset(<4 x i32> inreg %desc, i32 %offset) #0 {
189main_body:
190  %r = call float @llvm.SI.load.const.v4i32(<4 x i32> %desc, i32 %offset)
191  ret float %r
192}
193
194declare void @llvm.amdgcn.exp.f32(i32, i32, float, float, float, float, i1, i1) #0
195declare float @llvm.SI.load.const.v4i32(<4 x i32>, i32) #1
196
197attributes #0 = { nounwind }
198attributes #1 = { nounwind readnone }
199