1//===-------- NVPTX.cpp - Emit LLVM Code for builtins ---------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Builtin calls as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGBuiltin.h"
14#include "TargetInfo.h"
15#include "clang/Basic/TargetBuiltins.h"
16#include "llvm/IR/IntrinsicsNVPTX.h"
17#include "llvm/TargetParser/AtomicScope.h"
18
19using namespace clang;
20using namespace CodeGen;
21using namespace llvm;
22
23namespace {
24// Helper classes for mapping MMA builtins to particular LLVM intrinsic variant.
25struct NVPTXMmaLdstInfo {
26 unsigned NumResults; // Number of elements to load/store
27 // Intrinsic IDs for row/col variants. 0 if particular layout is unsupported.
28 unsigned IID_col;
29 unsigned IID_row;
30};
31
32#define MMA_INTR(geom_op_type, layout) \
33 Intrinsic::nvvm_wmma_##geom_op_type##_##layout##_stride
34#define MMA_LDST(n, geom_op_type) \
35 { n, MMA_INTR(geom_op_type, col), MMA_INTR(geom_op_type, row) }
36
37static NVPTXMmaLdstInfo getNVPTXMmaLdstInfo(unsigned BuiltinID) {
38 switch (BuiltinID) {
39 // FP MMA loads
40 case NVPTX::BI__hmma_m16n16k16_ld_a:
41 return MMA_LDST(8, m16n16k16_load_a_f16);
42 case NVPTX::BI__hmma_m16n16k16_ld_b:
43 return MMA_LDST(8, m16n16k16_load_b_f16);
44 case NVPTX::BI__hmma_m16n16k16_ld_c_f16:
45 return MMA_LDST(4, m16n16k16_load_c_f16);
46 case NVPTX::BI__hmma_m16n16k16_ld_c_f32:
47 return MMA_LDST(8, m16n16k16_load_c_f32);
48 case NVPTX::BI__hmma_m32n8k16_ld_a:
49 return MMA_LDST(8, m32n8k16_load_a_f16);
50 case NVPTX::BI__hmma_m32n8k16_ld_b:
51 return MMA_LDST(8, m32n8k16_load_b_f16);
52 case NVPTX::BI__hmma_m32n8k16_ld_c_f16:
53 return MMA_LDST(4, m32n8k16_load_c_f16);
54 case NVPTX::BI__hmma_m32n8k16_ld_c_f32:
55 return MMA_LDST(8, m32n8k16_load_c_f32);
56 case NVPTX::BI__hmma_m8n32k16_ld_a:
57 return MMA_LDST(8, m8n32k16_load_a_f16);
58 case NVPTX::BI__hmma_m8n32k16_ld_b:
59 return MMA_LDST(8, m8n32k16_load_b_f16);
60 case NVPTX::BI__hmma_m8n32k16_ld_c_f16:
61 return MMA_LDST(4, m8n32k16_load_c_f16);
62 case NVPTX::BI__hmma_m8n32k16_ld_c_f32:
63 return MMA_LDST(8, m8n32k16_load_c_f32);
64
65 // Integer MMA loads
66 case NVPTX::BI__imma_m16n16k16_ld_a_s8:
67 return MMA_LDST(2, m16n16k16_load_a_s8);
68 case NVPTX::BI__imma_m16n16k16_ld_a_u8:
69 return MMA_LDST(2, m16n16k16_load_a_u8);
70 case NVPTX::BI__imma_m16n16k16_ld_b_s8:
71 return MMA_LDST(2, m16n16k16_load_b_s8);
72 case NVPTX::BI__imma_m16n16k16_ld_b_u8:
73 return MMA_LDST(2, m16n16k16_load_b_u8);
74 case NVPTX::BI__imma_m16n16k16_ld_c:
75 return MMA_LDST(8, m16n16k16_load_c_s32);
76 case NVPTX::BI__imma_m32n8k16_ld_a_s8:
77 return MMA_LDST(4, m32n8k16_load_a_s8);
78 case NVPTX::BI__imma_m32n8k16_ld_a_u8:
79 return MMA_LDST(4, m32n8k16_load_a_u8);
80 case NVPTX::BI__imma_m32n8k16_ld_b_s8:
81 return MMA_LDST(1, m32n8k16_load_b_s8);
82 case NVPTX::BI__imma_m32n8k16_ld_b_u8:
83 return MMA_LDST(1, m32n8k16_load_b_u8);
84 case NVPTX::BI__imma_m32n8k16_ld_c:
85 return MMA_LDST(8, m32n8k16_load_c_s32);
86 case NVPTX::BI__imma_m8n32k16_ld_a_s8:
87 return MMA_LDST(1, m8n32k16_load_a_s8);
88 case NVPTX::BI__imma_m8n32k16_ld_a_u8:
89 return MMA_LDST(1, m8n32k16_load_a_u8);
90 case NVPTX::BI__imma_m8n32k16_ld_b_s8:
91 return MMA_LDST(4, m8n32k16_load_b_s8);
92 case NVPTX::BI__imma_m8n32k16_ld_b_u8:
93 return MMA_LDST(4, m8n32k16_load_b_u8);
94 case NVPTX::BI__imma_m8n32k16_ld_c:
95 return MMA_LDST(8, m8n32k16_load_c_s32);
96
97 // Sub-integer MMA loads.
98 // Only row/col layout is supported by A/B fragments.
99 case NVPTX::BI__imma_m8n8k32_ld_a_s4:
100 return {.NumResults: 1, .IID_col: 0, MMA_INTR(m8n8k32_load_a_s4, row)};
101 case NVPTX::BI__imma_m8n8k32_ld_a_u4:
102 return {.NumResults: 1, .IID_col: 0, MMA_INTR(m8n8k32_load_a_u4, row)};
103 case NVPTX::BI__imma_m8n8k32_ld_b_s4:
104 return {.NumResults: 1, MMA_INTR(m8n8k32_load_b_s4, col), .IID_row: 0};
105 case NVPTX::BI__imma_m8n8k32_ld_b_u4:
106 return {.NumResults: 1, MMA_INTR(m8n8k32_load_b_u4, col), .IID_row: 0};
107 case NVPTX::BI__imma_m8n8k32_ld_c:
108 return MMA_LDST(2, m8n8k32_load_c_s32);
109 case NVPTX::BI__bmma_m8n8k128_ld_a_b1:
110 return {.NumResults: 1, .IID_col: 0, MMA_INTR(m8n8k128_load_a_b1, row)};
111 case NVPTX::BI__bmma_m8n8k128_ld_b_b1:
112 return {.NumResults: 1, MMA_INTR(m8n8k128_load_b_b1, col), .IID_row: 0};
113 case NVPTX::BI__bmma_m8n8k128_ld_c:
114 return MMA_LDST(2, m8n8k128_load_c_s32);
115
116 // Double MMA loads
117 case NVPTX::BI__dmma_m8n8k4_ld_a:
118 return MMA_LDST(1, m8n8k4_load_a_f64);
119 case NVPTX::BI__dmma_m8n8k4_ld_b:
120 return MMA_LDST(1, m8n8k4_load_b_f64);
121 case NVPTX::BI__dmma_m8n8k4_ld_c:
122 return MMA_LDST(2, m8n8k4_load_c_f64);
123
124 // Alternate float MMA loads
125 case NVPTX::BI__mma_bf16_m16n16k16_ld_a:
126 return MMA_LDST(4, m16n16k16_load_a_bf16);
127 case NVPTX::BI__mma_bf16_m16n16k16_ld_b:
128 return MMA_LDST(4, m16n16k16_load_b_bf16);
129 case NVPTX::BI__mma_bf16_m8n32k16_ld_a:
130 return MMA_LDST(2, m8n32k16_load_a_bf16);
131 case NVPTX::BI__mma_bf16_m8n32k16_ld_b:
132 return MMA_LDST(8, m8n32k16_load_b_bf16);
133 case NVPTX::BI__mma_bf16_m32n8k16_ld_a:
134 return MMA_LDST(8, m32n8k16_load_a_bf16);
135 case NVPTX::BI__mma_bf16_m32n8k16_ld_b:
136 return MMA_LDST(2, m32n8k16_load_b_bf16);
137 case NVPTX::BI__mma_tf32_m16n16k8_ld_a:
138 return MMA_LDST(4, m16n16k8_load_a_tf32);
139 case NVPTX::BI__mma_tf32_m16n16k8_ld_b:
140 return MMA_LDST(4, m16n16k8_load_b_tf32);
141 case NVPTX::BI__mma_tf32_m16n16k8_ld_c:
142 return MMA_LDST(8, m16n16k8_load_c_f32);
143
144 // NOTE: We need to follow inconsitent naming scheme used by NVCC. Unlike
145 // PTX and LLVM IR where stores always use fragment D, NVCC builtins always
146 // use fragment C for both loads and stores.
147 // FP MMA stores.
148 case NVPTX::BI__hmma_m16n16k16_st_c_f16:
149 return MMA_LDST(4, m16n16k16_store_d_f16);
150 case NVPTX::BI__hmma_m16n16k16_st_c_f32:
151 return MMA_LDST(8, m16n16k16_store_d_f32);
152 case NVPTX::BI__hmma_m32n8k16_st_c_f16:
153 return MMA_LDST(4, m32n8k16_store_d_f16);
154 case NVPTX::BI__hmma_m32n8k16_st_c_f32:
155 return MMA_LDST(8, m32n8k16_store_d_f32);
156 case NVPTX::BI__hmma_m8n32k16_st_c_f16:
157 return MMA_LDST(4, m8n32k16_store_d_f16);
158 case NVPTX::BI__hmma_m8n32k16_st_c_f32:
159 return MMA_LDST(8, m8n32k16_store_d_f32);
160
161 // Integer and sub-integer MMA stores.
162 // Another naming quirk. Unlike other MMA builtins that use PTX types in the
163 // name, integer loads/stores use LLVM's i32.
164 case NVPTX::BI__imma_m16n16k16_st_c_i32:
165 return MMA_LDST(8, m16n16k16_store_d_s32);
166 case NVPTX::BI__imma_m32n8k16_st_c_i32:
167 return MMA_LDST(8, m32n8k16_store_d_s32);
168 case NVPTX::BI__imma_m8n32k16_st_c_i32:
169 return MMA_LDST(8, m8n32k16_store_d_s32);
170 case NVPTX::BI__imma_m8n8k32_st_c_i32:
171 return MMA_LDST(2, m8n8k32_store_d_s32);
172 case NVPTX::BI__bmma_m8n8k128_st_c_i32:
173 return MMA_LDST(2, m8n8k128_store_d_s32);
174
175 // Double MMA store
176 case NVPTX::BI__dmma_m8n8k4_st_c_f64:
177 return MMA_LDST(2, m8n8k4_store_d_f64);
178
179 // Alternate float MMA store
180 case NVPTX::BI__mma_m16n16k8_st_c_f32:
181 return MMA_LDST(8, m16n16k8_store_d_f32);
182
183 default:
184 llvm_unreachable("Unknown MMA builtin");
185 }
186}
187#undef MMA_LDST
188#undef MMA_INTR
189
190
191struct NVPTXMmaInfo {
192 unsigned NumEltsA;
193 unsigned NumEltsB;
194 unsigned NumEltsC;
195 unsigned NumEltsD;
196
197 // Variants are ordered by layout-A/layout-B/satf, where 'row' has priority
198 // over 'col' for layout. The index of non-satf variants is expected to match
199 // the undocumented layout constants used by CUDA's mma.hpp.
200 std::array<unsigned, 8> Variants;
201
202 unsigned getMMAIntrinsic(int Layout, bool Satf) {
203 unsigned Index = Layout + 4 * Satf;
204 if (Index >= Variants.size())
205 return 0;
206 return Variants[Index];
207 }
208};
209
210 // Returns an intrinsic that matches Layout and Satf for valid combinations of
211 // Layout and Satf, 0 otherwise.
212static NVPTXMmaInfo getNVPTXMmaInfo(unsigned BuiltinID) {
213 // clang-format off
214#define MMA_VARIANTS(geom, type) \
215 Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type, \
216 Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
217 Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type, \
218 Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type
219#define MMA_SATF_VARIANTS(geom, type) \
220 MMA_VARIANTS(geom, type), \
221 Intrinsic::nvvm_wmma_##geom##_mma_row_row_##type##_satfinite, \
222 Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
223 Intrinsic::nvvm_wmma_##geom##_mma_col_row_##type##_satfinite, \
224 Intrinsic::nvvm_wmma_##geom##_mma_col_col_##type##_satfinite
225// Sub-integer MMA only supports row.col layout.
226#define MMA_VARIANTS_I4(geom, type) \
227 0, \
228 Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type, \
229 0, \
230 0, \
231 0, \
232 Intrinsic::nvvm_wmma_##geom##_mma_row_col_##type##_satfinite, \
233 0, \
234 0
235// b1 MMA does not support .satfinite.
236#define MMA_VARIANTS_B1_XOR(geom, type) \
237 0, \
238 Intrinsic::nvvm_wmma_##geom##_mma_xor_popc_row_col_##type, \
239 0, \
240 0, \
241 0, \
242 0, \
243 0, \
244 0
245#define MMA_VARIANTS_B1_AND(geom, type) \
246 0, \
247 Intrinsic::nvvm_wmma_##geom##_mma_and_popc_row_col_##type, \
248 0, \
249 0, \
250 0, \
251 0, \
252 0, \
253 0
254 // clang-format on
255 switch (BuiltinID) {
256 // FP MMA
257 // Note that 'type' argument of MMA_SATF_VARIANTS uses D_C notation, while
258 // NumEltsN of return value are ordered as A,B,C,D.
259 case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
260 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, f16_f16)}}};
261 case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
262 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, f32_f16)}}};
263 case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
264 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, f16_f32)}}};
265 case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
266 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, f32_f32)}}};
267 case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
268 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, f16_f16)}}};
269 case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
270 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, f32_f16)}}};
271 case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
272 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, f16_f32)}}};
273 case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
274 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, f32_f32)}}};
275 case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
276 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, f16_f16)}}};
277 case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
278 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 4, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, f32_f16)}}};
279 case NVPTX::BI__hmma_m8n32k16_mma_f16f32:
280 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 4, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, f16_f32)}}};
281 case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
282 return {.NumEltsA: 8, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, f32_f32)}}};
283
284 // Integer MMA
285 case NVPTX::BI__imma_m16n16k16_mma_s8:
286 return {.NumEltsA: 2, .NumEltsB: 2, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, s8)}}};
287 case NVPTX::BI__imma_m16n16k16_mma_u8:
288 return {.NumEltsA: 2, .NumEltsB: 2, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m16n16k16, u8)}}};
289 case NVPTX::BI__imma_m32n8k16_mma_s8:
290 return {.NumEltsA: 4, .NumEltsB: 1, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, s8)}}};
291 case NVPTX::BI__imma_m32n8k16_mma_u8:
292 return {.NumEltsA: 4, .NumEltsB: 1, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m32n8k16, u8)}}};
293 case NVPTX::BI__imma_m8n32k16_mma_s8:
294 return {.NumEltsA: 1, .NumEltsB: 4, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, s8)}}};
295 case NVPTX::BI__imma_m8n32k16_mma_u8:
296 return {.NumEltsA: 1, .NumEltsB: 4, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_SATF_VARIANTS(m8n32k16, u8)}}};
297
298 // Sub-integer MMA
299 case NVPTX::BI__imma_m8n8k32_mma_s4:
300 return {.NumEltsA: 1, .NumEltsB: 1, .NumEltsC: 2, .NumEltsD: 2, .Variants: {._M_elems: {MMA_VARIANTS_I4(m8n8k32, s4)}}};
301 case NVPTX::BI__imma_m8n8k32_mma_u4:
302 return {.NumEltsA: 1, .NumEltsB: 1, .NumEltsC: 2, .NumEltsD: 2, .Variants: {._M_elems: {MMA_VARIANTS_I4(m8n8k32, u4)}}};
303 case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1:
304 return {.NumEltsA: 1, .NumEltsB: 1, .NumEltsC: 2, .NumEltsD: 2, .Variants: {._M_elems: {MMA_VARIANTS_B1_XOR(m8n8k128, b1)}}};
305 case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1:
306 return {.NumEltsA: 1, .NumEltsB: 1, .NumEltsC: 2, .NumEltsD: 2, .Variants: {._M_elems: {MMA_VARIANTS_B1_AND(m8n8k128, b1)}}};
307
308 // Double MMA
309 case NVPTX::BI__dmma_m8n8k4_mma_f64:
310 return {.NumEltsA: 1, .NumEltsB: 1, .NumEltsC: 2, .NumEltsD: 2, .Variants: {._M_elems: {MMA_VARIANTS(m8n8k4, f64)}}};
311
312 // Alternate FP MMA
313 case NVPTX::BI__mma_bf16_m16n16k16_mma_f32:
314 return {.NumEltsA: 4, .NumEltsB: 4, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_VARIANTS(m16n16k16, bf16)}}};
315 case NVPTX::BI__mma_bf16_m8n32k16_mma_f32:
316 return {.NumEltsA: 2, .NumEltsB: 8, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_VARIANTS(m8n32k16, bf16)}}};
317 case NVPTX::BI__mma_bf16_m32n8k16_mma_f32:
318 return {.NumEltsA: 8, .NumEltsB: 2, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_VARIANTS(m32n8k16, bf16)}}};
319 case NVPTX::BI__mma_tf32_m16n16k8_mma_f32:
320 return {.NumEltsA: 4, .NumEltsB: 4, .NumEltsC: 8, .NumEltsD: 8, .Variants: {._M_elems: {MMA_VARIANTS(m16n16k8, tf32)}}};
321 default:
322 llvm_unreachable("Unexpected builtin ID.");
323 }
324#undef MMA_VARIANTS
325#undef MMA_SATF_VARIANTS
326#undef MMA_VARIANTS_I4
327#undef MMA_VARIANTS_B1_AND
328#undef MMA_VARIANTS_B1_XOR
329}
330
331static Value *MakeLdu(unsigned IntrinsicID, CodeGenFunction &CGF,
332 const CallExpr *E) {
333 Value *Ptr = CGF.EmitScalarExpr(E: E->getArg(Arg: 0));
334 QualType ArgType = E->getArg(Arg: 0)->getType();
335 clang::CharUnits Align = CGF.CGM.getNaturalPointeeTypeAlignment(T: ArgType);
336 llvm::Type *ElemTy = CGF.ConvertTypeForMem(T: ArgType->getPointeeType());
337 return CGF.Builder.CreateCall(
338 Callee: CGF.CGM.getIntrinsic(IID: IntrinsicID, Tys: {ElemTy, Ptr->getType()}),
339 Args: {Ptr, ConstantInt::get(Ty: CGF.Builder.getInt32Ty(), V: Align.getQuantity())});
340}
341
342static Value *MakeLdg(CodeGenFunction &CGF, const CallExpr *E) {
343 Value *Ptr = CGF.EmitScalarExpr(E: E->getArg(Arg: 0));
344 QualType ArgType = E->getArg(Arg: 0)->getType();
345 clang::CharUnits AlignV = CGF.CGM.getNaturalPointeeTypeAlignment(T: ArgType);
346 llvm::Type *ElemTy = CGF.ConvertTypeForMem(T: ArgType->getPointeeType());
347
348 // Use addrspace(1) for NVPTX ADDRESS_SPACE_GLOBAL
349 auto *ASC = CGF.Builder.CreateAddrSpaceCast(V: Ptr, DestTy: CGF.Builder.getPtrTy(AddrSpace: 1));
350 auto *LD = CGF.Builder.CreateAlignedLoad(Ty: ElemTy, Ptr: ASC, Align: AlignV.getAsAlign());
351 MDNode *MD = MDNode::get(Context&: CGF.Builder.getContext(), MDs: {});
352 LD->setMetadata(KindID: LLVMContext::MD_invariant_load, Node: MD);
353
354 return LD;
355}
356
357// `Scope` is AtomicScope::Workgroup for _cta builtins and AtomicScope::System
358// for _sys builtins.
359static Value *MakeScopedAtomicRMW(CodeGenFunction &CGF, const CallExpr *E,
360 llvm::AtomicRMWInst::BinOp Kind,
361 llvm::AtomicScope Scope) {
362 Address Ptr = CGF.EmitPointerWithAlignment(Addr: E->getArg(Arg: 0));
363 Value *Val = CGF.EmitScalarExpr(E: E->getArg(Arg: 1));
364 llvm::SyncScope::ID SSID = CGF.getLLVMContext().getOrInsertSyncScopeID(
365 SSN: *llvm::getAtomicScopeIRString(T: CGF.getTarget().getTriple(), S: Scope));
366 llvm::AtomicRMWInst *RMW = CGF.Builder.CreateAtomicRMW(
367 Op: Kind, Addr: Ptr, Val, Ordering: llvm::AtomicOrdering::Monotonic, SSID);
368
369 // CUDA's atomicAdd_block()/atomicAdd_system() reach this through the scoped
370 // add builtins, and are defined in terms of the native atom.add just as the
371 // unscoped atomicAdd() is. The helper ignores everything that is not a
372 // floating-point add, so the other scoped operations are unaffected.
373 addAtomicIgnoreDenormalModeMetadata(CGF, AtomicInst&: *RMW, /*AllowHalf=*/true);
374 return RMW;
375}
376
377// `Scope` is AtomicScope::Workgroup for _cta builtins and AtomicScope::System
378// for _sys builtins.
379static Value *MakeScopedAtomicCAS(CodeGenFunction &CGF, const CallExpr *E,
380 llvm::AtomicScope Scope) {
381 Address Ptr = CGF.EmitPointerWithAlignment(Addr: E->getArg(Arg: 0));
382 Value *Cmp = CGF.EmitScalarExpr(E: E->getArg(Arg: 1));
383 Value *New = CGF.EmitScalarExpr(E: E->getArg(Arg: 2));
384 llvm::SyncScope::ID SSID = CGF.getLLVMContext().getOrInsertSyncScopeID(
385 SSN: *llvm::getAtomicScopeIRString(T: CGF.getTarget().getTriple(), S: Scope));
386 Value *Pair = CGF.Builder.CreateAtomicCmpXchg(
387 Addr: Ptr, Cmp, New, SuccessOrdering: llvm::AtomicOrdering::Monotonic,
388 FailureOrdering: llvm::AtomicOrdering::Monotonic, SSID);
389 return CGF.Builder.CreateExtractValue(Agg: Pair, Idxs: 0);
390}
391
392static Value *MakeCpAsync(unsigned IntrinsicID, unsigned IntrinsicIDS,
393 CodeGenFunction &CGF, const CallExpr *E,
394 int SrcSize) {
395 return E->getNumArgs() == 3
396 ? CGF.Builder.CreateCall(Callee: CGF.CGM.getIntrinsic(IID: IntrinsicIDS),
397 Args: {CGF.EmitScalarExpr(E: E->getArg(Arg: 0)),
398 CGF.EmitScalarExpr(E: E->getArg(Arg: 1)),
399 CGF.EmitScalarExpr(E: E->getArg(Arg: 2))})
400 : CGF.Builder.CreateCall(Callee: CGF.CGM.getIntrinsic(IID: IntrinsicID),
401 Args: {CGF.EmitScalarExpr(E: E->getArg(Arg: 0)),
402 CGF.EmitScalarExpr(E: E->getArg(Arg: 1))});
403}
404
405static Value *MakeHalfType(Function *Intrinsic, unsigned BuiltinID,
406 const CallExpr *E, CodeGenFunction &CGF,
407 ArrayRef<Value *> TrailingArgs = {}) {
408 SmallVector<Value *, 16> Args;
409 auto *FTy = Intrinsic->getFunctionType();
410 unsigned ICEArguments = 0;
411 ASTContext::GetBuiltinTypeError Error;
412 CGF.CGM.getContext().GetBuiltinType(ID: BuiltinID, Error, IntegerConstantArgs: &ICEArguments);
413 assert(Error == ASTContext::GE_None && "Should not codegen an error");
414 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
415 assert((ICEArguments & (1 << i)) == 0);
416 auto *ArgValue = CGF.EmitScalarExpr(E: E->getArg(Arg: i));
417 auto *PTy = FTy->getParamType(i);
418 if (PTy != ArgValue->getType())
419 ArgValue = CGF.Builder.CreateBitCast(V: ArgValue, DestTy: PTy);
420 Args.push_back(Elt: ArgValue);
421 }
422
423 llvm::append_range(C&: Args, R&: TrailingArgs);
424 appendDefaultIntrinsicArgs(Args, F: Intrinsic);
425
426 return CGF.Builder.CreateCall(Callee: Intrinsic, Args);
427}
428
429static Value *MakeHalfType(unsigned IntrinsicID, unsigned BuiltinID,
430 const CallExpr *E, CodeGenFunction &CGF,
431 ArrayRef<Value *> TrailingArgs = {}) {
432 return MakeHalfType(Intrinsic: CGF.CGM.getIntrinsic(IID: IntrinsicID), BuiltinID, E, CGF,
433 TrailingArgs);
434}
435
436static Value *MakeFMAOOB(unsigned IntrinsicID, llvm::Type *Ty,
437 const CallExpr *E, CodeGenFunction &CGF) {
438 return CGF.Builder.CreateCall(Callee: CGF.CGM.getIntrinsic(IID: IntrinsicID, Tys: {Ty}),
439 Args: {CGF.EmitScalarExpr(E: E->getArg(Arg: 0)),
440 CGF.EmitScalarExpr(E: E->getArg(Arg: 1)),
441 CGF.EmitScalarExpr(E: E->getArg(Arg: 2))});
442}
443
444static Value *MakeFPArith(unsigned IntrinsicID, APFloat::roundingMode RM,
445 unsigned BuiltinID, const CallExpr *E,
446 CodeGenFunction &CGF) {
447 llvm::Type *Ty = CGF.ConvertType(T: E->getType());
448 return MakeHalfType(Intrinsic: CGF.CGM.getIntrinsic(IID: IntrinsicID, Tys: Ty), BuiltinID, E, CGF,
449 TrailingArgs: {CGF.Builder.getInt32(C: static_cast<int>(RM))});
450}
451
452} // namespace
453
454Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
455 const CallExpr *E) {
456 switch (BuiltinID) {
457 case NVPTX::BI__nvvm_mulhi_i:
458 case NVPTX::BI__nvvm_mulhi_ui:
459 case NVPTX::BI__nvvm_mulhi_ll:
460 case NVPTX::BI__nvvm_mulhi_ull:
461 return Builder.CreateBinaryIntrinsic(
462 ID: E->getType()->hasSignedIntegerRepresentation() ? Intrinsic::smulh
463 : Intrinsic::umulh,
464 LHS: EmitScalarExpr(E: E->getArg(Arg: 0)), RHS: EmitScalarExpr(E: E->getArg(Arg: 1)));
465 case NVPTX::BI__nvvm_atom_add_gen_i:
466 case NVPTX::BI__nvvm_atom_add_gen_l:
467 case NVPTX::BI__nvvm_atom_add_gen_ll:
468 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Add, E,
469 Ordering: AtomicOrdering::Monotonic);
470
471 case NVPTX::BI__nvvm_atom_sub_gen_i:
472 case NVPTX::BI__nvvm_atom_sub_gen_l:
473 case NVPTX::BI__nvvm_atom_sub_gen_ll:
474 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Sub, E,
475 Ordering: AtomicOrdering::Monotonic);
476
477 case NVPTX::BI__nvvm_atom_and_gen_i:
478 case NVPTX::BI__nvvm_atom_and_gen_l:
479 case NVPTX::BI__nvvm_atom_and_gen_ll:
480 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::And, E,
481 Ordering: AtomicOrdering::Monotonic);
482
483 case NVPTX::BI__nvvm_atom_or_gen_i:
484 case NVPTX::BI__nvvm_atom_or_gen_l:
485 case NVPTX::BI__nvvm_atom_or_gen_ll:
486 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Or, E,
487 Ordering: AtomicOrdering::Monotonic);
488
489 case NVPTX::BI__nvvm_atom_xor_gen_i:
490 case NVPTX::BI__nvvm_atom_xor_gen_l:
491 case NVPTX::BI__nvvm_atom_xor_gen_ll:
492 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Xor, E,
493 Ordering: AtomicOrdering::Monotonic);
494
495 case NVPTX::BI__nvvm_atom_xchg_gen_i:
496 case NVPTX::BI__nvvm_atom_xchg_gen_l:
497 case NVPTX::BI__nvvm_atom_xchg_gen_ll:
498 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Xchg, E,
499 Ordering: AtomicOrdering::Monotonic);
500
501 case NVPTX::BI__nvvm_atom_max_gen_i:
502 case NVPTX::BI__nvvm_atom_max_gen_l:
503 case NVPTX::BI__nvvm_atom_max_gen_ll:
504 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Max, E,
505 Ordering: AtomicOrdering::Monotonic);
506
507 case NVPTX::BI__nvvm_atom_max_gen_ui:
508 case NVPTX::BI__nvvm_atom_max_gen_ul:
509 case NVPTX::BI__nvvm_atom_max_gen_ull:
510 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::UMax, E,
511 Ordering: AtomicOrdering::Monotonic);
512
513 case NVPTX::BI__nvvm_atom_min_gen_i:
514 case NVPTX::BI__nvvm_atom_min_gen_l:
515 case NVPTX::BI__nvvm_atom_min_gen_ll:
516 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::Min, E,
517 Ordering: AtomicOrdering::Monotonic);
518
519 case NVPTX::BI__nvvm_atom_min_gen_ui:
520 case NVPTX::BI__nvvm_atom_min_gen_ul:
521 case NVPTX::BI__nvvm_atom_min_gen_ull:
522 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::UMin, E,
523 Ordering: AtomicOrdering::Monotonic);
524
525 case NVPTX::BI__nvvm_atom_cas_gen_us:
526 case NVPTX::BI__nvvm_atom_cas_gen_i:
527 case NVPTX::BI__nvvm_atom_cas_gen_l:
528 case NVPTX::BI__nvvm_atom_cas_gen_ll:
529 // __nvvm_atom_cas_gen_* should return the old value rather than the
530 // success flag.
531 return MakeAtomicCmpXchgValue(CGF&: *this, E, /*ReturnBool=*/false,
532 SuccessOrdering: AtomicOrdering::Monotonic,
533 FailureOrdering: AtomicOrdering::Monotonic);
534
535 case NVPTX::BI__nvvm_atom_add_gen_f:
536 case NVPTX::BI__nvvm_atom_add_gen_d: {
537 Address DestAddr = EmitPointerWithAlignment(Addr: E->getArg(Arg: 0));
538 Value *Val = EmitScalarExpr(E: E->getArg(Arg: 1));
539
540 llvm::AtomicRMWInst *RMW = Builder.CreateAtomicRMW(
541 Op: llvm::AtomicRMWInst::FAdd, Addr: DestAddr, Val, Ordering: AtomicOrdering::Monotonic);
542
543 // CUDA's atomicAdd() is defined in terms of the native atom.add
544 // instruction, whose denormal behavior is fixed by the hardware and need
545 // not agree with the function's denormal mode. Without this the atomic is
546 // expanded into a CAS loop whenever the two disagree.
547 addAtomicIgnoreDenormalModeMetadata(CGF&: *this, AtomicInst&: *RMW, /*AllowHalf=*/true);
548 return RMW;
549 }
550
551 case NVPTX::BI__nvvm_atom_inc_gen_ui:
552 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::UIncWrap, E,
553 Ordering: AtomicOrdering::Monotonic);
554
555 case NVPTX::BI__nvvm_atom_dec_gen_ui:
556 return MakeBinaryAtomicValue(CGF&: *this, Kind: llvm::AtomicRMWInst::UDecWrap, E,
557 Ordering: AtomicOrdering::Monotonic);
558
559 case NVPTX::BI__nvvm_ldg_c:
560 case NVPTX::BI__nvvm_ldg_sc:
561 case NVPTX::BI__nvvm_ldg_c2:
562 case NVPTX::BI__nvvm_ldg_sc2:
563 case NVPTX::BI__nvvm_ldg_c4:
564 case NVPTX::BI__nvvm_ldg_sc4:
565 case NVPTX::BI__nvvm_ldg_s:
566 case NVPTX::BI__nvvm_ldg_s2:
567 case NVPTX::BI__nvvm_ldg_s4:
568 case NVPTX::BI__nvvm_ldg_i:
569 case NVPTX::BI__nvvm_ldg_i2:
570 case NVPTX::BI__nvvm_ldg_i4:
571 case NVPTX::BI__nvvm_ldg_l:
572 case NVPTX::BI__nvvm_ldg_l2:
573 case NVPTX::BI__nvvm_ldg_ll:
574 case NVPTX::BI__nvvm_ldg_ll2:
575 case NVPTX::BI__nvvm_ldg_uc:
576 case NVPTX::BI__nvvm_ldg_uc2:
577 case NVPTX::BI__nvvm_ldg_uc4:
578 case NVPTX::BI__nvvm_ldg_us:
579 case NVPTX::BI__nvvm_ldg_us2:
580 case NVPTX::BI__nvvm_ldg_us4:
581 case NVPTX::BI__nvvm_ldg_ui:
582 case NVPTX::BI__nvvm_ldg_ui2:
583 case NVPTX::BI__nvvm_ldg_ui4:
584 case NVPTX::BI__nvvm_ldg_ul:
585 case NVPTX::BI__nvvm_ldg_ul2:
586 case NVPTX::BI__nvvm_ldg_ull:
587 case NVPTX::BI__nvvm_ldg_ull2:
588 case NVPTX::BI__nvvm_ldg_f:
589 case NVPTX::BI__nvvm_ldg_f2:
590 case NVPTX::BI__nvvm_ldg_f4:
591 case NVPTX::BI__nvvm_ldg_d:
592 case NVPTX::BI__nvvm_ldg_d2:
593 // PTX Interoperability section 2.2: "For a vector with an even number of
594 // elements, its alignment is set to number of elements times the alignment
595 // of its member: n*alignof(t)."
596 return MakeLdg(CGF&: *this, E);
597
598 case NVPTX::BI__nvvm_ldu_c:
599 case NVPTX::BI__nvvm_ldu_sc:
600 case NVPTX::BI__nvvm_ldu_c2:
601 case NVPTX::BI__nvvm_ldu_sc2:
602 case NVPTX::BI__nvvm_ldu_c4:
603 case NVPTX::BI__nvvm_ldu_sc4:
604 case NVPTX::BI__nvvm_ldu_s:
605 case NVPTX::BI__nvvm_ldu_s2:
606 case NVPTX::BI__nvvm_ldu_s4:
607 case NVPTX::BI__nvvm_ldu_i:
608 case NVPTX::BI__nvvm_ldu_i2:
609 case NVPTX::BI__nvvm_ldu_i4:
610 case NVPTX::BI__nvvm_ldu_l:
611 case NVPTX::BI__nvvm_ldu_l2:
612 case NVPTX::BI__nvvm_ldu_ll:
613 case NVPTX::BI__nvvm_ldu_ll2:
614 case NVPTX::BI__nvvm_ldu_uc:
615 case NVPTX::BI__nvvm_ldu_uc2:
616 case NVPTX::BI__nvvm_ldu_uc4:
617 case NVPTX::BI__nvvm_ldu_us:
618 case NVPTX::BI__nvvm_ldu_us2:
619 case NVPTX::BI__nvvm_ldu_us4:
620 case NVPTX::BI__nvvm_ldu_ui:
621 case NVPTX::BI__nvvm_ldu_ui2:
622 case NVPTX::BI__nvvm_ldu_ui4:
623 case NVPTX::BI__nvvm_ldu_ul:
624 case NVPTX::BI__nvvm_ldu_ul2:
625 case NVPTX::BI__nvvm_ldu_ull:
626 case NVPTX::BI__nvvm_ldu_ull2:
627 return MakeLdu(IntrinsicID: Intrinsic::nvvm_ldu_global_i, CGF&: *this, E);
628 case NVPTX::BI__nvvm_ldu_f:
629 case NVPTX::BI__nvvm_ldu_f2:
630 case NVPTX::BI__nvvm_ldu_f4:
631 case NVPTX::BI__nvvm_ldu_d:
632 case NVPTX::BI__nvvm_ldu_d2:
633 return MakeLdu(IntrinsicID: Intrinsic::nvvm_ldu_global_f, CGF&: *this, E);
634
635 case NVPTX::BI__nvvm_atom_cta_add_gen_i:
636 case NVPTX::BI__nvvm_atom_cta_add_gen_l:
637 case NVPTX::BI__nvvm_atom_cta_add_gen_ll:
638 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Add,
639 Scope: llvm::AtomicScope::Workgroup);
640 case NVPTX::BI__nvvm_atom_sys_add_gen_i:
641 case NVPTX::BI__nvvm_atom_sys_add_gen_l:
642 case NVPTX::BI__nvvm_atom_sys_add_gen_ll:
643 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Add,
644 Scope: llvm::AtomicScope::System);
645 case NVPTX::BI__nvvm_atom_cta_add_gen_f:
646 case NVPTX::BI__nvvm_atom_cta_add_gen_d:
647 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::FAdd,
648 Scope: llvm::AtomicScope::Workgroup);
649 case NVPTX::BI__nvvm_atom_sys_add_gen_f:
650 case NVPTX::BI__nvvm_atom_sys_add_gen_d:
651 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::FAdd,
652 Scope: llvm::AtomicScope::System);
653 case NVPTX::BI__nvvm_atom_cta_xchg_gen_i:
654 case NVPTX::BI__nvvm_atom_cta_xchg_gen_l:
655 case NVPTX::BI__nvvm_atom_cta_xchg_gen_ll:
656 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Xchg,
657 Scope: llvm::AtomicScope::Workgroup);
658 case NVPTX::BI__nvvm_atom_sys_xchg_gen_i:
659 case NVPTX::BI__nvvm_atom_sys_xchg_gen_l:
660 case NVPTX::BI__nvvm_atom_sys_xchg_gen_ll:
661 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Xchg,
662 Scope: llvm::AtomicScope::System);
663 case NVPTX::BI__nvvm_atom_cta_max_gen_i:
664 case NVPTX::BI__nvvm_atom_cta_max_gen_l:
665 case NVPTX::BI__nvvm_atom_cta_max_gen_ll:
666 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Max,
667 Scope: llvm::AtomicScope::Workgroup);
668 case NVPTX::BI__nvvm_atom_cta_max_gen_ui:
669 case NVPTX::BI__nvvm_atom_cta_max_gen_ul:
670 case NVPTX::BI__nvvm_atom_cta_max_gen_ull:
671 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UMax,
672 Scope: llvm::AtomicScope::Workgroup);
673 case NVPTX::BI__nvvm_atom_sys_max_gen_i:
674 case NVPTX::BI__nvvm_atom_sys_max_gen_l:
675 case NVPTX::BI__nvvm_atom_sys_max_gen_ll:
676 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Max,
677 Scope: llvm::AtomicScope::System);
678 case NVPTX::BI__nvvm_atom_sys_max_gen_ui:
679 case NVPTX::BI__nvvm_atom_sys_max_gen_ul:
680 case NVPTX::BI__nvvm_atom_sys_max_gen_ull:
681 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UMax,
682 Scope: llvm::AtomicScope::System);
683 case NVPTX::BI__nvvm_atom_cta_min_gen_i:
684 case NVPTX::BI__nvvm_atom_cta_min_gen_l:
685 case NVPTX::BI__nvvm_atom_cta_min_gen_ll:
686 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Min,
687 Scope: llvm::AtomicScope::Workgroup);
688 case NVPTX::BI__nvvm_atom_cta_min_gen_ui:
689 case NVPTX::BI__nvvm_atom_cta_min_gen_ul:
690 case NVPTX::BI__nvvm_atom_cta_min_gen_ull:
691 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UMin,
692 Scope: llvm::AtomicScope::Workgroup);
693 case NVPTX::BI__nvvm_atom_sys_min_gen_i:
694 case NVPTX::BI__nvvm_atom_sys_min_gen_l:
695 case NVPTX::BI__nvvm_atom_sys_min_gen_ll:
696 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Min,
697 Scope: llvm::AtomicScope::System);
698 case NVPTX::BI__nvvm_atom_sys_min_gen_ui:
699 case NVPTX::BI__nvvm_atom_sys_min_gen_ul:
700 case NVPTX::BI__nvvm_atom_sys_min_gen_ull:
701 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UMin,
702 Scope: llvm::AtomicScope::System);
703 case NVPTX::BI__nvvm_atom_cta_inc_gen_ui:
704 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UIncWrap,
705 Scope: llvm::AtomicScope::Workgroup);
706 case NVPTX::BI__nvvm_atom_cta_dec_gen_ui:
707 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UDecWrap,
708 Scope: llvm::AtomicScope::Workgroup);
709 case NVPTX::BI__nvvm_atom_sys_inc_gen_ui:
710 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UIncWrap,
711 Scope: llvm::AtomicScope::System);
712 case NVPTX::BI__nvvm_atom_sys_dec_gen_ui:
713 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::UDecWrap,
714 Scope: llvm::AtomicScope::System);
715 case NVPTX::BI__nvvm_atom_cta_and_gen_i:
716 case NVPTX::BI__nvvm_atom_cta_and_gen_l:
717 case NVPTX::BI__nvvm_atom_cta_and_gen_ll:
718 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::And,
719 Scope: llvm::AtomicScope::Workgroup);
720 case NVPTX::BI__nvvm_atom_sys_and_gen_i:
721 case NVPTX::BI__nvvm_atom_sys_and_gen_l:
722 case NVPTX::BI__nvvm_atom_sys_and_gen_ll:
723 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::And,
724 Scope: llvm::AtomicScope::System);
725 case NVPTX::BI__nvvm_atom_cta_or_gen_i:
726 case NVPTX::BI__nvvm_atom_cta_or_gen_l:
727 case NVPTX::BI__nvvm_atom_cta_or_gen_ll:
728 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Or,
729 Scope: llvm::AtomicScope::Workgroup);
730 case NVPTX::BI__nvvm_atom_sys_or_gen_i:
731 case NVPTX::BI__nvvm_atom_sys_or_gen_l:
732 case NVPTX::BI__nvvm_atom_sys_or_gen_ll:
733 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Or,
734 Scope: llvm::AtomicScope::System);
735 case NVPTX::BI__nvvm_atom_cta_xor_gen_i:
736 case NVPTX::BI__nvvm_atom_cta_xor_gen_l:
737 case NVPTX::BI__nvvm_atom_cta_xor_gen_ll:
738 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Xor,
739 Scope: llvm::AtomicScope::Workgroup);
740 case NVPTX::BI__nvvm_atom_sys_xor_gen_i:
741 case NVPTX::BI__nvvm_atom_sys_xor_gen_l:
742 case NVPTX::BI__nvvm_atom_sys_xor_gen_ll:
743 return MakeScopedAtomicRMW(CGF&: *this, E, Kind: llvm::AtomicRMWInst::Xor,
744 Scope: llvm::AtomicScope::System);
745 case NVPTX::BI__nvvm_atom_cta_cas_gen_us:
746 case NVPTX::BI__nvvm_atom_cta_cas_gen_i:
747 case NVPTX::BI__nvvm_atom_cta_cas_gen_l:
748 case NVPTX::BI__nvvm_atom_cta_cas_gen_ll:
749 return MakeScopedAtomicCAS(CGF&: *this, E, Scope: llvm::AtomicScope::Workgroup);
750 case NVPTX::BI__nvvm_atom_sys_cas_gen_us:
751 case NVPTX::BI__nvvm_atom_sys_cas_gen_i:
752 case NVPTX::BI__nvvm_atom_sys_cas_gen_l:
753 case NVPTX::BI__nvvm_atom_sys_cas_gen_ll:
754 return MakeScopedAtomicCAS(CGF&: *this, E, Scope: llvm::AtomicScope::System);
755 case NVPTX::BI__nvvm_match_all_sync_i32p:
756 case NVPTX::BI__nvvm_match_all_sync_i64p: {
757 Value *Mask = EmitScalarExpr(E: E->getArg(Arg: 0));
758 Value *Val = EmitScalarExpr(E: E->getArg(Arg: 1));
759 Address PredOutPtr = EmitPointerWithAlignment(Addr: E->getArg(Arg: 2));
760 Value *ResultPair = Builder.CreateCall(
761 Callee: CGM.getIntrinsic(IID: BuiltinID == NVPTX::BI__nvvm_match_all_sync_i32p
762 ? Intrinsic::nvvm_match_all_sync_i32p
763 : Intrinsic::nvvm_match_all_sync_i64p),
764 Args: {Mask, Val});
765 Value *Pred = Builder.CreateZExt(V: Builder.CreateExtractValue(Agg: ResultPair, Idxs: 1),
766 DestTy: PredOutPtr.getElementType());
767 Builder.CreateStore(Val: Pred, Addr: PredOutPtr);
768 return Builder.CreateExtractValue(Agg: ResultPair, Idxs: 0);
769 }
770
771 // FP MMA loads
772 case NVPTX::BI__hmma_m16n16k16_ld_a:
773 case NVPTX::BI__hmma_m16n16k16_ld_b:
774 case NVPTX::BI__hmma_m16n16k16_ld_c_f16:
775 case NVPTX::BI__hmma_m16n16k16_ld_c_f32:
776 case NVPTX::BI__hmma_m32n8k16_ld_a:
777 case NVPTX::BI__hmma_m32n8k16_ld_b:
778 case NVPTX::BI__hmma_m32n8k16_ld_c_f16:
779 case NVPTX::BI__hmma_m32n8k16_ld_c_f32:
780 case NVPTX::BI__hmma_m8n32k16_ld_a:
781 case NVPTX::BI__hmma_m8n32k16_ld_b:
782 case NVPTX::BI__hmma_m8n32k16_ld_c_f16:
783 case NVPTX::BI__hmma_m8n32k16_ld_c_f32:
784 // Integer MMA loads.
785 case NVPTX::BI__imma_m16n16k16_ld_a_s8:
786 case NVPTX::BI__imma_m16n16k16_ld_a_u8:
787 case NVPTX::BI__imma_m16n16k16_ld_b_s8:
788 case NVPTX::BI__imma_m16n16k16_ld_b_u8:
789 case NVPTX::BI__imma_m16n16k16_ld_c:
790 case NVPTX::BI__imma_m32n8k16_ld_a_s8:
791 case NVPTX::BI__imma_m32n8k16_ld_a_u8:
792 case NVPTX::BI__imma_m32n8k16_ld_b_s8:
793 case NVPTX::BI__imma_m32n8k16_ld_b_u8:
794 case NVPTX::BI__imma_m32n8k16_ld_c:
795 case NVPTX::BI__imma_m8n32k16_ld_a_s8:
796 case NVPTX::BI__imma_m8n32k16_ld_a_u8:
797 case NVPTX::BI__imma_m8n32k16_ld_b_s8:
798 case NVPTX::BI__imma_m8n32k16_ld_b_u8:
799 case NVPTX::BI__imma_m8n32k16_ld_c:
800 // Sub-integer MMA loads.
801 case NVPTX::BI__imma_m8n8k32_ld_a_s4:
802 case NVPTX::BI__imma_m8n8k32_ld_a_u4:
803 case NVPTX::BI__imma_m8n8k32_ld_b_s4:
804 case NVPTX::BI__imma_m8n8k32_ld_b_u4:
805 case NVPTX::BI__imma_m8n8k32_ld_c:
806 case NVPTX::BI__bmma_m8n8k128_ld_a_b1:
807 case NVPTX::BI__bmma_m8n8k128_ld_b_b1:
808 case NVPTX::BI__bmma_m8n8k128_ld_c:
809 // Double MMA loads.
810 case NVPTX::BI__dmma_m8n8k4_ld_a:
811 case NVPTX::BI__dmma_m8n8k4_ld_b:
812 case NVPTX::BI__dmma_m8n8k4_ld_c:
813 // Alternate float MMA loads.
814 case NVPTX::BI__mma_bf16_m16n16k16_ld_a:
815 case NVPTX::BI__mma_bf16_m16n16k16_ld_b:
816 case NVPTX::BI__mma_bf16_m8n32k16_ld_a:
817 case NVPTX::BI__mma_bf16_m8n32k16_ld_b:
818 case NVPTX::BI__mma_bf16_m32n8k16_ld_a:
819 case NVPTX::BI__mma_bf16_m32n8k16_ld_b:
820 case NVPTX::BI__mma_tf32_m16n16k8_ld_a:
821 case NVPTX::BI__mma_tf32_m16n16k8_ld_b:
822 case NVPTX::BI__mma_tf32_m16n16k8_ld_c: {
823 Address Dst = EmitPointerWithAlignment(Addr: E->getArg(Arg: 0));
824 Value *Src = EmitScalarExpr(E: E->getArg(Arg: 1));
825 Value *Ldm = EmitScalarExpr(E: E->getArg(Arg: 2));
826 std::optional<llvm::APSInt> isColMajorArg =
827 E->getArg(Arg: 3)->getIntegerConstantExpr(Ctx: getContext());
828 if (!isColMajorArg)
829 return nullptr;
830 bool isColMajor = isColMajorArg->getSExtValue();
831 NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID);
832 unsigned IID = isColMajor ? II.IID_col : II.IID_row;
833 if (IID == 0)
834 return nullptr;
835
836 Value *Result =
837 Builder.CreateCall(Callee: CGM.getIntrinsic(IID, Tys: Src->getType()), Args: {Src, Ldm});
838
839 // Save returned values.
840 assert(II.NumResults);
841 if (II.NumResults == 1) {
842 Builder.CreateAlignedStore(Val: Result, Addr: Dst.emitRawPointer(CGF&: *this),
843 Align: CharUnits::fromQuantity(Quantity: 4));
844 } else {
845 for (unsigned i = 0; i < II.NumResults; ++i) {
846 Builder.CreateAlignedStore(
847 Val: Builder.CreateBitCast(V: Builder.CreateExtractValue(Agg: Result, Idxs: i),
848 DestTy: Dst.getElementType()),
849 Addr: Builder.CreateGEP(Ty: Dst.getElementType(), Ptr: Dst.emitRawPointer(CGF&: *this),
850 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
851 Align: CharUnits::fromQuantity(Quantity: 4));
852 }
853 }
854 return Result;
855 }
856
857 case NVPTX::BI__hmma_m16n16k16_st_c_f16:
858 case NVPTX::BI__hmma_m16n16k16_st_c_f32:
859 case NVPTX::BI__hmma_m32n8k16_st_c_f16:
860 case NVPTX::BI__hmma_m32n8k16_st_c_f32:
861 case NVPTX::BI__hmma_m8n32k16_st_c_f16:
862 case NVPTX::BI__hmma_m8n32k16_st_c_f32:
863 case NVPTX::BI__imma_m16n16k16_st_c_i32:
864 case NVPTX::BI__imma_m32n8k16_st_c_i32:
865 case NVPTX::BI__imma_m8n32k16_st_c_i32:
866 case NVPTX::BI__imma_m8n8k32_st_c_i32:
867 case NVPTX::BI__bmma_m8n8k128_st_c_i32:
868 case NVPTX::BI__dmma_m8n8k4_st_c_f64:
869 case NVPTX::BI__mma_m16n16k8_st_c_f32: {
870 Value *Dst = EmitScalarExpr(E: E->getArg(Arg: 0));
871 Address Src = EmitPointerWithAlignment(Addr: E->getArg(Arg: 1));
872 Value *Ldm = EmitScalarExpr(E: E->getArg(Arg: 2));
873 std::optional<llvm::APSInt> isColMajorArg =
874 E->getArg(Arg: 3)->getIntegerConstantExpr(Ctx: getContext());
875 if (!isColMajorArg)
876 return nullptr;
877 bool isColMajor = isColMajorArg->getSExtValue();
878 NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID);
879 unsigned IID = isColMajor ? II.IID_col : II.IID_row;
880 if (IID == 0)
881 return nullptr;
882 Function *Intrinsic =
883 CGM.getIntrinsic(IID, Tys: Dst->getType());
884 llvm::Type *ParamType = Intrinsic->getFunctionType()->getParamType(i: 1);
885 SmallVector<Value *, 10> Values = {Dst};
886 for (unsigned i = 0; i < II.NumResults; ++i) {
887 Value *V = Builder.CreateAlignedLoad(
888 Ty: Src.getElementType(),
889 Addr: Builder.CreateGEP(Ty: Src.getElementType(), Ptr: Src.emitRawPointer(CGF&: *this),
890 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
891 Align: CharUnits::fromQuantity(Quantity: 4));
892 Values.push_back(Elt: Builder.CreateBitCast(V, DestTy: ParamType));
893 }
894 Values.push_back(Elt: Ldm);
895 Value *Result = Builder.CreateCall(Callee: Intrinsic, Args: Values);
896 return Result;
897 }
898
899 // BI__hmma_m16n16k16_mma_<Dtype><CType>(d, a, b, c, layout, satf) -->
900 // Intrinsic::nvvm_wmma_m16n16k16_mma_sync<layout A,B><DType><CType><Satf>
901 case NVPTX::BI__hmma_m16n16k16_mma_f16f16:
902 case NVPTX::BI__hmma_m16n16k16_mma_f32f16:
903 case NVPTX::BI__hmma_m16n16k16_mma_f32f32:
904 case NVPTX::BI__hmma_m16n16k16_mma_f16f32:
905 case NVPTX::BI__hmma_m32n8k16_mma_f16f16:
906 case NVPTX::BI__hmma_m32n8k16_mma_f32f16:
907 case NVPTX::BI__hmma_m32n8k16_mma_f32f32:
908 case NVPTX::BI__hmma_m32n8k16_mma_f16f32:
909 case NVPTX::BI__hmma_m8n32k16_mma_f16f16:
910 case NVPTX::BI__hmma_m8n32k16_mma_f32f16:
911 case NVPTX::BI__hmma_m8n32k16_mma_f32f32:
912 case NVPTX::BI__hmma_m8n32k16_mma_f16f32:
913 case NVPTX::BI__imma_m16n16k16_mma_s8:
914 case NVPTX::BI__imma_m16n16k16_mma_u8:
915 case NVPTX::BI__imma_m32n8k16_mma_s8:
916 case NVPTX::BI__imma_m32n8k16_mma_u8:
917 case NVPTX::BI__imma_m8n32k16_mma_s8:
918 case NVPTX::BI__imma_m8n32k16_mma_u8:
919 case NVPTX::BI__imma_m8n8k32_mma_s4:
920 case NVPTX::BI__imma_m8n8k32_mma_u4:
921 case NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1:
922 case NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1:
923 case NVPTX::BI__dmma_m8n8k4_mma_f64:
924 case NVPTX::BI__mma_bf16_m16n16k16_mma_f32:
925 case NVPTX::BI__mma_bf16_m8n32k16_mma_f32:
926 case NVPTX::BI__mma_bf16_m32n8k16_mma_f32:
927 case NVPTX::BI__mma_tf32_m16n16k8_mma_f32: {
928 Address Dst = EmitPointerWithAlignment(Addr: E->getArg(Arg: 0));
929 Address SrcA = EmitPointerWithAlignment(Addr: E->getArg(Arg: 1));
930 Address SrcB = EmitPointerWithAlignment(Addr: E->getArg(Arg: 2));
931 Address SrcC = EmitPointerWithAlignment(Addr: E->getArg(Arg: 3));
932 std::optional<llvm::APSInt> LayoutArg =
933 E->getArg(Arg: 4)->getIntegerConstantExpr(Ctx: getContext());
934 if (!LayoutArg)
935 return nullptr;
936 int Layout = LayoutArg->getSExtValue();
937 if (Layout < 0 || Layout > 3)
938 return nullptr;
939 llvm::APSInt SatfArg;
940 if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1 ||
941 BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_and_popc_b1)
942 SatfArg = 0; // .b1 does not have satf argument.
943 else if (std::optional<llvm::APSInt> OptSatfArg =
944 E->getArg(Arg: 5)->getIntegerConstantExpr(Ctx: getContext()))
945 SatfArg = *OptSatfArg;
946 else
947 return nullptr;
948 bool Satf = SatfArg.getSExtValue();
949 NVPTXMmaInfo MI = getNVPTXMmaInfo(BuiltinID);
950 unsigned IID = MI.getMMAIntrinsic(Layout, Satf);
951 if (IID == 0) // Unsupported combination of Layout/Satf.
952 return nullptr;
953
954 SmallVector<Value *, 24> Values;
955 Function *Intrinsic = CGM.getIntrinsic(IID);
956 llvm::Type *AType = Intrinsic->getFunctionType()->getParamType(i: 0);
957 // Load A
958 for (unsigned i = 0; i < MI.NumEltsA; ++i) {
959 Value *V = Builder.CreateAlignedLoad(
960 Ty: SrcA.getElementType(),
961 Addr: Builder.CreateGEP(Ty: SrcA.getElementType(), Ptr: SrcA.emitRawPointer(CGF&: *this),
962 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
963 Align: CharUnits::fromQuantity(Quantity: 4));
964 Values.push_back(Elt: Builder.CreateBitCast(V, DestTy: AType));
965 }
966 // Load B
967 llvm::Type *BType = Intrinsic->getFunctionType()->getParamType(i: MI.NumEltsA);
968 for (unsigned i = 0; i < MI.NumEltsB; ++i) {
969 Value *V = Builder.CreateAlignedLoad(
970 Ty: SrcB.getElementType(),
971 Addr: Builder.CreateGEP(Ty: SrcB.getElementType(), Ptr: SrcB.emitRawPointer(CGF&: *this),
972 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
973 Align: CharUnits::fromQuantity(Quantity: 4));
974 Values.push_back(Elt: Builder.CreateBitCast(V, DestTy: BType));
975 }
976 // Load C
977 llvm::Type *CType =
978 Intrinsic->getFunctionType()->getParamType(i: MI.NumEltsA + MI.NumEltsB);
979 for (unsigned i = 0; i < MI.NumEltsC; ++i) {
980 Value *V = Builder.CreateAlignedLoad(
981 Ty: SrcC.getElementType(),
982 Addr: Builder.CreateGEP(Ty: SrcC.getElementType(), Ptr: SrcC.emitRawPointer(CGF&: *this),
983 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
984 Align: CharUnits::fromQuantity(Quantity: 4));
985 Values.push_back(Elt: Builder.CreateBitCast(V, DestTy: CType));
986 }
987 Value *Result = Builder.CreateCall(Callee: Intrinsic, Args: Values);
988 llvm::Type *DType = Dst.getElementType();
989 for (unsigned i = 0; i < MI.NumEltsD; ++i)
990 Builder.CreateAlignedStore(
991 Val: Builder.CreateBitCast(V: Builder.CreateExtractValue(Agg: Result, Idxs: i), DestTy: DType),
992 Addr: Builder.CreateGEP(Ty: Dst.getElementType(), Ptr: Dst.emitRawPointer(CGF&: *this),
993 IdxList: llvm::ConstantInt::get(Ty: IntTy, V: i)),
994 Align: CharUnits::fromQuantity(Quantity: 4));
995 return Result;
996 }
997 // The following builtins require half type support
998 case NVPTX::BI__nvvm_ex2_approx_f16:
999 return MakeHalfType(
1000 Intrinsic: CGM.getIntrinsic(IID: Intrinsic::nvvm_ex2_approx, Tys: Builder.getHalfTy()),
1001 BuiltinID, E, CGF&: *this);
1002 case NVPTX::BI__nvvm_ex2_approx_f16x2:
1003 return MakeHalfType(
1004 Intrinsic: CGM.getIntrinsic(IID: Intrinsic::nvvm_ex2_approx,
1005 Tys: FixedVectorType::get(ElementType: Builder.getHalfTy(), NumElts: 2)),
1006 BuiltinID, E, CGF&: *this);
1007 case NVPTX::BI__nvvm_ff2f16x2_rn:
1008 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_ff2f16x2_rn, BuiltinID, E, CGF&: *this);
1009 case NVPTX::BI__nvvm_ff2f16x2_rn_relu:
1010 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_ff2f16x2_rn_relu, BuiltinID, E, CGF&: *this);
1011 case NVPTX::BI__nvvm_ff2f16x2_rz:
1012 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_ff2f16x2_rz, BuiltinID, E, CGF&: *this);
1013 case NVPTX::BI__nvvm_ff2f16x2_rz_relu:
1014 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_ff2f16x2_rz_relu, BuiltinID, E, CGF&: *this);
1015
1016#define PZO_CVT(cvt) \
1017 case NVPTX::BI__nvvm_##cvt##_pzo: \
1018 return MakeHalfType(Intrinsic::nvvm_##cvt, BuiltinID, E, *this, \
1019 {Builder.getTrue()})
1020
1021 PZO_CVT(ff2f16x2_rn);
1022 PZO_CVT(ff2f16x2_rn_relu);
1023 PZO_CVT(ff2f16x2_rz);
1024 PZO_CVT(ff2f16x2_rz_relu);
1025 PZO_CVT(ff2f16x2_rn_satfinite);
1026 PZO_CVT(ff2f16x2_rn_relu_satfinite);
1027 PZO_CVT(ff2f16x2_rz_satfinite);
1028 PZO_CVT(ff2f16x2_rz_relu_satfinite);
1029 PZO_CVT(ff2bf16x2_rn);
1030 PZO_CVT(ff2bf16x2_rn_relu);
1031 PZO_CVT(ff2bf16x2_rz);
1032 PZO_CVT(ff2bf16x2_rz_relu);
1033 PZO_CVT(ff2bf16x2_rn_satfinite);
1034 PZO_CVT(ff2bf16x2_rn_relu_satfinite);
1035 PZO_CVT(ff2bf16x2_rz_satfinite);
1036 PZO_CVT(ff2bf16x2_rz_relu_satfinite);
1037 PZO_CVT(f2f16_rn);
1038 PZO_CVT(f2f16_rn_relu);
1039 PZO_CVT(f2f16_rz);
1040 PZO_CVT(f2f16_rz_relu);
1041 PZO_CVT(f2f16_rn_satfinite);
1042 PZO_CVT(f2f16_rn_relu_satfinite);
1043 PZO_CVT(f2f16_rz_satfinite);
1044 PZO_CVT(f2f16_rz_relu_satfinite);
1045 PZO_CVT(f2bf16_rn);
1046 PZO_CVT(f2bf16_rn_relu);
1047 PZO_CVT(f2bf16_rz);
1048 PZO_CVT(f2bf16_rz_relu);
1049 PZO_CVT(f2bf16_rn_satfinite);
1050 PZO_CVT(f2bf16_rn_relu_satfinite);
1051 PZO_CVT(f2bf16_rz_satfinite);
1052 PZO_CVT(f2bf16_rz_relu_satfinite);
1053
1054 PZO_CVT(ff_to_e4m3x2_rn);
1055 PZO_CVT(ff_to_e4m3x2_rn_relu);
1056 PZO_CVT(ff_to_e4m3x2_rz);
1057 PZO_CVT(ff_to_e4m3x2_rz_relu);
1058 PZO_CVT(ff_to_e5m2x2_rn);
1059 PZO_CVT(ff_to_e5m2x2_rn_relu);
1060 PZO_CVT(ff_to_e5m2x2_rz);
1061 PZO_CVT(ff_to_e5m2x2_rz_relu);
1062 PZO_CVT(f16x2_to_e4m3x2_rn);
1063 PZO_CVT(f16x2_to_e4m3x2_rn_relu);
1064 PZO_CVT(f16x2_to_e4m3x2_rz);
1065 PZO_CVT(f16x2_to_e4m3x2_rz_relu);
1066 PZO_CVT(f16x2_to_e5m2x2_rn);
1067 PZO_CVT(f16x2_to_e5m2x2_rn_relu);
1068 PZO_CVT(f16x2_to_e5m2x2_rz);
1069 PZO_CVT(f16x2_to_e5m2x2_rz_relu);
1070 PZO_CVT(bf16x2_to_e4m3x2_rn_satfinite);
1071 PZO_CVT(bf16x2_to_e4m3x2_rn_relu_satfinite);
1072 PZO_CVT(bf16x2_to_e4m3x2_rz_satfinite);
1073 PZO_CVT(bf16x2_to_e4m3x2_rz_relu_satfinite);
1074 PZO_CVT(bf16x2_to_e5m2x2_rn_satfinite);
1075 PZO_CVT(bf16x2_to_e5m2x2_rn_relu_satfinite);
1076 PZO_CVT(bf16x2_to_e5m2x2_rz_satfinite);
1077 PZO_CVT(bf16x2_to_e5m2x2_rz_relu_satfinite);
1078
1079 PZO_CVT(ff_to_e4m3x2_rn_scale_n1_ue8m0);
1080 PZO_CVT(ff_to_e4m3x2_rn_relu_scale_n1_ue8m0);
1081 PZO_CVT(ff_to_e4m3x2_rz_scale_n1_ue8m0);
1082 PZO_CVT(ff_to_e4m3x2_rz_relu_scale_n1_ue8m0);
1083 PZO_CVT(ff_to_e5m2x2_rn_scale_n1_ue8m0);
1084 PZO_CVT(ff_to_e5m2x2_rn_relu_scale_n1_ue8m0);
1085 PZO_CVT(ff_to_e5m2x2_rz_scale_n1_ue8m0);
1086 PZO_CVT(ff_to_e5m2x2_rz_relu_scale_n1_ue8m0);
1087 PZO_CVT(f16x2_to_e4m3x2_rn_scale_n1_ue8m0);
1088 PZO_CVT(f16x2_to_e4m3x2_rn_relu_scale_n1_ue8m0);
1089 PZO_CVT(f16x2_to_e4m3x2_rz_scale_n1_ue8m0);
1090 PZO_CVT(f16x2_to_e4m3x2_rz_relu_scale_n1_ue8m0);
1091 PZO_CVT(f16x2_to_e5m2x2_rn_scale_n1_ue8m0);
1092 PZO_CVT(f16x2_to_e5m2x2_rn_relu_scale_n1_ue8m0);
1093 PZO_CVT(f16x2_to_e5m2x2_rz_scale_n1_ue8m0);
1094 PZO_CVT(f16x2_to_e5m2x2_rz_relu_scale_n1_ue8m0);
1095 PZO_CVT(bf16x2_to_e4m3x2_rn_satfinite_scale_n1_ue8m0);
1096 PZO_CVT(bf16x2_to_e4m3x2_rn_relu_satfinite_scale_n1_ue8m0);
1097 PZO_CVT(bf16x2_to_e4m3x2_rz_satfinite_scale_n1_ue8m0);
1098 PZO_CVT(bf16x2_to_e4m3x2_rz_relu_satfinite_scale_n1_ue8m0);
1099 PZO_CVT(bf16x2_to_e5m2x2_rn_satfinite_scale_n1_ue8m0);
1100 PZO_CVT(bf16x2_to_e5m2x2_rn_relu_satfinite_scale_n1_ue8m0);
1101 PZO_CVT(bf16x2_to_e5m2x2_rz_satfinite_scale_n1_ue8m0);
1102 PZO_CVT(bf16x2_to_e5m2x2_rz_relu_satfinite_scale_n1_ue8m0);
1103
1104 PZO_CVT(ff_to_e2m3x2_rn_satfinite);
1105 PZO_CVT(ff_to_e2m3x2_rn_relu_satfinite);
1106 PZO_CVT(ff_to_e2m3x2_rz_satfinite);
1107 PZO_CVT(ff_to_e2m3x2_rz_relu_satfinite);
1108 PZO_CVT(ff_to_e3m2x2_rn_satfinite);
1109 PZO_CVT(ff_to_e3m2x2_rn_relu_satfinite);
1110 PZO_CVT(ff_to_e3m2x2_rz_satfinite);
1111 PZO_CVT(ff_to_e3m2x2_rz_relu_satfinite);
1112 PZO_CVT(f16x2_to_e2m3x2_rn_satfinite);
1113 PZO_CVT(f16x2_to_e2m3x2_rn_relu_satfinite);
1114 PZO_CVT(f16x2_to_e2m3x2_rz_satfinite);
1115 PZO_CVT(f16x2_to_e2m3x2_rz_relu_satfinite);
1116 PZO_CVT(f16x2_to_e3m2x2_rn_satfinite);
1117 PZO_CVT(f16x2_to_e3m2x2_rn_relu_satfinite);
1118 PZO_CVT(f16x2_to_e3m2x2_rz_satfinite);
1119 PZO_CVT(f16x2_to_e3m2x2_rz_relu_satfinite);
1120 PZO_CVT(bf16x2_to_e2m3x2_rn_satfinite);
1121 PZO_CVT(bf16x2_to_e2m3x2_rn_relu_satfinite);
1122 PZO_CVT(bf16x2_to_e2m3x2_rz_satfinite);
1123 PZO_CVT(bf16x2_to_e2m3x2_rz_relu_satfinite);
1124 PZO_CVT(bf16x2_to_e3m2x2_rn_satfinite);
1125 PZO_CVT(bf16x2_to_e3m2x2_rn_relu_satfinite);
1126 PZO_CVT(bf16x2_to_e3m2x2_rz_satfinite);
1127 PZO_CVT(bf16x2_to_e3m2x2_rz_relu_satfinite);
1128
1129 PZO_CVT(ff_to_e2m3x2_rn_satfinite_scale_n1_ue8m0);
1130 PZO_CVT(ff_to_e2m3x2_rn_relu_satfinite_scale_n1_ue8m0);
1131 PZO_CVT(ff_to_e2m3x2_rz_satfinite_scale_n1_ue8m0);
1132 PZO_CVT(ff_to_e2m3x2_rz_relu_satfinite_scale_n1_ue8m0);
1133 PZO_CVT(ff_to_e3m2x2_rn_satfinite_scale_n1_ue8m0);
1134 PZO_CVT(ff_to_e3m2x2_rn_relu_satfinite_scale_n1_ue8m0);
1135 PZO_CVT(ff_to_e3m2x2_rz_satfinite_scale_n1_ue8m0);
1136 PZO_CVT(ff_to_e3m2x2_rz_relu_satfinite_scale_n1_ue8m0);
1137 PZO_CVT(f16x2_to_e2m3x2_rn_satfinite_scale_n1_ue8m0);
1138 PZO_CVT(f16x2_to_e2m3x2_rn_relu_satfinite_scale_n1_ue8m0);
1139 PZO_CVT(f16x2_to_e2m3x2_rz_satfinite_scale_n1_ue8m0);
1140 PZO_CVT(f16x2_to_e2m3x2_rz_relu_satfinite_scale_n1_ue8m0);
1141 PZO_CVT(f16x2_to_e3m2x2_rn_satfinite_scale_n1_ue8m0);
1142 PZO_CVT(f16x2_to_e3m2x2_rn_relu_satfinite_scale_n1_ue8m0);
1143 PZO_CVT(f16x2_to_e3m2x2_rz_satfinite_scale_n1_ue8m0);
1144 PZO_CVT(f16x2_to_e3m2x2_rz_relu_satfinite_scale_n1_ue8m0);
1145 PZO_CVT(bf16x2_to_e2m3x2_rn_satfinite_scale_n1_ue8m0);
1146 PZO_CVT(bf16x2_to_e2m3x2_rn_relu_satfinite_scale_n1_ue8m0);
1147 PZO_CVT(bf16x2_to_e2m3x2_rz_satfinite_scale_n1_ue8m0);
1148 PZO_CVT(bf16x2_to_e2m3x2_rz_relu_satfinite_scale_n1_ue8m0);
1149 PZO_CVT(bf16x2_to_e3m2x2_rn_satfinite_scale_n1_ue8m0);
1150 PZO_CVT(bf16x2_to_e3m2x2_rn_relu_satfinite_scale_n1_ue8m0);
1151 PZO_CVT(bf16x2_to_e3m2x2_rz_satfinite_scale_n1_ue8m0);
1152 PZO_CVT(bf16x2_to_e3m2x2_rz_relu_satfinite_scale_n1_ue8m0);
1153
1154 PZO_CVT(ff_to_e2m1x2_rn_satfinite);
1155 PZO_CVT(ff_to_e2m1x2_rn_relu_satfinite);
1156 PZO_CVT(ff_to_e2m1x2_rz_satfinite);
1157 PZO_CVT(ff_to_e2m1x2_rz_relu_satfinite);
1158 PZO_CVT(f16x2_to_e2m1x2_rn_satfinite);
1159 PZO_CVT(f16x2_to_e2m1x2_rn_relu_satfinite);
1160 PZO_CVT(f16x2_to_e2m1x2_rz_satfinite);
1161 PZO_CVT(f16x2_to_e2m1x2_rz_relu_satfinite);
1162 PZO_CVT(bf16x2_to_e2m1x2_rn_satfinite);
1163 PZO_CVT(bf16x2_to_e2m1x2_rn_relu_satfinite);
1164 PZO_CVT(bf16x2_to_e2m1x2_rz_satfinite);
1165 PZO_CVT(bf16x2_to_e2m1x2_rz_relu_satfinite);
1166
1167 PZO_CVT(ff_to_e2m1x2_rn_satfinite_scale_n1_ue8m0);
1168 PZO_CVT(ff_to_e2m1x2_rn_relu_satfinite_scale_n1_ue8m0);
1169 PZO_CVT(ff_to_e2m1x2_rz_satfinite_scale_n1_ue8m0);
1170 PZO_CVT(ff_to_e2m1x2_rz_relu_satfinite_scale_n1_ue8m0);
1171 PZO_CVT(f16x2_to_e2m1x2_rn_satfinite_scale_n1_ue8m0);
1172 PZO_CVT(f16x2_to_e2m1x2_rn_relu_satfinite_scale_n1_ue8m0);
1173 PZO_CVT(f16x2_to_e2m1x2_rz_satfinite_scale_n1_ue8m0);
1174 PZO_CVT(f16x2_to_e2m1x2_rz_relu_satfinite_scale_n1_ue8m0);
1175 PZO_CVT(bf16x2_to_e2m1x2_rn_satfinite_scale_n1_ue8m0);
1176 PZO_CVT(bf16x2_to_e2m1x2_rn_relu_satfinite_scale_n1_ue8m0);
1177 PZO_CVT(bf16x2_to_e2m1x2_rz_satfinite_scale_n1_ue8m0);
1178 PZO_CVT(bf16x2_to_e2m1x2_rz_relu_satfinite_scale_n1_ue8m0);
1179
1180#undef PZO_CVT
1181
1182 case NVPTX::BI__nvvm_fma_rn_f16:
1183 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_f16, BuiltinID, E, CGF&: *this);
1184 case NVPTX::BI__nvvm_fma_rn_f16x2:
1185 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_f16x2, BuiltinID, E, CGF&: *this);
1186 case NVPTX::BI__nvvm_fma_rn_ftz_f16:
1187 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_f16, BuiltinID, E, CGF&: *this);
1188 case NVPTX::BI__nvvm_fma_rn_ftz_f16x2:
1189 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_f16x2, BuiltinID, E, CGF&: *this);
1190 case NVPTX::BI__nvvm_fma_rn_ftz_relu_f16:
1191 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_relu_f16, BuiltinID, E,
1192 CGF&: *this);
1193 case NVPTX::BI__nvvm_fma_rn_ftz_relu_f16x2:
1194 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_relu_f16x2, BuiltinID, E,
1195 CGF&: *this);
1196 case NVPTX::BI__nvvm_fma_rn_ftz_sat_f16:
1197 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_sat_f16, BuiltinID, E,
1198 CGF&: *this);
1199 case NVPTX::BI__nvvm_fma_rn_ftz_sat_f16x2:
1200 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_ftz_sat_f16x2, BuiltinID, E,
1201 CGF&: *this);
1202 case NVPTX::BI__nvvm_fma_rn_relu_f16:
1203 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_relu_f16, BuiltinID, E, CGF&: *this);
1204 case NVPTX::BI__nvvm_fma_rn_relu_f16x2:
1205 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_relu_f16x2, BuiltinID, E, CGF&: *this);
1206 case NVPTX::BI__nvvm_fma_rn_sat_f16:
1207 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_sat_f16, BuiltinID, E, CGF&: *this);
1208 case NVPTX::BI__nvvm_fma_rn_sat_f16x2:
1209 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fma_rn_sat_f16x2, BuiltinID, E, CGF&: *this);
1210 case NVPTX::BI__nvvm_fma_rn_oob_f16:
1211 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob, Ty: Builder.getHalfTy(), E,
1212 CGF&: *this);
1213 case NVPTX::BI__nvvm_fma_rn_oob_f16x2:
1214 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob,
1215 Ty: llvm::FixedVectorType::get(ElementType: Builder.getHalfTy(), NumElts: 2), E,
1216 CGF&: *this);
1217 case NVPTX::BI__nvvm_fma_rn_oob_bf16:
1218 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob, Ty: Builder.getBFloatTy(), E,
1219 CGF&: *this);
1220 case NVPTX::BI__nvvm_fma_rn_oob_bf16x2:
1221 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob,
1222 Ty: llvm::FixedVectorType::get(ElementType: Builder.getBFloatTy(), NumElts: 2), E,
1223 CGF&: *this);
1224 case NVPTX::BI__nvvm_fma_rn_oob_relu_f16:
1225 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob_relu, Ty: Builder.getHalfTy(), E,
1226 CGF&: *this);
1227 case NVPTX::BI__nvvm_fma_rn_oob_relu_f16x2:
1228 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob_relu,
1229 Ty: llvm::FixedVectorType::get(ElementType: Builder.getHalfTy(), NumElts: 2), E,
1230 CGF&: *this);
1231 case NVPTX::BI__nvvm_fma_rn_oob_relu_bf16:
1232 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob_relu, Ty: Builder.getBFloatTy(), E,
1233 CGF&: *this);
1234 case NVPTX::BI__nvvm_fma_rn_oob_relu_bf16x2:
1235 return MakeFMAOOB(IntrinsicID: Intrinsic::nvvm_fma_rn_oob_relu,
1236 Ty: llvm::FixedVectorType::get(ElementType: Builder.getBFloatTy(), NumElts: 2), E,
1237 CGF&: *this);
1238 case NVPTX::BI__nvvm_fmax_f16:
1239 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_f16, BuiltinID, E, CGF&: *this);
1240 case NVPTX::BI__nvvm_fmax_f16x2:
1241 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_f16x2, BuiltinID, E, CGF&: *this);
1242 case NVPTX::BI__nvvm_fmax_ftz_f16:
1243 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_f16, BuiltinID, E, CGF&: *this);
1244 case NVPTX::BI__nvvm_fmax_ftz_f16x2:
1245 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_f16x2, BuiltinID, E, CGF&: *this);
1246 case NVPTX::BI__nvvm_fmax_ftz_nan_f16:
1247 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_nan_f16, BuiltinID, E, CGF&: *this);
1248 case NVPTX::BI__nvvm_fmax_ftz_nan_f16x2:
1249 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_nan_f16x2, BuiltinID, E,
1250 CGF&: *this);
1251 case NVPTX::BI__nvvm_fmax_ftz_nan_xorsign_abs_f16:
1252 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_f16, BuiltinID,
1253 E, CGF&: *this);
1254 case NVPTX::BI__nvvm_fmax_ftz_nan_xorsign_abs_f16x2:
1255 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_f16x2,
1256 BuiltinID, E, CGF&: *this);
1257 case NVPTX::BI__nvvm_fmax_ftz_xorsign_abs_f16:
1258 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_xorsign_abs_f16, BuiltinID, E,
1259 CGF&: *this);
1260 case NVPTX::BI__nvvm_fmax_ftz_xorsign_abs_f16x2:
1261 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_ftz_xorsign_abs_f16x2, BuiltinID,
1262 E, CGF&: *this);
1263 case NVPTX::BI__nvvm_fmax_nan_f16:
1264 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_nan_f16, BuiltinID, E, CGF&: *this);
1265 case NVPTX::BI__nvvm_fmax_nan_f16x2:
1266 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_nan_f16x2, BuiltinID, E, CGF&: *this);
1267 case NVPTX::BI__nvvm_fmax_nan_xorsign_abs_f16:
1268 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_nan_xorsign_abs_f16, BuiltinID, E,
1269 CGF&: *this);
1270 case NVPTX::BI__nvvm_fmax_nan_xorsign_abs_f16x2:
1271 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_nan_xorsign_abs_f16x2, BuiltinID,
1272 E, CGF&: *this);
1273 case NVPTX::BI__nvvm_fmax_xorsign_abs_f16:
1274 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_xorsign_abs_f16, BuiltinID, E,
1275 CGF&: *this);
1276 case NVPTX::BI__nvvm_fmax_xorsign_abs_f16x2:
1277 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmax_xorsign_abs_f16x2, BuiltinID, E,
1278 CGF&: *this);
1279 case NVPTX::BI__nvvm_fmin_f16:
1280 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_f16, BuiltinID, E, CGF&: *this);
1281 case NVPTX::BI__nvvm_fmin_f16x2:
1282 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_f16x2, BuiltinID, E, CGF&: *this);
1283 case NVPTX::BI__nvvm_fmin_ftz_f16:
1284 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_f16, BuiltinID, E, CGF&: *this);
1285 case NVPTX::BI__nvvm_fmin_ftz_f16x2:
1286 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_f16x2, BuiltinID, E, CGF&: *this);
1287 case NVPTX::BI__nvvm_fmin_ftz_nan_f16:
1288 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_nan_f16, BuiltinID, E, CGF&: *this);
1289 case NVPTX::BI__nvvm_fmin_ftz_nan_f16x2:
1290 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_nan_f16x2, BuiltinID, E,
1291 CGF&: *this);
1292 case NVPTX::BI__nvvm_fmin_ftz_nan_xorsign_abs_f16:
1293 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_f16, BuiltinID,
1294 E, CGF&: *this);
1295 case NVPTX::BI__nvvm_fmin_ftz_nan_xorsign_abs_f16x2:
1296 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_f16x2,
1297 BuiltinID, E, CGF&: *this);
1298 case NVPTX::BI__nvvm_fmin_ftz_xorsign_abs_f16:
1299 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_xorsign_abs_f16, BuiltinID, E,
1300 CGF&: *this);
1301 case NVPTX::BI__nvvm_fmin_ftz_xorsign_abs_f16x2:
1302 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_ftz_xorsign_abs_f16x2, BuiltinID,
1303 E, CGF&: *this);
1304 case NVPTX::BI__nvvm_fmin_nan_f16:
1305 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_nan_f16, BuiltinID, E, CGF&: *this);
1306 case NVPTX::BI__nvvm_fmin_nan_f16x2:
1307 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_nan_f16x2, BuiltinID, E, CGF&: *this);
1308 case NVPTX::BI__nvvm_fmin_nan_xorsign_abs_f16:
1309 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_nan_xorsign_abs_f16, BuiltinID, E,
1310 CGF&: *this);
1311 case NVPTX::BI__nvvm_fmin_nan_xorsign_abs_f16x2:
1312 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_nan_xorsign_abs_f16x2, BuiltinID,
1313 E, CGF&: *this);
1314 case NVPTX::BI__nvvm_fmin_xorsign_abs_f16:
1315 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_xorsign_abs_f16, BuiltinID, E,
1316 CGF&: *this);
1317 case NVPTX::BI__nvvm_fmin_xorsign_abs_f16x2:
1318 return MakeHalfType(IntrinsicID: Intrinsic::nvvm_fmin_xorsign_abs_f16x2, BuiltinID, E,
1319 CGF&: *this);
1320 case NVPTX::BI__nvvm_fabs_f:
1321 case NVPTX::BI__nvvm_abs_bf16:
1322 case NVPTX::BI__nvvm_abs_bf16x2:
1323 case NVPTX::BI__nvvm_fabs_f16:
1324 case NVPTX::BI__nvvm_fabs_f16x2:
1325 return Builder.CreateUnaryIntrinsic(ID: Intrinsic::nvvm_fabs,
1326 Op: EmitScalarExpr(E: E->getArg(Arg: 0)));
1327 case NVPTX::BI__nvvm_fabs_ftz_f:
1328 case NVPTX::BI__nvvm_fabs_ftz_f16:
1329 case NVPTX::BI__nvvm_fabs_ftz_f16x2:
1330 return Builder.CreateUnaryIntrinsic(ID: Intrinsic::nvvm_fabs_ftz,
1331 Op: EmitScalarExpr(E: E->getArg(Arg: 0)));
1332 case NVPTX::BI__nvvm_fabs_d:
1333 return Builder.CreateFAbs(V: EmitScalarExpr(E: E->getArg(Arg: 0)));
1334 case NVPTX::BI__nvvm_ex2_approx_d:
1335 case NVPTX::BI__nvvm_ex2_approx_f:
1336 return Builder.CreateUnaryIntrinsic(ID: Intrinsic::nvvm_ex2_approx,
1337 Op: EmitScalarExpr(E: E->getArg(Arg: 0)));
1338 case NVPTX::BI__nvvm_ex2_approx_ftz_f:
1339 return Builder.CreateUnaryIntrinsic(ID: Intrinsic::nvvm_ex2_approx_ftz,
1340 Op: EmitScalarExpr(E: E->getArg(Arg: 0)));
1341 case NVPTX::BI__nvvm_add_rn_f:
1342 case NVPTX::BI__nvvm_add_rn_d:
1343 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd, RM: APFloat::rmNearestTiesToEven,
1344 BuiltinID, E, CGF&: *this);
1345 case NVPTX::BI__nvvm_add_rz_f:
1346 case NVPTX::BI__nvvm_add_rz_d:
1347 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd, RM: APFloat::rmTowardZero, BuiltinID,
1348 E, CGF&: *this);
1349 case NVPTX::BI__nvvm_add_rm_f:
1350 case NVPTX::BI__nvvm_add_rm_d:
1351 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd, RM: APFloat::rmTowardNegative,
1352 BuiltinID, E, CGF&: *this);
1353 case NVPTX::BI__nvvm_add_rp_f:
1354 case NVPTX::BI__nvvm_add_rp_d:
1355 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd, RM: APFloat::rmTowardPositive,
1356 BuiltinID, E, CGF&: *this);
1357 case NVPTX::BI__nvvm_add_rn_ftz_f:
1358 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz, RM: APFloat::rmNearestTiesToEven,
1359 BuiltinID, E, CGF&: *this);
1360 case NVPTX::BI__nvvm_add_rz_ftz_f:
1361 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz, RM: APFloat::rmTowardZero,
1362 BuiltinID, E, CGF&: *this);
1363 case NVPTX::BI__nvvm_add_rm_ftz_f:
1364 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz, RM: APFloat::rmTowardNegative,
1365 BuiltinID, E, CGF&: *this);
1366 case NVPTX::BI__nvvm_add_rp_ftz_f:
1367 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz, RM: APFloat::rmTowardPositive,
1368 BuiltinID, E, CGF&: *this);
1369 case NVPTX::BI__nvvm_add_rn_sat_f:
1370 case NVPTX::BI__nvvm_add_rn_sat_f16:
1371 case NVPTX::BI__nvvm_add_rn_sat_v2f16:
1372 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_sat, RM: APFloat::rmNearestTiesToEven,
1373 BuiltinID, E, CGF&: *this);
1374 case NVPTX::BI__nvvm_add_rz_sat_f:
1375 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_sat, RM: APFloat::rmTowardZero,
1376 BuiltinID, E, CGF&: *this);
1377 case NVPTX::BI__nvvm_add_rm_sat_f:
1378 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_sat, RM: APFloat::rmTowardNegative,
1379 BuiltinID, E, CGF&: *this);
1380 case NVPTX::BI__nvvm_add_rp_sat_f:
1381 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_sat, RM: APFloat::rmTowardPositive,
1382 BuiltinID, E, CGF&: *this);
1383 case NVPTX::BI__nvvm_add_rn_ftz_sat_f:
1384 case NVPTX::BI__nvvm_add_rn_ftz_sat_f16:
1385 case NVPTX::BI__nvvm_add_rn_ftz_sat_v2f16:
1386 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz_sat,
1387 RM: APFloat::rmNearestTiesToEven, BuiltinID, E, CGF&: *this);
1388 case NVPTX::BI__nvvm_add_rz_ftz_sat_f:
1389 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz_sat, RM: APFloat::rmTowardZero,
1390 BuiltinID, E, CGF&: *this);
1391 case NVPTX::BI__nvvm_add_rm_ftz_sat_f:
1392 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz_sat, RM: APFloat::rmTowardNegative,
1393 BuiltinID, E, CGF&: *this);
1394 case NVPTX::BI__nvvm_add_rp_ftz_sat_f:
1395 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fadd_ftz_sat, RM: APFloat::rmTowardPositive,
1396 BuiltinID, E, CGF&: *this);
1397 case NVPTX::BI__nvvm_mul_rn_f:
1398 case NVPTX::BI__nvvm_mul_rn_d:
1399 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul, RM: APFloat::rmNearestTiesToEven,
1400 BuiltinID, E, CGF&: *this);
1401 case NVPTX::BI__nvvm_mul_rz_f:
1402 case NVPTX::BI__nvvm_mul_rz_d:
1403 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul, RM: APFloat::rmTowardZero, BuiltinID,
1404 E, CGF&: *this);
1405 case NVPTX::BI__nvvm_mul_rm_f:
1406 case NVPTX::BI__nvvm_mul_rm_d:
1407 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul, RM: APFloat::rmTowardNegative,
1408 BuiltinID, E, CGF&: *this);
1409 case NVPTX::BI__nvvm_mul_rp_f:
1410 case NVPTX::BI__nvvm_mul_rp_d:
1411 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul, RM: APFloat::rmTowardPositive,
1412 BuiltinID, E, CGF&: *this);
1413 case NVPTX::BI__nvvm_mul_rn_ftz_f:
1414 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_ftz, RM: APFloat::rmNearestTiesToEven,
1415 BuiltinID, E, CGF&: *this);
1416 case NVPTX::BI__nvvm_mul_rz_ftz_f:
1417 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_ftz, RM: APFloat::rmTowardZero,
1418 BuiltinID, E, CGF&: *this);
1419 case NVPTX::BI__nvvm_mul_rm_ftz_f:
1420 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_ftz, RM: APFloat::rmTowardNegative,
1421 BuiltinID, E, CGF&: *this);
1422 case NVPTX::BI__nvvm_mul_rp_ftz_f:
1423 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_ftz, RM: APFloat::rmTowardPositive,
1424 BuiltinID, E, CGF&: *this);
1425 case NVPTX::BI__nvvm_mul_rn_sat_f16:
1426 case NVPTX::BI__nvvm_mul_rn_sat_v2f16:
1427 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_sat, RM: APFloat::rmNearestTiesToEven,
1428 BuiltinID, E, CGF&: *this);
1429 case NVPTX::BI__nvvm_mul_rn_ftz_sat_f16:
1430 case NVPTX::BI__nvvm_mul_rn_ftz_sat_v2f16:
1431 return MakeFPArith(IntrinsicID: Intrinsic::nvvm_fmul_ftz_sat,
1432 RM: APFloat::rmNearestTiesToEven, BuiltinID, E, CGF&: *this);
1433 case NVPTX::BI__nvvm_ldg_h:
1434 case NVPTX::BI__nvvm_ldg_h2:
1435 return MakeLdg(CGF&: *this, E);
1436 case NVPTX::BI__nvvm_ldu_h:
1437 case NVPTX::BI__nvvm_ldu_h2:
1438 return MakeLdu(IntrinsicID: Intrinsic::nvvm_ldu_global_f, CGF&: *this, E);
1439 case NVPTX::BI__nvvm_cp_async_ca_shared_global_4:
1440 return MakeCpAsync(IntrinsicID: Intrinsic::nvvm_cp_async_ca_shared_global_4,
1441 IntrinsicIDS: Intrinsic::nvvm_cp_async_ca_shared_global_4_s, CGF&: *this, E,
1442 SrcSize: 4);
1443 case NVPTX::BI__nvvm_cp_async_ca_shared_global_8:
1444 return MakeCpAsync(IntrinsicID: Intrinsic::nvvm_cp_async_ca_shared_global_8,
1445 IntrinsicIDS: Intrinsic::nvvm_cp_async_ca_shared_global_8_s, CGF&: *this, E,
1446 SrcSize: 8);
1447 case NVPTX::BI__nvvm_cp_async_ca_shared_global_16:
1448 return MakeCpAsync(IntrinsicID: Intrinsic::nvvm_cp_async_ca_shared_global_16,
1449 IntrinsicIDS: Intrinsic::nvvm_cp_async_ca_shared_global_16_s, CGF&: *this, E,
1450 SrcSize: 16);
1451 case NVPTX::BI__nvvm_cp_async_cg_shared_global_16:
1452 return MakeCpAsync(IntrinsicID: Intrinsic::nvvm_cp_async_cg_shared_global_16,
1453 IntrinsicIDS: Intrinsic::nvvm_cp_async_cg_shared_global_16_s, CGF&: *this, E,
1454 SrcSize: 16);
1455 case NVPTX::BI__nvvm_read_ptx_sreg_clusterid_x:
1456 return Builder.CreateCall(
1457 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_clusterid_x));
1458 case NVPTX::BI__nvvm_read_ptx_sreg_clusterid_y:
1459 return Builder.CreateCall(
1460 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_clusterid_y));
1461 case NVPTX::BI__nvvm_read_ptx_sreg_clusterid_z:
1462 return Builder.CreateCall(
1463 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_clusterid_z));
1464 case NVPTX::BI__nvvm_read_ptx_sreg_clusterid_w:
1465 return Builder.CreateCall(
1466 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_clusterid_w));
1467 case NVPTX::BI__nvvm_read_ptx_sreg_nclusterid_x:
1468 return Builder.CreateCall(
1469 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_nclusterid_x));
1470 case NVPTX::BI__nvvm_read_ptx_sreg_nclusterid_y:
1471 return Builder.CreateCall(
1472 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_nclusterid_y));
1473 case NVPTX::BI__nvvm_read_ptx_sreg_nclusterid_z:
1474 return Builder.CreateCall(
1475 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_nclusterid_z));
1476 case NVPTX::BI__nvvm_read_ptx_sreg_nclusterid_w:
1477 return Builder.CreateCall(
1478 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_nclusterid_w));
1479 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_ctaid_x:
1480 return Builder.CreateCall(
1481 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_ctaid_x));
1482 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_ctaid_y:
1483 return Builder.CreateCall(
1484 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_ctaid_y));
1485 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_ctaid_z:
1486 return Builder.CreateCall(
1487 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_ctaid_z));
1488 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_ctaid_w:
1489 return Builder.CreateCall(
1490 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_ctaid_w));
1491 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_nctaid_x:
1492 return Builder.CreateCall(
1493 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_nctaid_x));
1494 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_nctaid_y:
1495 return Builder.CreateCall(
1496 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_nctaid_y));
1497 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_nctaid_z:
1498 return Builder.CreateCall(
1499 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_nctaid_z));
1500 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_nctaid_w:
1501 return Builder.CreateCall(
1502 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_nctaid_w));
1503 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_ctarank:
1504 return Builder.CreateCall(
1505 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_ctarank));
1506 case NVPTX::BI__nvvm_read_ptx_sreg_cluster_nctarank:
1507 return Builder.CreateCall(
1508 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_read_ptx_sreg_cluster_nctarank));
1509 case NVPTX::BI__nvvm_is_explicit_cluster:
1510 return Builder.CreateCall(
1511 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_is_explicit_cluster));
1512 case NVPTX::BI__nvvm_isspacep_shared_cluster:
1513 return Builder.CreateCall(
1514 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_isspacep_shared_cluster),
1515 Args: EmitScalarExpr(E: E->getArg(Arg: 0)));
1516 case NVPTX::BI__nvvm_mapa:
1517 return Builder.CreateCall(
1518 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_mapa),
1519 Args: {EmitScalarExpr(E: E->getArg(Arg: 0)), EmitScalarExpr(E: E->getArg(Arg: 1))});
1520 case NVPTX::BI__nvvm_mapa_shared_cluster:
1521 return Builder.CreateCall(
1522 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_mapa_shared_cluster),
1523 Args: {EmitScalarExpr(E: E->getArg(Arg: 0)), EmitScalarExpr(E: E->getArg(Arg: 1))});
1524 case NVPTX::BI__nvvm_getctarank:
1525 return Builder.CreateCall(
1526 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_getctarank),
1527 Args: EmitScalarExpr(E: E->getArg(Arg: 0)));
1528 case NVPTX::BI__nvvm_getctarank_shared_cluster:
1529 return Builder.CreateCall(
1530 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_getctarank_shared_cluster),
1531 Args: EmitScalarExpr(E: E->getArg(Arg: 0)));
1532 case NVPTX::BI__nvvm_barrier_cluster_arrive:
1533 return Builder.CreateCall(
1534 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cluster_arrive));
1535 case NVPTX::BI__nvvm_barrier_cluster_arrive_relaxed:
1536 return Builder.CreateCall(
1537 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cluster_arrive_relaxed));
1538 case NVPTX::BI__nvvm_barrier_cluster_wait:
1539 return Builder.CreateCall(
1540 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cluster_wait));
1541 case NVPTX::BI__nvvm_fence_sc_cluster:
1542 return Builder.CreateCall(
1543 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_fence_sc_cluster));
1544 case NVPTX::BI__nvvm_bar_sync:
1545 return Builder.CreateCall(
1546 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cta_sync_aligned_all),
1547 Args: EmitScalarExpr(E: E->getArg(Arg: 0)));
1548 case NVPTX::BI__syncthreads:
1549 return Builder.CreateCall(
1550 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cta_sync_aligned_all),
1551 Args: Builder.getInt32(C: 0));
1552 case NVPTX::BI__nvvm_barrier_sync:
1553 return Builder.CreateCall(
1554 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cta_sync_all),
1555 Args: EmitScalarExpr(E: E->getArg(Arg: 0)));
1556 case NVPTX::BI__nvvm_barrier_sync_cnt:
1557 return Builder.CreateCall(
1558 Callee: CGM.getIntrinsic(IID: Intrinsic::nvvm_barrier_cta_sync_count),
1559 Args: {EmitScalarExpr(E: E->getArg(Arg: 0)), EmitScalarExpr(E: E->getArg(Arg: 1))});
1560 case NVPTX::BI__nvvm_bar0_and:
1561 return Builder.CreateZExt(
1562 V: Builder.CreateIntrinsic(
1563 ID: Intrinsic::nvvm_barrier_cta_red_and_aligned_all, OverloadTypes: {},
1564 Args: {Builder.getInt32(C: 0),
1565 Builder.CreateICmpNE(LHS: EmitScalarExpr(E: E->getArg(Arg: 0)),
1566 RHS: Builder.getInt32(C: 0))}),
1567 DestTy: Builder.getInt32Ty());
1568 case NVPTX::BI__nvvm_bar0_or:
1569 return Builder.CreateZExt(
1570 V: Builder.CreateIntrinsic(
1571 ID: Intrinsic::nvvm_barrier_cta_red_or_aligned_all, OverloadTypes: {},
1572 Args: {Builder.getInt32(C: 0),
1573 Builder.CreateICmpNE(LHS: EmitScalarExpr(E: E->getArg(Arg: 0)),
1574 RHS: Builder.getInt32(C: 0))}),
1575 DestTy: Builder.getInt32Ty());
1576 case NVPTX::BI__nvvm_bar0_popc:
1577 return Builder.CreateIntrinsic(
1578 ID: Intrinsic::nvvm_barrier_cta_red_popc_aligned_all, OverloadTypes: {},
1579 Args: {Builder.getInt32(C: 0), Builder.CreateICmpNE(LHS: EmitScalarExpr(E: E->getArg(Arg: 0)),
1580 RHS: Builder.getInt32(C: 0))});
1581 case NVPTX::BI__nvvm_mbarrier_init:
1582 case NVPTX::BI__nvvm_mbarrier_init_shared: {
1583 // The intrinsic is overloaded on the pointer, so the two builtins differ
1584 // only in the address space of their first argument.
1585 Value *Ptr = EmitScalarExpr(E: E->getArg(Arg: 0));
1586 return Builder.CreateIntrinsic(
1587 ID: Intrinsic::nvvm_mbarrier_init, OverloadTypes: {Ptr->getType()},
1588 Args: {Ptr, EmitScalarExpr(E: E->getArg(Arg: 1)), Builder.getInt32(C: 0)});
1589 }
1590 default:
1591 return nullptr;
1592 }
1593}
1594