LLVM 24.0.0git
AutoUpgrade.cpp
Go to the documentation of this file.
1//===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
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 file implements the auto-upgrade helper functions.
10// This is where deprecated IR intrinsics and other IR features are updated to
11// current specifications.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/AutoUpgrade.h"
16#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/StringRef.h"
22#include "llvm/IR/Attributes.h"
23#include "llvm/IR/CallingConv.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DebugInfo.h"
28#include "llvm/IR/Function.h"
29#include "llvm/IR/GlobalValue.h"
30#include "llvm/IR/IRBuilder.h"
31#include "llvm/IR/InstVisitor.h"
32#include "llvm/IR/Instruction.h"
34#include "llvm/IR/Intrinsics.h"
35#include "llvm/IR/IntrinsicsAArch64.h"
36#include "llvm/IR/IntrinsicsAMDGPU.h"
37#include "llvm/IR/IntrinsicsARM.h"
38#include "llvm/IR/IntrinsicsNVPTX.h"
39#include "llvm/IR/IntrinsicsRISCV.h"
40#include "llvm/IR/IntrinsicsWebAssembly.h"
41#include "llvm/IR/IntrinsicsX86.h"
42#include "llvm/IR/LLVMContext.h"
43#include "llvm/IR/MDBuilder.h"
44#include "llvm/IR/Metadata.h"
45#include "llvm/IR/Module.h"
47#include "llvm/IR/Value.h"
48#include "llvm/IR/Verifier.h"
55#include "llvm/Support/Regex.h"
58#include <cstdint>
59#include <cstring>
60#include <numeric>
61
62using namespace llvm;
63
64static cl::opt<bool>
65 DisableAutoUpgradeDebugInfo("disable-auto-upgrade-debug-info",
66 cl::desc("Disable autoupgrade of debug info"));
67
68static void rename(GlobalValue *GV) { GV->setName(GV->getName() + ".old"); }
69
70// Report a fatal error along with the
71// Call Instruction which caused the error
72[[noreturn]] static void reportFatalUsageErrorWithCI(StringRef reason,
73 CallBase *CI) {
74 CI->print(llvm::errs());
75 llvm::errs() << "\n";
77}
78
79// Upgrade the declarations of the SSE4.1 ptest intrinsics whose arguments have
80// changed their type from v4f32 to v2i64.
82 Function *&NewFn) {
83 // Check whether this is an old version of the function, which received
84 // v4f32 arguments.
85 Type *Arg0Type = F->getFunctionType()->getParamType(0);
86 if (Arg0Type != FixedVectorType::get(Type::getFloatTy(F->getContext()), 4))
87 return false;
88
89 // Yes, it's old, replace it with new version.
90 rename(F);
91 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
92 return true;
93}
94
95// Upgrade the declarations of intrinsic functions whose 8-bit immediate mask
96// arguments have changed their type from i32 to i8.
98 Function *&NewFn) {
99 // Check that the last argument is an i32.
100 Type *LastArgType = F->getFunctionType()->getParamType(
101 F->getFunctionType()->getNumParams() - 1);
102 if (!LastArgType->isIntegerTy(32))
103 return false;
104
105 // Move this function aside and map down.
106 rename(F);
107 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
108 return true;
109}
110
111// Upgrade the declaration of fp compare intrinsics that change return type
112// from scalar to vXi1 mask.
114 Function *&NewFn) {
115 // Check if the return type is a vector.
116 if (F->getReturnType()->isVectorTy())
117 return false;
118
119 rename(F);
120 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
121 return true;
122}
123
124// Upgrade the declaration of multiply and add bytes intrinsics whose input
125// arguments' types have changed from vectors of i32 to vectors of i8
127 Function *&NewFn) {
128 // check if input argument type is a vector of i8
129 Type *Arg1Type = F->getFunctionType()->getParamType(1);
130 Type *Arg2Type = F->getFunctionType()->getParamType(2);
131 if (Arg1Type->isVectorTy() &&
132 cast<VectorType>(Arg1Type)->getElementType()->isIntegerTy(8) &&
133 Arg2Type->isVectorTy() &&
134 cast<VectorType>(Arg2Type)->getElementType()->isIntegerTy(8))
135 return false;
136
137 rename(F);
138 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
139 return true;
140}
141
142// Upgrade the declaration of multipy and add words intrinsics whose input
143// arguments' types have changed to vectors of i32 to vectors of i16
145 Function *&NewFn) {
146 // check if input argument type is a vector of i16
147 Type *Arg1Type = F->getFunctionType()->getParamType(1);
148 Type *Arg2Type = F->getFunctionType()->getParamType(2);
149 if (Arg1Type->isVectorTy() &&
150 cast<VectorType>(Arg1Type)->getElementType()->isIntegerTy(16) &&
151 Arg2Type->isVectorTy() &&
152 cast<VectorType>(Arg2Type)->getElementType()->isIntegerTy(16))
153 return false;
154
155 rename(F);
156 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
157 return true;
158}
159
161 Function *&NewFn) {
162 if (F->getReturnType()->getScalarType()->isBFloatTy())
163 return false;
164
165 rename(F);
166 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
167 return true;
168}
169
171 Function *&NewFn) {
172 if (F->getFunctionType()->getParamType(1)->getScalarType()->isBFloatTy())
173 return false;
174
175 rename(F);
176 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
177 return true;
178}
179
181 // All of the intrinsics matches below should be marked with which llvm
182 // version started autoupgrading them. At some point in the future we would
183 // like to use this information to remove upgrade code for some older
184 // intrinsics. It is currently undecided how we will determine that future
185 // point.
186 if (Name.consume_front("avx."))
187 return (Name.starts_with("blend.p") || // Added in 3.7
188 Name == "cvt.ps2.pd.256" || // Added in 3.9
189 Name == "cvtdq2.pd.256" || // Added in 3.9
190 Name == "cvtdq2.ps.256" || // Added in 7.0
191 Name.starts_with("movnt.") || // Added in 3.2
192 Name.starts_with("sqrt.p") || // Added in 7.0
193 Name.starts_with("storeu.") || // Added in 3.9
194 Name.starts_with("vbroadcast.s") || // Added in 3.5
195 Name.starts_with("vbroadcastf128") || // Added in 4.0
196 Name.starts_with("vextractf128.") || // Added in 3.7
197 Name.starts_with("vinsertf128.") || // Added in 3.7
198 Name.starts_with("vperm2f128.") || // Added in 6.0
199 Name.starts_with("vpermil.")); // Added in 3.1
200
201 if (Name.consume_front("avx2."))
202 return (Name == "movntdqa" || // Added in 5.0
203 Name.starts_with("pabs.") || // Added in 6.0
204 Name.starts_with("padds.") || // Added in 8.0
205 Name.starts_with("paddus.") || // Added in 8.0
206 Name.starts_with("pblendd.") || // Added in 3.7
207 Name == "pblendw" || // Added in 3.7
208 Name.starts_with("pbroadcast") || // Added in 3.8
209 Name.starts_with("pcmpeq.") || // Added in 3.1
210 Name.starts_with("pcmpgt.") || // Added in 3.1
211 Name.starts_with("pmax") || // Added in 3.9
212 Name.starts_with("pmin") || // Added in 3.9
213 Name.starts_with("pmovsx") || // Added in 3.9
214 Name.starts_with("pmovzx") || // Added in 3.9
215 Name == "pmul.dq" || // Added in 7.0
216 Name == "pmulu.dq" || // Added in 7.0
217 Name.starts_with("psll.dq") || // Added in 3.7
218 Name.starts_with("psrl.dq") || // Added in 3.7
219 Name.starts_with("psubs.") || // Added in 8.0
220 Name.starts_with("psubus.") || // Added in 8.0
221 Name.starts_with("vbroadcast") || // Added in 3.8
222 Name == "vbroadcasti128" || // Added in 3.7
223 Name == "vextracti128" || // Added in 3.7
224 Name == "vinserti128" || // Added in 3.7
225 Name == "vperm2i128"); // Added in 6.0
226
227 if (Name.consume_front("avx512.")) {
228 if (Name.consume_front("mask."))
229 // 'avx512.mask.*'
230 return (Name.starts_with("add.p") || // Added in 7.0. 128/256 in 4.0
231 Name.starts_with("and.") || // Added in 3.9
232 Name.starts_with("andn.") || // Added in 3.9
233 Name.starts_with("broadcast.s") || // Added in 3.9
234 Name.starts_with("broadcastf32x4.") || // Added in 6.0
235 Name.starts_with("broadcastf32x8.") || // Added in 6.0
236 Name.starts_with("broadcastf64x2.") || // Added in 6.0
237 Name.starts_with("broadcastf64x4.") || // Added in 6.0
238 Name.starts_with("broadcasti32x4.") || // Added in 6.0
239 Name.starts_with("broadcasti32x8.") || // Added in 6.0
240 Name.starts_with("broadcasti64x2.") || // Added in 6.0
241 Name.starts_with("broadcasti64x4.") || // Added in 6.0
242 Name.starts_with("cmp.b") || // Added in 5.0
243 Name.starts_with("cmp.d") || // Added in 5.0
244 Name.starts_with("cmp.q") || // Added in 5.0
245 Name.starts_with("cmp.w") || // Added in 5.0
246 Name.starts_with("compress.b") || // Added in 9.0
247 Name.starts_with("compress.d") || // Added in 9.0
248 Name.starts_with("compress.p") || // Added in 9.0
249 Name.starts_with("compress.q") || // Added in 9.0
250 Name.starts_with("compress.store.") || // Added in 7.0
251 Name.starts_with("compress.w") || // Added in 9.0
252 Name.starts_with("conflict.") || // Added in 9.0
253 Name.starts_with("cvtdq2pd.") || // Added in 4.0
254 Name.starts_with("cvtdq2ps.") || // Added in 7.0 updated 9.0
255 Name == "cvtpd2dq.256" || // Added in 7.0
256 Name == "cvtpd2ps.256" || // Added in 7.0
257 Name == "cvtps2pd.128" || // Added in 7.0
258 Name == "cvtps2pd.256" || // Added in 7.0
259 Name.starts_with("cvtqq2pd.") || // Added in 7.0 updated 9.0
260 Name == "cvtqq2ps.256" || // Added in 9.0
261 Name == "cvtqq2ps.512" || // Added in 9.0
262 Name == "cvttpd2dq.256" || // Added in 7.0
263 Name == "cvttps2dq.128" || // Added in 7.0
264 Name == "cvttps2dq.256" || // Added in 7.0
265 Name.starts_with("cvtudq2pd.") || // Added in 4.0
266 Name.starts_with("cvtudq2ps.") || // Added in 7.0 updated 9.0
267 Name.starts_with("cvtuqq2pd.") || // Added in 7.0 updated 9.0
268 Name == "cvtuqq2ps.256" || // Added in 9.0
269 Name == "cvtuqq2ps.512" || // Added in 9.0
270 Name.starts_with("dbpsadbw.") || // Added in 7.0
271 Name.starts_with("div.p") || // Added in 7.0. 128/256 in 4.0
272 Name.starts_with("expand.b") || // Added in 9.0
273 Name.starts_with("expand.d") || // Added in 9.0
274 Name.starts_with("expand.load.") || // Added in 7.0
275 Name.starts_with("expand.p") || // Added in 9.0
276 Name.starts_with("expand.q") || // Added in 9.0
277 Name.starts_with("expand.w") || // Added in 9.0
278 Name.starts_with("fpclass.p") || // Added in 7.0
279 Name.starts_with("insert") || // Added in 4.0
280 Name.starts_with("load.") || // Added in 3.9
281 Name.starts_with("loadu.") || // Added in 3.9
282 Name.starts_with("lzcnt.") || // Added in 5.0
283 Name.starts_with("max.p") || // Added in 7.0. 128/256 in 5.0
284 Name.starts_with("min.p") || // Added in 7.0. 128/256 in 5.0
285 Name.starts_with("movddup") || // Added in 3.9
286 Name.starts_with("move.s") || // Added in 4.0
287 Name.starts_with("movshdup") || // Added in 3.9
288 Name.starts_with("movsldup") || // Added in 3.9
289 Name.starts_with("mul.p") || // Added in 7.0. 128/256 in 4.0
290 Name.starts_with("or.") || // Added in 3.9
291 Name.starts_with("pabs.") || // Added in 6.0
292 Name.starts_with("packssdw.") || // Added in 5.0
293 Name.starts_with("packsswb.") || // Added in 5.0
294 Name.starts_with("packusdw.") || // Added in 5.0
295 Name.starts_with("packuswb.") || // Added in 5.0
296 Name.starts_with("padd.") || // Added in 4.0
297 Name.starts_with("padds.") || // Added in 8.0
298 Name.starts_with("paddus.") || // Added in 8.0
299 Name.starts_with("palignr.") || // Added in 3.9
300 Name.starts_with("pand.") || // Added in 3.9
301 Name.starts_with("pandn.") || // Added in 3.9
302 Name.starts_with("pavg") || // Added in 6.0
303 Name.starts_with("pbroadcast") || // Added in 6.0
304 Name.starts_with("pcmpeq.") || // Added in 3.9
305 Name.starts_with("pcmpgt.") || // Added in 3.9
306 Name.starts_with("perm.df.") || // Added in 3.9
307 Name.starts_with("perm.di.") || // Added in 3.9
308 Name.starts_with("permvar.") || // Added in 7.0
309 Name.starts_with("pmaddubs.w.") || // Added in 7.0
310 Name.starts_with("pmaddw.d.") || // Added in 7.0
311 Name.starts_with("pmax") || // Added in 4.0
312 Name.starts_with("pmin") || // Added in 4.0
313 Name == "pmov.qd.256" || // Added in 9.0
314 Name == "pmov.qd.512" || // Added in 9.0
315 Name == "pmov.wb.256" || // Added in 9.0
316 Name == "pmov.wb.512" || // Added in 9.0
317 Name.starts_with("pmovsx") || // Added in 4.0
318 Name.starts_with("pmovzx") || // Added in 4.0
319 Name.starts_with("pmul.dq.") || // Added in 4.0
320 Name.starts_with("pmul.hr.sw.") || // Added in 7.0
321 Name.starts_with("pmulh.w.") || // Added in 7.0
322 Name.starts_with("pmulhu.w.") || // Added in 7.0
323 Name.starts_with("pmull.") || // Added in 4.0
324 Name.starts_with("pmultishift.qb.") || // Added in 8.0
325 Name.starts_with("pmulu.dq.") || // Added in 4.0
326 Name.starts_with("por.") || // Added in 3.9
327 Name.starts_with("prol.") || // Added in 8.0
328 Name.starts_with("prolv.") || // Added in 8.0
329 Name.starts_with("pror.") || // Added in 8.0
330 Name.starts_with("prorv.") || // Added in 8.0
331 Name.starts_with("pshuf.b.") || // Added in 4.0
332 Name.starts_with("pshuf.d.") || // Added in 3.9
333 Name.starts_with("pshufh.w.") || // Added in 3.9
334 Name.starts_with("pshufl.w.") || // Added in 3.9
335 Name.starts_with("psll.d") || // Added in 4.0
336 Name.starts_with("psll.q") || // Added in 4.0
337 Name.starts_with("psll.w") || // Added in 4.0
338 Name.starts_with("pslli") || // Added in 4.0
339 Name.starts_with("psllv") || // Added in 4.0
340 Name.starts_with("psra.d") || // Added in 4.0
341 Name.starts_with("psra.q") || // Added in 4.0
342 Name.starts_with("psra.w") || // Added in 4.0
343 Name.starts_with("psrai") || // Added in 4.0
344 Name.starts_with("psrav") || // Added in 4.0
345 Name.starts_with("psrl.d") || // Added in 4.0
346 Name.starts_with("psrl.q") || // Added in 4.0
347 Name.starts_with("psrl.w") || // Added in 4.0
348 Name.starts_with("psrli") || // Added in 4.0
349 Name.starts_with("psrlv") || // Added in 4.0
350 Name.starts_with("psub.") || // Added in 4.0
351 Name.starts_with("psubs.") || // Added in 8.0
352 Name.starts_with("psubus.") || // Added in 8.0
353 Name.starts_with("pternlog.") || // Added in 7.0
354 Name.starts_with("punpckh") || // Added in 3.9
355 Name.starts_with("punpckl") || // Added in 3.9
356 Name.starts_with("pxor.") || // Added in 3.9
357 Name.starts_with("shuf.f") || // Added in 6.0
358 Name.starts_with("shuf.i") || // Added in 6.0
359 Name.starts_with("shuf.p") || // Added in 4.0
360 Name.starts_with("sqrt.p") || // Added in 7.0
361 Name.starts_with("store.b.") || // Added in 3.9
362 Name.starts_with("store.d.") || // Added in 3.9
363 Name.starts_with("store.p") || // Added in 3.9
364 Name.starts_with("store.q.") || // Added in 3.9
365 Name.starts_with("store.w.") || // Added in 3.9
366 Name == "store.ss" || // Added in 7.0
367 Name.starts_with("storeu.") || // Added in 3.9
368 Name.starts_with("sub.p") || // Added in 7.0. 128/256 in 4.0
369 Name.starts_with("ucmp.") || // Added in 5.0
370 Name.starts_with("unpckh.") || // Added in 3.9
371 Name.starts_with("unpckl.") || // Added in 3.9
372 Name.starts_with("valign.") || // Added in 4.0
373 Name == "vcvtph2ps.128" || // Added in 11.0
374 Name == "vcvtph2ps.256" || // Added in 11.0
375 Name.starts_with("vextract") || // Added in 4.0
376 Name.starts_with("vfmadd.") || // Added in 7.0
377 Name.starts_with("vfmaddsub.") || // Added in 7.0
378 Name.starts_with("vfnmadd.") || // Added in 7.0
379 Name.starts_with("vfnmsub.") || // Added in 7.0
380 Name.starts_with("vpdpbusd.") || // Added in 7.0
381 Name.starts_with("vpdpbusds.") || // Added in 7.0
382 Name.starts_with("vpdpwssd.") || // Added in 7.0
383 Name.starts_with("vpdpwssds.") || // Added in 7.0
384 Name.starts_with("vpermi2var.") || // Added in 7.0
385 Name.starts_with("vpermil.p") || // Added in 3.9
386 Name.starts_with("vpermilvar.") || // Added in 4.0
387 Name.starts_with("vpermt2var.") || // Added in 7.0
388 Name.starts_with("vpmadd52") || // Added in 7.0
389 Name.starts_with("vpshld.") || // Added in 7.0
390 Name.starts_with("vpshldv.") || // Added in 8.0
391 Name.starts_with("vpshrd.") || // Added in 7.0
392 Name.starts_with("vpshrdv.") || // Added in 8.0
393 Name.starts_with("vpshufbitqmb.") || // Added in 8.0
394 Name.starts_with("xor.")); // Added in 3.9
395
396 if (Name.consume_front("mask3."))
397 // 'avx512.mask3.*'
398 return (Name.starts_with("vfmadd.") || // Added in 7.0
399 Name.starts_with("vfmaddsub.") || // Added in 7.0
400 Name.starts_with("vfmsub.") || // Added in 7.0
401 Name.starts_with("vfmsubadd.") || // Added in 7.0
402 Name.starts_with("vfnmsub.")); // Added in 7.0
403
404 if (Name.consume_front("maskz."))
405 // 'avx512.maskz.*'
406 return (Name.starts_with("pternlog.") || // Added in 7.0
407 Name.starts_with("vfmadd.") || // Added in 7.0
408 Name.starts_with("vfmaddsub.") || // Added in 7.0
409 Name.starts_with("vpdpbusd.") || // Added in 7.0
410 Name.starts_with("vpdpbusds.") || // Added in 7.0
411 Name.starts_with("vpdpwssd.") || // Added in 7.0
412 Name.starts_with("vpdpwssds.") || // Added in 7.0
413 Name.starts_with("vpermt2var.") || // Added in 7.0
414 Name.starts_with("vpmadd52") || // Added in 7.0
415 Name.starts_with("vpshldv.") || // Added in 8.0
416 Name.starts_with("vpshrdv.")); // Added in 8.0
417
418 // 'avx512.*'
419 return (Name == "movntdqa" || // Added in 5.0
420 Name == "pmul.dq.512" || // Added in 7.0
421 Name == "pmulu.dq.512" || // Added in 7.0
422 Name.starts_with("broadcastm") || // Added in 6.0
423 Name.starts_with("cmp.p") || // Added in 12.0
424 Name.starts_with("cvtb2mask.") || // Added in 7.0
425 Name.starts_with("cvtd2mask.") || // Added in 7.0
426 Name.starts_with("cvtmask2") || // Added in 5.0
427 Name.starts_with("cvtq2mask.") || // Added in 7.0
428 Name == "cvtusi2sd" || // Added in 7.0
429 Name.starts_with("cvtw2mask.") || // Added in 7.0
430 Name == "kand.w" || // Added in 7.0
431 Name == "kandn.w" || // Added in 7.0
432 Name == "knot.w" || // Added in 7.0
433 Name == "kor.w" || // Added in 7.0
434 Name == "kortestc.w" || // Added in 7.0
435 Name == "kortestz.w" || // Added in 7.0
436 Name.starts_with("kunpck") || // added in 6.0
437 Name == "kxnor.w" || // Added in 7.0
438 Name == "kxor.w" || // Added in 7.0
439 Name.starts_with("padds.") || // Added in 8.0
440 Name.starts_with("pbroadcast") || // Added in 3.9
441 Name.starts_with("prol") || // Added in 8.0
442 Name.starts_with("pror") || // Added in 8.0
443 Name.starts_with("psll.dq") || // Added in 3.9
444 Name.starts_with("psrl.dq") || // Added in 3.9
445 Name.starts_with("psubs.") || // Added in 8.0
446 Name.starts_with("ptestm") || // Added in 6.0
447 Name.starts_with("ptestnm") || // Added in 6.0
448 Name.starts_with("storent.") || // Added in 3.9
449 Name.starts_with("vbroadcast.s") || // Added in 7.0
450 Name.starts_with("vpshld.") || // Added in 8.0
451 Name.starts_with("vpshrd.")); // Added in 8.0
452 }
453
454 if (Name.consume_front("fma."))
455 return (Name.starts_with("vfmadd.") || // Added in 7.0
456 Name.starts_with("vfmsub.") || // Added in 7.0
457 Name.starts_with("vfmsubadd.") || // Added in 7.0
458 Name.starts_with("vfnmadd.") || // Added in 7.0
459 Name.starts_with("vfnmsub.")); // Added in 7.0
460
461 if (Name.consume_front("fma4."))
462 return Name.starts_with("vfmadd.s"); // Added in 7.0
463
464 if (Name.consume_front("sse."))
465 return (Name == "add.ss" || // Added in 4.0
466 Name == "cvtsi2ss" || // Added in 7.0
467 Name == "cvtsi642ss" || // Added in 7.0
468 Name == "div.ss" || // Added in 4.0
469 Name == "mul.ss" || // Added in 4.0
470 Name.starts_with("sqrt.p") || // Added in 7.0
471 Name == "sqrt.ss" || // Added in 7.0
472 Name.starts_with("storeu.") || // Added in 3.9
473 Name == "sub.ss"); // Added in 4.0
474
475 if (Name.consume_front("sse2."))
476 return (Name == "add.sd" || // Added in 4.0
477 Name == "cvtdq2pd" || // Added in 3.9
478 Name == "cvtdq2ps" || // Added in 7.0
479 Name == "cvtps2pd" || // Added in 3.9
480 Name == "cvtsi2sd" || // Added in 7.0
481 Name == "cvtsi642sd" || // Added in 7.0
482 Name == "cvtss2sd" || // Added in 7.0
483 Name == "div.sd" || // Added in 4.0
484 Name == "mul.sd" || // Added in 4.0
485 Name.starts_with("padds.") || // Added in 8.0
486 Name.starts_with("paddus.") || // Added in 8.0
487 Name.starts_with("pcmpeq.") || // Added in 3.1
488 Name.starts_with("pcmpgt.") || // Added in 3.1
489 Name == "pmaxs.w" || // Added in 3.9
490 Name == "pmaxu.b" || // Added in 3.9
491 Name == "pmins.w" || // Added in 3.9
492 Name == "pminu.b" || // Added in 3.9
493 Name == "pmulu.dq" || // Added in 7.0
494 Name.starts_with("pshuf") || // Added in 3.9
495 Name.starts_with("psll.dq") || // Added in 3.7
496 Name.starts_with("psrl.dq") || // Added in 3.7
497 Name.starts_with("psubs.") || // Added in 8.0
498 Name.starts_with("psubus.") || // Added in 8.0
499 Name.starts_with("sqrt.p") || // Added in 7.0
500 Name == "sqrt.sd" || // Added in 7.0
501 Name == "storel.dq" || // Added in 3.9
502 Name.starts_with("storeu.") || // Added in 3.9
503 Name == "sub.sd"); // Added in 4.0
504
505 if (Name.consume_front("sse41."))
506 return (Name.starts_with("blendp") || // Added in 3.7
507 Name == "movntdqa" || // Added in 5.0
508 Name == "pblendw" || // Added in 3.7
509 Name == "pmaxsb" || // Added in 3.9
510 Name == "pmaxsd" || // Added in 3.9
511 Name == "pmaxud" || // Added in 3.9
512 Name == "pmaxuw" || // Added in 3.9
513 Name == "pminsb" || // Added in 3.9
514 Name == "pminsd" || // Added in 3.9
515 Name == "pminud" || // Added in 3.9
516 Name == "pminuw" || // Added in 3.9
517 Name.starts_with("pmovsx") || // Added in 3.8
518 Name.starts_with("pmovzx") || // Added in 3.9
519 Name == "pmuldq"); // Added in 7.0
520
521 if (Name.consume_front("sse42."))
522 return Name == "crc32.64.8"; // Added in 3.4
523
524 if (Name.consume_front("sse4a."))
525 return Name.starts_with("movnt."); // Added in 3.9
526
527 if (Name.consume_front("ssse3."))
528 return (Name == "pabs.b.128" || // Added in 6.0
529 Name == "pabs.d.128" || // Added in 6.0
530 Name == "pabs.w.128"); // Added in 6.0
531
532 if (Name.consume_front("xop."))
533 return (Name == "vpcmov" || // Added in 3.8
534 Name == "vpcmov.256" || // Added in 5.0
535 Name.starts_with("vpcom") || // Added in 3.2, Updated in 9.0
536 Name.starts_with("vprot")); // Added in 8.0
537
538 if (Name.consume_front("bmi."))
539 return (Name.starts_with("pdep.") || // Added in 23.0
540 Name.starts_with("pext.")); // Added in 23.0
541
542 return (Name == "addcarry.u32" || // Added in 8.0
543 Name == "addcarry.u64" || // Added in 8.0
544 Name == "addcarryx.u32" || // Added in 8.0
545 Name == "addcarryx.u64" || // Added in 8.0
546 Name == "subborrow.u32" || // Added in 8.0
547 Name == "subborrow.u64" || // Added in 8.0
548 Name.starts_with("vcvtph2ps.")); // Added in 11.0
549}
550
552 Function *&NewFn) {
553 // Only handle intrinsics that start with "x86.".
554 if (!Name.consume_front("x86."))
555 return false;
556
557 if (shouldUpgradeX86Intrinsic(F, Name)) {
558 NewFn = nullptr;
559 return true;
560 }
561
562 if (Name == "rdtscp") { // Added in 8.0
563 // If this intrinsic has 0 operands, it's the new version.
564 if (F->getFunctionType()->getNumParams() == 0)
565 return false;
566
567 rename(F);
568 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
569 Intrinsic::x86_rdtscp);
570 return true;
571 }
572
573 Intrinsic::ID ID;
574
575 // SSE4.1 ptest functions may have an old signature.
576 if (Name.consume_front("sse41.ptest")) { // Added in 3.2
578 .Case("c", Intrinsic::x86_sse41_ptestc)
579 .Case("z", Intrinsic::x86_sse41_ptestz)
580 .Case("nzc", Intrinsic::x86_sse41_ptestnzc)
582 if (ID != Intrinsic::not_intrinsic)
583 return upgradePTESTIntrinsic(F, ID, NewFn);
584
585 return false;
586 }
587
588 // Several blend and other instructions with masks used the wrong number of
589 // bits.
590
591 // Added in 3.6
593 .Case("sse41.insertps", Intrinsic::x86_sse41_insertps)
594 .Case("sse41.dppd", Intrinsic::x86_sse41_dppd)
595 .Case("sse41.dpps", Intrinsic::x86_sse41_dpps)
596 .Case("sse41.mpsadbw", Intrinsic::x86_sse41_mpsadbw)
597 .Case("avx.dp.ps.256", Intrinsic::x86_avx_dp_ps_256)
598 .Case("avx2.mpsadbw", Intrinsic::x86_avx2_mpsadbw)
600 if (ID != Intrinsic::not_intrinsic)
601 return upgradeX86IntrinsicsWith8BitMask(F, ID, NewFn);
602
603 if (Name.consume_front("avx512.")) {
604 if (Name.consume_front("mask.cmp.")) {
605 // Added in 7.0
607 .Case("pd.128", Intrinsic::x86_avx512_mask_cmp_pd_128)
608 .Case("pd.256", Intrinsic::x86_avx512_mask_cmp_pd_256)
609 .Case("pd.512", Intrinsic::x86_avx512_mask_cmp_pd_512)
610 .Case("ps.128", Intrinsic::x86_avx512_mask_cmp_ps_128)
611 .Case("ps.256", Intrinsic::x86_avx512_mask_cmp_ps_256)
612 .Case("ps.512", Intrinsic::x86_avx512_mask_cmp_ps_512)
614 if (ID != Intrinsic::not_intrinsic)
615 return upgradeX86MaskedFPCompare(F, ID, NewFn);
616 } else if (Name.starts_with("vpdpbusd.") ||
617 Name.starts_with("vpdpbusds.")) {
618 // Added in 21.1
620 .Case("vpdpbusd.128", Intrinsic::x86_avx512_vpdpbusd_128)
621 .Case("vpdpbusd.256", Intrinsic::x86_avx512_vpdpbusd_256)
622 .Case("vpdpbusd.512", Intrinsic::x86_avx512_vpdpbusd_512)
623 .Case("vpdpbusds.128", Intrinsic::x86_avx512_vpdpbusds_128)
624 .Case("vpdpbusds.256", Intrinsic::x86_avx512_vpdpbusds_256)
625 .Case("vpdpbusds.512", Intrinsic::x86_avx512_vpdpbusds_512)
627 if (ID != Intrinsic::not_intrinsic)
628 return upgradeX86MultiplyAddBytes(F, ID, NewFn);
629 } else if (Name.starts_with("vpdpwssd.") ||
630 Name.starts_with("vpdpwssds.")) {
631 // Added in 21.1
633 .Case("vpdpwssd.128", Intrinsic::x86_avx512_vpdpwssd_128)
634 .Case("vpdpwssd.256", Intrinsic::x86_avx512_vpdpwssd_256)
635 .Case("vpdpwssd.512", Intrinsic::x86_avx512_vpdpwssd_512)
636 .Case("vpdpwssds.128", Intrinsic::x86_avx512_vpdpwssds_128)
637 .Case("vpdpwssds.256", Intrinsic::x86_avx512_vpdpwssds_256)
638 .Case("vpdpwssds.512", Intrinsic::x86_avx512_vpdpwssds_512)
640 if (ID != Intrinsic::not_intrinsic)
641 return upgradeX86MultiplyAddWords(F, ID, NewFn);
642 }
643 return false; // No other 'x86.avx512.*'.
644 }
645
646 if (Name.consume_front("avx2.")) {
647 if (Name.consume_front("vpdpb")) {
648 // Added in 21.1
650 .Case("ssd.128", Intrinsic::x86_avx2_vpdpbssd_128)
651 .Case("ssd.256", Intrinsic::x86_avx2_vpdpbssd_256)
652 .Case("ssds.128", Intrinsic::x86_avx2_vpdpbssds_128)
653 .Case("ssds.256", Intrinsic::x86_avx2_vpdpbssds_256)
654 .Case("sud.128", Intrinsic::x86_avx2_vpdpbsud_128)
655 .Case("sud.256", Intrinsic::x86_avx2_vpdpbsud_256)
656 .Case("suds.128", Intrinsic::x86_avx2_vpdpbsuds_128)
657 .Case("suds.256", Intrinsic::x86_avx2_vpdpbsuds_256)
658 .Case("uud.128", Intrinsic::x86_avx2_vpdpbuud_128)
659 .Case("uud.256", Intrinsic::x86_avx2_vpdpbuud_256)
660 .Case("uuds.128", Intrinsic::x86_avx2_vpdpbuuds_128)
661 .Case("uuds.256", Intrinsic::x86_avx2_vpdpbuuds_256)
663 if (ID != Intrinsic::not_intrinsic)
664 return upgradeX86MultiplyAddBytes(F, ID, NewFn);
665 } else if (Name.consume_front("vpdpw")) {
666 // Added in 21.1
668 .Case("sud.128", Intrinsic::x86_avx2_vpdpwsud_128)
669 .Case("sud.256", Intrinsic::x86_avx2_vpdpwsud_256)
670 .Case("suds.128", Intrinsic::x86_avx2_vpdpwsuds_128)
671 .Case("suds.256", Intrinsic::x86_avx2_vpdpwsuds_256)
672 .Case("usd.128", Intrinsic::x86_avx2_vpdpwusd_128)
673 .Case("usd.256", Intrinsic::x86_avx2_vpdpwusd_256)
674 .Case("usds.128", Intrinsic::x86_avx2_vpdpwusds_128)
675 .Case("usds.256", Intrinsic::x86_avx2_vpdpwusds_256)
676 .Case("uud.128", Intrinsic::x86_avx2_vpdpwuud_128)
677 .Case("uud.256", Intrinsic::x86_avx2_vpdpwuud_256)
678 .Case("uuds.128", Intrinsic::x86_avx2_vpdpwuuds_128)
679 .Case("uuds.256", Intrinsic::x86_avx2_vpdpwuuds_256)
681 if (ID != Intrinsic::not_intrinsic)
682 return upgradeX86MultiplyAddWords(F, ID, NewFn);
683 }
684 return false; // No other 'x86.avx2.*'
685 }
686
687 if (Name.consume_front("avx10.")) {
688 if (Name.consume_front("vpdpb")) {
689 // Added in 21.1
691 .Case("ssd.512", Intrinsic::x86_avx10_vpdpbssd_512)
692 .Case("ssds.512", Intrinsic::x86_avx10_vpdpbssds_512)
693 .Case("sud.512", Intrinsic::x86_avx10_vpdpbsud_512)
694 .Case("suds.512", Intrinsic::x86_avx10_vpdpbsuds_512)
695 .Case("uud.512", Intrinsic::x86_avx10_vpdpbuud_512)
696 .Case("uuds.512", Intrinsic::x86_avx10_vpdpbuuds_512)
698 if (ID != Intrinsic::not_intrinsic)
699 return upgradeX86MultiplyAddBytes(F, ID, NewFn);
700 } else if (Name.consume_front("vpdpw")) {
702 .Case("sud.512", Intrinsic::x86_avx10_vpdpwsud_512)
703 .Case("suds.512", Intrinsic::x86_avx10_vpdpwsuds_512)
704 .Case("usd.512", Intrinsic::x86_avx10_vpdpwusd_512)
705 .Case("usds.512", Intrinsic::x86_avx10_vpdpwusds_512)
706 .Case("uud.512", Intrinsic::x86_avx10_vpdpwuud_512)
707 .Case("uuds.512", Intrinsic::x86_avx10_vpdpwuuds_512)
709 if (ID != Intrinsic::not_intrinsic)
710 return upgradeX86MultiplyAddWords(F, ID, NewFn);
711 }
712 return false; // No other 'x86.avx10.*'
713 }
714
715 if (Name.consume_front("avx512bf16.")) {
716 // Added in 9.0
718 .Case("cvtne2ps2bf16.128",
719 Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128)
720 .Case("cvtne2ps2bf16.256",
721 Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256)
722 .Case("cvtne2ps2bf16.512",
723 Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512)
724 .Case("mask.cvtneps2bf16.128",
725 Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
726 .Case("cvtneps2bf16.256",
727 Intrinsic::x86_avx512bf16_cvtneps2bf16_256)
728 .Case("cvtneps2bf16.512",
729 Intrinsic::x86_avx512bf16_cvtneps2bf16_512)
731 if (ID != Intrinsic::not_intrinsic)
732 return upgradeX86BF16Intrinsic(F, ID, NewFn);
733
734 // Added in 9.0
736 .Case("dpbf16ps.128", Intrinsic::x86_avx512bf16_dpbf16ps_128)
737 .Case("dpbf16ps.256", Intrinsic::x86_avx512bf16_dpbf16ps_256)
738 .Case("dpbf16ps.512", Intrinsic::x86_avx512bf16_dpbf16ps_512)
740 if (ID != Intrinsic::not_intrinsic)
741 return upgradeX86BF16DPIntrinsic(F, ID, NewFn);
742 return false; // No other 'x86.avx512bf16.*'.
743 }
744
745 if (Name.consume_front("xop.")) {
747 if (Name.starts_with("vpermil2")) { // Added in 3.9
748 // Upgrade any XOP PERMIL2 index operand still using a float/double
749 // vector.
750 auto Idx = F->getFunctionType()->getParamType(2);
751 if (Idx->isFPOrFPVectorTy()) {
752 unsigned IdxSize = Idx->getPrimitiveSizeInBits();
753 unsigned EltSize = Idx->getScalarSizeInBits();
754 if (EltSize == 64 && IdxSize == 128)
755 ID = Intrinsic::x86_xop_vpermil2pd;
756 else if (EltSize == 32 && IdxSize == 128)
757 ID = Intrinsic::x86_xop_vpermil2ps;
758 else if (EltSize == 64 && IdxSize == 256)
759 ID = Intrinsic::x86_xop_vpermil2pd_256;
760 else
761 ID = Intrinsic::x86_xop_vpermil2ps_256;
762 }
763 } else if (F->arg_size() == 2)
764 // frcz.ss/sd may need to have an argument dropped. Added in 3.2
766 .Case("vfrcz.ss", Intrinsic::x86_xop_vfrcz_ss)
767 .Case("vfrcz.sd", Intrinsic::x86_xop_vfrcz_sd)
769
770 if (ID != Intrinsic::not_intrinsic) {
771 rename(F);
772 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
773 return true;
774 }
775 return false; // No other 'x86.xop.*'
776 }
777
778 if (Name == "seh.recoverfp") {
779 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
780 Intrinsic::eh_recoverfp);
781 return true;
782 }
783
784 return false;
785}
786
787// Upgrade ARM (IsArm) or Aarch64 (!IsArm) intrinsic fns. Return true iff so.
788// IsArm: 'arm.*', !IsArm: 'aarch64.*'.
790 StringRef Name,
791 Function *&NewFn) {
792 if (Name.starts_with("rbit")) {
793 // '(arm|aarch64).rbit'.
795 F->getParent(), Intrinsic::bitreverse, F->arg_begin()->getType());
796 return true;
797 }
798
799 if (Name == "thread.pointer") {
800 // '(arm|aarch64).thread.pointer'.
802 F->getParent(), Intrinsic::thread_pointer, F->getReturnType());
803 return true;
804 }
805
806 bool Neon = Name.consume_front("neon.");
807 if (Neon) {
808 // '(arm|aarch64).neon.*'.
809 // Changed in 12.0: bfdot accept v4bf16 and v8bf16 instead of v8i8 and
810 // v16i8 respectively.
811 if (Name.consume_front("bfdot.")) {
812 // (arm|aarch64).neon.bfdot.*'.
813 Intrinsic::ID ID =
815 .Cases({"v2f32.v8i8", "v4f32.v16i8"},
816 IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfdot
817 : (Intrinsic::ID)Intrinsic::aarch64_neon_bfdot)
819 if (ID != Intrinsic::not_intrinsic) {
820 size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits();
821 assert((OperandWidth == 64 || OperandWidth == 128) &&
822 "Unexpected operand width");
823 LLVMContext &Ctx = F->getParent()->getContext();
824 std::array<Type *, 2> Tys{
825 {F->getReturnType(),
826 FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16)}};
827 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID, Tys);
828 return true;
829 }
830 return false; // No other '(arm|aarch64).neon.bfdot.*'.
831 }
832
833 // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic
834 // anymore and accept v8bf16 instead of v16i8.
835 if (Name.consume_front("bfm")) {
836 // (arm|aarch64).neon.bfm*'.
837 if (Name.consume_back(".v4f32.v16i8")) {
838 // (arm|aarch64).neon.bfm*.v4f32.v16i8'.
839 Intrinsic::ID ID =
841 .Case("mla",
842 IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmmla
843 : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmmla)
844 .Case("lalb",
845 IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalb
846 : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalb)
847 .Case("lalt",
848 IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalt
849 : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalt)
851 if (ID != Intrinsic::not_intrinsic) {
852 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
853 return true;
854 }
855 return false; // No other '(arm|aarch64).neon.bfm*.v16i8'.
856 }
857 return false; // No other '(arm|aarch64).neon.bfm*.
858 }
859 // Continue on to Aarch64 Neon or Arm Neon.
860 }
861 // Continue on to Arm or Aarch64.
862
863 if (IsArm) {
864 // 'arm.*'.
865 if (Neon) {
866 // 'arm.neon.*'.
868 .StartsWith("vclz.", Intrinsic::ctlz)
869 .StartsWith("vcnt.", Intrinsic::ctpop)
870 .StartsWith("vqadds.", Intrinsic::sadd_sat)
871 .StartsWith("vqaddu.", Intrinsic::uadd_sat)
872 .StartsWith("vqsubs.", Intrinsic::ssub_sat)
873 .StartsWith("vqsubu.", Intrinsic::usub_sat)
874 .StartsWith("vrinta.", Intrinsic::round)
875 .StartsWith("vrintn.", Intrinsic::roundeven)
876 .StartsWith("vrintm.", Intrinsic::floor)
877 .StartsWith("vrintp.", Intrinsic::ceil)
878 .StartsWith("vrintx.", Intrinsic::rint)
879 .StartsWith("vrintz.", Intrinsic::trunc)
881 if (ID != Intrinsic::not_intrinsic) {
882 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID,
883 F->arg_begin()->getType());
884 return true;
885 }
886
887 if (Name.consume_front("vst")) {
888 // 'arm.neon.vst*'.
889 static const Regex vstRegex("^([1234]|[234]lane)\\.v[a-z0-9]*$");
891 if (vstRegex.match(Name, &Groups)) {
892 static const Intrinsic::ID StoreInts[] = {
893 Intrinsic::arm_neon_vst1, Intrinsic::arm_neon_vst2,
894 Intrinsic::arm_neon_vst3, Intrinsic::arm_neon_vst4};
895
896 static const Intrinsic::ID StoreLaneInts[] = {
897 Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane,
898 Intrinsic::arm_neon_vst4lane};
899
900 auto fArgs = F->getFunctionType()->params();
901 Type *Tys[] = {fArgs[0], fArgs[1]};
902 if (Groups[1].size() == 1)
904 F->getParent(), StoreInts[fArgs.size() - 3], Tys);
905 else
907 F->getParent(), StoreLaneInts[fArgs.size() - 5], Tys);
908 return true;
909 }
910 return false; // No other 'arm.neon.vst*'.
911 }
912
913 return false; // No other 'arm.neon.*'.
914 }
915
916 if (Name.consume_front("mve.")) {
917 // 'arm.mve.*'.
918 if (Name == "vctp64") {
919 if (cast<FixedVectorType>(F->getReturnType())->getNumElements() == 4) {
920 // A vctp64 returning a v4i1 is converted to return a v2i1. Rename
921 // the function and deal with it below in UpgradeIntrinsicCall.
922 rename(F);
923 return true;
924 }
925 return false; // Not 'arm.mve.vctp64'.
926 }
927
928 if (Name.starts_with("vrintn.v")) {
930 F->getParent(), Intrinsic::roundeven, F->arg_begin()->getType());
931 return true;
932 }
933
934 // These too are changed to accept a v2i1 instead of the old v4i1.
935 if (Name.consume_back(".v4i1")) {
936 // 'arm.mve.*.v4i1'.
937 if (Name.consume_back(".predicated.v2i64.v4i32"))
938 // 'arm.mve.*.predicated.v2i64.v4i32.v4i1'
939 return Name == "mull.int" || Name == "vqdmull";
940
941 if (Name.consume_back(".v2i64")) {
942 // 'arm.mve.*.v2i64.v4i1'
943 bool IsGather = Name.consume_front("vldr.gather.");
944 if (IsGather || Name.consume_front("vstr.scatter.")) {
945 if (Name.consume_front("base.")) {
946 // Optional 'wb.' prefix.
947 Name.consume_front("wb.");
948 // 'arm.mve.(vldr.gather|vstr.scatter).base.(wb.)?
949 // predicated.v2i64.v2i64.v4i1'.
950 return Name == "predicated.v2i64";
951 }
952
953 if (Name.consume_front("offset.predicated."))
954 return Name == (IsGather ? "v2i64.p0i64" : "p0i64.v2i64") ||
955 Name == (IsGather ? "v2i64.p0" : "p0.v2i64");
956
957 // No other 'arm.mve.(vldr.gather|vstr.scatter).*.v2i64.v4i1'.
958 return false;
959 }
960
961 return false; // No other 'arm.mve.*.v2i64.v4i1'.
962 }
963 return false; // No other 'arm.mve.*.v4i1'.
964 }
965 return false; // No other 'arm.mve.*'.
966 }
967
968 if (Name.consume_front("cde.vcx")) {
969 // 'arm.cde.vcx*'.
970 if (Name.consume_back(".predicated.v2i64.v4i1"))
971 // 'arm.cde.vcx*.predicated.v2i64.v4i1'.
972 return Name == "1q" || Name == "1qa" || Name == "2q" || Name == "2qa" ||
973 Name == "3q" || Name == "3qa";
974
975 return false; // No other 'arm.cde.vcx*'.
976 }
977 } else {
978 // 'aarch64.*'.
979 if (Neon) {
980 // 'aarch64.neon.*'.
982 .StartsWith("frintn", Intrinsic::roundeven)
983 .StartsWith("rbit", Intrinsic::bitreverse)
985 if (ID != Intrinsic::not_intrinsic) {
986 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID,
987 F->arg_begin()->getType());
988 return true;
989 }
990
991 if (Name.starts_with("addp")) {
992 // 'aarch64.neon.addp*'.
993 if (F->arg_size() != 2)
994 return false; // Invalid IR.
995 VectorType *Ty = dyn_cast<VectorType>(F->getReturnType());
996 if (Ty && Ty->getElementType()->isFloatingPointTy()) {
998 F->getParent(), Intrinsic::aarch64_neon_faddp, Ty);
999 return true;
1000 }
1001 }
1002
1003 // Changed in 20.0: bfcvt/bfcvtn/bcvtn2 have been replaced with fptrunc.
1004 if (Name.starts_with("bfcvt")) {
1005 NewFn = nullptr;
1006 return true;
1007 }
1008
1009 // vcvtfp2hf and vcvthf2fp -> fpext and fptrunc
1010 if (Name == "vcvtfp2hf" || Name == "vcvthf2fp") {
1011 NewFn = nullptr;
1012 return true;
1013 }
1014
1015 return false; // No other 'aarch64.neon.*'.
1016 }
1017 if (Name.consume_front("sve.")) {
1018 // 'aarch64.sve.*'.
1019 if (Name.consume_front("bf")) {
1020 if (Name == "mmla") {
1021 Type *Tys[] = {F->getReturnType(),
1022 std::next(F->arg_begin())->getType()};
1024 F->getParent(), Intrinsic::aarch64_sve_fmmla, Tys);
1025 return true;
1026 }
1027 if (Name.consume_back(".lane")) {
1028 // 'aarch64.sve.bf*.lane'.
1029 Intrinsic::ID ID =
1031 .Case("dot", Intrinsic::aarch64_sve_bfdot_lane_v2)
1032 .Case("mlalb", Intrinsic::aarch64_sve_bfmlalb_lane_v2)
1033 .Case("mlalt", Intrinsic::aarch64_sve_bfmlalt_lane_v2)
1035 if (ID != Intrinsic::not_intrinsic) {
1036 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
1037 return true;
1038 }
1039 return false; // No other 'aarch64.sve.bf*.lane'.
1040 }
1041 return false; // No other 'aarch64.sve.bf*'.
1042 }
1043
1044 // 'aarch64.sve.fcvt.bf16f32' || 'aarch64.sve.fcvtnt.bf16f32'
1045 if (Name == "fcvt.bf16f32" || Name == "fcvtnt.bf16f32") {
1046 NewFn = nullptr;
1047 return true;
1048 }
1049
1050 if (Name.consume_front("addqv")) {
1051 // 'aarch64.sve.addqv'.
1052 if (!F->getReturnType()->isFPOrFPVectorTy())
1053 return false;
1054
1055 auto Args = F->getFunctionType()->params();
1056 Type *Tys[] = {F->getReturnType(), Args[1]};
1058 F->getParent(), Intrinsic::aarch64_sve_faddqv, Tys);
1059 return true;
1060 }
1061
1062 if (Name.consume_front("ld")) {
1063 // 'aarch64.sve.ld*'.
1064 static const Regex LdRegex("^[234](.nxv[a-z0-9]+|$)");
1065 if (LdRegex.match(Name)) {
1066 Type *ScalarTy =
1067 cast<VectorType>(F->getReturnType())->getElementType();
1068 ElementCount EC =
1069 cast<VectorType>(F->arg_begin()->getType())->getElementCount();
1070 assert(F->arg_size() == 2 &&
1071 "Expected 2 arguments for ld* intrinsic.");
1072 Type *PtrTy = F->getArg(1)->getType();
1073 Type *Ty = VectorType::get(ScalarTy, EC);
1074 static const Intrinsic::ID LoadIDs[] = {
1075 Intrinsic::aarch64_sve_ld2_sret,
1076 Intrinsic::aarch64_sve_ld3_sret,
1077 Intrinsic::aarch64_sve_ld4_sret,
1078 };
1080 F->getParent(), LoadIDs[Name[0] - '2'], {Ty, PtrTy});
1081 return true;
1082 }
1083 return false; // No other 'aarch64.sve.ld*'.
1084 }
1085
1086 if (Name.consume_front("tuple.")) {
1087 // 'aarch64.sve.tuple.*'.
1088 if (Name.starts_with("get")) {
1089 // 'aarch64.sve.tuple.get*'.
1090 Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
1092 F->getParent(), Intrinsic::vector_extract, Tys);
1093 return true;
1094 }
1095
1096 if (Name.starts_with("set")) {
1097 // 'aarch64.sve.tuple.set*'.
1098 auto Args = F->getFunctionType()->params();
1099 Type *Tys[] = {Args[0], Args[2], Args[1]};
1101 F->getParent(), Intrinsic::vector_insert, Tys);
1102 return true;
1103 }
1104
1105 static const Regex CreateTupleRegex("^create[234](.nxv[a-z0-9]+|$)");
1106 if (CreateTupleRegex.match(Name)) {
1107 // 'aarch64.sve.tuple.create*'.
1108 auto Args = F->getFunctionType()->params();
1109 Type *Tys[] = {F->getReturnType(), Args[1]};
1111 F->getParent(), Intrinsic::vector_insert, Tys);
1112 return true;
1113 }
1114 return false; // No other 'aarch64.sve.tuple.*'.
1115 }
1116
1117 if (Name.starts_with("rev.nxv")) {
1118 // 'aarch64.sve.rev.<Ty>'
1120 F->getParent(), Intrinsic::vector_reverse, F->getReturnType());
1121 return true;
1122 }
1123
1124 return false; // No other 'aarch64.sve.*'.
1125 }
1126 if (Name.consume_front("sme.")) {
1127 // 'aarch64.sme.*'.
1128 if (Name.consume_front("ftmopa.")) {
1129 // The FP8 FTMOPA intrinsics were split out from the non-FP8 FTMOPA
1130 // intrinsics to model their FPMR dependency.
1131 Intrinsic::ID ID =
1133 .Case("za16.nxv16i8", Intrinsic::aarch64_sme_fp8_ftmopa_za16)
1134 .Case("za32.nxv16i8", Intrinsic::aarch64_sme_fp8_ftmopa_za32)
1136 if (ID != Intrinsic::not_intrinsic) {
1137 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
1138 return true;
1139 }
1140 return false; // No other 'aarch64.sme.ftmopa.*'.
1141 }
1142
1143 return false; // No other 'aarch64.sme.*'.
1144 }
1145 }
1146 return false; // No other 'arm.*', 'aarch64.*'.
1147}
1148
1150 StringRef Name) {
1151 if (Name.consume_front("cp.async.bulk.tensor.g2s.")) {
1152 Intrinsic::ID ID =
1154 .Case("im2col.3d",
1155 Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_3d)
1156 .Case("im2col.4d",
1157 Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_4d)
1158 .Case("im2col.5d",
1159 Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_5d)
1160 .Case("tile.1d", Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_1d)
1161 .Case("tile.2d", Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_2d)
1162 .Case("tile.3d", Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_3d)
1163 .Case("tile.4d", Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_4d)
1164 .Case("tile.5d", Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_5d)
1166
1167 if (ID == Intrinsic::not_intrinsic)
1168 return ID;
1169
1170 // These intrinsics may need upgrade for two reasons:
1171 // (1) When the address-space of the first argument is shared[AS=3]
1172 // (and we upgrade it to use shared_cluster address-space[AS=7])
1173 if (F->getArg(0)->getType()->getPointerAddressSpace() ==
1175 return ID;
1176
1177 // (2) When there are only two boolean flag arguments at the end:
1178 //
1179 // The last three parameters of the older version of these
1180 // intrinsics are: arg1, arg2, .. i64 ch, i1 mc_flag, i1 ch_flag
1181 //
1182 // The newer version reads as:
1183 // arg1, arg2, .. i64 ch, i1 mc_flag, i1 ch_flag, i32 cta_group_flag
1184 //
1185 // So, when the type of the [N-3]rd argument is "not i1", then
1186 // it is the older version and we need to upgrade.
1187 size_t FlagStartIndex = F->getFunctionType()->getNumParams() - 3;
1188 Type *ArgType = F->getFunctionType()->getParamType(FlagStartIndex);
1189 if (!ArgType->isIntegerTy(1))
1190 return ID;
1191 }
1192
1194}
1195
1196// The legacy TMA reduction intrinsics encode the reduction operator in their
1197// name, while the current ones take it as an immediate argument. Map the
1198// operator part of a legacy name to the corresponding immediate value.
1199static std::optional<unsigned> getNVPTXTMAReductionOp(StringRef Name) {
1201 .Case("add", static_cast<unsigned>(nvvm::TMAReductionOp::ADD))
1202 .Case("min", static_cast<unsigned>(nvvm::TMAReductionOp::MIN))
1203 .Case("max", static_cast<unsigned>(nvvm::TMAReductionOp::MAX))
1204 .Case("inc", static_cast<unsigned>(nvvm::TMAReductionOp::INC))
1205 .Case("dec", static_cast<unsigned>(nvvm::TMAReductionOp::DEC))
1206 .Case("and", static_cast<unsigned>(nvvm::TMAReductionOp::AND))
1207 .Case("or", static_cast<unsigned>(nvvm::TMAReductionOp::OR))
1208 .Case("xor", static_cast<unsigned>(nvvm::TMAReductionOp::XOR))
1209 .Default(std::nullopt);
1210}
1211
1213 if (!Name.consume_front("cp.async.bulk.tensor.reduce."))
1215
1216 auto [RedOpName, ShapeName] = Name.split('.');
1217 if (!getNVPTXTMAReductionOp(RedOpName))
1219
1220 return StringSwitch<Intrinsic::ID>(ShapeName)
1221 .Case("tile.1d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_1d)
1222 .Case("tile.2d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_2d)
1223 .Case("tile.3d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_3d)
1224 .Case("tile.4d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_4d)
1225 .Case("tile.5d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_5d)
1226 .Case("im2col.3d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_3d)
1227 .Case("im2col.4d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_4d)
1228 .Case("im2col.5d", Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_5d)
1230}
1231
1233 StringRef Name) {
1234 if (Name.consume_front("mapa.shared.cluster"))
1235 if (F->getReturnType()->getPointerAddressSpace() ==
1237 return Intrinsic::nvvm_mapa_shared_cluster;
1238
1239 if (Name.consume_front("cp.async.bulk.")) {
1240 Intrinsic::ID ID =
1242 .Case("global.to.shared.cluster",
1243 Intrinsic::nvvm_cp_async_bulk_global_to_shared_cluster)
1244 .Case("shared.cta.to.cluster",
1245 Intrinsic::nvvm_cp_async_bulk_shared_cta_to_cluster)
1247
1248 if (ID != Intrinsic::not_intrinsic)
1249 if (F->getArg(0)->getType()->getPointerAddressSpace() ==
1251 return ID;
1252 }
1253
1255}
1256
1257static Intrinsic::ID
1259 if (!Name.consume_front("tcgen05.commit."))
1261
1262 if (Name.consume_front("shared."))
1263 return StringSwitch<Intrinsic::ID>(Name)
1264 .Case("cg1", Intrinsic::nvvm_tcgen05_commit_cg1)
1265 .Case("cg2", Intrinsic::nvvm_tcgen05_commit_cg2)
1267
1268 if (Name.consume_front("mc.shared.")) {
1269 // Only upgrade older i16 mc variants.
1270 if (!F->getArg(1)->getType()->isIntegerTy(16))
1272
1273 return StringSwitch<Intrinsic::ID>(Name)
1274 .Case("cg1", Intrinsic::nvvm_tcgen05_commit_mc_cg1)
1275 .Case("cg2", Intrinsic::nvvm_tcgen05_commit_mc_cg2)
1277 }
1278
1280}
1281
1283 if (Name.consume_front("fma.rn."))
1284 return StringSwitch<Intrinsic::ID>(Name)
1285 .Case("bf16", Intrinsic::nvvm_fma_rn_bf16)
1286 .Case("bf16x2", Intrinsic::nvvm_fma_rn_bf16x2)
1287 .Case("relu.bf16", Intrinsic::nvvm_fma_rn_relu_bf16)
1288 .Case("relu.bf16x2", Intrinsic::nvvm_fma_rn_relu_bf16x2)
1290
1291 if (Name.consume_front("fmax."))
1292 return StringSwitch<Intrinsic::ID>(Name)
1293 .Case("bf16", Intrinsic::nvvm_fmax_bf16)
1294 .Case("bf16x2", Intrinsic::nvvm_fmax_bf16x2)
1295 .Case("ftz.bf16", Intrinsic::nvvm_fmax_ftz_bf16)
1296 .Case("ftz.bf16x2", Intrinsic::nvvm_fmax_ftz_bf16x2)
1297 .Case("ftz.nan.bf16", Intrinsic::nvvm_fmax_ftz_nan_bf16)
1298 .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmax_ftz_nan_bf16x2)
1299 .Case("ftz.nan.xorsign.abs.bf16",
1300 Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16)
1301 .Case("ftz.nan.xorsign.abs.bf16x2",
1302 Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16x2)
1303 .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16)
1304 .Case("ftz.xorsign.abs.bf16x2",
1305 Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16x2)
1306 .Case("nan.bf16", Intrinsic::nvvm_fmax_nan_bf16)
1307 .Case("nan.bf16x2", Intrinsic::nvvm_fmax_nan_bf16x2)
1308 .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16)
1309 .Case("nan.xorsign.abs.bf16x2",
1310 Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16x2)
1311 .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmax_xorsign_abs_bf16)
1312 .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmax_xorsign_abs_bf16x2)
1314
1315 if (Name.consume_front("fmin."))
1316 return StringSwitch<Intrinsic::ID>(Name)
1317 .Case("bf16", Intrinsic::nvvm_fmin_bf16)
1318 .Case("bf16x2", Intrinsic::nvvm_fmin_bf16x2)
1319 .Case("ftz.bf16", Intrinsic::nvvm_fmin_ftz_bf16)
1320 .Case("ftz.bf16x2", Intrinsic::nvvm_fmin_ftz_bf16x2)
1321 .Case("ftz.nan.bf16", Intrinsic::nvvm_fmin_ftz_nan_bf16)
1322 .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmin_ftz_nan_bf16x2)
1323 .Case("ftz.nan.xorsign.abs.bf16",
1324 Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16)
1325 .Case("ftz.nan.xorsign.abs.bf16x2",
1326 Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16x2)
1327 .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16)
1328 .Case("ftz.xorsign.abs.bf16x2",
1329 Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16x2)
1330 .Case("nan.bf16", Intrinsic::nvvm_fmin_nan_bf16)
1331 .Case("nan.bf16x2", Intrinsic::nvvm_fmin_nan_bf16x2)
1332 .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16)
1333 .Case("nan.xorsign.abs.bf16x2",
1334 Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16x2)
1335 .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmin_xorsign_abs_bf16)
1336 .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmin_xorsign_abs_bf16x2)
1338
1339 if (Name.consume_front("neg."))
1340 return StringSwitch<Intrinsic::ID>(Name)
1341 .Case("bf16", Intrinsic::nvvm_neg_bf16)
1342 .Case("bf16x2", Intrinsic::nvvm_neg_bf16x2)
1344
1346}
1347
1349 StringRef Name) {
1350 if (!Name.consume_front("tcgen05.mma."))
1352
1353 // tcgen05.mma.ws.* variants do not need collector-b appended.
1354 if (Name.starts_with("ws"))
1356
1357 return F->getIntrinsicID();
1358}
1359
1361 return Name.consume_front("local") || Name.consume_front("shared") ||
1362 Name.consume_front("global") || Name.consume_front("constant") ||
1363 Name.consume_front("param");
1364}
1365
1367 const FunctionType *FuncTy) {
1368 Type *HalfTy = Type::getHalfTy(FuncTy->getContext());
1369 if (Name.starts_with("to.fp16")) {
1370 return CastInst::castIsValid(Instruction::FPTrunc, FuncTy->getParamType(0),
1371 HalfTy) &&
1372 CastInst::castIsValid(Instruction::BitCast, HalfTy,
1373 FuncTy->getReturnType());
1374 }
1375
1376 if (Name.starts_with("from.fp16")) {
1377 return CastInst::castIsValid(Instruction::BitCast, FuncTy->getParamType(0),
1378 HalfTy) &&
1379 CastInst::castIsValid(Instruction::FPExt, HalfTy,
1380 FuncTy->getReturnType());
1381 }
1382
1383 return false;
1384}
1385
1388 if (IID == Intrinsic::not_intrinsic)
1389 return false;
1390
1391 auto [FirstDefault, Defaults] = Intrinsic::getAllDefaultArgValues(IID);
1392 if (Defaults.empty())
1393 return false;
1394
1395 // Overloaded intrinsics are out of scope for the default-arg feature
1396 // and will be supported in a follow-up.
1397 if (Intrinsic::isOverloaded(IID))
1398 return false;
1399
1400 // Get the canonical full declaration for this intrinsic.
1401 Function *FullDecl = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
1402
1403 // If the existing declaration already has all args, nothing to upgrade
1404 if (F->arg_size() >= FullDecl->arg_size())
1405 return false;
1406
1407 // Defaults are a contiguous trailing block, so checking the first missing
1408 // argument is enough.
1409 if (F->arg_size() < FirstDefault)
1410 return false;
1411
1412 NewFn = FullDecl;
1413 return true;
1414}
1415
1417 bool CanUpgradeDebugIntrinsicsToRecords) {
1418 assert(F && "Illegal to upgrade a non-existent Function.");
1419
1420 StringRef Name = F->getName();
1421
1422 // Quickly eliminate it, if it's not a candidate.
1423 if (!Name.consume_front("llvm.") || Name.empty())
1424 return false;
1425
1426 switch (Name[0]) {
1427 default: break;
1428 case 'a': {
1429 bool IsArm = Name.consume_front("arm.");
1430 if (IsArm || Name.consume_front("aarch64.")) {
1431 if (upgradeArmOrAarch64IntrinsicFunction(IsArm, F, Name, NewFn))
1432 return true;
1433 break;
1434 }
1435
1436 if (Name.consume_front("amdgcn.")) {
1437 if (Name == "alignbit") {
1438 // Target specific intrinsic became redundant
1440 F->getParent(), Intrinsic::fshr, {F->getReturnType()});
1441 return true;
1442 }
1443
1444 if (Name.consume_front("atomic.")) {
1445 if (Name.starts_with("inc") || Name.starts_with("dec") ||
1446 Name.starts_with("cond.sub") || Name.starts_with("csub")) {
1447 // These were replaced with atomicrmw uinc_wrap, udec_wrap, usub_cond
1448 // and usub_sat so there's no new declaration.
1449 NewFn = nullptr;
1450 return true;
1451 }
1452 break; // No other 'amdgcn.atomic.*'
1453 }
1454
1455 switch (F->getIntrinsicID()) {
1456 default:
1457 break;
1458 // Legacy wmma iu intrinsics without the optional clamp operand.
1459 case Intrinsic::amdgcn_wmma_i32_16x16x64_iu8:
1460 if (F->arg_size() == 7) {
1461 NewFn = nullptr;
1462 return true;
1463 }
1464 break;
1465 case Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8:
1466 case Intrinsic::amdgcn_wmma_f32_16x16x4_f32:
1467 case Intrinsic::amdgcn_wmma_f32_16x16x32_bf16:
1468 case Intrinsic::amdgcn_wmma_f32_16x16x32_f16:
1469 case Intrinsic::amdgcn_wmma_f16_16x16x32_f16:
1470 case Intrinsic::amdgcn_wmma_bf16_16x16x32_bf16:
1471 case Intrinsic::amdgcn_wmma_bf16f32_16x16x32_bf16:
1472 if (F->arg_size() == 8) {
1473 NewFn = nullptr;
1474 return true;
1475 }
1476 break;
1477 }
1478
1479 if (Name.consume_front("ds.") || Name.consume_front("global.atomic.") ||
1480 Name.consume_front("flat.atomic.")) {
1481 if (Name.starts_with("fadd") ||
1482 // FIXME: We should also remove fmin.num and fmax.num intrinsics.
1483 (Name.starts_with("fmin") && !Name.starts_with("fmin.num")) ||
1484 (Name.starts_with("fmax") && !Name.starts_with("fmax.num"))) {
1485 // Replaced with atomicrmw fadd/fmin/fmax, so there's no new
1486 // declaration.
1487 NewFn = nullptr;
1488 return true;
1489 }
1490 }
1491
1492 if (Name.starts_with("ldexp.")) {
1493 // Target specific intrinsic became redundant
1495 F->getParent(), Intrinsic::ldexp,
1496 {F->getReturnType(), F->getArg(1)->getType()});
1497 return true;
1498 }
1499 break; // No other 'amdgcn.*'
1500 }
1501
1502 break;
1503 }
1504 case 'c': {
1505 if (F->arg_size() == 1) {
1506 if (Name.consume_front("convert.")) {
1507 if (convertIntrinsicValidType(Name, F->getFunctionType())) {
1508 NewFn = nullptr;
1509 return true;
1510 }
1511 }
1512
1514 .StartsWith("ctlz.", Intrinsic::ctlz)
1515 .StartsWith("cttz.", Intrinsic::cttz)
1517 if (ID != Intrinsic::not_intrinsic) {
1518 rename(F);
1519 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID,
1520 F->arg_begin()->getType());
1521 return true;
1522 }
1523 }
1524
1526 if (Name == "coro.end" &&
1527 (F->arg_size() == 2 || F->getReturnType()->isIntegerTy(1)))
1528 CoroEndID = Intrinsic::coro_end;
1529 else if (Name == "coro.end.async" && F->getReturnType()->isIntegerTy(1))
1530 CoroEndID = Intrinsic::coro_end_async;
1531
1532 if (CoroEndID != Intrinsic::not_intrinsic) {
1533 rename(F);
1534 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), CoroEndID);
1535 return true;
1536 }
1537
1538 break;
1539 }
1540 case 'd':
1541 if (Name.consume_front("dbg.")) {
1542 // Mark debug intrinsics for upgrade to new debug format.
1543 if (CanUpgradeDebugIntrinsicsToRecords) {
1544 if (Name == "addr" || Name == "value" || Name == "assign" ||
1545 Name == "declare" || Name == "label") {
1546 // There's no function to replace these with.
1547 NewFn = nullptr;
1548 // But we do want these to get upgraded.
1549 return true;
1550 }
1551 }
1552 // Update llvm.dbg.addr intrinsics even in "new debug mode"; they'll get
1553 // converted to DbgVariableRecords later.
1554 if (Name == "addr" || (Name == "value" && F->arg_size() == 4)) {
1555 rename(F);
1556 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
1557 Intrinsic::dbg_value);
1558 return true;
1559 }
1560 break; // No other 'dbg.*'.
1561 }
1562 break;
1563 case 'e':
1564 if (Name.consume_front("experimental.vector.")) {
1565 Intrinsic::ID ID =
1567 // Skip over extract.last.active, otherwise it will be 'upgraded'
1568 // to a regular vector extract which is a different operation.
1569 .StartsWith("extract.last.active.", Intrinsic::not_intrinsic)
1570 .StartsWith("extract.", Intrinsic::vector_extract)
1571 .StartsWith("insert.", Intrinsic::vector_insert)
1572 .StartsWith("reverse.", Intrinsic::vector_reverse)
1573 .StartsWith("interleave2.", Intrinsic::vector_interleave2)
1574 .StartsWith("deinterleave2.", Intrinsic::vector_deinterleave2)
1575 .StartsWith("partial.reduce.add",
1576 Intrinsic::vector_partial_reduce_add)
1578 if (ID != Intrinsic::not_intrinsic) {
1579 const auto *FT = F->getFunctionType();
1581 if (ID == Intrinsic::vector_extract ||
1582 ID == Intrinsic::vector_interleave2)
1583 // Extracting overloads the return type.
1584 Tys.push_back(FT->getReturnType());
1585 if (ID != Intrinsic::vector_interleave2)
1586 Tys.push_back(FT->getParamType(0));
1587 if (ID == Intrinsic::vector_insert ||
1588 ID == Intrinsic::vector_partial_reduce_add)
1589 // Inserting overloads the inserted type.
1590 Tys.push_back(FT->getParamType(1));
1591 rename(F);
1592 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID, Tys);
1593 return true;
1594 }
1595
1596 if (Name.consume_front("reduce.")) {
1598 static const Regex R("^([a-z]+)\\.[a-z][0-9]+");
1599 if (R.match(Name, &Groups))
1601 .Case("add", Intrinsic::vector_reduce_add)
1602 .Case("mul", Intrinsic::vector_reduce_mul)
1603 .Case("and", Intrinsic::vector_reduce_and)
1604 .Case("or", Intrinsic::vector_reduce_or)
1605 .Case("xor", Intrinsic::vector_reduce_xor)
1606 .Case("smax", Intrinsic::vector_reduce_smax)
1607 .Case("smin", Intrinsic::vector_reduce_smin)
1608 .Case("umax", Intrinsic::vector_reduce_umax)
1609 .Case("umin", Intrinsic::vector_reduce_umin)
1610 .Case("fmax", Intrinsic::vector_reduce_fmax)
1611 .Case("fmin", Intrinsic::vector_reduce_fmin)
1613
1614 bool V2 = false;
1615 if (ID == Intrinsic::not_intrinsic) {
1616 static const Regex R2("^v2\\.([a-z]+)\\.[fi][0-9]+");
1617 Groups.clear();
1618 V2 = true;
1619 if (R2.match(Name, &Groups))
1621 .Case("fadd", Intrinsic::vector_reduce_fadd)
1622 .Case("fmul", Intrinsic::vector_reduce_fmul)
1624 }
1625 if (ID != Intrinsic::not_intrinsic) {
1626 rename(F);
1627 auto Args = F->getFunctionType()->params();
1628 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID,
1629 {Args[V2 ? 1 : 0]});
1630 return true;
1631 }
1632 break; // No other 'expermental.vector.reduce.*'.
1633 }
1634
1635 if (Name.consume_front("splice"))
1636 return true;
1637 break; // No other 'experimental.vector.*'.
1638 }
1639 if (Name.consume_front("experimental.stepvector.")) {
1640 Intrinsic::ID ID = Intrinsic::stepvector;
1641 rename(F);
1643 F->getParent(), ID, F->getFunctionType()->getReturnType());
1644 return true;
1645 }
1646 break; // No other 'e*'.
1647 case 'f':
1648 if (Name.starts_with("flt.rounds")) {
1649 rename(F);
1650 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
1651 Intrinsic::get_rounding);
1652 return true;
1653 }
1654 break;
1655 case 'i':
1656 if (Name.starts_with("invariant.group.barrier")) {
1657 // Rename invariant.group.barrier to launder.invariant.group
1658 auto Args = F->getFunctionType()->params();
1659 Type* ObjectPtr[1] = {Args[0]};
1660 rename(F);
1662 F->getParent(), Intrinsic::launder_invariant_group, ObjectPtr);
1663 return true;
1664 }
1665 break;
1666 case 'l': {
1667 bool IsLifetimeStart = Name.consume_front("lifetime.start");
1668 bool IsLifetimeEnd = !IsLifetimeStart && Name.consume_front("lifetime.end");
1669 if (IsLifetimeStart || IsLifetimeEnd) {
1670 if (F->arg_size() == 2) {
1671 Intrinsic::ID IID = IsLifetimeStart ? Intrinsic::lifetime_start
1672 : Intrinsic::lifetime_end;
1673 rename(F);
1674 // Old 2 argument form of these intrinsics have [Size, Ptr] as
1675 // arguments. Use the Ptr argument to create new declaration.
1676 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID,
1677 F->getArg(1)->getType());
1678 return true;
1679 } else if (F->arg_size() == 1 && Name == ".i64") {
1680 // Matches @llvm.lifetime.{start/end}.i64 which used to be created by
1681 // Autoupgrade prior to
1682 // https://github.com/llvm/llvm-project/pull/204601. This is an invalid
1683 // intrinsic with no expected calls. To allow auto-upgrade process to
1684 // delete such invalid intrinsic declaration, set NewFn = nullptr
1685 // and return true here. If there are actual calls to this intrinsic
1686 // (which is not expected), they will be deleted in
1687 // UpgradeIntrinsicCall.
1688 NewFn = nullptr;
1689 return true;
1690 }
1691 }
1692 break;
1693 }
1694 case 'm': {
1695 // Updating the memory intrinsics (memcpy/memmove/memset) that have an
1696 // alignment parameter to embedding the alignment as an attribute of
1697 // the pointer args.
1698 if (unsigned ID = StringSwitch<unsigned>(Name)
1699 .StartsWith("memcpy.", Intrinsic::memcpy)
1700 .StartsWith("memmove.", Intrinsic::memmove)
1701 .Default(0)) {
1702 if (F->arg_size() == 5) {
1703 rename(F);
1704 // Get the types of dest, src, and len
1705 ArrayRef<Type *> ParamTypes =
1706 F->getFunctionType()->params().slice(0, 3);
1707 NewFn =
1708 Intrinsic::getOrInsertDeclaration(F->getParent(), ID, ParamTypes);
1709 return true;
1710 }
1711 }
1712 if (Name.starts_with("memset.") && F->arg_size() == 5) {
1713 rename(F);
1714 // Get the types of dest, and len
1715 const auto *FT = F->getFunctionType();
1716 Type *ParamTypes[2] = {
1717 FT->getParamType(0), // Dest
1718 FT->getParamType(2) // len
1719 };
1720 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
1721 Intrinsic::memset, ParamTypes);
1722 return true;
1723 }
1724
1725 unsigned MaskedID =
1727 .StartsWith("masked.load", Intrinsic::masked_load)
1728 .StartsWith("masked.gather", Intrinsic::masked_gather)
1729 .StartsWith("masked.store", Intrinsic::masked_store)
1730 .StartsWith("masked.scatter", Intrinsic::masked_scatter)
1731 .Default(0);
1732 if (MaskedID && F->arg_size() == 4) {
1733 rename(F);
1734 if (MaskedID == Intrinsic::masked_load ||
1735 MaskedID == Intrinsic::masked_gather) {
1737 F->getParent(), MaskedID,
1738 {F->getReturnType(), F->getArg(0)->getType()});
1739 return true;
1740 }
1742 F->getParent(), MaskedID,
1743 {F->getArg(0)->getType(), F->getArg(1)->getType()});
1744 return true;
1745 }
1746 break;
1747 }
1748 case 'n': {
1749 if (Name.consume_front("nvvm.")) {
1750 // Check for nvvm intrinsics corresponding exactly to an LLVM intrinsic.
1751 if (F->arg_size() == 1) {
1752 Intrinsic::ID IID =
1754 .Cases({"brev32", "brev64"}, Intrinsic::bitreverse)
1755 .Case("clz.i", Intrinsic::ctlz)
1756 .Case("popc.i", Intrinsic::ctpop)
1758 if (IID != Intrinsic::not_intrinsic) {
1759 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID,
1760 {F->getReturnType()});
1761 return true;
1762 }
1763 } else if (F->arg_size() == 2) {
1764 Intrinsic::ID IID =
1766 .Cases({"max.s", "max.i", "max.ll"}, Intrinsic::smax)
1767 .Cases({"min.s", "min.i", "min.ll"}, Intrinsic::smin)
1768 .Cases({"max.us", "max.ui", "max.ull"}, Intrinsic::umax)
1769 .Cases({"min.us", "min.ui", "min.ull"}, Intrinsic::umin)
1771 if (IID != Intrinsic::not_intrinsic) {
1772 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID,
1773 {F->getReturnType()});
1774 return true;
1775 }
1776 }
1777
1778 // Check for nvvm intrinsics that need a return type adjustment.
1779 if (!F->getReturnType()->getScalarType()->isBFloatTy()) {
1781 if (IID != Intrinsic::not_intrinsic) {
1782 NewFn = nullptr;
1783 return true;
1784 }
1785 }
1786
1787 // Upgrade Distributed Shared Memory Intrinsics
1789 if (IID != Intrinsic::not_intrinsic) {
1790 rename(F);
1791 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
1792 return true;
1793 }
1794
1795 // Upgrade TMA reduction intrinsics
1796 // llvm.nvvm.cp.async.bulk.tensor.reduce.<red_op>* =>
1797 // llvm.nvvm.cp.async.bulk.tensor.reduce.<shape>*
1799 if (IID != Intrinsic::not_intrinsic) {
1800 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
1801 return true;
1802 }
1803
1804 // Upgrade tcgen05.commit shared variants to anyptr intrinsics.
1806 if (IID != Intrinsic::not_intrinsic) {
1807 rename(F);
1809 F->getParent(), IID, F->getReturnType(),
1810 F->getFunctionType()->params());
1811 return true;
1812 }
1813
1814 // Upgrade TMA copy G2S Intrinsics
1816 if (IID != Intrinsic::not_intrinsic) {
1817 rename(F);
1818 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
1819 return true;
1820 }
1821
1822 // Upgrade tcgen05.mma intrinsics missing collector_usage_b.
1824 if (IID != Intrinsic::not_intrinsic) {
1825 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
1826 return NewFn != F;
1827 }
1828
1829 // The following nvvm intrinsics correspond exactly to an LLVM idiom, but
1830 // not to an intrinsic alone. We expand them in UpgradeIntrinsicCall.
1831 //
1832 // TODO: We could add lohi.i2d.
1833 bool Expand = false;
1834 if (Name.consume_front("abs."))
1835 // nvvm.abs.{i,ii}
1836 Expand =
1837 Name == "i" || Name == "ll" || Name == "bf16" || Name == "bf16x2";
1838 else if (Name.consume_front("fabs."))
1839 // nvvm.fabs.{f,ftz.f,d}
1840 Expand = Name == "f" || Name == "ftz.f" || Name == "d";
1841 else if (Name.consume_front("ex2.approx."))
1842 // nvvm.ex2.approx.{f,ftz.f,d,f16x2}
1843 Expand =
1844 Name == "f" || Name == "ftz.f" || Name == "d" || Name == "f16x2";
1845 else if (Name.consume_front("atomic.load."))
1846 // nvvm.atomic.load.add.{f32,f64}.p
1847 // nvvm.atomic.load.{inc,dec}.32.p
1848 Expand = StringSwitch<bool>(Name)
1849 .StartsWith("add.f32.p", true)
1850 .StartsWith("add.f64.p", true)
1851 .StartsWith("inc.32.p", true)
1852 .StartsWith("dec.32.p", true)
1853 .Default(false);
1854 else if (Name.consume_front("atomic."))
1855 // nvvm.atomic.{add,exch,max,min,inc,dec,and,or,xor}.gen.{i,f}.{cta,sys}
1856 // nvvm.atomic.cas.gen.i.{cta,sys}
1857 Expand = StringSwitch<bool>(Name)
1858 .StartsWith("add.gen.", true)
1859 .StartsWith("exch.gen.", true)
1860 .StartsWith("max.gen.", true)
1861 .StartsWith("min.gen.", true)
1862 .StartsWith("inc.gen.", true)
1863 .StartsWith("dec.gen.", true)
1864 .StartsWith("and.gen.", true)
1865 .StartsWith("or.gen.", true)
1866 .StartsWith("xor.gen.", true)
1867 .StartsWith("cas.gen.", true)
1868 .Default(false);
1869 else if (Name.consume_front("bitcast."))
1870 // nvvm.bitcast.{f2i,i2f,ll2d,d2ll}
1871 Expand =
1872 Name == "f2i" || Name == "i2f" || Name == "ll2d" || Name == "d2ll";
1873 else if (Name.consume_front("rotate."))
1874 // nvvm.rotate.{b32,b64,right.b64}
1875 Expand = Name == "b32" || Name == "b64" || Name == "right.b64";
1876 else if (Name.consume_front("ptr.gen.to."))
1877 // nvvm.ptr.gen.to.{local,shared,global,constant,param}
1878 Expand = consumeNVVMPtrAddrSpace(Name);
1879 else if (Name.consume_front("ptr."))
1880 // nvvm.ptr.{local,shared,global,constant,param}.to.gen
1881 Expand = consumeNVVMPtrAddrSpace(Name) && Name.starts_with(".to.gen");
1882 else if (Name.consume_front("ldg.global."))
1883 // nvvm.ldg.global.{i,p,f}
1884 Expand = (Name.starts_with("i.") || Name.starts_with("f.") ||
1885 Name.starts_with("p."));
1886 else
1887 Expand = StringSwitch<bool>(Name)
1888 .Case("barrier0", true)
1889 .Case("barrier.n", true)
1890 .Case("barrier.sync.cnt", true)
1891 .Case("barrier.sync", true)
1892 .Case("barrier", true)
1893 .Case("bar.sync", true)
1894 .Case("barrier0.popc", true)
1895 .Case("barrier0.and", true)
1896 .Case("barrier0.or", true)
1897 .Case("clz.ll", true)
1898 .Case("popc.ll", true)
1899 .Case("h2f", true)
1900 .Case("swap.lo.hi.b64", true)
1901 .Case("tanh.approx.f32", true)
1902 .Default(false);
1903
1904 if (Expand) {
1905 NewFn = nullptr;
1906 return true;
1907 }
1908 break; // No other 'nvvm.*'.
1909 }
1910 break;
1911 }
1912 case 'o':
1913 if (Name.starts_with("objectsize.")) {
1914 Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
1915 if (F->arg_size() == 2 || F->arg_size() == 3) {
1916 rename(F);
1917 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(),
1918 Intrinsic::objectsize, Tys);
1919 return true;
1920 }
1921 }
1922 break;
1923
1924 case 'p':
1925 if (Name.starts_with("ptr.annotation.") && F->arg_size() == 4) {
1926 rename(F);
1928 F->getParent(), Intrinsic::ptr_annotation,
1929 {F->arg_begin()->getType(), F->getArg(1)->getType()});
1930 return true;
1931 }
1932 break;
1933
1934 case 'r': {
1935 if (Name.consume_front("riscv.")) {
1936 Intrinsic::ID ID;
1938 .Case("aes32dsi", Intrinsic::riscv_aes32dsi)
1939 .Case("aes32dsmi", Intrinsic::riscv_aes32dsmi)
1940 .Case("aes32esi", Intrinsic::riscv_aes32esi)
1941 .Case("aes32esmi", Intrinsic::riscv_aes32esmi)
1943 if (ID != Intrinsic::not_intrinsic) {
1944 if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32)) {
1945 rename(F);
1946 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
1947 return true;
1948 }
1949 break; // No other applicable upgrades.
1950 }
1951
1953 .StartsWith("sm4ks", Intrinsic::riscv_sm4ks)
1954 .StartsWith("sm4ed", Intrinsic::riscv_sm4ed)
1956 if (ID != Intrinsic::not_intrinsic) {
1957 if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32) ||
1958 F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
1959 rename(F);
1960 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
1961 return true;
1962 }
1963 break; // No other applicable upgrades.
1964 }
1965
1967 .StartsWith("sha256sig0", Intrinsic::riscv_sha256sig0)
1968 .StartsWith("sha256sig1", Intrinsic::riscv_sha256sig1)
1969 .StartsWith("sha256sum0", Intrinsic::riscv_sha256sum0)
1970 .StartsWith("sha256sum1", Intrinsic::riscv_sha256sum1)
1971 .StartsWith("sm3p0", Intrinsic::riscv_sm3p0)
1972 .StartsWith("sm3p1", Intrinsic::riscv_sm3p1)
1974 if (ID != Intrinsic::not_intrinsic) {
1975 if (F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
1976 rename(F);
1977 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
1978 return true;
1979 }
1980 break; // No other applicable upgrades.
1981 }
1982
1983 // Replace llvm.riscv.clmul with llvm.clmul.
1984 if (Name == "clmul.i32" || Name == "clmul.i64") {
1986 F->getParent(), Intrinsic::clmul, {F->getReturnType()});
1987 return true;
1988 }
1989
1990 break; // No other 'riscv.*' intrinsics
1991 }
1992 } break;
1993
1994 case 's':
1995 if (Name == "stackprotectorcheck") {
1996 NewFn = nullptr;
1997 return true;
1998 }
1999 break;
2000
2001 case 't':
2002 if (Name == "thread.pointer") {
2004 F->getParent(), Intrinsic::thread_pointer, F->getReturnType());
2005 return true;
2006 }
2007 break;
2008
2009 case 'v': {
2010 if (Name == "var.annotation" && F->arg_size() == 4) {
2011 rename(F);
2013 F->getParent(), Intrinsic::var_annotation,
2014 {{F->arg_begin()->getType(), F->getArg(1)->getType()}});
2015 return true;
2016 }
2017 if (Name.consume_front("vector.splice")) {
2018 if (Name.starts_with(".left") || Name.starts_with(".right"))
2019 break;
2020 return true;
2021 }
2022 break;
2023 }
2024
2025 case 'w':
2026 if (Name.consume_front("wasm.")) {
2027 Intrinsic::ID ID =
2029 .StartsWith("fma.", Intrinsic::wasm_relaxed_madd)
2030 .StartsWith("fms.", Intrinsic::wasm_relaxed_nmadd)
2031 .StartsWith("laneselect.", Intrinsic::wasm_relaxed_laneselect)
2033 if (ID != Intrinsic::not_intrinsic) {
2034 rename(F);
2035 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID,
2036 F->getReturnType());
2037 return true;
2038 }
2039
2040 if (Name.consume_front("dot.i8x16.i7x16.")) {
2042 .Case("signed", Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed)
2043 .Case("add.signed",
2044 Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed)
2046 if (ID != Intrinsic::not_intrinsic) {
2047 rename(F);
2048 NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
2049 return true;
2050 }
2051 break; // No other 'wasm.dot.i8x16.i7x16.*'.
2052 }
2053 break; // No other 'wasm.*'.
2054 }
2055 break;
2056
2057 case 'x':
2058 if (upgradeX86IntrinsicFunction(F, Name, NewFn))
2059 return true;
2060 }
2061
2062 auto *ST = dyn_cast<StructType>(F->getReturnType());
2063 if (ST && (!ST->isLiteral() || ST->isPacked()) &&
2064 F->getIntrinsicID() != Intrinsic::not_intrinsic) {
2065 // Replace return type with literal non-packed struct. Only do this for
2066 // intrinsics declared to return a struct, not for intrinsics with
2067 // overloaded return type, in which case the exact struct type will be
2068 // mangled into the name.
2069 if (Intrinsic::hasStructReturnType(F->getIntrinsicID())) {
2070 FunctionType *FT = F->getFunctionType();
2071 auto *NewST = StructType::get(ST->getContext(), ST->elements());
2072 auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());
2073 std::string Name = F->getName().str();
2074 rename(F);
2075 NewFn = Function::Create(NewFT, F->getLinkage(), F->getAddressSpace(),
2076 Name, F->getParent());
2077
2078 // The new function may also need remangling.
2079 if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn))
2080 NewFn = *Result;
2081 return true;
2082 }
2083 }
2084
2085 // Remangle our intrinsic since we upgrade the mangling
2087 if (Result != std::nullopt) {
2088 NewFn = *Result;
2089 return true;
2090 }
2091
2092 // This may not belong here. This function is effectively being overloaded
2093 // to both detect an intrinsic which needs upgrading, and to provide the
2094 // upgraded form of the intrinsic. We should perhaps have two separate
2095 // functions for this.
2097 return true;
2098
2099 return false;
2100}
2101
2103 bool CanUpgradeDebugIntrinsicsToRecords) {
2104 NewFn = nullptr;
2105 bool Upgraded =
2106 upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords);
2107
2108 // Upgrade intrinsic attributes. This does not change the function.
2109 if (NewFn)
2110 F = NewFn;
2111 if (Intrinsic::ID id = F->getIntrinsicID()) {
2112 // Only do this if the intrinsic signature is valid.
2113 SmallVector<Type *> OverloadTys;
2114 if (Intrinsic::isSignatureValid(id, F->getFunctionType(), OverloadTys))
2115 F->setAttributes(
2116 Intrinsic::getAttributes(F->getContext(), id, F->getFunctionType()));
2117 }
2118 return Upgraded;
2119}
2120
2122 if (!(GV->hasName() && (GV->getName() == "llvm.global_ctors" ||
2123 GV->getName() == "llvm.global_dtors")) ||
2124 !GV->hasInitializer())
2125 return nullptr;
2127 if (!ATy)
2128 return nullptr;
2130 if (!STy || STy->getNumElements() != 2)
2131 return nullptr;
2132
2133 LLVMContext &C = GV->getContext();
2134 IRBuilder<> IRB(C);
2135 auto EltTy = StructType::get(STy->getElementType(0), STy->getElementType(1),
2136 IRB.getPtrTy());
2137 Constant *Init = GV->getInitializer();
2138 unsigned N = Init->getNumOperands();
2139 std::vector<Constant *> NewCtors(N);
2140 for (unsigned i = 0; i != N; ++i) {
2141 auto Ctor = cast<Constant>(Init->getOperand(i));
2142 NewCtors[i] = ConstantStruct::get(EltTy, Ctor->getAggregateElement(0u),
2143 Ctor->getAggregateElement(1),
2145 }
2146 Constant *NewInit = ConstantArray::get(ArrayType::get(EltTy, N), NewCtors);
2147
2148 return new GlobalVariable(NewInit->getType(), false, GV->getLinkage(),
2149 NewInit, GV->getName());
2150}
2151
2152// Handles upgrading SSE2/AVX2/AVX512BW PSLLDQ intrinsics by converting them
2153// to byte shuffles.
2155 unsigned Shift) {
2156 auto *ResultTy = cast<FixedVectorType>(Op->getType());
2157 unsigned NumElts = ResultTy->getNumElements() * 8;
2158
2159 // Bitcast from a 64-bit element type to a byte element type.
2160 Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
2161 Op = Builder.CreateBitCast(Op, VecTy, "cast");
2162
2163 // We'll be shuffling in zeroes.
2164 Value *Res = Constant::getNullValue(VecTy);
2165
2166 // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
2167 // we'll just return the zero vector.
2168 if (Shift < 16) {
2169 int Idxs[64];
2170 // 256/512-bit version is split into 2/4 16-byte lanes.
2171 for (unsigned l = 0; l != NumElts; l += 16)
2172 for (unsigned i = 0; i != 16; ++i) {
2173 unsigned Idx = NumElts + i - Shift;
2174 if (Idx < NumElts)
2175 Idx -= NumElts - 16; // end of lane, switch operand.
2176 Idxs[l + i] = Idx + l;
2177 }
2178
2179 Res = Builder.CreateShuffleVector(Res, Op, ArrayRef(Idxs, NumElts));
2180 }
2181
2182 // Bitcast back to a 64-bit element type.
2183 return Builder.CreateBitCast(Res, ResultTy, "cast");
2184}
2185
2186// Handles upgrading SSE2/AVX2/AVX512BW PSRLDQ intrinsics by converting them
2187// to byte shuffles.
2189 unsigned Shift) {
2190 auto *ResultTy = cast<FixedVectorType>(Op->getType());
2191 unsigned NumElts = ResultTy->getNumElements() * 8;
2192
2193 // Bitcast from a 64-bit element type to a byte element type.
2194 Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
2195 Op = Builder.CreateBitCast(Op, VecTy, "cast");
2196
2197 // We'll be shuffling in zeroes.
2198 Value *Res = Constant::getNullValue(VecTy);
2199
2200 // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
2201 // we'll just return the zero vector.
2202 if (Shift < 16) {
2203 int Idxs[64];
2204 // 256/512-bit version is split into 2/4 16-byte lanes.
2205 for (unsigned l = 0; l != NumElts; l += 16)
2206 for (unsigned i = 0; i != 16; ++i) {
2207 unsigned Idx = i + Shift;
2208 if (Idx >= 16)
2209 Idx += NumElts - 16; // end of lane, switch operand.
2210 Idxs[l + i] = Idx + l;
2211 }
2212
2213 Res = Builder.CreateShuffleVector(Op, Res, ArrayRef(Idxs, NumElts));
2214 }
2215
2216 // Bitcast back to a 64-bit element type.
2217 return Builder.CreateBitCast(Res, ResultTy, "cast");
2218}
2219
2220static Value *getX86MaskVec(IRBuilder<> &Builder, Value *Mask,
2221 unsigned NumElts) {
2222 assert(isPowerOf2_32(NumElts) && "Expected power-of-2 mask elements");
2224 Builder.getInt1Ty(), cast<IntegerType>(Mask->getType())->getBitWidth());
2225 Mask = Builder.CreateBitCast(Mask, MaskTy);
2226
2227 // If we have less than 8 elements (1, 2 or 4), then the starting mask was an
2228 // i8 and we need to extract down to the right number of elements.
2229 if (NumElts <= 4) {
2230 int Indices[4];
2231 for (unsigned i = 0; i != NumElts; ++i)
2232 Indices[i] = i;
2233 Mask = Builder.CreateShuffleVector(Mask, Mask, ArrayRef(Indices, NumElts),
2234 "extract");
2235 }
2236
2237 return Mask;
2238}
2239
2240static Value *emitX86Select(IRBuilder<> &Builder, Value *Mask, Value *Op0,
2241 Value *Op1) {
2242 // If the mask is all ones just emit the first operation.
2243 if (const auto *C = dyn_cast<Constant>(Mask))
2244 if (C->isAllOnesValue())
2245 return Op0;
2246
2247 Mask = getX86MaskVec(Builder, Mask,
2248 cast<FixedVectorType>(Op0->getType())->getNumElements());
2249 return Builder.CreateSelect(Mask, Op0, Op1);
2250}
2251
2252static Value *emitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask, Value *Op0,
2253 Value *Op1) {
2254 // If the mask is all ones just emit the first operation.
2255 if (const auto *C = dyn_cast<Constant>(Mask))
2256 if (C->isAllOnesValue())
2257 return Op0;
2258
2259 auto *MaskTy = FixedVectorType::get(Builder.getInt1Ty(),
2260 Mask->getType()->getIntegerBitWidth());
2261 Mask = Builder.CreateBitCast(Mask, MaskTy);
2262 Mask = Builder.CreateExtractElement(Mask, (uint64_t)0);
2263 return Builder.CreateSelect(Mask, Op0, Op1);
2264}
2265
2266// Handle autoupgrade for masked PALIGNR and VALIGND/Q intrinsics.
2267// PALIGNR handles large immediates by shifting while VALIGN masks the immediate
2268// so we need to handle both cases. VALIGN also doesn't have 128-bit lanes.
2270 Value *Op1, Value *Shift,
2271 Value *Passthru, Value *Mask,
2272 bool IsVALIGN) {
2273 unsigned ShiftVal = cast<llvm::ConstantInt>(Shift)->getZExtValue();
2274
2275 unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
2276 assert((IsVALIGN || NumElts % 16 == 0) && "Illegal NumElts for PALIGNR!");
2277 assert((!IsVALIGN || NumElts <= 16) && "NumElts too large for VALIGN!");
2278 assert(isPowerOf2_32(NumElts) && "NumElts not a power of 2!");
2279
2280 // Mask the immediate for VALIGN.
2281 if (IsVALIGN)
2282 ShiftVal &= (NumElts - 1);
2283
2284 // If palignr is shifting the pair of vectors more than the size of two
2285 // lanes, emit zero.
2286 if (ShiftVal >= 32)
2288
2289 // If palignr is shifting the pair of input vectors more than one lane,
2290 // but less than two lanes, convert to shifting in zeroes.
2291 if (ShiftVal > 16) {
2292 ShiftVal -= 16;
2293 Op1 = Op0;
2295 }
2296
2297 int Indices[64];
2298 // 256-bit palignr operates on 128-bit lanes so we need to handle that
2299 for (unsigned l = 0; l < NumElts; l += 16) {
2300 for (unsigned i = 0; i != 16; ++i) {
2301 unsigned Idx = ShiftVal + i;
2302 if (!IsVALIGN && Idx >= 16) // Disable wrap for VALIGN.
2303 Idx += NumElts - 16; // End of lane, switch operand.
2304 Indices[l + i] = Idx + l;
2305 }
2306 }
2307
2308 Value *Align = Builder.CreateShuffleVector(
2309 Op1, Op0, ArrayRef(Indices, NumElts), "palignr");
2310
2311 return emitX86Select(Builder, Mask, Align, Passthru);
2312}
2313
2315 bool ZeroMask, bool IndexForm) {
2316 Type *Ty = CI.getType();
2317 unsigned VecWidth = Ty->getPrimitiveSizeInBits();
2318 unsigned EltWidth = Ty->getScalarSizeInBits();
2319 bool IsFloat = Ty->isFPOrFPVectorTy();
2320 Intrinsic::ID IID;
2321 if (VecWidth == 128 && EltWidth == 32 && IsFloat)
2322 IID = Intrinsic::x86_avx512_vpermi2var_ps_128;
2323 else if (VecWidth == 128 && EltWidth == 32 && !IsFloat)
2324 IID = Intrinsic::x86_avx512_vpermi2var_d_128;
2325 else if (VecWidth == 128 && EltWidth == 64 && IsFloat)
2326 IID = Intrinsic::x86_avx512_vpermi2var_pd_128;
2327 else if (VecWidth == 128 && EltWidth == 64 && !IsFloat)
2328 IID = Intrinsic::x86_avx512_vpermi2var_q_128;
2329 else if (VecWidth == 256 && EltWidth == 32 && IsFloat)
2330 IID = Intrinsic::x86_avx512_vpermi2var_ps_256;
2331 else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
2332 IID = Intrinsic::x86_avx512_vpermi2var_d_256;
2333 else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
2334 IID = Intrinsic::x86_avx512_vpermi2var_pd_256;
2335 else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
2336 IID = Intrinsic::x86_avx512_vpermi2var_q_256;
2337 else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
2338 IID = Intrinsic::x86_avx512_vpermi2var_ps_512;
2339 else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
2340 IID = Intrinsic::x86_avx512_vpermi2var_d_512;
2341 else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
2342 IID = Intrinsic::x86_avx512_vpermi2var_pd_512;
2343 else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
2344 IID = Intrinsic::x86_avx512_vpermi2var_q_512;
2345 else if (VecWidth == 128 && EltWidth == 16)
2346 IID = Intrinsic::x86_avx512_vpermi2var_hi_128;
2347 else if (VecWidth == 256 && EltWidth == 16)
2348 IID = Intrinsic::x86_avx512_vpermi2var_hi_256;
2349 else if (VecWidth == 512 && EltWidth == 16)
2350 IID = Intrinsic::x86_avx512_vpermi2var_hi_512;
2351 else if (VecWidth == 128 && EltWidth == 8)
2352 IID = Intrinsic::x86_avx512_vpermi2var_qi_128;
2353 else if (VecWidth == 256 && EltWidth == 8)
2354 IID = Intrinsic::x86_avx512_vpermi2var_qi_256;
2355 else if (VecWidth == 512 && EltWidth == 8)
2356 IID = Intrinsic::x86_avx512_vpermi2var_qi_512;
2357 else
2358 llvm_unreachable("Unexpected intrinsic");
2359
2360 Value *Args[] = { CI.getArgOperand(0) , CI.getArgOperand(1),
2361 CI.getArgOperand(2) };
2362
2363 // If this isn't index form we need to swap operand 0 and 1.
2364 if (!IndexForm)
2365 std::swap(Args[0], Args[1]);
2366
2367 Value *V = Builder.CreateIntrinsic(IID, Args);
2368 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty)
2369 : Builder.CreateBitCast(CI.getArgOperand(1),
2370 Ty);
2371 return emitX86Select(Builder, CI.getArgOperand(3), V, PassThru);
2372}
2373
2375 Intrinsic::ID IID) {
2376 Type *Ty = CI.getType();
2377 Value *Op0 = CI.getOperand(0);
2378 Value *Op1 = CI.getOperand(1);
2379 Value *Res = Builder.CreateIntrinsic(IID, Ty, {Op0, Op1});
2380
2381 if (CI.arg_size() == 4) { // For masked intrinsics.
2382 Value *VecSrc = CI.getOperand(2);
2383 Value *Mask = CI.getOperand(3);
2384 Res = emitX86Select(Builder, Mask, Res, VecSrc);
2385 }
2386 return Res;
2387}
2388
2390 bool IsRotateRight) {
2391 Type *Ty = CI.getType();
2392 Value *Src = CI.getArgOperand(0);
2393 Value *Amt = CI.getArgOperand(1);
2394
2395 // Amount may be scalar immediate, in which case create a splat vector.
2396 // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
2397 // we only care about the lowest log2 bits anyway.
2398 if (Amt->getType() != Ty) {
2399 unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
2400 Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
2401 Amt = Builder.CreateVectorSplat(NumElts, Amt);
2402 }
2403
2404 Intrinsic::ID IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl;
2405 Value *Res = Builder.CreateIntrinsic(IID, Ty, {Src, Src, Amt});
2406
2407 if (CI.arg_size() == 4) { // For masked intrinsics.
2408 Value *VecSrc = CI.getOperand(2);
2409 Value *Mask = CI.getOperand(3);
2410 Res = emitX86Select(Builder, Mask, Res, VecSrc);
2411 }
2412 return Res;
2413}
2414
2415static Value *upgradeX86vpcom(IRBuilder<> &Builder, CallBase &CI, unsigned Imm,
2416 bool IsSigned) {
2417 Type *Ty = CI.getType();
2418 Value *LHS = CI.getArgOperand(0);
2419 Value *RHS = CI.getArgOperand(1);
2420
2421 CmpInst::Predicate Pred;
2422 switch (Imm) {
2423 case 0x0:
2424 Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
2425 break;
2426 case 0x1:
2427 Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
2428 break;
2429 case 0x2:
2430 Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
2431 break;
2432 case 0x3:
2433 Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
2434 break;
2435 case 0x4:
2436 Pred = ICmpInst::ICMP_EQ;
2437 break;
2438 case 0x5:
2439 Pred = ICmpInst::ICMP_NE;
2440 break;
2441 case 0x6:
2442 return Constant::getNullValue(Ty); // FALSE
2443 case 0x7:
2444 return Constant::getAllOnesValue(Ty); // TRUE
2445 default:
2446 llvm_unreachable("Unknown XOP vpcom/vpcomu predicate");
2447 }
2448
2449 Value *Cmp = Builder.CreateICmp(Pred, LHS, RHS);
2450 Value *Ext = Builder.CreateSExt(Cmp, Ty);
2451 return Ext;
2452}
2453
2455 bool IsShiftRight, bool ZeroMask) {
2456 Type *Ty = CI.getType();
2457 Value *Op0 = CI.getArgOperand(0);
2458 Value *Op1 = CI.getArgOperand(1);
2459 Value *Amt = CI.getArgOperand(2);
2460
2461 if (IsShiftRight)
2462 std::swap(Op0, Op1);
2463
2464 // Amount may be scalar immediate, in which case create a splat vector.
2465 // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
2466 // we only care about the lowest log2 bits anyway.
2467 if (Amt->getType() != Ty) {
2468 unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
2469 Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
2470 Amt = Builder.CreateVectorSplat(NumElts, Amt);
2471 }
2472
2473 Intrinsic::ID IID = IsShiftRight ? Intrinsic::fshr : Intrinsic::fshl;
2474 Value *Res = Builder.CreateIntrinsic(IID, Ty, {Op0, Op1, Amt});
2475
2476 unsigned NumArgs = CI.arg_size();
2477 if (NumArgs >= 4) { // For masked intrinsics.
2478 Value *VecSrc = NumArgs == 5 ? CI.getArgOperand(3) :
2479 ZeroMask ? ConstantAggregateZero::get(CI.getType()) :
2480 CI.getArgOperand(0);
2481 Value *Mask = CI.getOperand(NumArgs - 1);
2482 Res = emitX86Select(Builder, Mask, Res, VecSrc);
2483 }
2484 return Res;
2485}
2486
2488 Value *Mask, bool Aligned) {
2489 const Align Alignment =
2490 Aligned
2491 ? Align(Data->getType()->getPrimitiveSizeInBits().getFixedValue() / 8)
2492 : Align(1);
2493
2494 // If the mask is all ones just emit a regular store.
2495 if (const auto *C = dyn_cast<Constant>(Mask))
2496 if (C->isAllOnesValue())
2497 return Builder.CreateAlignedStore(Data, Ptr, Alignment);
2498
2499 // Convert the mask from an integer type to a vector of i1.
2500 unsigned NumElts = cast<FixedVectorType>(Data->getType())->getNumElements();
2501 Mask = getX86MaskVec(Builder, Mask, NumElts);
2502 return Builder.CreateMaskedStore(Data, Ptr, Alignment, Mask);
2503}
2504
2506 Value *Passthru, Value *Mask, bool Aligned) {
2507 Type *ValTy = Passthru->getType();
2508 const Align Alignment =
2509 Aligned
2510 ? Align(
2512 8)
2513 : Align(1);
2514
2515 // If the mask is all ones just emit a regular store.
2516 if (const auto *C = dyn_cast<Constant>(Mask))
2517 if (C->isAllOnesValue())
2518 return Builder.CreateAlignedLoad(ValTy, Ptr, Alignment);
2519
2520 // Convert the mask from an integer type to a vector of i1.
2521 unsigned NumElts = cast<FixedVectorType>(ValTy)->getNumElements();
2522 Mask = getX86MaskVec(Builder, Mask, NumElts);
2523 return Builder.CreateMaskedLoad(ValTy, Ptr, Alignment, Mask, Passthru);
2524}
2525
2526static Value *upgradeAbs(IRBuilder<> &Builder, CallBase &CI) {
2527 Type *Ty = CI.getType();
2528 Value *Op0 = CI.getArgOperand(0);
2529 Value *Res = Builder.CreateIntrinsic(Intrinsic::abs, Ty,
2530 {Op0, Builder.getInt1(false)});
2531 if (CI.arg_size() == 3)
2532 Res = emitX86Select(Builder, CI.getArgOperand(2), Res, CI.getArgOperand(1));
2533 return Res;
2534}
2535
2536static Value *upgradePMULDQ(IRBuilder<> &Builder, CallBase &CI, bool IsSigned) {
2537 Type *Ty = CI.getType();
2538
2539 // Arguments have a vXi32 type so cast to vXi64.
2540 Value *LHS = Builder.CreateBitCast(CI.getArgOperand(0), Ty);
2541 Value *RHS = Builder.CreateBitCast(CI.getArgOperand(1), Ty);
2542
2543 if (IsSigned) {
2544 // Shift left then arithmetic shift right.
2545 Constant *ShiftAmt = ConstantInt::get(Ty, 32);
2546 LHS = Builder.CreateShl(LHS, ShiftAmt);
2547 LHS = Builder.CreateAShr(LHS, ShiftAmt);
2548 RHS = Builder.CreateShl(RHS, ShiftAmt);
2549 RHS = Builder.CreateAShr(RHS, ShiftAmt);
2550 } else {
2551 // Clear the upper bits.
2552 Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
2553 LHS = Builder.CreateAnd(LHS, Mask);
2554 RHS = Builder.CreateAnd(RHS, Mask);
2555 }
2556
2557 Value *Res = Builder.CreateMul(LHS, RHS);
2558
2559 if (CI.arg_size() == 4)
2560 Res = emitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2));
2561
2562 return Res;
2563}
2564
2565// Applying mask on vector of i1's and make sure result is at least 8 bits wide.
2567 Value *Mask) {
2568 unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
2569 if (Mask) {
2570 const auto *C = dyn_cast<Constant>(Mask);
2571 if (!C || !C->isAllOnesValue())
2572 Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
2573 }
2574
2575 if (NumElts < 8) {
2576 int Indices[8];
2577 for (unsigned i = 0; i != NumElts; ++i)
2578 Indices[i] = i;
2579 for (unsigned i = NumElts; i != 8; ++i)
2580 Indices[i] = NumElts + i % NumElts;
2581 Vec = Builder.CreateShuffleVector(Vec,
2583 Indices);
2584 }
2585 return Builder.CreateBitCast(Vec, Builder.getIntNTy(std::max(NumElts, 8U)));
2586}
2587
2589 unsigned CC, bool Signed) {
2590 Value *Op0 = CI.getArgOperand(0);
2591 unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
2592
2593 Value *Cmp;
2594 if (CC == 3) {
2596 FixedVectorType::get(Builder.getInt1Ty(), NumElts));
2597 } else if (CC == 7) {
2599 FixedVectorType::get(Builder.getInt1Ty(), NumElts));
2600 } else {
2602 switch (CC) {
2603 default: llvm_unreachable("Unknown condition code");
2604 case 0: Pred = ICmpInst::ICMP_EQ; break;
2605 case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
2606 case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
2607 case 4: Pred = ICmpInst::ICMP_NE; break;
2608 case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
2609 case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
2610 }
2611 Cmp = Builder.CreateICmp(Pred, Op0, CI.getArgOperand(1));
2612 }
2613
2614 Value *Mask = CI.getArgOperand(CI.arg_size() - 1);
2615
2616 return applyX86MaskOn1BitsVec(Builder, Cmp, Mask);
2617}
2618
2619// Replace a masked intrinsic with an older unmasked intrinsic.
2621 Intrinsic::ID IID) {
2622 Value *Rep =
2623 Builder.CreateIntrinsic(IID, {CI.getArgOperand(0), CI.getArgOperand(1)});
2624 return emitX86Select(Builder, CI.getArgOperand(3), Rep, CI.getArgOperand(2));
2625}
2626
2628 Value* A = CI.getArgOperand(0);
2629 Value* B = CI.getArgOperand(1);
2630 Value* Src = CI.getArgOperand(2);
2631 Value* Mask = CI.getArgOperand(3);
2632
2633 Value* AndNode = Builder.CreateAnd(Mask, APInt(8, 1));
2634 Value* Cmp = Builder.CreateIsNotNull(AndNode);
2635 Value* Extract1 = Builder.CreateExtractElement(B, (uint64_t)0);
2636 Value* Extract2 = Builder.CreateExtractElement(Src, (uint64_t)0);
2637 Value* Select = Builder.CreateSelect(Cmp, Extract1, Extract2);
2638 return Builder.CreateInsertElement(A, Select, (uint64_t)0);
2639}
2640
2642 Value* Op = CI.getArgOperand(0);
2643 Type* ReturnOp = CI.getType();
2644 unsigned NumElts = cast<FixedVectorType>(CI.getType())->getNumElements();
2645 Value *Mask = getX86MaskVec(Builder, Op, NumElts);
2646 return Builder.CreateSExt(Mask, ReturnOp, "vpmovm2");
2647}
2648
2649// Replace intrinsic with unmasked version and a select.
2651 CallBase &CI, Value *&Rep) {
2652 Name = Name.substr(12); // Remove avx512.mask.
2653
2654 unsigned VecWidth = CI.getType()->getPrimitiveSizeInBits();
2655 unsigned EltWidth = CI.getType()->getScalarSizeInBits();
2656 Intrinsic::ID IID;
2657 if (Name.starts_with("max.p")) {
2658 if (VecWidth == 128 && EltWidth == 32)
2659 IID = Intrinsic::x86_sse_max_ps;
2660 else if (VecWidth == 128 && EltWidth == 64)
2661 IID = Intrinsic::x86_sse2_max_pd;
2662 else if (VecWidth == 256 && EltWidth == 32)
2663 IID = Intrinsic::x86_avx_max_ps_256;
2664 else if (VecWidth == 256 && EltWidth == 64)
2665 IID = Intrinsic::x86_avx_max_pd_256;
2666 else
2667 llvm_unreachable("Unexpected intrinsic");
2668 } else if (Name.starts_with("min.p")) {
2669 if (VecWidth == 128 && EltWidth == 32)
2670 IID = Intrinsic::x86_sse_min_ps;
2671 else if (VecWidth == 128 && EltWidth == 64)
2672 IID = Intrinsic::x86_sse2_min_pd;
2673 else if (VecWidth == 256 && EltWidth == 32)
2674 IID = Intrinsic::x86_avx_min_ps_256;
2675 else if (VecWidth == 256 && EltWidth == 64)
2676 IID = Intrinsic::x86_avx_min_pd_256;
2677 else
2678 llvm_unreachable("Unexpected intrinsic");
2679 } else if (Name.starts_with("pshuf.b.")) {
2680 if (VecWidth == 128)
2681 IID = Intrinsic::x86_ssse3_pshuf_b_128;
2682 else if (VecWidth == 256)
2683 IID = Intrinsic::x86_avx2_pshuf_b;
2684 else if (VecWidth == 512)
2685 IID = Intrinsic::x86_avx512_pshuf_b_512;
2686 else
2687 llvm_unreachable("Unexpected intrinsic");
2688 } else if (Name.starts_with("pmul.hr.sw.")) {
2689 if (VecWidth == 128)
2690 IID = Intrinsic::x86_ssse3_pmul_hr_sw_128;
2691 else if (VecWidth == 256)
2692 IID = Intrinsic::x86_avx2_pmul_hr_sw;
2693 else if (VecWidth == 512)
2694 IID = Intrinsic::x86_avx512_pmul_hr_sw_512;
2695 else
2696 llvm_unreachable("Unexpected intrinsic");
2697 } else if (Name.starts_with("pmulh.w.")) {
2698 if (VecWidth == 128)
2699 IID = Intrinsic::x86_sse2_pmulh_w;
2700 else if (VecWidth == 256)
2701 IID = Intrinsic::x86_avx2_pmulh_w;
2702 else if (VecWidth == 512)
2703 IID = Intrinsic::x86_avx512_pmulh_w_512;
2704 else
2705 llvm_unreachable("Unexpected intrinsic");
2706 } else if (Name.starts_with("pmulhu.w.")) {
2707 if (VecWidth == 128)
2708 IID = Intrinsic::x86_sse2_pmulhu_w;
2709 else if (VecWidth == 256)
2710 IID = Intrinsic::x86_avx2_pmulhu_w;
2711 else if (VecWidth == 512)
2712 IID = Intrinsic::x86_avx512_pmulhu_w_512;
2713 else
2714 llvm_unreachable("Unexpected intrinsic");
2715 } else if (Name.starts_with("pmaddw.d.")) {
2716 if (VecWidth == 128)
2717 IID = Intrinsic::x86_sse2_pmadd_wd;
2718 else if (VecWidth == 256)
2719 IID = Intrinsic::x86_avx2_pmadd_wd;
2720 else if (VecWidth == 512)
2721 IID = Intrinsic::x86_avx512_pmaddw_d_512;
2722 else
2723 llvm_unreachable("Unexpected intrinsic");
2724 } else if (Name.starts_with("pmaddubs.w.")) {
2725 if (VecWidth == 128)
2726 IID = Intrinsic::x86_ssse3_pmadd_ub_sw_128;
2727 else if (VecWidth == 256)
2728 IID = Intrinsic::x86_avx2_pmadd_ub_sw;
2729 else if (VecWidth == 512)
2730 IID = Intrinsic::x86_avx512_pmaddubs_w_512;
2731 else
2732 llvm_unreachable("Unexpected intrinsic");
2733 } else if (Name.starts_with("packsswb.")) {
2734 if (VecWidth == 128)
2735 IID = Intrinsic::x86_sse2_packsswb_128;
2736 else if (VecWidth == 256)
2737 IID = Intrinsic::x86_avx2_packsswb;
2738 else if (VecWidth == 512)
2739 IID = Intrinsic::x86_avx512_packsswb_512;
2740 else
2741 llvm_unreachable("Unexpected intrinsic");
2742 } else if (Name.starts_with("packssdw.")) {
2743 if (VecWidth == 128)
2744 IID = Intrinsic::x86_sse2_packssdw_128;
2745 else if (VecWidth == 256)
2746 IID = Intrinsic::x86_avx2_packssdw;
2747 else if (VecWidth == 512)
2748 IID = Intrinsic::x86_avx512_packssdw_512;
2749 else
2750 llvm_unreachable("Unexpected intrinsic");
2751 } else if (Name.starts_with("packuswb.")) {
2752 if (VecWidth == 128)
2753 IID = Intrinsic::x86_sse2_packuswb_128;
2754 else if (VecWidth == 256)
2755 IID = Intrinsic::x86_avx2_packuswb;
2756 else if (VecWidth == 512)
2757 IID = Intrinsic::x86_avx512_packuswb_512;
2758 else
2759 llvm_unreachable("Unexpected intrinsic");
2760 } else if (Name.starts_with("packusdw.")) {
2761 if (VecWidth == 128)
2762 IID = Intrinsic::x86_sse41_packusdw;
2763 else if (VecWidth == 256)
2764 IID = Intrinsic::x86_avx2_packusdw;
2765 else if (VecWidth == 512)
2766 IID = Intrinsic::x86_avx512_packusdw_512;
2767 else
2768 llvm_unreachable("Unexpected intrinsic");
2769 } else if (Name.starts_with("vpermilvar.")) {
2770 if (VecWidth == 128 && EltWidth == 32)
2771 IID = Intrinsic::x86_avx_vpermilvar_ps;
2772 else if (VecWidth == 128 && EltWidth == 64)
2773 IID = Intrinsic::x86_avx_vpermilvar_pd;
2774 else if (VecWidth == 256 && EltWidth == 32)
2775 IID = Intrinsic::x86_avx_vpermilvar_ps_256;
2776 else if (VecWidth == 256 && EltWidth == 64)
2777 IID = Intrinsic::x86_avx_vpermilvar_pd_256;
2778 else if (VecWidth == 512 && EltWidth == 32)
2779 IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
2780 else if (VecWidth == 512 && EltWidth == 64)
2781 IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
2782 else
2783 llvm_unreachable("Unexpected intrinsic");
2784 } else if (Name == "cvtpd2dq.256") {
2785 IID = Intrinsic::x86_avx_cvt_pd2dq_256;
2786 } else if (Name == "cvtpd2ps.256") {
2787 IID = Intrinsic::x86_avx_cvt_pd2_ps_256;
2788 } else if (Name == "cvttpd2dq.256") {
2789 IID = Intrinsic::x86_avx_cvtt_pd2dq_256;
2790 } else if (Name == "cvttps2dq.128") {
2791 IID = Intrinsic::x86_sse2_cvttps2dq;
2792 } else if (Name == "cvttps2dq.256") {
2793 IID = Intrinsic::x86_avx_cvtt_ps2dq_256;
2794 } else if (Name.starts_with("permvar.")) {
2795 bool IsFloat = CI.getType()->isFPOrFPVectorTy();
2796 if (VecWidth == 256 && EltWidth == 32 && IsFloat)
2797 IID = Intrinsic::x86_avx2_permps;
2798 else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
2799 IID = Intrinsic::x86_avx2_permd;
2800 else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
2801 IID = Intrinsic::x86_avx512_permvar_df_256;
2802 else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
2803 IID = Intrinsic::x86_avx512_permvar_di_256;
2804 else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
2805 IID = Intrinsic::x86_avx512_permvar_sf_512;
2806 else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
2807 IID = Intrinsic::x86_avx512_permvar_si_512;
2808 else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
2809 IID = Intrinsic::x86_avx512_permvar_df_512;
2810 else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
2811 IID = Intrinsic::x86_avx512_permvar_di_512;
2812 else if (VecWidth == 128 && EltWidth == 16)
2813 IID = Intrinsic::x86_avx512_permvar_hi_128;
2814 else if (VecWidth == 256 && EltWidth == 16)
2815 IID = Intrinsic::x86_avx512_permvar_hi_256;
2816 else if (VecWidth == 512 && EltWidth == 16)
2817 IID = Intrinsic::x86_avx512_permvar_hi_512;
2818 else if (VecWidth == 128 && EltWidth == 8)
2819 IID = Intrinsic::x86_avx512_permvar_qi_128;
2820 else if (VecWidth == 256 && EltWidth == 8)
2821 IID = Intrinsic::x86_avx512_permvar_qi_256;
2822 else if (VecWidth == 512 && EltWidth == 8)
2823 IID = Intrinsic::x86_avx512_permvar_qi_512;
2824 else
2825 llvm_unreachable("Unexpected intrinsic");
2826 } else if (Name.starts_with("dbpsadbw.")) {
2827 if (VecWidth == 128)
2828 IID = Intrinsic::x86_avx512_dbpsadbw_128;
2829 else if (VecWidth == 256)
2830 IID = Intrinsic::x86_avx512_dbpsadbw_256;
2831 else if (VecWidth == 512)
2832 IID = Intrinsic::x86_avx512_dbpsadbw_512;
2833 else
2834 llvm_unreachable("Unexpected intrinsic");
2835 } else if (Name.starts_with("pmultishift.qb.")) {
2836 if (VecWidth == 128)
2837 IID = Intrinsic::x86_avx512_pmultishift_qb_128;
2838 else if (VecWidth == 256)
2839 IID = Intrinsic::x86_avx512_pmultishift_qb_256;
2840 else if (VecWidth == 512)
2841 IID = Intrinsic::x86_avx512_pmultishift_qb_512;
2842 else
2843 llvm_unreachable("Unexpected intrinsic");
2844 } else if (Name.starts_with("conflict.")) {
2845 if (Name[9] == 'd' && VecWidth == 128)
2846 IID = Intrinsic::x86_avx512_conflict_d_128;
2847 else if (Name[9] == 'd' && VecWidth == 256)
2848 IID = Intrinsic::x86_avx512_conflict_d_256;
2849 else if (Name[9] == 'd' && VecWidth == 512)
2850 IID = Intrinsic::x86_avx512_conflict_d_512;
2851 else if (Name[9] == 'q' && VecWidth == 128)
2852 IID = Intrinsic::x86_avx512_conflict_q_128;
2853 else if (Name[9] == 'q' && VecWidth == 256)
2854 IID = Intrinsic::x86_avx512_conflict_q_256;
2855 else if (Name[9] == 'q' && VecWidth == 512)
2856 IID = Intrinsic::x86_avx512_conflict_q_512;
2857 else
2858 llvm_unreachable("Unexpected intrinsic");
2859 } else if (Name.starts_with("pavg.")) {
2860 if (Name[5] == 'b' && VecWidth == 128)
2861 IID = Intrinsic::x86_sse2_pavg_b;
2862 else if (Name[5] == 'b' && VecWidth == 256)
2863 IID = Intrinsic::x86_avx2_pavg_b;
2864 else if (Name[5] == 'b' && VecWidth == 512)
2865 IID = Intrinsic::x86_avx512_pavg_b_512;
2866 else if (Name[5] == 'w' && VecWidth == 128)
2867 IID = Intrinsic::x86_sse2_pavg_w;
2868 else if (Name[5] == 'w' && VecWidth == 256)
2869 IID = Intrinsic::x86_avx2_pavg_w;
2870 else if (Name[5] == 'w' && VecWidth == 512)
2871 IID = Intrinsic::x86_avx512_pavg_w_512;
2872 else
2873 llvm_unreachable("Unexpected intrinsic");
2874 } else
2875 return false;
2876
2877 SmallVector<Value *, 4> Args(CI.args());
2878 Args.pop_back();
2879 Args.pop_back();
2880 Rep = Builder.CreateIntrinsic(IID, Args);
2881 unsigned NumArgs = CI.arg_size();
2882 Rep = emitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep,
2883 CI.getArgOperand(NumArgs - 2));
2884 return true;
2885}
2886
2887/// Upgrade comment in call to inline asm that represents an objc retain release
2888/// marker.
2889void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
2890 size_t Pos;
2891 if (AsmStr->find("mov\tfp") == 0 &&
2892 AsmStr->find("objc_retainAutoreleaseReturnValue") != std::string::npos &&
2893 (Pos = AsmStr->find("# marker")) != std::string::npos) {
2894 AsmStr->replace(Pos, 1, ";");
2895 }
2896}
2897
2899 Function *F, IRBuilder<> &Builder) {
2900 Value *Rep = nullptr;
2901
2902 if (Name == "abs.i" || Name == "abs.ll") {
2903 Value *Arg = CI->getArgOperand(0);
2904 Rep = Builder.CreateIntrinsic(Intrinsic::abs, {Arg->getType()},
2905 {Arg, Builder.getTrue()},
2906 /*FMFSource=*/nullptr, "abs");
2907 } else if (Name == "abs.bf16" || Name == "abs.bf16x2") {
2908 Type *Ty = (Name == "abs.bf16")
2909 ? Builder.getBFloatTy()
2910 : FixedVectorType::get(Builder.getBFloatTy(), 2);
2911 Value *Arg = Builder.CreateBitCast(CI->getArgOperand(0), Ty);
2912 Value *Abs = Builder.CreateUnaryIntrinsic(Intrinsic::nvvm_fabs, Arg);
2913 Rep = Builder.CreateBitCast(Abs, CI->getType());
2914 } else if (Name == "fabs.f" || Name == "fabs.ftz.f" || Name == "fabs.d") {
2915 Intrinsic::ID IID = (Name == "fabs.ftz.f") ? Intrinsic::nvvm_fabs_ftz
2916 : Intrinsic::nvvm_fabs;
2917 Rep = Builder.CreateUnaryIntrinsic(IID, CI->getArgOperand(0));
2918 } else if (Name.consume_front("ex2.approx.")) {
2919 // nvvm.ex2.approx.{f,ftz.f,d,f16x2}
2920 Intrinsic::ID IID = Name.starts_with("ftz") ? Intrinsic::nvvm_ex2_approx_ftz
2921 : Intrinsic::nvvm_ex2_approx;
2922 Rep = Builder.CreateUnaryIntrinsic(IID, CI->getArgOperand(0));
2923 } else if (Name.starts_with("atomic.load.add.f32.p") ||
2924 Name.starts_with("atomic.load.add.f64.p")) {
2925 Value *Ptr = CI->getArgOperand(0);
2926 Value *Val = CI->getArgOperand(1);
2927 Rep = Builder.CreateAtomicRMW(
2929 CI->getContext().getOrInsertSyncScopeID("device"));
2930 // The default scope for atomic.load.* intrinsics is device
2931 // (= gpu scope in ptx), but the default LLVM atomic scope is
2932 // "system"
2933 } else if (Name.starts_with("atomic.load.inc.32.p") ||
2934 Name.starts_with("atomic.load.dec.32.p")) {
2935 Value *Ptr = CI->getArgOperand(0);
2936 Value *Val = CI->getArgOperand(1);
2937 auto Op = Name.starts_with("atomic.load.inc") ? AtomicRMWInst::UIncWrap
2939 Rep = Builder.CreateAtomicRMW(
2941 CI->getContext().getOrInsertSyncScopeID("device"));
2942 // See comment above.
2943 } else if (Name.starts_with("atomic.") && Name.contains(".gen.")) {
2944 // nvvm.atomic.{op}.gen.{i,f}.{cta,sys} -> atomicrmw / cmpxchg.
2945 StringRef Op = Name.substr(StringRef("atomic.").size());
2946 Value *Ptr = CI->getArgOperand(0);
2947 Value *Val = CI->getArgOperand(1);
2949 Op.contains(".cta.") ? "block" : "");
2950 if (Op.starts_with("cas.")) {
2951 Value *New = CI->getArgOperand(2);
2952 Value *Pair = Builder.CreateAtomicCmpXchg(
2953 Ptr, Val, New, MaybeAlign(), AtomicOrdering::Monotonic,
2955 Rep = Builder.CreateExtractValue(Pair, 0);
2956 } else {
2957 // Note we don't upgrade anything to AtomicRMWInst::UMin/UMax. This is
2958 // because we were actually missing those intrinsics!
2959 AtomicRMWInst::BinOp BinOp =
2961 .StartsWith("add.gen.f", AtomicRMWInst::FAdd)
2962 .StartsWith("add.gen.i", AtomicRMWInst::Add)
2973 "unexpected nvvm scoped atomic intrinsic");
2974 Rep = Builder.CreateAtomicRMW(BinOp, Ptr, Val, MaybeAlign(),
2976 }
2977 } else if (Name == "clz.ll") {
2978 // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 returns an i64.
2979 Value *Arg = CI->getArgOperand(0);
2980 Value *Ctlz = Builder.CreateIntrinsic(Intrinsic::ctlz, {Arg->getType()},
2981 {Arg, Builder.getFalse()},
2982 /*FMFSource=*/nullptr, "ctlz");
2983 Rep = Builder.CreateTrunc(Ctlz, Builder.getInt32Ty(), "ctlz.trunc");
2984 } else if (Name == "popc.ll") {
2985 // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 returns an
2986 // i64.
2987 Value *Arg = CI->getArgOperand(0);
2988 Value *Popc = Builder.CreateIntrinsic(Intrinsic::ctpop, {Arg->getType()},
2989 Arg, /*FMFSource=*/nullptr, "ctpop");
2990 Rep = Builder.CreateTrunc(Popc, Builder.getInt32Ty(), "ctpop.trunc");
2991 } else if (Name == "h2f") {
2992 Value *Cast =
2993 Builder.CreateBitCast(CI->getArgOperand(0), Builder.getHalfTy());
2994 Rep = Builder.CreateFPExt(Cast, Builder.getFloatTy());
2995 } else if (Name.consume_front("bitcast.") &&
2996 (Name == "f2i" || Name == "i2f" || Name == "ll2d" ||
2997 Name == "d2ll")) {
2998 Rep = Builder.CreateBitCast(CI->getArgOperand(0), CI->getType());
2999 } else if (Name == "rotate.b32") {
3000 Value *Arg = CI->getOperand(0);
3001 Value *ShiftAmt = CI->getOperand(1);
3002 Rep = Builder.CreateIntrinsic(Builder.getInt32Ty(), Intrinsic::fshl,
3003 {Arg, Arg, ShiftAmt});
3004 } else if (Name == "rotate.b64") {
3005 Type *Int64Ty = Builder.getInt64Ty();
3006 Value *Arg = CI->getOperand(0);
3007 Value *ZExtShiftAmt = Builder.CreateZExt(CI->getOperand(1), Int64Ty);
3008 Rep = Builder.CreateIntrinsic(Int64Ty, Intrinsic::fshl,
3009 {Arg, Arg, ZExtShiftAmt});
3010 } else if (Name == "rotate.right.b64") {
3011 Type *Int64Ty = Builder.getInt64Ty();
3012 Value *Arg = CI->getOperand(0);
3013 Value *ZExtShiftAmt = Builder.CreateZExt(CI->getOperand(1), Int64Ty);
3014 Rep = Builder.CreateIntrinsic(Int64Ty, Intrinsic::fshr,
3015 {Arg, Arg, ZExtShiftAmt});
3016 } else if (Name == "swap.lo.hi.b64") {
3017 Type *Int64Ty = Builder.getInt64Ty();
3018 Value *Arg = CI->getOperand(0);
3019 Rep = Builder.CreateIntrinsic(Int64Ty, Intrinsic::fshl,
3020 {Arg, Arg, Builder.getInt64(32)});
3021 } else if ((Name.consume_front("ptr.gen.to.") &&
3022 consumeNVVMPtrAddrSpace(Name)) ||
3023 (Name.consume_front("ptr.") && consumeNVVMPtrAddrSpace(Name) &&
3024 Name.starts_with(".to.gen"))) {
3025 Rep = Builder.CreateAddrSpaceCast(CI->getArgOperand(0), CI->getType());
3026 } else if (Name.consume_front("ldg.global")) {
3027 Value *Ptr = CI->getArgOperand(0);
3028 Align PtrAlign = cast<ConstantInt>(CI->getArgOperand(1))->getAlignValue();
3029 // Use addrspace(1) for NVPTX ADDRESS_SPACE_GLOBAL
3030 Value *ASC = Builder.CreateAddrSpaceCast(Ptr, Builder.getPtrTy(1));
3031 Instruction *LD = Builder.CreateAlignedLoad(CI->getType(), ASC, PtrAlign);
3032 MDNode *MD = MDNode::get(Builder.getContext(), {});
3033 LD->setMetadata(LLVMContext::MD_invariant_load, MD);
3034 return LD;
3035 } else if (Name == "tanh.approx.f32") {
3036 // nvvm.tanh.approx.f32 -> afn llvm.tanh.f32
3037 FastMathFlags FMF;
3038 FMF.setApproxFunc();
3039 Rep = Builder.CreateUnaryIntrinsic(Intrinsic::tanh, CI->getArgOperand(0),
3040 FMF);
3041 } else if (Name == "barrier0" || Name == "barrier.n" || Name == "bar.sync") {
3042 Value *Arg =
3043 Name.ends_with('0') ? Builder.getInt32(0) : CI->getArgOperand(0);
3044 Rep = Builder.CreateIntrinsic(Intrinsic::nvvm_barrier_cta_sync_aligned_all,
3045 {}, {Arg});
3046 } else if (Name == "barrier") {
3047 Rep = Builder.CreateIntrinsic(
3048 Intrinsic::nvvm_barrier_cta_sync_aligned_count, {},
3049 {CI->getArgOperand(0), CI->getArgOperand(1)});
3050 } else if (Name == "barrier.sync") {
3051 Rep = Builder.CreateIntrinsic(Intrinsic::nvvm_barrier_cta_sync_all, {},
3052 {CI->getArgOperand(0)});
3053 } else if (Name == "barrier.sync.cnt") {
3054 Rep = Builder.CreateIntrinsic(Intrinsic::nvvm_barrier_cta_sync_count, {},
3055 {CI->getArgOperand(0), CI->getArgOperand(1)});
3056 } else if (Name == "barrier0.popc" || Name == "barrier0.and" ||
3057 Name == "barrier0.or") {
3058 Value *C = CI->getArgOperand(0);
3059 C = Builder.CreateICmpNE(C, Builder.getInt32(0));
3060
3061 Intrinsic::ID IID =
3063 .Case("barrier0.popc",
3064 Intrinsic::nvvm_barrier_cta_red_popc_aligned_all)
3065 .Case("barrier0.and",
3066 Intrinsic::nvvm_barrier_cta_red_and_aligned_all)
3067 .Case("barrier0.or",
3068 Intrinsic::nvvm_barrier_cta_red_or_aligned_all);
3069 Value *Bar = Builder.CreateIntrinsic(IID, {}, {Builder.getInt32(0), C});
3070 Rep = Builder.CreateZExt(Bar, CI->getType());
3071 } else {
3073 if (IID != Intrinsic::not_intrinsic &&
3074 !F->getReturnType()->getScalarType()->isBFloatTy()) {
3075 rename(F);
3076 Function *NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
3078 for (size_t I = 0; I < NewFn->arg_size(); ++I) {
3079 Value *Arg = CI->getArgOperand(I);
3080 Type *OldType = Arg->getType();
3081 Type *NewType = NewFn->getArg(I)->getType();
3082 Args.push_back(
3083 (OldType->isIntegerTy() && NewType->getScalarType()->isBFloatTy())
3084 ? Builder.CreateBitCast(Arg, NewType)
3085 : Arg);
3086 }
3087 Rep = Builder.CreateCall(NewFn, Args);
3088 if (F->getReturnType()->isIntegerTy())
3089 Rep = Builder.CreateBitCast(Rep, F->getReturnType());
3090 }
3091 }
3092
3093 return Rep;
3094}
3095
3097 IRBuilder<> &Builder) {
3098 LLVMContext &C = F->getContext();
3099 Value *Rep = nullptr;
3100
3101 if (Name.starts_with("sse4a.movnt.")) {
3103 Elts.push_back(
3104 ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
3105 MDNode *Node = MDNode::get(C, Elts);
3106
3107 Value *Arg0 = CI->getArgOperand(0);
3108 Value *Arg1 = CI->getArgOperand(1);
3109
3110 // Nontemporal (unaligned) store of the 0'th element of the float/double
3111 // vector.
3112 Value *Extract =
3113 Builder.CreateExtractElement(Arg1, (uint64_t)0, "extractelement");
3114
3115 StoreInst *SI = Builder.CreateAlignedStore(Extract, Arg0, Align(1));
3116 SI->setMetadata(LLVMContext::MD_nontemporal, Node);
3117 } else if (Name.starts_with("avx.movnt.") ||
3118 Name.starts_with("avx512.storent.")) {
3120 Elts.push_back(
3121 ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
3122 MDNode *Node = MDNode::get(C, Elts);
3123
3124 Value *Arg0 = CI->getArgOperand(0);
3125 Value *Arg1 = CI->getArgOperand(1);
3126
3127 StoreInst *SI = Builder.CreateAlignedStore(
3128 Arg1, Arg0,
3130 SI->setMetadata(LLVMContext::MD_nontemporal, Node);
3131 } else if (Name == "sse2.storel.dq") {
3132 Value *Arg0 = CI->getArgOperand(0);
3133 Value *Arg1 = CI->getArgOperand(1);
3134
3135 auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
3136 Value *BC0 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
3137 Value *Elt = Builder.CreateExtractElement(BC0, (uint64_t)0);
3138 Builder.CreateAlignedStore(Elt, Arg0, Align(1));
3139 } else if (Name.starts_with("sse.storeu.") ||
3140 Name.starts_with("sse2.storeu.") ||
3141 Name.starts_with("avx.storeu.")) {
3142 Value *Arg0 = CI->getArgOperand(0);
3143 Value *Arg1 = CI->getArgOperand(1);
3144 Builder.CreateAlignedStore(Arg1, Arg0, Align(1));
3145 } else if (Name == "avx512.mask.store.ss") {
3146 Value *Mask = Builder.CreateAnd(CI->getArgOperand(2), Builder.getInt8(1));
3147 upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
3148 Mask, false);
3149 } else if (Name.starts_with("avx512.mask.store")) {
3150 // "avx512.mask.storeu." or "avx512.mask.store."
3151 bool Aligned = Name[17] != 'u'; // "avx512.mask.storeu".
3152 upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
3153 CI->getArgOperand(2), Aligned);
3154 } else if (Name.starts_with("sse2.pcmp") || Name.starts_with("avx2.pcmp")) {
3155 // Upgrade packed integer vector compare intrinsics to compare instructions.
3156 // "sse2.pcpmpeq." "sse2.pcmpgt." "avx2.pcmpeq." or "avx2.pcmpgt."
3157 bool CmpEq = Name[9] == 'e';
3158 Rep = Builder.CreateICmp(CmpEq ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_SGT,
3159 CI->getArgOperand(0), CI->getArgOperand(1));
3160 Rep = Builder.CreateSExt(Rep, CI->getType(), "");
3161 } else if (Name.starts_with("avx512.broadcastm")) {
3162 Type *ExtTy = Type::getInt32Ty(C);
3163 if (CI->getOperand(0)->getType()->isIntegerTy(8))
3164 ExtTy = Type::getInt64Ty(C);
3165 unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() /
3166 ExtTy->getPrimitiveSizeInBits();
3167 Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy);
3168 Rep = Builder.CreateVectorSplat(NumElts, Rep);
3169 } else if (Name == "sse.sqrt.ss" || Name == "sse2.sqrt.sd") {
3170 Value *Vec = CI->getArgOperand(0);
3171 Value *Elt0 = Builder.CreateExtractElement(Vec, (uint64_t)0);
3172 Elt0 = Builder.CreateIntrinsic(Intrinsic::sqrt, Elt0->getType(), Elt0);
3173 Rep = Builder.CreateInsertElement(Vec, Elt0, (uint64_t)0);
3174 } else if (Name.starts_with("avx.sqrt.p") ||
3175 Name.starts_with("sse2.sqrt.p") ||
3176 Name.starts_with("sse.sqrt.p")) {
3177 Rep = Builder.CreateIntrinsic(Intrinsic::sqrt, CI->getType(),
3178 {CI->getArgOperand(0)});
3179 } else if (Name.starts_with("avx512.mask.sqrt.p")) {
3180 if (CI->arg_size() == 4 &&
3181 (!isa<ConstantInt>(CI->getArgOperand(3)) ||
3182 cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
3183 Intrinsic::ID IID = Name[18] == 's' ? Intrinsic::x86_avx512_sqrt_ps_512
3184 : Intrinsic::x86_avx512_sqrt_pd_512;
3185
3186 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(3)};
3187 Rep = Builder.CreateIntrinsic(IID, Args);
3188 } else {
3189 Rep = Builder.CreateIntrinsic(Intrinsic::sqrt, CI->getType(),
3190 {CI->getArgOperand(0)});
3191 }
3192 Rep =
3193 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3194 } else if (Name.starts_with("avx512.ptestm") ||
3195 Name.starts_with("avx512.ptestnm")) {
3196 Value *Op0 = CI->getArgOperand(0);
3197 Value *Op1 = CI->getArgOperand(1);
3198 Value *Mask = CI->getArgOperand(2);
3199 Rep = Builder.CreateAnd(Op0, Op1);
3200 llvm::Type *Ty = Op0->getType();
3202 ICmpInst::Predicate Pred = Name.starts_with("avx512.ptestm")
3205 Rep = Builder.CreateICmp(Pred, Rep, Zero);
3206 Rep = applyX86MaskOn1BitsVec(Builder, Rep, Mask);
3207 } else if (Name.starts_with("avx512.mask.pbroadcast")) {
3208 unsigned NumElts = cast<FixedVectorType>(CI->getArgOperand(1)->getType())
3209 ->getNumElements();
3210 Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0));
3211 Rep =
3212 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3213 } else if (Name.starts_with("avx512.kunpck")) {
3214 unsigned NumElts = CI->getType()->getScalarSizeInBits();
3215 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), NumElts);
3216 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), NumElts);
3217 int Indices[64];
3218 for (unsigned i = 0; i != NumElts; ++i)
3219 Indices[i] = i;
3220
3221 // First extract half of each vector. This gives better codegen than
3222 // doing it in a single shuffle.
3223 LHS = Builder.CreateShuffleVector(LHS, LHS, ArrayRef(Indices, NumElts / 2));
3224 RHS = Builder.CreateShuffleVector(RHS, RHS, ArrayRef(Indices, NumElts / 2));
3225 // Concat the vectors.
3226 // NOTE: Operands have to be swapped to match intrinsic definition.
3227 Rep = Builder.CreateShuffleVector(RHS, LHS, ArrayRef(Indices, NumElts));
3228 Rep = Builder.CreateBitCast(Rep, CI->getType());
3229 } else if (Name == "avx512.kand.w") {
3230 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3231 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3232 Rep = Builder.CreateAnd(LHS, RHS);
3233 Rep = Builder.CreateBitCast(Rep, CI->getType());
3234 } else if (Name == "avx512.kandn.w") {
3235 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3236 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3237 LHS = Builder.CreateNot(LHS);
3238 Rep = Builder.CreateAnd(LHS, RHS);
3239 Rep = Builder.CreateBitCast(Rep, CI->getType());
3240 } else if (Name == "avx512.kor.w") {
3241 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3242 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3243 Rep = Builder.CreateOr(LHS, RHS);
3244 Rep = Builder.CreateBitCast(Rep, CI->getType());
3245 } else if (Name == "avx512.kxor.w") {
3246 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3247 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3248 Rep = Builder.CreateXor(LHS, RHS);
3249 Rep = Builder.CreateBitCast(Rep, CI->getType());
3250 } else if (Name == "avx512.kxnor.w") {
3251 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3252 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3253 LHS = Builder.CreateNot(LHS);
3254 Rep = Builder.CreateXor(LHS, RHS);
3255 Rep = Builder.CreateBitCast(Rep, CI->getType());
3256 } else if (Name == "avx512.knot.w") {
3257 Rep = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3258 Rep = Builder.CreateNot(Rep);
3259 Rep = Builder.CreateBitCast(Rep, CI->getType());
3260 } else if (Name == "avx512.kortestz.w" || Name == "avx512.kortestc.w") {
3261 Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
3262 Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
3263 Rep = Builder.CreateOr(LHS, RHS);
3264 Rep = Builder.CreateBitCast(Rep, Builder.getInt16Ty());
3265 Value *C;
3266 if (Name[14] == 'c')
3267 C = ConstantInt::getAllOnesValue(Builder.getInt16Ty());
3268 else
3269 C = ConstantInt::getNullValue(Builder.getInt16Ty());
3270 Rep = Builder.CreateICmpEQ(Rep, C);
3271 Rep = Builder.CreateZExt(Rep, Builder.getInt32Ty());
3272 } else if (Name == "sse.add.ss" || Name == "sse2.add.sd" ||
3273 Name == "sse.sub.ss" || Name == "sse2.sub.sd" ||
3274 Name == "sse.mul.ss" || Name == "sse2.mul.sd" ||
3275 Name == "sse.div.ss" || Name == "sse2.div.sd") {
3276 Type *I32Ty = Type::getInt32Ty(C);
3277 Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0),
3278 ConstantInt::get(I32Ty, 0));
3279 Value *Elt1 = Builder.CreateExtractElement(CI->getArgOperand(1),
3280 ConstantInt::get(I32Ty, 0));
3281 Value *EltOp;
3282 if (Name.contains(".add."))
3283 EltOp = Builder.CreateFAdd(Elt0, Elt1);
3284 else if (Name.contains(".sub."))
3285 EltOp = Builder.CreateFSub(Elt0, Elt1);
3286 else if (Name.contains(".mul."))
3287 EltOp = Builder.CreateFMul(Elt0, Elt1);
3288 else
3289 EltOp = Builder.CreateFDiv(Elt0, Elt1);
3290 Rep = Builder.CreateInsertElement(CI->getArgOperand(0), EltOp,
3291 ConstantInt::get(I32Ty, 0));
3292 } else if (Name.starts_with("avx512.mask.pcmp")) {
3293 // "avx512.mask.pcmpeq." or "avx512.mask.pcmpgt."
3294 bool CmpEq = Name[16] == 'e';
3295 Rep = upgradeMaskedCompare(Builder, *CI, CmpEq ? 0 : 6, true);
3296 } else if (Name.starts_with("avx512.mask.vpshufbitqmb.")) {
3297 Type *OpTy = CI->getArgOperand(0)->getType();
3298 unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
3299 Intrinsic::ID IID;
3300 switch (VecWidth) {
3301 default:
3302 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
3303 break;
3304 case 128:
3305 IID = Intrinsic::x86_avx512_vpshufbitqmb_128;
3306 break;
3307 case 256:
3308 IID = Intrinsic::x86_avx512_vpshufbitqmb_256;
3309 break;
3310 case 512:
3311 IID = Intrinsic::x86_avx512_vpshufbitqmb_512;
3312 break;
3313 }
3314
3315 Rep =
3316 Builder.CreateIntrinsic(IID, {CI->getOperand(0), CI->getArgOperand(1)});
3317 Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
3318 } else if (Name.starts_with("avx512.mask.fpclass.p")) {
3319 Type *OpTy = CI->getArgOperand(0)->getType();
3320 unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
3321 unsigned EltWidth = OpTy->getScalarSizeInBits();
3322 Intrinsic::ID IID;
3323 if (VecWidth == 128 && EltWidth == 32)
3324 IID = Intrinsic::x86_avx512_fpclass_ps_128;
3325 else if (VecWidth == 256 && EltWidth == 32)
3326 IID = Intrinsic::x86_avx512_fpclass_ps_256;
3327 else if (VecWidth == 512 && EltWidth == 32)
3328 IID = Intrinsic::x86_avx512_fpclass_ps_512;
3329 else if (VecWidth == 128 && EltWidth == 64)
3330 IID = Intrinsic::x86_avx512_fpclass_pd_128;
3331 else if (VecWidth == 256 && EltWidth == 64)
3332 IID = Intrinsic::x86_avx512_fpclass_pd_256;
3333 else if (VecWidth == 512 && EltWidth == 64)
3334 IID = Intrinsic::x86_avx512_fpclass_pd_512;
3335 else
3336 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
3337
3338 Rep =
3339 Builder.CreateIntrinsic(IID, {CI->getOperand(0), CI->getArgOperand(1)});
3340 Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
3341 } else if (Name.starts_with("avx512.cmp.p")) {
3342 SmallVector<Value *, 4> Args(CI->args());
3343 Type *OpTy = Args[0]->getType();
3344 unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
3345 unsigned EltWidth = OpTy->getScalarSizeInBits();
3346 Intrinsic::ID IID;
3347 if (VecWidth == 128 && EltWidth == 32)
3348 IID = Intrinsic::x86_avx512_mask_cmp_ps_128;
3349 else if (VecWidth == 256 && EltWidth == 32)
3350 IID = Intrinsic::x86_avx512_mask_cmp_ps_256;
3351 else if (VecWidth == 512 && EltWidth == 32)
3352 IID = Intrinsic::x86_avx512_mask_cmp_ps_512;
3353 else if (VecWidth == 128 && EltWidth == 64)
3354 IID = Intrinsic::x86_avx512_mask_cmp_pd_128;
3355 else if (VecWidth == 256 && EltWidth == 64)
3356 IID = Intrinsic::x86_avx512_mask_cmp_pd_256;
3357 else if (VecWidth == 512 && EltWidth == 64)
3358 IID = Intrinsic::x86_avx512_mask_cmp_pd_512;
3359 else
3360 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
3361
3363 if (VecWidth == 512)
3364 std::swap(Mask, Args.back());
3365 Args.push_back(Mask);
3366
3367 Rep = Builder.CreateIntrinsic(IID, Args);
3368 } else if (Name.starts_with("avx512.mask.cmp.")) {
3369 // Integer compare intrinsics.
3370 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3371 Rep = upgradeMaskedCompare(Builder, *CI, Imm, true);
3372 } else if (Name.starts_with("avx512.mask.ucmp.")) {
3373 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3374 Rep = upgradeMaskedCompare(Builder, *CI, Imm, false);
3375 } else if (Name.starts_with("avx512.cvtb2mask.") ||
3376 Name.starts_with("avx512.cvtw2mask.") ||
3377 Name.starts_with("avx512.cvtd2mask.") ||
3378 Name.starts_with("avx512.cvtq2mask.")) {
3379 Value *Op = CI->getArgOperand(0);
3380 Value *Zero = llvm::Constant::getNullValue(Op->getType());
3381 Rep = Builder.CreateICmp(ICmpInst::ICMP_SLT, Op, Zero);
3382 Rep = applyX86MaskOn1BitsVec(Builder, Rep, nullptr);
3383 } else if (Name == "ssse3.pabs.b.128" || Name == "ssse3.pabs.w.128" ||
3384 Name == "ssse3.pabs.d.128" || Name.starts_with("avx2.pabs") ||
3385 Name.starts_with("avx512.mask.pabs")) {
3386 Rep = upgradeAbs(Builder, *CI);
3387 } else if (Name == "sse41.pmaxsb" || Name == "sse2.pmaxs.w" ||
3388 Name == "sse41.pmaxsd" || Name.starts_with("avx2.pmaxs") ||
3389 Name.starts_with("avx512.mask.pmaxs")) {
3390 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smax);
3391 } else if (Name == "sse2.pmaxu.b" || Name == "sse41.pmaxuw" ||
3392 Name == "sse41.pmaxud" || Name.starts_with("avx2.pmaxu") ||
3393 Name.starts_with("avx512.mask.pmaxu")) {
3394 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umax);
3395 } else if (Name == "sse41.pminsb" || Name == "sse2.pmins.w" ||
3396 Name == "sse41.pminsd" || Name.starts_with("avx2.pmins") ||
3397 Name.starts_with("avx512.mask.pmins")) {
3398 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smin);
3399 } else if (Name == "sse2.pminu.b" || Name == "sse41.pminuw" ||
3400 Name == "sse41.pminud" || Name.starts_with("avx2.pminu") ||
3401 Name.starts_with("avx512.mask.pminu")) {
3402 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umin);
3403 } else if (Name == "sse2.pmulu.dq" || Name == "avx2.pmulu.dq" ||
3404 Name == "avx512.pmulu.dq.512" ||
3405 Name.starts_with("avx512.mask.pmulu.dq.")) {
3406 Rep = upgradePMULDQ(Builder, *CI, /*Signed*/ false);
3407 } else if (Name == "sse41.pmuldq" || Name == "avx2.pmul.dq" ||
3408 Name == "avx512.pmul.dq.512" ||
3409 Name.starts_with("avx512.mask.pmul.dq.")) {
3410 Rep = upgradePMULDQ(Builder, *CI, /*Signed*/ true);
3411 } else if (Name == "sse.cvtsi2ss" || Name == "sse2.cvtsi2sd" ||
3412 Name == "sse.cvtsi642ss" || Name == "sse2.cvtsi642sd") {
3413 Rep =
3414 Builder.CreateSIToFP(CI->getArgOperand(1),
3415 cast<VectorType>(CI->getType())->getElementType());
3416 Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
3417 } else if (Name == "avx512.cvtusi2sd") {
3418 Rep =
3419 Builder.CreateUIToFP(CI->getArgOperand(1),
3420 cast<VectorType>(CI->getType())->getElementType());
3421 Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
3422 } else if (Name == "sse2.cvtss2sd") {
3423 Rep = Builder.CreateExtractElement(CI->getArgOperand(1), (uint64_t)0);
3424 Rep = Builder.CreateFPExt(
3425 Rep, cast<VectorType>(CI->getType())->getElementType());
3426 Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
3427 } else if (Name == "sse2.cvtdq2pd" || Name == "sse2.cvtdq2ps" ||
3428 Name == "avx.cvtdq2.pd.256" || Name == "avx.cvtdq2.ps.256" ||
3429 Name.starts_with("avx512.mask.cvtdq2pd.") ||
3430 Name.starts_with("avx512.mask.cvtudq2pd.") ||
3431 Name.starts_with("avx512.mask.cvtdq2ps.") ||
3432 Name.starts_with("avx512.mask.cvtudq2ps.") ||
3433 Name.starts_with("avx512.mask.cvtqq2pd.") ||
3434 Name.starts_with("avx512.mask.cvtuqq2pd.") ||
3435 Name == "avx512.mask.cvtqq2ps.256" ||
3436 Name == "avx512.mask.cvtqq2ps.512" ||
3437 Name == "avx512.mask.cvtuqq2ps.256" ||
3438 Name == "avx512.mask.cvtuqq2ps.512" || Name == "sse2.cvtps2pd" ||
3439 Name == "avx.cvt.ps2.pd.256" ||
3440 Name == "avx512.mask.cvtps2pd.128" ||
3441 Name == "avx512.mask.cvtps2pd.256") {
3442 auto *DstTy = cast<FixedVectorType>(CI->getType());
3443 Rep = CI->getArgOperand(0);
3444 auto *SrcTy = cast<FixedVectorType>(Rep->getType());
3445
3446 unsigned NumDstElts = DstTy->getNumElements();
3447 if (NumDstElts < SrcTy->getNumElements()) {
3448 assert(NumDstElts == 2 && "Unexpected vector size");
3449 Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1});
3450 }
3451
3452 bool IsPS2PD = SrcTy->getElementType()->isFloatTy();
3453 bool IsUnsigned = Name.contains("cvtu");
3454 if (IsPS2PD)
3455 Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd");
3456 else if (CI->arg_size() == 4 &&
3457 (!isa<ConstantInt>(CI->getArgOperand(3)) ||
3458 cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
3459 Intrinsic::ID IID = IsUnsigned ? Intrinsic::x86_avx512_uitofp_round
3460 : Intrinsic::x86_avx512_sitofp_round;
3461 Rep = Builder.CreateIntrinsic(IID, {DstTy, SrcTy},
3462 {Rep, CI->getArgOperand(3)});
3463 } else {
3464 Rep = IsUnsigned ? Builder.CreateUIToFP(Rep, DstTy, "cvt")
3465 : Builder.CreateSIToFP(Rep, DstTy, "cvt");
3466 }
3467
3468 if (CI->arg_size() >= 3)
3469 Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
3470 CI->getArgOperand(1));
3471 } else if (Name.starts_with("avx512.mask.vcvtph2ps.") ||
3472 Name.starts_with("vcvtph2ps.")) {
3473 auto *DstTy = cast<FixedVectorType>(CI->getType());
3474 Rep = CI->getArgOperand(0);
3475 auto *SrcTy = cast<FixedVectorType>(Rep->getType());
3476 unsigned NumDstElts = DstTy->getNumElements();
3477 if (NumDstElts != SrcTy->getNumElements()) {
3478 assert(NumDstElts == 4 && "Unexpected vector size");
3479 Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1, 2, 3});
3480 }
3481 Rep = Builder.CreateBitCast(
3482 Rep, FixedVectorType::get(Type::getHalfTy(C), NumDstElts));
3483 Rep = Builder.CreateFPExt(Rep, DstTy, "cvtph2ps");
3484 if (CI->arg_size() >= 3)
3485 Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
3486 CI->getArgOperand(1));
3487 } else if (Name.starts_with("avx512.mask.load")) {
3488 // "avx512.mask.loadu." or "avx512.mask.load."
3489 bool Aligned = Name[16] != 'u'; // "avx512.mask.loadu".
3490 Rep = upgradeMaskedLoad(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
3491 CI->getArgOperand(2), Aligned);
3492 } else if (Name.starts_with("avx512.mask.expand.load.")) {
3493 auto *ResultTy = cast<FixedVectorType>(CI->getType());
3494 auto *PtrTy = CI->getOperand(0)->getType();
3495 Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
3496 ResultTy->getNumElements());
3497 Rep = Builder.CreateIntrinsic(
3498 Intrinsic::masked_expandload, {ResultTy, PtrTy},
3499 {CI->getOperand(0), MaskVec, CI->getOperand(1)});
3500 } else if (Name.starts_with("avx512.mask.compress.store.")) {
3501 auto *ResultTy = cast<VectorType>(CI->getArgOperand(1)->getType());
3502 auto *PtrTy = CI->getArgOperand(0)->getType();
3503 Value *MaskVec =
3504 getX86MaskVec(Builder, CI->getArgOperand(2),
3505 cast<FixedVectorType>(ResultTy)->getNumElements());
3506 Rep = Builder.CreateIntrinsic(
3507 Intrinsic::masked_compressstore, {ResultTy, PtrTy},
3508 {CI->getArgOperand(1), CI->getArgOperand(0), MaskVec});
3509 } else if (Name.starts_with("avx512.mask.compress.") ||
3510 Name.starts_with("avx512.mask.expand.")) {
3511 auto *ResultTy = cast<FixedVectorType>(CI->getType());
3512
3513 Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
3514 ResultTy->getNumElements());
3515
3516 bool IsCompress = Name[12] == 'c';
3517 Intrinsic::ID IID = IsCompress ? Intrinsic::x86_avx512_mask_compress
3518 : Intrinsic::x86_avx512_mask_expand;
3519 Rep = Builder.CreateIntrinsic(
3520 IID, ResultTy, {CI->getOperand(0), CI->getOperand(1), MaskVec});
3521 } else if (Name.starts_with("xop.vpcom")) {
3522 bool IsSigned;
3523 if (Name.ends_with("ub") || Name.ends_with("uw") || Name.ends_with("ud") ||
3524 Name.ends_with("uq"))
3525 IsSigned = false;
3526 else if (Name.ends_with("b") || Name.ends_with("w") ||
3527 Name.ends_with("d") || Name.ends_with("q"))
3528 IsSigned = true;
3529 else
3530 reportFatalUsageErrorWithCI("Intrinsic has unknown suffix", CI);
3531
3532 unsigned Imm;
3533 if (CI->arg_size() == 3) {
3534 Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3535 } else {
3536 Name = Name.substr(9); // strip off "xop.vpcom"
3537 if (Name.starts_with("lt"))
3538 Imm = 0;
3539 else if (Name.starts_with("le"))
3540 Imm = 1;
3541 else if (Name.starts_with("gt"))
3542 Imm = 2;
3543 else if (Name.starts_with("ge"))
3544 Imm = 3;
3545 else if (Name.starts_with("eq"))
3546 Imm = 4;
3547 else if (Name.starts_with("ne"))
3548 Imm = 5;
3549 else if (Name.starts_with("false"))
3550 Imm = 6;
3551 else if (Name.starts_with("true"))
3552 Imm = 7;
3553 else
3554 llvm_unreachable("Unknown condition");
3555 }
3556
3557 Rep = upgradeX86vpcom(Builder, *CI, Imm, IsSigned);
3558 } else if (Name.starts_with("xop.vpcmov")) {
3559 Value *Sel = CI->getArgOperand(2);
3560 Value *NotSel = Builder.CreateNot(Sel);
3561 Value *Sel0 = Builder.CreateAnd(CI->getArgOperand(0), Sel);
3562 Value *Sel1 = Builder.CreateAnd(CI->getArgOperand(1), NotSel);
3563 Rep = Builder.CreateOr(Sel0, Sel1);
3564 } else if (Name.starts_with("xop.vprot") || Name.starts_with("avx512.prol") ||
3565 Name.starts_with("avx512.mask.prol")) {
3566 Rep = upgradeX86Rotate(Builder, *CI, false);
3567 } else if (Name.starts_with("avx512.pror") ||
3568 Name.starts_with("avx512.mask.pror")) {
3569 Rep = upgradeX86Rotate(Builder, *CI, true);
3570 } else if (Name.starts_with("avx512.vpshld.") ||
3571 Name.starts_with("avx512.mask.vpshld") ||
3572 Name.starts_with("avx512.maskz.vpshld")) {
3573 bool ZeroMask = Name[11] == 'z';
3574 Rep = upgradeX86ConcatShift(Builder, *CI, false, ZeroMask);
3575 } else if (Name.starts_with("avx512.vpshrd.") ||
3576 Name.starts_with("avx512.mask.vpshrd") ||
3577 Name.starts_with("avx512.maskz.vpshrd")) {
3578 bool ZeroMask = Name[11] == 'z';
3579 Rep = upgradeX86ConcatShift(Builder, *CI, true, ZeroMask);
3580 } else if (Name == "sse42.crc32.64.8") {
3581 Value *Trunc0 =
3582 Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
3583 Rep = Builder.CreateIntrinsic(Intrinsic::x86_sse42_crc32_32_8,
3584 {Trunc0, CI->getArgOperand(1)});
3585 Rep = Builder.CreateZExt(Rep, CI->getType(), "");
3586 } else if (Name.starts_with("avx.vbroadcast.s") ||
3587 Name.starts_with("avx512.vbroadcast.s")) {
3588 // Replace broadcasts with a series of insertelements.
3589 auto *VecTy = cast<FixedVectorType>(CI->getType());
3590 Type *EltTy = VecTy->getElementType();
3591 unsigned EltNum = VecTy->getNumElements();
3592 Value *Load = Builder.CreateLoad(EltTy, CI->getArgOperand(0));
3593 Type *I32Ty = Type::getInt32Ty(C);
3594 Rep = PoisonValue::get(VecTy);
3595 for (unsigned I = 0; I < EltNum; ++I)
3596 Rep = Builder.CreateInsertElement(Rep, Load, ConstantInt::get(I32Ty, I));
3597 } else if (Name.starts_with("sse41.pmovsx") ||
3598 Name.starts_with("sse41.pmovzx") ||
3599 Name.starts_with("avx2.pmovsx") ||
3600 Name.starts_with("avx2.pmovzx") ||
3601 Name.starts_with("avx512.mask.pmovsx") ||
3602 Name.starts_with("avx512.mask.pmovzx")) {
3603 auto *DstTy = cast<FixedVectorType>(CI->getType());
3604 unsigned NumDstElts = DstTy->getNumElements();
3605
3606 // Extract a subvector of the first NumDstElts lanes and sign/zero extend.
3607 SmallVector<int, 8> ShuffleMask(NumDstElts);
3608 for (unsigned i = 0; i != NumDstElts; ++i)
3609 ShuffleMask[i] = i;
3610
3611 Value *SV = Builder.CreateShuffleVector(CI->getArgOperand(0), ShuffleMask);
3612
3613 bool DoSext = Name.contains("pmovsx");
3614 Rep =
3615 DoSext ? Builder.CreateSExt(SV, DstTy) : Builder.CreateZExt(SV, DstTy);
3616 // If there are 3 arguments, it's a masked intrinsic so we need a select.
3617 if (CI->arg_size() == 3)
3618 Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
3619 CI->getArgOperand(1));
3620 } else if (Name == "avx512.mask.pmov.qd.256" ||
3621 Name == "avx512.mask.pmov.qd.512" ||
3622 Name == "avx512.mask.pmov.wb.256" ||
3623 Name == "avx512.mask.pmov.wb.512") {
3624 Type *Ty = CI->getArgOperand(1)->getType();
3625 Rep = Builder.CreateTrunc(CI->getArgOperand(0), Ty);
3626 Rep =
3627 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3628 } else if (Name.starts_with("avx.vbroadcastf128") ||
3629 Name == "avx2.vbroadcasti128") {
3630 // Replace vbroadcastf128/vbroadcasti128 with a vector load+shuffle.
3631 Type *EltTy = cast<VectorType>(CI->getType())->getElementType();
3632 unsigned NumSrcElts = 128 / EltTy->getPrimitiveSizeInBits();
3633 auto *VT = FixedVectorType::get(EltTy, NumSrcElts);
3634 Value *Load = Builder.CreateAlignedLoad(VT, CI->getArgOperand(0), Align(1));
3635 if (NumSrcElts == 2)
3636 Rep = Builder.CreateShuffleVector(Load, ArrayRef<int>{0, 1, 0, 1});
3637 else
3638 Rep = Builder.CreateShuffleVector(Load,
3639 ArrayRef<int>{0, 1, 2, 3, 0, 1, 2, 3});
3640 } else if (Name.starts_with("avx512.mask.shuf.i") ||
3641 Name.starts_with("avx512.mask.shuf.f")) {
3642 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3643 Type *VT = CI->getType();
3644 unsigned NumLanes = VT->getPrimitiveSizeInBits() / 128;
3645 unsigned NumElementsInLane = 128 / VT->getScalarSizeInBits();
3646 unsigned ControlBitsMask = NumLanes - 1;
3647 unsigned NumControlBits = NumLanes / 2;
3648 SmallVector<int, 8> ShuffleMask(0);
3649
3650 for (unsigned l = 0; l != NumLanes; ++l) {
3651 unsigned LaneMask = (Imm >> (l * NumControlBits)) & ControlBitsMask;
3652 // We actually need the other source.
3653 if (l >= NumLanes / 2)
3654 LaneMask += NumLanes;
3655 for (unsigned i = 0; i != NumElementsInLane; ++i)
3656 ShuffleMask.push_back(LaneMask * NumElementsInLane + i);
3657 }
3658 Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
3659 CI->getArgOperand(1), ShuffleMask);
3660 Rep =
3661 emitX86Select(Builder, CI->getArgOperand(4), Rep, CI->getArgOperand(3));
3662 } else if (Name.starts_with("avx512.mask.broadcastf") ||
3663 Name.starts_with("avx512.mask.broadcasti")) {
3664 unsigned NumSrcElts = cast<FixedVectorType>(CI->getArgOperand(0)->getType())
3665 ->getNumElements();
3666 unsigned NumDstElts =
3667 cast<FixedVectorType>(CI->getType())->getNumElements();
3668
3669 SmallVector<int, 8> ShuffleMask(NumDstElts);
3670 for (unsigned i = 0; i != NumDstElts; ++i)
3671 ShuffleMask[i] = i % NumSrcElts;
3672
3673 Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
3674 CI->getArgOperand(0), ShuffleMask);
3675 Rep =
3676 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3677 } else if (Name.starts_with("avx2.pbroadcast") ||
3678 Name.starts_with("avx2.vbroadcast") ||
3679 Name.starts_with("avx512.pbroadcast") ||
3680 Name.starts_with("avx512.mask.broadcast.s")) {
3681 // Replace vp?broadcasts with a vector shuffle.
3682 Value *Op = CI->getArgOperand(0);
3683 ElementCount EC = cast<VectorType>(CI->getType())->getElementCount();
3684 Type *MaskTy = VectorType::get(Type::getInt32Ty(C), EC);
3687 Rep = Builder.CreateShuffleVector(Op, M);
3688
3689 if (CI->arg_size() == 3)
3690 Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
3691 CI->getArgOperand(1));
3692 } else if (Name.starts_with("sse2.padds.") ||
3693 Name.starts_with("avx2.padds.") ||
3694 Name.starts_with("avx512.padds.") ||
3695 Name.starts_with("avx512.mask.padds.")) {
3696 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::sadd_sat);
3697 } else if (Name.starts_with("sse2.psubs.") ||
3698 Name.starts_with("avx2.psubs.") ||
3699 Name.starts_with("avx512.psubs.") ||
3700 Name.starts_with("avx512.mask.psubs.")) {
3701 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::ssub_sat);
3702 } else if (Name.starts_with("sse2.paddus.") ||
3703 Name.starts_with("avx2.paddus.") ||
3704 Name.starts_with("avx512.mask.paddus.")) {
3705 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::uadd_sat);
3706 } else if (Name.starts_with("sse2.psubus.") ||
3707 Name.starts_with("avx2.psubus.") ||
3708 Name.starts_with("avx512.mask.psubus.")) {
3709 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::usub_sat);
3710 } else if (Name.starts_with("avx512.mask.palignr.")) {
3711 Rep = upgradeX86ALIGNIntrinsics(Builder, CI->getArgOperand(0),
3712 CI->getArgOperand(1), CI->getArgOperand(2),
3713 CI->getArgOperand(3), CI->getArgOperand(4),
3714 false);
3715 } else if (Name.starts_with("avx512.mask.valign.")) {
3717 Builder, CI->getArgOperand(0), CI->getArgOperand(1),
3718 CI->getArgOperand(2), CI->getArgOperand(3), CI->getArgOperand(4), true);
3719 } else if (Name == "sse2.psll.dq" || Name == "avx2.psll.dq") {
3720 // 128/256-bit shift left specified in bits.
3721 unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3722 Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0),
3723 Shift / 8); // Shift is in bits.
3724 } else if (Name == "sse2.psrl.dq" || Name == "avx2.psrl.dq") {
3725 // 128/256-bit shift right specified in bits.
3726 unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3727 Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0),
3728 Shift / 8); // Shift is in bits.
3729 } else if (Name == "sse2.psll.dq.bs" || Name == "avx2.psll.dq.bs" ||
3730 Name == "avx512.psll.dq.512") {
3731 // 128/256/512-bit shift left specified in bytes.
3732 unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3733 Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
3734 } else if (Name == "sse2.psrl.dq.bs" || Name == "avx2.psrl.dq.bs" ||
3735 Name == "avx512.psrl.dq.512") {
3736 // 128/256/512-bit shift right specified in bytes.
3737 unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3738 Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
3739 } else if (Name == "sse41.pblendw" || Name.starts_with("sse41.blendp") ||
3740 Name.starts_with("avx.blend.p") || Name == "avx2.pblendw" ||
3741 Name.starts_with("avx2.pblendd.")) {
3742 Value *Op0 = CI->getArgOperand(0);
3743 Value *Op1 = CI->getArgOperand(1);
3744 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3745 auto *VecTy = cast<FixedVectorType>(CI->getType());
3746 unsigned NumElts = VecTy->getNumElements();
3747
3748 SmallVector<int, 16> Idxs(NumElts);
3749 for (unsigned i = 0; i != NumElts; ++i)
3750 Idxs[i] = ((Imm >> (i % 8)) & 1) ? i + NumElts : i;
3751
3752 Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
3753 } else if (Name.starts_with("avx.vinsertf128.") ||
3754 Name == "avx2.vinserti128" ||
3755 Name.starts_with("avx512.mask.insert")) {
3756 Value *Op0 = CI->getArgOperand(0);
3757 Value *Op1 = CI->getArgOperand(1);
3758 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3759 unsigned DstNumElts =
3760 cast<FixedVectorType>(CI->getType())->getNumElements();
3761 unsigned SrcNumElts =
3762 cast<FixedVectorType>(Op1->getType())->getNumElements();
3763 unsigned Scale = DstNumElts / SrcNumElts;
3764
3765 // Mask off the high bits of the immediate value; hardware ignores those.
3766 Imm = Imm % Scale;
3767
3768 // Extend the second operand into a vector the size of the destination.
3769 SmallVector<int, 8> Idxs(DstNumElts);
3770 for (unsigned i = 0; i != SrcNumElts; ++i)
3771 Idxs[i] = i;
3772 for (unsigned i = SrcNumElts; i != DstNumElts; ++i)
3773 Idxs[i] = SrcNumElts;
3774 Rep = Builder.CreateShuffleVector(Op1, Idxs);
3775
3776 // Insert the second operand into the first operand.
3777
3778 // Note that there is no guarantee that instruction lowering will actually
3779 // produce a vinsertf128 instruction for the created shuffles. In
3780 // particular, the 0 immediate case involves no lane changes, so it can
3781 // be handled as a blend.
3782
3783 // Example of shuffle mask for 32-bit elements:
3784 // Imm = 1 <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
3785 // Imm = 0 <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7 >
3786
3787 // First fill with identify mask.
3788 for (unsigned i = 0; i != DstNumElts; ++i)
3789 Idxs[i] = i;
3790 // Then replace the elements where we need to insert.
3791 for (unsigned i = 0; i != SrcNumElts; ++i)
3792 Idxs[i + Imm * SrcNumElts] = i + DstNumElts;
3793 Rep = Builder.CreateShuffleVector(Op0, Rep, Idxs);
3794
3795 // If the intrinsic has a mask operand, handle that.
3796 if (CI->arg_size() == 5)
3797 Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep,
3798 CI->getArgOperand(3));
3799 } else if (Name.starts_with("avx.vextractf128.") ||
3800 Name == "avx2.vextracti128" ||
3801 Name.starts_with("avx512.mask.vextract")) {
3802 Value *Op0 = CI->getArgOperand(0);
3803 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3804 unsigned DstNumElts =
3805 cast<FixedVectorType>(CI->getType())->getNumElements();
3806 unsigned SrcNumElts =
3807 cast<FixedVectorType>(Op0->getType())->getNumElements();
3808 unsigned Scale = SrcNumElts / DstNumElts;
3809
3810 // Mask off the high bits of the immediate value; hardware ignores those.
3811 Imm = Imm % Scale;
3812
3813 // Get indexes for the subvector of the input vector.
3814 SmallVector<int, 8> Idxs(DstNumElts);
3815 for (unsigned i = 0; i != DstNumElts; ++i) {
3816 Idxs[i] = i + (Imm * DstNumElts);
3817 }
3818 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3819
3820 // If the intrinsic has a mask operand, handle that.
3821 if (CI->arg_size() == 4)
3822 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3823 CI->getArgOperand(2));
3824 } else if (Name.starts_with("avx512.mask.perm.df.") ||
3825 Name.starts_with("avx512.mask.perm.di.")) {
3826 Value *Op0 = CI->getArgOperand(0);
3827 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3828 auto *VecTy = cast<FixedVectorType>(CI->getType());
3829 unsigned NumElts = VecTy->getNumElements();
3830
3831 SmallVector<int, 8> Idxs(NumElts);
3832 for (unsigned i = 0; i != NumElts; ++i)
3833 Idxs[i] = (i & ~0x3) + ((Imm >> (2 * (i & 0x3))) & 3);
3834
3835 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3836
3837 if (CI->arg_size() == 4)
3838 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3839 CI->getArgOperand(2));
3840 } else if (Name.starts_with("avx.vperm2f128.") || Name == "avx2.vperm2i128") {
3841 // The immediate permute control byte looks like this:
3842 // [1:0] - select 128 bits from sources for low half of destination
3843 // [2] - ignore
3844 // [3] - zero low half of destination
3845 // [5:4] - select 128 bits from sources for high half of destination
3846 // [6] - ignore
3847 // [7] - zero high half of destination
3848
3849 uint8_t Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3850
3851 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3852 unsigned HalfSize = NumElts / 2;
3853 SmallVector<int, 8> ShuffleMask(NumElts);
3854
3855 // Determine which operand(s) are actually in use for this instruction.
3856 Value *V0 = (Imm & 0x02) ? CI->getArgOperand(1) : CI->getArgOperand(0);
3857 Value *V1 = (Imm & 0x20) ? CI->getArgOperand(1) : CI->getArgOperand(0);
3858
3859 // If needed, replace operands based on zero mask.
3860 V0 = (Imm & 0x08) ? ConstantAggregateZero::get(CI->getType()) : V0;
3861 V1 = (Imm & 0x80) ? ConstantAggregateZero::get(CI->getType()) : V1;
3862
3863 // Permute low half of result.
3864 unsigned StartIndex = (Imm & 0x01) ? HalfSize : 0;
3865 for (unsigned i = 0; i < HalfSize; ++i)
3866 ShuffleMask[i] = StartIndex + i;
3867
3868 // Permute high half of result.
3869 StartIndex = (Imm & 0x10) ? HalfSize : 0;
3870 for (unsigned i = 0; i < HalfSize; ++i)
3871 ShuffleMask[i + HalfSize] = NumElts + StartIndex + i;
3872
3873 Rep = Builder.CreateShuffleVector(V0, V1, ShuffleMask);
3874
3875 } else if (Name.starts_with("avx.vpermil.") || Name == "sse2.pshuf.d" ||
3876 Name.starts_with("avx512.mask.vpermil.p") ||
3877 Name.starts_with("avx512.mask.pshuf.d.")) {
3878 Value *Op0 = CI->getArgOperand(0);
3879 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3880 auto *VecTy = cast<FixedVectorType>(CI->getType());
3881 unsigned NumElts = VecTy->getNumElements();
3882 // Calculate the size of each index in the immediate.
3883 unsigned IdxSize = 64 / VecTy->getScalarSizeInBits();
3884 unsigned IdxMask = ((1 << IdxSize) - 1);
3885
3886 SmallVector<int, 8> Idxs(NumElts);
3887 // Lookup the bits for this element, wrapping around the immediate every
3888 // 8-bits. Elements are grouped into sets of 2 or 4 elements so we need
3889 // to offset by the first index of each group.
3890 for (unsigned i = 0; i != NumElts; ++i)
3891 Idxs[i] = ((Imm >> ((i * IdxSize) % 8)) & IdxMask) | (i & ~IdxMask);
3892
3893 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3894
3895 if (CI->arg_size() == 4)
3896 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3897 CI->getArgOperand(2));
3898 } else if (Name == "sse2.pshufl.w" ||
3899 Name.starts_with("avx512.mask.pshufl.w.")) {
3900 Value *Op0 = CI->getArgOperand(0);
3901 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3902 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3903
3904 if (Name == "sse2.pshufl.w" && NumElts % 8 != 0)
3905 reportFatalUsageErrorWithCI("Intrinsic has invalid signature", CI);
3906
3907 SmallVector<int, 16> Idxs(NumElts);
3908 for (unsigned l = 0; l != NumElts; l += 8) {
3909 for (unsigned i = 0; i != 4; ++i)
3910 Idxs[i + l] = ((Imm >> (2 * i)) & 0x3) + l;
3911 for (unsigned i = 4; i != 8; ++i)
3912 Idxs[i + l] = i + l;
3913 }
3914
3915 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3916
3917 if (CI->arg_size() == 4)
3918 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3919 CI->getArgOperand(2));
3920 } else if (Name == "sse2.pshufh.w" ||
3921 Name.starts_with("avx512.mask.pshufh.w.")) {
3922 Value *Op0 = CI->getArgOperand(0);
3923 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3924 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3925
3926 if (Name == "sse2.pshufh.w" && NumElts % 8 != 0)
3927 reportFatalUsageErrorWithCI("Intrinsic has invalid signature", CI);
3928
3929 SmallVector<int, 16> Idxs(NumElts);
3930 for (unsigned l = 0; l != NumElts; l += 8) {
3931 for (unsigned i = 0; i != 4; ++i)
3932 Idxs[i + l] = i + l;
3933 for (unsigned i = 0; i != 4; ++i)
3934 Idxs[i + l + 4] = ((Imm >> (2 * i)) & 0x3) + 4 + l;
3935 }
3936
3937 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3938
3939 if (CI->arg_size() == 4)
3940 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3941 CI->getArgOperand(2));
3942 } else if (Name.starts_with("avx512.mask.shuf.p")) {
3943 Value *Op0 = CI->getArgOperand(0);
3944 Value *Op1 = CI->getArgOperand(1);
3945 unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3946 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3947
3948 unsigned NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3949 unsigned HalfLaneElts = NumLaneElts / 2;
3950
3951 SmallVector<int, 16> Idxs(NumElts);
3952 for (unsigned i = 0; i != NumElts; ++i) {
3953 // Base index is the starting element of the lane.
3954 Idxs[i] = i - (i % NumLaneElts);
3955 // If we are half way through the lane switch to the other source.
3956 if ((i % NumLaneElts) >= HalfLaneElts)
3957 Idxs[i] += NumElts;
3958 // Now select the specific element. By adding HalfLaneElts bits from
3959 // the immediate. Wrapping around the immediate every 8-bits.
3960 Idxs[i] += (Imm >> ((i * HalfLaneElts) % 8)) & ((1 << HalfLaneElts) - 1);
3961 }
3962
3963 Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
3964
3965 Rep =
3966 emitX86Select(Builder, CI->getArgOperand(4), Rep, CI->getArgOperand(3));
3967 } else if (Name.starts_with("avx512.mask.movddup") ||
3968 Name.starts_with("avx512.mask.movshdup") ||
3969 Name.starts_with("avx512.mask.movsldup")) {
3970 Value *Op0 = CI->getArgOperand(0);
3971 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3972 unsigned NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3973
3974 unsigned Offset = 0;
3975 if (Name.starts_with("avx512.mask.movshdup."))
3976 Offset = 1;
3977
3978 SmallVector<int, 16> Idxs(NumElts);
3979 for (unsigned l = 0; l != NumElts; l += NumLaneElts)
3980 for (unsigned i = 0; i != NumLaneElts; i += 2) {
3981 Idxs[i + l + 0] = i + l + Offset;
3982 Idxs[i + l + 1] = i + l + Offset;
3983 }
3984
3985 Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3986
3987 Rep =
3988 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3989 } else if (Name.starts_with("avx512.mask.punpckl") ||
3990 Name.starts_with("avx512.mask.unpckl.")) {
3991 Value *Op0 = CI->getArgOperand(0);
3992 Value *Op1 = CI->getArgOperand(1);
3993 int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3994 int NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3995
3996 SmallVector<int, 64> Idxs(NumElts);
3997 for (int l = 0; l != NumElts; l += NumLaneElts)
3998 for (int i = 0; i != NumLaneElts; ++i)
3999 Idxs[i + l] = l + (i / 2) + NumElts * (i % 2);
4000
4001 Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
4002
4003 Rep =
4004 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4005 } else if (Name.starts_with("avx512.mask.punpckh") ||
4006 Name.starts_with("avx512.mask.unpckh.")) {
4007 Value *Op0 = CI->getArgOperand(0);
4008 Value *Op1 = CI->getArgOperand(1);
4009 int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
4010 int NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
4011
4012 SmallVector<int, 64> Idxs(NumElts);
4013 for (int l = 0; l != NumElts; l += NumLaneElts)
4014 for (int i = 0; i != NumLaneElts; ++i)
4015 Idxs[i + l] = (NumLaneElts / 2) + l + (i / 2) + NumElts * (i % 2);
4016
4017 Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
4018
4019 Rep =
4020 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4021 } else if (Name.starts_with("avx512.mask.and.") ||
4022 Name.starts_with("avx512.mask.pand.")) {
4023 VectorType *FTy = cast<VectorType>(CI->getType());
4025 Rep = Builder.CreateAnd(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
4026 Builder.CreateBitCast(CI->getArgOperand(1), ITy));
4027 Rep = Builder.CreateBitCast(Rep, FTy);
4028 Rep =
4029 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4030 } else if (Name.starts_with("avx512.mask.andn.") ||
4031 Name.starts_with("avx512.mask.pandn.")) {
4032 VectorType *FTy = cast<VectorType>(CI->getType());
4034 Rep = Builder.CreateNot(Builder.CreateBitCast(CI->getArgOperand(0), ITy));
4035 Rep = Builder.CreateAnd(Rep,
4036 Builder.CreateBitCast(CI->getArgOperand(1), ITy));
4037 Rep = Builder.CreateBitCast(Rep, FTy);
4038 Rep =
4039 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4040 } else if (Name.starts_with("avx512.mask.or.") ||
4041 Name.starts_with("avx512.mask.por.")) {
4042 VectorType *FTy = cast<VectorType>(CI->getType());
4044 Rep = Builder.CreateOr(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
4045 Builder.CreateBitCast(CI->getArgOperand(1), ITy));
4046 Rep = Builder.CreateBitCast(Rep, FTy);
4047 Rep =
4048 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4049 } else if (Name.starts_with("avx512.mask.xor.") ||
4050 Name.starts_with("avx512.mask.pxor.")) {
4051 VectorType *FTy = cast<VectorType>(CI->getType());
4053 Rep = Builder.CreateXor(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
4054 Builder.CreateBitCast(CI->getArgOperand(1), ITy));
4055 Rep = Builder.CreateBitCast(Rep, FTy);
4056 Rep =
4057 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4058 } else if (Name.starts_with("avx512.mask.padd.")) {
4059 Rep = Builder.CreateAdd(CI->getArgOperand(0), CI->getArgOperand(1));
4060 Rep =
4061 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4062 } else if (Name.starts_with("avx512.mask.psub.")) {
4063 Rep = Builder.CreateSub(CI->getArgOperand(0), CI->getArgOperand(1));
4064 Rep =
4065 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4066 } else if (Name.starts_with("avx512.mask.pmull.")) {
4067 Rep = Builder.CreateMul(CI->getArgOperand(0), CI->getArgOperand(1));
4068 Rep =
4069 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4070 } else if (Name.starts_with("avx512.mask.add.p")) {
4071 if (Name.ends_with(".512")) {
4072 Intrinsic::ID IID;
4073 if (Name[17] == 's')
4074 IID = Intrinsic::x86_avx512_add_ps_512;
4075 else
4076 IID = Intrinsic::x86_avx512_add_pd_512;
4077
4078 Rep = Builder.CreateIntrinsic(
4079 IID,
4080 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
4081 } else {
4082 Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
4083 }
4084 Rep =
4085 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4086 } else if (Name.starts_with("avx512.mask.div.p")) {
4087 if (Name.ends_with(".512")) {
4088 Intrinsic::ID IID;
4089 if (Name[17] == 's')
4090 IID = Intrinsic::x86_avx512_div_ps_512;
4091 else
4092 IID = Intrinsic::x86_avx512_div_pd_512;
4093
4094 Rep = Builder.CreateIntrinsic(
4095 IID,
4096 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
4097 } else {
4098 Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
4099 }
4100 Rep =
4101 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4102 } else if (Name.starts_with("avx512.mask.mul.p")) {
4103 if (Name.ends_with(".512")) {
4104 Intrinsic::ID IID;
4105 if (Name[17] == 's')
4106 IID = Intrinsic::x86_avx512_mul_ps_512;
4107 else
4108 IID = Intrinsic::x86_avx512_mul_pd_512;
4109
4110 Rep = Builder.CreateIntrinsic(
4111 IID,
4112 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
4113 } else {
4114 Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
4115 }
4116 Rep =
4117 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4118 } else if (Name.starts_with("avx512.mask.sub.p")) {
4119 if (Name.ends_with(".512")) {
4120 Intrinsic::ID IID;
4121 if (Name[17] == 's')
4122 IID = Intrinsic::x86_avx512_sub_ps_512;
4123 else
4124 IID = Intrinsic::x86_avx512_sub_pd_512;
4125
4126 Rep = Builder.CreateIntrinsic(
4127 IID,
4128 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
4129 } else {
4130 Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
4131 }
4132 Rep =
4133 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4134 } else if ((Name.starts_with("avx512.mask.max.p") ||
4135 Name.starts_with("avx512.mask.min.p")) &&
4136 Name.drop_front(18) == ".512") {
4137 bool IsDouble = Name[17] == 'd';
4138 bool IsMin = Name[13] == 'i';
4139 static const Intrinsic::ID MinMaxTbl[2][2] = {
4140 {Intrinsic::x86_avx512_max_ps_512, Intrinsic::x86_avx512_max_pd_512},
4141 {Intrinsic::x86_avx512_min_ps_512, Intrinsic::x86_avx512_min_pd_512}};
4142 Intrinsic::ID IID = MinMaxTbl[IsMin][IsDouble];
4143
4144 Rep = Builder.CreateIntrinsic(
4145 IID,
4146 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
4147 Rep =
4148 emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
4149 } else if (Name.starts_with("avx512.mask.lzcnt.")) {
4150 Rep =
4151 Builder.CreateIntrinsic(Intrinsic::ctlz, CI->getType(),
4152 {CI->getArgOperand(0), Builder.getInt1(false)});
4153 Rep =
4154 emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
4155 } else if (Name.starts_with("avx512.mask.psll")) {
4156 bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
4157 bool IsVariable = Name[16] == 'v';
4158 char Size = Name[16] == '.' ? Name[17]
4159 : Name[17] == '.' ? Name[18]
4160 : Name[18] == '.' ? Name[19]
4161 : Name[20];
4162
4163 Intrinsic::ID IID;
4164 if (IsVariable && Name[17] != '.') {
4165 if (Size == 'd' && Name[17] == '2') // avx512.mask.psllv2.di
4166 IID = Intrinsic::x86_avx2_psllv_q;
4167 else if (Size == 'd' && Name[17] == '4') // avx512.mask.psllv4.di
4168 IID = Intrinsic::x86_avx2_psllv_q_256;
4169 else if (Size == 's' && Name[17] == '4') // avx512.mask.psllv4.si
4170 IID = Intrinsic::x86_avx2_psllv_d;
4171 else if (Size == 's' && Name[17] == '8') // avx512.mask.psllv8.si
4172 IID = Intrinsic::x86_avx2_psllv_d_256;
4173 else if (Size == 'h' && Name[17] == '8') // avx512.mask.psllv8.hi
4174 IID = Intrinsic::x86_avx512_psllv_w_128;
4175 else if (Size == 'h' && Name[17] == '1') // avx512.mask.psllv16.hi
4176 IID = Intrinsic::x86_avx512_psllv_w_256;
4177 else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psllv32hi
4178 IID = Intrinsic::x86_avx512_psllv_w_512;
4179 else
4180 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4181 } else if (Name.ends_with(".128")) {
4182 if (Size == 'd') // avx512.mask.psll.d.128, avx512.mask.psll.di.128
4183 IID = IsImmediate ? Intrinsic::x86_sse2_pslli_d
4184 : Intrinsic::x86_sse2_psll_d;
4185 else if (Size == 'q') // avx512.mask.psll.q.128, avx512.mask.psll.qi.128
4186 IID = IsImmediate ? Intrinsic::x86_sse2_pslli_q
4187 : Intrinsic::x86_sse2_psll_q;
4188 else if (Size == 'w') // avx512.mask.psll.w.128, avx512.mask.psll.wi.128
4189 IID = IsImmediate ? Intrinsic::x86_sse2_pslli_w
4190 : Intrinsic::x86_sse2_psll_w;
4191 else
4192 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4193 } else if (Name.ends_with(".256")) {
4194 if (Size == 'd') // avx512.mask.psll.d.256, avx512.mask.psll.di.256
4195 IID = IsImmediate ? Intrinsic::x86_avx2_pslli_d
4196 : Intrinsic::x86_avx2_psll_d;
4197 else if (Size == 'q') // avx512.mask.psll.q.256, avx512.mask.psll.qi.256
4198 IID = IsImmediate ? Intrinsic::x86_avx2_pslli_q
4199 : Intrinsic::x86_avx2_psll_q;
4200 else if (Size == 'w') // avx512.mask.psll.w.256, avx512.mask.psll.wi.256
4201 IID = IsImmediate ? Intrinsic::x86_avx2_pslli_w
4202 : Intrinsic::x86_avx2_psll_w;
4203 else
4204 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4205 } else {
4206 if (Size == 'd') // psll.di.512, pslli.d, psll.d, psllv.d.512
4207 IID = IsImmediate ? Intrinsic::x86_avx512_pslli_d_512
4208 : IsVariable ? Intrinsic::x86_avx512_psllv_d_512
4209 : Intrinsic::x86_avx512_psll_d_512;
4210 else if (Size == 'q') // psll.qi.512, pslli.q, psll.q, psllv.q.512
4211 IID = IsImmediate ? Intrinsic::x86_avx512_pslli_q_512
4212 : IsVariable ? Intrinsic::x86_avx512_psllv_q_512
4213 : Intrinsic::x86_avx512_psll_q_512;
4214 else if (Size == 'w') // psll.wi.512, pslli.w, psll.w
4215 IID = IsImmediate ? Intrinsic::x86_avx512_pslli_w_512
4216 : Intrinsic::x86_avx512_psll_w_512;
4217 else
4218 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4219 }
4220
4221 Rep = upgradeX86MaskedShift(Builder, *CI, IID);
4222 } else if (Name.starts_with("avx512.mask.psrl")) {
4223 bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
4224 bool IsVariable = Name[16] == 'v';
4225 char Size = Name[16] == '.' ? Name[17]
4226 : Name[17] == '.' ? Name[18]
4227 : Name[18] == '.' ? Name[19]
4228 : Name[20];
4229
4230 Intrinsic::ID IID;
4231 if (IsVariable && Name[17] != '.') {
4232 if (Size == 'd' && Name[17] == '2') // avx512.mask.psrlv2.di
4233 IID = Intrinsic::x86_avx2_psrlv_q;
4234 else if (Size == 'd' && Name[17] == '4') // avx512.mask.psrlv4.di
4235 IID = Intrinsic::x86_avx2_psrlv_q_256;
4236 else if (Size == 's' && Name[17] == '4') // avx512.mask.psrlv4.si
4237 IID = Intrinsic::x86_avx2_psrlv_d;
4238 else if (Size == 's' && Name[17] == '8') // avx512.mask.psrlv8.si
4239 IID = Intrinsic::x86_avx2_psrlv_d_256;
4240 else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrlv8.hi
4241 IID = Intrinsic::x86_avx512_psrlv_w_128;
4242 else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrlv16.hi
4243 IID = Intrinsic::x86_avx512_psrlv_w_256;
4244 else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrlv32hi
4245 IID = Intrinsic::x86_avx512_psrlv_w_512;
4246 else
4247 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4248 } else if (Name.ends_with(".128")) {
4249 if (Size == 'd') // avx512.mask.psrl.d.128, avx512.mask.psrl.di.128
4250 IID = IsImmediate ? Intrinsic::x86_sse2_psrli_d
4251 : Intrinsic::x86_sse2_psrl_d;
4252 else if (Size == 'q') // avx512.mask.psrl.q.128, avx512.mask.psrl.qi.128
4253 IID = IsImmediate ? Intrinsic::x86_sse2_psrli_q
4254 : Intrinsic::x86_sse2_psrl_q;
4255 else if (Size == 'w') // avx512.mask.psrl.w.128, avx512.mask.psrl.wi.128
4256 IID = IsImmediate ? Intrinsic::x86_sse2_psrli_w
4257 : Intrinsic::x86_sse2_psrl_w;
4258 else
4259 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4260 } else if (Name.ends_with(".256")) {
4261 if (Size == 'd') // avx512.mask.psrl.d.256, avx512.mask.psrl.di.256
4262 IID = IsImmediate ? Intrinsic::x86_avx2_psrli_d
4263 : Intrinsic::x86_avx2_psrl_d;
4264 else if (Size == 'q') // avx512.mask.psrl.q.256, avx512.mask.psrl.qi.256
4265 IID = IsImmediate ? Intrinsic::x86_avx2_psrli_q
4266 : Intrinsic::x86_avx2_psrl_q;
4267 else if (Size == 'w') // avx512.mask.psrl.w.256, avx512.mask.psrl.wi.256
4268 IID = IsImmediate ? Intrinsic::x86_avx2_psrli_w
4269 : Intrinsic::x86_avx2_psrl_w;
4270 else
4271 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4272 } else {
4273 if (Size == 'd') // psrl.di.512, psrli.d, psrl.d, psrl.d.512
4274 IID = IsImmediate ? Intrinsic::x86_avx512_psrli_d_512
4275 : IsVariable ? Intrinsic::x86_avx512_psrlv_d_512
4276 : Intrinsic::x86_avx512_psrl_d_512;
4277 else if (Size == 'q') // psrl.qi.512, psrli.q, psrl.q, psrl.q.512
4278 IID = IsImmediate ? Intrinsic::x86_avx512_psrli_q_512
4279 : IsVariable ? Intrinsic::x86_avx512_psrlv_q_512
4280 : Intrinsic::x86_avx512_psrl_q_512;
4281 else if (Size == 'w') // psrl.wi.512, psrli.w, psrl.w)
4282 IID = IsImmediate ? Intrinsic::x86_avx512_psrli_w_512
4283 : Intrinsic::x86_avx512_psrl_w_512;
4284 else
4285 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4286 }
4287
4288 Rep = upgradeX86MaskedShift(Builder, *CI, IID);
4289 } else if (Name.starts_with("avx512.mask.psra")) {
4290 bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
4291 bool IsVariable = Name[16] == 'v';
4292 char Size = Name[16] == '.' ? Name[17]
4293 : Name[17] == '.' ? Name[18]
4294 : Name[18] == '.' ? Name[19]
4295 : Name[20];
4296
4297 Intrinsic::ID IID;
4298 if (IsVariable && Name[17] != '.') {
4299 if (Size == 's' && Name[17] == '4') // avx512.mask.psrav4.si
4300 IID = Intrinsic::x86_avx2_psrav_d;
4301 else if (Size == 's' && Name[17] == '8') // avx512.mask.psrav8.si
4302 IID = Intrinsic::x86_avx2_psrav_d_256;
4303 else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrav8.hi
4304 IID = Intrinsic::x86_avx512_psrav_w_128;
4305 else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrav16.hi
4306 IID = Intrinsic::x86_avx512_psrav_w_256;
4307 else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrav32hi
4308 IID = Intrinsic::x86_avx512_psrav_w_512;
4309 else
4310 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4311 } else if (Name.ends_with(".128")) {
4312 if (Size == 'd') // avx512.mask.psra.d.128, avx512.mask.psra.di.128
4313 IID = IsImmediate ? Intrinsic::x86_sse2_psrai_d
4314 : Intrinsic::x86_sse2_psra_d;
4315 else if (Size == 'q') // avx512.mask.psra.q.128, avx512.mask.psra.qi.128
4316 IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_128
4317 : IsVariable ? Intrinsic::x86_avx512_psrav_q_128
4318 : Intrinsic::x86_avx512_psra_q_128;
4319 else if (Size == 'w') // avx512.mask.psra.w.128, avx512.mask.psra.wi.128
4320 IID = IsImmediate ? Intrinsic::x86_sse2_psrai_w
4321 : Intrinsic::x86_sse2_psra_w;
4322 else
4323 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4324 } else if (Name.ends_with(".256")) {
4325 if (Size == 'd') // avx512.mask.psra.d.256, avx512.mask.psra.di.256
4326 IID = IsImmediate ? Intrinsic::x86_avx2_psrai_d
4327 : Intrinsic::x86_avx2_psra_d;
4328 else if (Size == 'q') // avx512.mask.psra.q.256, avx512.mask.psra.qi.256
4329 IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_256
4330 : IsVariable ? Intrinsic::x86_avx512_psrav_q_256
4331 : Intrinsic::x86_avx512_psra_q_256;
4332 else if (Size == 'w') // avx512.mask.psra.w.256, avx512.mask.psra.wi.256
4333 IID = IsImmediate ? Intrinsic::x86_avx2_psrai_w
4334 : Intrinsic::x86_avx2_psra_w;
4335 else
4336 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4337 } else {
4338 if (Size == 'd') // psra.di.512, psrai.d, psra.d, psrav.d.512
4339 IID = IsImmediate ? Intrinsic::x86_avx512_psrai_d_512
4340 : IsVariable ? Intrinsic::x86_avx512_psrav_d_512
4341 : Intrinsic::x86_avx512_psra_d_512;
4342 else if (Size == 'q') // psra.qi.512, psrai.q, psra.q
4343 IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_512
4344 : IsVariable ? Intrinsic::x86_avx512_psrav_q_512
4345 : Intrinsic::x86_avx512_psra_q_512;
4346 else if (Size == 'w') // psra.wi.512, psrai.w, psra.w
4347 IID = IsImmediate ? Intrinsic::x86_avx512_psrai_w_512
4348 : Intrinsic::x86_avx512_psra_w_512;
4349 else
4350 reportFatalUsageErrorWithCI("Intrinsic has unexpected size", CI);
4351 }
4352
4353 Rep = upgradeX86MaskedShift(Builder, *CI, IID);
4354 } else if (Name.starts_with("avx512.mask.move.s")) {
4355 Rep = upgradeMaskedMove(Builder, *CI);
4356 } else if (Name.starts_with("avx512.cvtmask2")) {
4357 Rep = upgradeMaskToInt(Builder, *CI);
4358 } else if (Name.ends_with(".movntdqa")) {
4360 C, ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
4361
4362 LoadInst *LI = Builder.CreateAlignedLoad(
4363 CI->getType(), CI->getArgOperand(0),
4365 LI->setMetadata(LLVMContext::MD_nontemporal, Node);
4366 Rep = LI;
4367 } else if (Name.starts_with("fma.vfmadd.") ||
4368 Name.starts_with("fma.vfmsub.") ||
4369 Name.starts_with("fma.vfnmadd.") ||
4370 Name.starts_with("fma.vfnmsub.")) {
4371 bool NegMul = Name[6] == 'n';
4372 bool NegAcc = NegMul ? Name[8] == 's' : Name[7] == 's';
4373 bool IsScalar = NegMul ? Name[12] == 's' : Name[11] == 's';
4374
4375 Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4376 CI->getArgOperand(2)};
4377
4378 if (IsScalar) {
4379 Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
4380 Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
4381 Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
4382 }
4383
4384 if (NegMul && !IsScalar)
4385 Ops[0] = Builder.CreateFNeg(Ops[0]);
4386 if (NegMul && IsScalar)
4387 Ops[1] = Builder.CreateFNeg(Ops[1]);
4388 if (NegAcc)
4389 Ops[2] = Builder.CreateFNeg(Ops[2]);
4390
4391 Rep = Builder.CreateIntrinsic(Intrinsic::fma, Ops[0]->getType(), Ops);
4392
4393 if (IsScalar)
4394 Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
4395 } else if (Name.starts_with("fma4.vfmadd.s")) {
4396 Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4397 CI->getArgOperand(2)};
4398
4399 Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
4400 Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
4401 Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
4402
4403 Rep = Builder.CreateIntrinsic(Intrinsic::fma, Ops[0]->getType(), Ops);
4404
4405 Rep = Builder.CreateInsertElement(Constant::getNullValue(CI->getType()),
4406 Rep, (uint64_t)0);
4407 } else if (Name.starts_with("avx512.mask.vfmadd.s") ||
4408 Name.starts_with("avx512.maskz.vfmadd.s") ||
4409 Name.starts_with("avx512.mask3.vfmadd.s") ||
4410 Name.starts_with("avx512.mask3.vfmsub.s") ||
4411 Name.starts_with("avx512.mask3.vfnmsub.s")) {
4412 bool IsMask3 = Name[11] == '3';
4413 bool IsMaskZ = Name[11] == 'z';
4414 // Drop the "avx512.mask." to make it easier.
4415 Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
4416 bool NegMul = Name[2] == 'n';
4417 bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
4418
4419 Value *A = CI->getArgOperand(0);
4420 Value *B = CI->getArgOperand(1);
4421 Value *C = CI->getArgOperand(2);
4422
4423 if (NegMul && (IsMask3 || IsMaskZ))
4424 A = Builder.CreateFNeg(A);
4425 if (NegMul && !(IsMask3 || IsMaskZ))
4426 B = Builder.CreateFNeg(B);
4427 if (NegAcc)
4428 C = Builder.CreateFNeg(C);
4429
4430 A = Builder.CreateExtractElement(A, (uint64_t)0);
4431 B = Builder.CreateExtractElement(B, (uint64_t)0);
4432 C = Builder.CreateExtractElement(C, (uint64_t)0);
4433
4434 if (!isa<ConstantInt>(CI->getArgOperand(4)) ||
4435 cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4) {
4436 Value *Ops[] = {A, B, C, CI->getArgOperand(4)};
4437
4438 Intrinsic::ID IID;
4439 if (Name.back() == 'd')
4440 IID = Intrinsic::x86_avx512_vfmadd_f64;
4441 else
4442 IID = Intrinsic::x86_avx512_vfmadd_f32;
4443 Rep = Builder.CreateIntrinsic(IID, Ops);
4444 } else {
4445 Rep = Builder.CreateFMA(A, B, C);
4446 }
4447
4448 Value *PassThru = IsMaskZ ? Constant::getNullValue(Rep->getType())
4449 : IsMask3 ? C
4450 : A;
4451
4452 // For Mask3 with NegAcc, we need to create a new extractelement that
4453 // avoids the negation above.
4454 if (NegAcc && IsMask3)
4455 PassThru =
4456 Builder.CreateExtractElement(CI->getArgOperand(2), (uint64_t)0);
4457
4458 Rep = emitX86ScalarSelect(Builder, CI->getArgOperand(3), Rep, PassThru);
4459 Rep = Builder.CreateInsertElement(CI->getArgOperand(IsMask3 ? 2 : 0), Rep,
4460 (uint64_t)0);
4461 } else if (Name.starts_with("avx512.mask.vfmadd.p") ||
4462 Name.starts_with("avx512.mask.vfnmadd.p") ||
4463 Name.starts_with("avx512.mask.vfnmsub.p") ||
4464 Name.starts_with("avx512.mask3.vfmadd.p") ||
4465 Name.starts_with("avx512.mask3.vfmsub.p") ||
4466 Name.starts_with("avx512.mask3.vfnmsub.p") ||
4467 Name.starts_with("avx512.maskz.vfmadd.p")) {
4468 bool IsMask3 = Name[11] == '3';
4469 bool IsMaskZ = Name[11] == 'z';
4470 // Drop the "avx512.mask." to make it easier.
4471 Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
4472 bool NegMul = Name[2] == 'n';
4473 bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
4474
4475 Value *A = CI->getArgOperand(0);
4476 Value *B = CI->getArgOperand(1);
4477 Value *C = CI->getArgOperand(2);
4478
4479 if (NegMul && (IsMask3 || IsMaskZ))
4480 A = Builder.CreateFNeg(A);
4481 if (NegMul && !(IsMask3 || IsMaskZ))
4482 B = Builder.CreateFNeg(B);
4483 if (NegAcc)
4484 C = Builder.CreateFNeg(C);
4485
4486 if (CI->arg_size() == 5 &&
4487 (!isa<ConstantInt>(CI->getArgOperand(4)) ||
4488 cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
4489 Intrinsic::ID IID;
4490 // Check the character before ".512" in string.
4491 if (Name[Name.size() - 5] == 's')
4492 IID = Intrinsic::x86_avx512_vfmadd_ps_512;
4493 else
4494 IID = Intrinsic::x86_avx512_vfmadd_pd_512;
4495
4496 Rep = Builder.CreateIntrinsic(IID, {A, B, C, CI->getArgOperand(4)});
4497 } else {
4498 Rep = Builder.CreateFMA(A, B, C);
4499 }
4500
4501 Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType())
4502 : IsMask3 ? CI->getArgOperand(2)
4503 : CI->getArgOperand(0);
4504
4505 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
4506 } else if (Name.starts_with("fma.vfmsubadd.p")) {
4507 unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
4508 unsigned EltWidth = CI->getType()->getScalarSizeInBits();
4509 Intrinsic::ID IID;
4510 if (VecWidth == 128 && EltWidth == 32)
4511 IID = Intrinsic::x86_fma_vfmaddsub_ps;
4512 else if (VecWidth == 256 && EltWidth == 32)
4513 IID = Intrinsic::x86_fma_vfmaddsub_ps_256;
4514 else if (VecWidth == 128 && EltWidth == 64)
4515 IID = Intrinsic::x86_fma_vfmaddsub_pd;
4516 else if (VecWidth == 256 && EltWidth == 64)
4517 IID = Intrinsic::x86_fma_vfmaddsub_pd_256;
4518 else
4519 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4520
4521 Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4522 CI->getArgOperand(2)};
4523 Ops[2] = Builder.CreateFNeg(Ops[2]);
4524 Rep = Builder.CreateIntrinsic(IID, Ops);
4525 } else if (Name.starts_with("avx512.mask.vfmaddsub.p") ||
4526 Name.starts_with("avx512.mask3.vfmaddsub.p") ||
4527 Name.starts_with("avx512.maskz.vfmaddsub.p") ||
4528 Name.starts_with("avx512.mask3.vfmsubadd.p")) {
4529 bool IsMask3 = Name[11] == '3';
4530 bool IsMaskZ = Name[11] == 'z';
4531 // Drop the "avx512.mask." to make it easier.
4532 Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
4533 bool IsSubAdd = Name[3] == 's';
4534 if (CI->arg_size() == 5) {
4535 Intrinsic::ID IID;
4536 // Check the character before ".512" in string.
4537 if (Name[Name.size() - 5] == 's')
4538 IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;
4539 else
4540 IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;
4541
4542 Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4543 CI->getArgOperand(2), CI->getArgOperand(4)};
4544 if (IsSubAdd)
4545 Ops[2] = Builder.CreateFNeg(Ops[2]);
4546
4547 Rep = Builder.CreateIntrinsic(IID, Ops);
4548 } else {
4549 int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
4550
4551 Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4552 CI->getArgOperand(2)};
4553
4555 CI->getModule(), Intrinsic::fma, Ops[0]->getType());
4556 Value *Odd = Builder.CreateCall(FMA, Ops);
4557 Ops[2] = Builder.CreateFNeg(Ops[2]);
4558 Value *Even = Builder.CreateCall(FMA, Ops);
4559
4560 if (IsSubAdd)
4561 std::swap(Even, Odd);
4562
4563 SmallVector<int, 32> Idxs(NumElts);
4564 for (int i = 0; i != NumElts; ++i)
4565 Idxs[i] = i + (i % 2) * NumElts;
4566
4567 Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
4568 }
4569
4570 Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType())
4571 : IsMask3 ? CI->getArgOperand(2)
4572 : CI->getArgOperand(0);
4573
4574 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
4575 } else if (Name.starts_with("avx512.mask.pternlog.") ||
4576 Name.starts_with("avx512.maskz.pternlog.")) {
4577 bool ZeroMask = Name[11] == 'z';
4578 unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
4579 unsigned EltWidth = CI->getType()->getScalarSizeInBits();
4580 Intrinsic::ID IID;
4581 if (VecWidth == 128 && EltWidth == 32)
4582 IID = Intrinsic::x86_avx512_pternlog_d_128;
4583 else if (VecWidth == 256 && EltWidth == 32)
4584 IID = Intrinsic::x86_avx512_pternlog_d_256;
4585 else if (VecWidth == 512 && EltWidth == 32)
4586 IID = Intrinsic::x86_avx512_pternlog_d_512;
4587 else if (VecWidth == 128 && EltWidth == 64)
4588 IID = Intrinsic::x86_avx512_pternlog_q_128;
4589 else if (VecWidth == 256 && EltWidth == 64)
4590 IID = Intrinsic::x86_avx512_pternlog_q_256;
4591 else if (VecWidth == 512 && EltWidth == 64)
4592 IID = Intrinsic::x86_avx512_pternlog_q_512;
4593 else
4594 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4595
4596 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4597 CI->getArgOperand(2), CI->getArgOperand(3)};
4598 Rep = Builder.CreateIntrinsic(IID, Args);
4599 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
4600 : CI->getArgOperand(0);
4601 Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep, PassThru);
4602 } else if (Name.starts_with("avx512.mask.vpmadd52") ||
4603 Name.starts_with("avx512.maskz.vpmadd52")) {
4604 bool ZeroMask = Name[11] == 'z';
4605 bool High = Name[20] == 'h' || Name[21] == 'h';
4606 unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
4607 Intrinsic::ID IID;
4608 if (VecWidth == 128 && !High)
4609 IID = Intrinsic::x86_avx512_vpmadd52l_uq_128;
4610 else if (VecWidth == 256 && !High)
4611 IID = Intrinsic::x86_avx512_vpmadd52l_uq_256;
4612 else if (VecWidth == 512 && !High)
4613 IID = Intrinsic::x86_avx512_vpmadd52l_uq_512;
4614 else if (VecWidth == 128 && High)
4615 IID = Intrinsic::x86_avx512_vpmadd52h_uq_128;
4616 else if (VecWidth == 256 && High)
4617 IID = Intrinsic::x86_avx512_vpmadd52h_uq_256;
4618 else if (VecWidth == 512 && High)
4619 IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
4620 else
4621 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4622
4623 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4624 CI->getArgOperand(2)};
4625 Rep = Builder.CreateIntrinsic(IID, Args);
4626 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
4627 : CI->getArgOperand(0);
4628 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
4629 } else if (Name.starts_with("avx512.mask.vpermi2var.") ||
4630 Name.starts_with("avx512.mask.vpermt2var.") ||
4631 Name.starts_with("avx512.maskz.vpermt2var.")) {
4632 bool ZeroMask = Name[11] == 'z';
4633 bool IndexForm = Name[17] == 'i';
4634 Rep = upgradeX86VPERMT2Intrinsics(Builder, *CI, ZeroMask, IndexForm);
4635 } else if (Name.starts_with("avx512.mask.vpdpbusd.") ||
4636 Name.starts_with("avx512.maskz.vpdpbusd.") ||
4637 Name.starts_with("avx512.mask.vpdpbusds.") ||
4638 Name.starts_with("avx512.maskz.vpdpbusds.")) {
4639 bool ZeroMask = Name[11] == 'z';
4640 bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
4641 unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
4642 Intrinsic::ID IID;
4643 if (VecWidth == 128 && !IsSaturating)
4644 IID = Intrinsic::x86_avx512_vpdpbusd_128;
4645 else if (VecWidth == 256 && !IsSaturating)
4646 IID = Intrinsic::x86_avx512_vpdpbusd_256;
4647 else if (VecWidth == 512 && !IsSaturating)
4648 IID = Intrinsic::x86_avx512_vpdpbusd_512;
4649 else if (VecWidth == 128 && IsSaturating)
4650 IID = Intrinsic::x86_avx512_vpdpbusds_128;
4651 else if (VecWidth == 256 && IsSaturating)
4652 IID = Intrinsic::x86_avx512_vpdpbusds_256;
4653 else if (VecWidth == 512 && IsSaturating)
4654 IID = Intrinsic::x86_avx512_vpdpbusds_512;
4655 else
4656 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4657
4658 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4659 CI->getArgOperand(2)};
4660
4661 // Input arguments types were incorrectly set to vectors of i32 before but
4662 // they should be vectors of i8. Insert bit cast when encountering the old
4663 // types
4664 if (Args[1]->getType()->isVectorTy() &&
4665 cast<VectorType>(Args[1]->getType())
4666 ->getElementType()
4667 ->isIntegerTy(32) &&
4668 Args[2]->getType()->isVectorTy() &&
4669 cast<VectorType>(Args[2]->getType())
4670 ->getElementType()
4671 ->isIntegerTy(32)) {
4672 Type *NewArgType = nullptr;
4673 if (VecWidth == 128)
4674 NewArgType = VectorType::get(Builder.getInt8Ty(), 16, false);
4675 else if (VecWidth == 256)
4676 NewArgType = VectorType::get(Builder.getInt8Ty(), 32, false);
4677 else if (VecWidth == 512)
4678 NewArgType = VectorType::get(Builder.getInt8Ty(), 64, false);
4679 else
4680 reportFatalUsageErrorWithCI("Intrinsic has unexpected vector bit width",
4681 CI);
4682
4683 Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
4684 Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
4685 }
4686
4687 Rep = Builder.CreateIntrinsic(IID, Args);
4688 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
4689 : CI->getArgOperand(0);
4690 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
4691 } else if (Name.starts_with("avx512.mask.vpdpwssd.") ||
4692 Name.starts_with("avx512.maskz.vpdpwssd.") ||
4693 Name.starts_with("avx512.mask.vpdpwssds.") ||
4694 Name.starts_with("avx512.maskz.vpdpwssds.")) {
4695 bool ZeroMask = Name[11] == 'z';
4696 bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
4697 unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
4698 Intrinsic::ID IID;
4699 if (VecWidth == 128 && !IsSaturating)
4700 IID = Intrinsic::x86_avx512_vpdpwssd_128;
4701 else if (VecWidth == 256 && !IsSaturating)
4702 IID = Intrinsic::x86_avx512_vpdpwssd_256;
4703 else if (VecWidth == 512 && !IsSaturating)
4704 IID = Intrinsic::x86_avx512_vpdpwssd_512;
4705 else if (VecWidth == 128 && IsSaturating)
4706 IID = Intrinsic::x86_avx512_vpdpwssds_128;
4707 else if (VecWidth == 256 && IsSaturating)
4708 IID = Intrinsic::x86_avx512_vpdpwssds_256;
4709 else if (VecWidth == 512 && IsSaturating)
4710 IID = Intrinsic::x86_avx512_vpdpwssds_512;
4711 else
4712 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4713
4714 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4715 CI->getArgOperand(2)};
4716
4717 // Input arguments types were incorrectly set to vectors of i32 before but
4718 // they should be vectors of i16. Insert bit cast when encountering the old
4719 // types
4720 if (Args[1]->getType()->isVectorTy() &&
4721 cast<VectorType>(Args[1]->getType())
4722 ->getElementType()
4723 ->isIntegerTy(32) &&
4724 Args[2]->getType()->isVectorTy() &&
4725 cast<VectorType>(Args[2]->getType())
4726 ->getElementType()
4727 ->isIntegerTy(32)) {
4728 Type *NewArgType = nullptr;
4729 if (VecWidth == 128)
4730 NewArgType = VectorType::get(Builder.getInt16Ty(), 8, false);
4731 else if (VecWidth == 256)
4732 NewArgType = VectorType::get(Builder.getInt16Ty(), 16, false);
4733 else if (VecWidth == 512)
4734 NewArgType = VectorType::get(Builder.getInt16Ty(), 32, false);
4735 else
4736 reportFatalUsageErrorWithCI("Intrinsic has unexpected vector bit width",
4737 CI);
4738
4739 Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
4740 Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
4741 }
4742
4743 Rep = Builder.CreateIntrinsic(IID, Args);
4744 Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
4745 : CI->getArgOperand(0);
4746 Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
4747 } else if (Name == "addcarryx.u32" || Name == "addcarryx.u64" ||
4748 Name == "addcarry.u32" || Name == "addcarry.u64" ||
4749 Name == "subborrow.u32" || Name == "subborrow.u64") {
4750 Intrinsic::ID IID;
4751 if (Name[0] == 'a' && Name.back() == '2')
4752 IID = Intrinsic::x86_addcarry_32;
4753 else if (Name[0] == 'a' && Name.back() == '4')
4754 IID = Intrinsic::x86_addcarry_64;
4755 else if (Name[0] == 's' && Name.back() == '2')
4756 IID = Intrinsic::x86_subborrow_32;
4757 else if (Name[0] == 's' && Name.back() == '4')
4758 IID = Intrinsic::x86_subborrow_64;
4759 else
4760 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4761
4762 // Make a call with 3 operands.
4763 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
4764 CI->getArgOperand(2)};
4765 Value *NewCall = Builder.CreateIntrinsic(IID, Args);
4766
4767 // Extract the second result and store it.
4768 Value *Data = Builder.CreateExtractValue(NewCall, 1);
4769 Builder.CreateAlignedStore(Data, CI->getArgOperand(3), Align(1));
4770 // Replace the original call result with the first result of the new call.
4771 Value *CF = Builder.CreateExtractValue(NewCall, 0);
4772
4773 CI->replaceAllUsesWith(CF);
4774 Rep = nullptr;
4775 } else if (Name.starts_with("avx512.mask.") &&
4776 upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
4777 // Rep will be updated by the call in the condition.
4778 } else if (Name.starts_with("bmi.pdep.")) {
4779 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::pdep);
4780 } else if (Name.starts_with("bmi.pext.")) {
4781 Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::pext);
4782 } else
4783 reportFatalUsageErrorWithCI("Unexpected intrinsic", CI);
4784
4785 return Rep;
4786}
4787
4789 Function *F, IRBuilder<> &Builder) {
4790 if (Name.starts_with("neon.bfcvt")) {
4791 if (Name.starts_with("neon.bfcvtn2")) {
4792 SmallVector<int, 32> LoMask(4);
4793 std::iota(LoMask.begin(), LoMask.end(), 0);
4794 SmallVector<int, 32> ConcatMask(8);
4795 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
4796 Value *Inactive = Builder.CreateShuffleVector(CI->getOperand(0), LoMask);
4797 Value *Trunc =
4798 Builder.CreateFPTrunc(CI->getOperand(1), Inactive->getType());
4799 return Builder.CreateShuffleVector(Inactive, Trunc, ConcatMask);
4800 } else if (Name.starts_with("neon.bfcvtn")) {
4801 SmallVector<int, 32> ConcatMask(8);
4802 std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
4803 Type *V4BF16 =
4804 FixedVectorType::get(Type::getBFloatTy(F->getContext()), 4);
4805 Value *Trunc = Builder.CreateFPTrunc(CI->getOperand(0), V4BF16);
4806 dbgs() << "Trunc: " << *Trunc << "\n";
4807 return Builder.CreateShuffleVector(
4808 Trunc, ConstantAggregateZero::get(V4BF16), ConcatMask);
4809 } else {
4810 return Builder.CreateFPTrunc(CI->getOperand(0),
4811 Type::getBFloatTy(F->getContext()));
4812 }
4813 } else if (Name.starts_with("sve.fcvt")) {
4814 Intrinsic::ID NewID =
4816 .Case("sve.fcvt.bf16f32", Intrinsic::aarch64_sve_fcvt_bf16f32_v2)
4817 .Case("sve.fcvtnt.bf16f32",
4818 Intrinsic::aarch64_sve_fcvtnt_bf16f32_v2)
4820 if (NewID == Intrinsic::not_intrinsic)
4821 llvm_unreachable("Unhandled Intrinsic!");
4822
4823 SmallVector<Value *, 3> Args(CI->args());
4824
4825 // The original intrinsics incorrectly used a predicate based on the
4826 // smallest element type rather than the largest.
4827 Type *BadPredTy = ScalableVectorType::get(Builder.getInt1Ty(), 8);
4828 Type *GoodPredTy = ScalableVectorType::get(Builder.getInt1Ty(), 4);
4829
4830 if (Args[1]->getType() != BadPredTy)
4831 llvm_unreachable("Unexpected predicate type!");
4832
4833 Args[1] = Builder.CreateIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool,
4834 BadPredTy, Args[1]);
4835 Args[1] = Builder.CreateIntrinsic(
4836 Intrinsic::aarch64_sve_convert_from_svbool, GoodPredTy, Args[1]);
4837
4838 return Builder.CreateIntrinsic(NewID, Args, /*FMFSource=*/nullptr,
4839 CI->getName());
4840 }
4841
4842 if (Name == "neon.vcvtfp2hf")
4843 return Builder.CreateBitCast(
4844 Builder.CreateFPTrunc(
4845 CI->getOperand(0),
4846 FixedVectorType::get(Type::getHalfTy(F->getContext()), 4)),
4847 FixedVectorType::get(Type::getInt16Ty(F->getContext()), 4));
4848 if (Name == "neon.vcvthf2fp")
4849 return Builder.CreateFPExt(
4850 Builder.CreateBitCast(
4851 CI->getOperand(0),
4852 FixedVectorType::get(Type::getHalfTy(F->getContext()), 4)),
4853 FixedVectorType::get(Type::getFloatTy(F->getContext()), 4));
4854
4855 llvm_unreachable("Unhandled Intrinsic!");
4856}
4857
4859 IRBuilder<> &Builder) {
4860 if (Name == "mve.vctp64.old") {
4861 // Replace the old v4i1 vctp64 with a v2i1 vctp and predicate-casts to the
4862 // correct type.
4863 Value *VCTP = Builder.CreateIntrinsic(Intrinsic::arm_mve_vctp64, {},
4864 CI->getArgOperand(0),
4865 /*FMFSource=*/nullptr, CI->getName());
4866 Value *C1 = Builder.CreateIntrinsic(
4867 Intrinsic::arm_mve_pred_v2i,
4868 {VectorType::get(Builder.getInt1Ty(), 2, false)}, VCTP);
4869 return Builder.CreateIntrinsic(
4870 Intrinsic::arm_mve_pred_i2v,
4871 {VectorType::get(Builder.getInt1Ty(), 4, false)}, C1);
4872 } else if (Name == "mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
4873 Name == "mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
4874 Name == "mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
4875 Name == "mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
4876 Name ==
4877 "mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
4878 Name == "mve.vldr.gather.offset.predicated.v2i64.p0.v2i64.v4i1" ||
4879 Name == "mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
4880 Name == "mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
4881 Name ==
4882 "mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
4883 Name == "mve.vstr.scatter.offset.predicated.p0.v2i64.v2i64.v4i1" ||
4884 Name == "cde.vcx1q.predicated.v2i64.v4i1" ||
4885 Name == "cde.vcx1qa.predicated.v2i64.v4i1" ||
4886 Name == "cde.vcx2q.predicated.v2i64.v4i1" ||
4887 Name == "cde.vcx2qa.predicated.v2i64.v4i1" ||
4888 Name == "cde.vcx3q.predicated.v2i64.v4i1" ||
4889 Name == "cde.vcx3qa.predicated.v2i64.v4i1") {
4890 std::vector<Type *> Tys;
4891 unsigned ID = CI->getIntrinsicID();
4892 Type *V2I1Ty = FixedVectorType::get(Builder.getInt1Ty(), 2);
4893 switch (ID) {
4894 case Intrinsic::arm_mve_mull_int_predicated:
4895 case Intrinsic::arm_mve_vqdmull_predicated:
4896 case Intrinsic::arm_mve_vldr_gather_base_predicated:
4897 Tys = {CI->getType(), CI->getOperand(0)->getType(), V2I1Ty};
4898 break;
4899 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated:
4900 case Intrinsic::arm_mve_vstr_scatter_base_predicated:
4901 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated:
4902 Tys = {CI->getOperand(0)->getType(), CI->getOperand(0)->getType(),
4903 V2I1Ty};
4904 break;
4905 case Intrinsic::arm_mve_vldr_gather_offset_predicated:
4906 Tys = {CI->getType(), CI->getOperand(0)->getType(),
4907 CI->getOperand(1)->getType(), V2I1Ty};
4908 break;
4909 case Intrinsic::arm_mve_vstr_scatter_offset_predicated:
4910 Tys = {CI->getOperand(0)->getType(), CI->getOperand(1)->getType(),
4911 CI->getOperand(2)->getType(), V2I1Ty};
4912 break;
4913 case Intrinsic::arm_cde_vcx1q_predicated:
4914 case Intrinsic::arm_cde_vcx1qa_predicated:
4915 case Intrinsic::arm_cde_vcx2q_predicated:
4916 case Intrinsic::arm_cde_vcx2qa_predicated:
4917 case Intrinsic::arm_cde_vcx3q_predicated:
4918 case Intrinsic::arm_cde_vcx3qa_predicated:
4919 Tys = {CI->getOperand(1)->getType(), V2I1Ty};
4920 break;
4921 default:
4922 llvm_unreachable("Unhandled Intrinsic!");
4923 }
4924
4925 std::vector<Value *> Ops;
4926 for (Value *Op : CI->args()) {
4927 Type *Ty = Op->getType();
4928 if (Ty->getScalarSizeInBits() == 1) {
4929 Value *C1 = Builder.CreateIntrinsic(
4930 Intrinsic::arm_mve_pred_v2i,
4931 {VectorType::get(Builder.getInt1Ty(), 4, false)}, Op);
4932 Op = Builder.CreateIntrinsic(Intrinsic::arm_mve_pred_i2v, {V2I1Ty}, C1);
4933 }
4934 Ops.push_back(Op);
4935 }
4936
4937 return Builder.CreateIntrinsic(ID, Tys, Ops, /*FMFSource=*/nullptr,
4938 CI->getName());
4939 }
4940 llvm_unreachable("Unknown function for ARM CallBase upgrade.");
4941}
4942
4943// These are expected to have the arguments:
4944// atomic.intrin (ptr, rmw_value, ordering, scope, isVolatile)
4945//
4946// Except for int_amdgcn_ds_fadd_v2bf16 which only has (ptr, rmw_value).
4947//
4949 Function *F, IRBuilder<> &Builder) {
4950 // Legacy WMMA iu intrinsics missed the optional clamp operand. Append clamp=0
4951 // for compatibility.
4952 auto UpgradeLegacyWMMAIUIntrinsicCall =
4953 [](Function *F, CallBase *CI, IRBuilder<> &Builder,
4954 ArrayRef<Type *> OverloadTys) -> Value * {
4955 // Prepare arguments, append clamp=0 for compatibility
4956 SmallVector<Value *, 10> Args(CI->args().begin(), CI->args().end());
4957 Args.push_back(Builder.getFalse());
4958
4959 // Insert the declaration for the right overload types
4961 F->getParent(), F->getIntrinsicID(), OverloadTys);
4962
4963 // Copy operand bundles if any
4965 CI->getOperandBundlesAsDefs(Bundles);
4966
4967 // Create the new call and copy calling properties
4968 auto *NewCall = cast<CallInst>(Builder.CreateCall(NewDecl, Args, Bundles));
4969 NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
4970 NewCall->setCallingConv(CI->getCallingConv());
4971 NewCall->setAttributes(CI->getAttributes());
4972 NewCall->setDebugLoc(CI->getDebugLoc());
4973 NewCall->copyMetadata(*CI);
4974 return NewCall;
4975 };
4976
4977 if (F->getIntrinsicID() == Intrinsic::amdgcn_wmma_i32_16x16x64_iu8) {
4978 assert(CI->arg_size() == 7 && "Legacy int_amdgcn_wmma_i32_16x16x64_iu8 "
4979 "intrinsic should have 7 arguments");
4980 Type *T1 = CI->getArgOperand(4)->getType();
4981 Type *T2 = CI->getArgOperand(1)->getType();
4982 return UpgradeLegacyWMMAIUIntrinsicCall(F, CI, Builder, {T1, T2});
4983 }
4984 if (F->getIntrinsicID() == Intrinsic::amdgcn_swmmac_i32_16x16x128_iu8) {
4985 assert(CI->arg_size() == 8 && "Legacy int_amdgcn_swmmac_i32_16x16x128_iu8 "
4986 "intrinsic should have 8 arguments");
4987 Type *T1 = CI->getArgOperand(4)->getType();
4988 Type *T2 = CI->getArgOperand(1)->getType();
4989 Type *T3 = CI->getArgOperand(3)->getType();
4990 Type *T4 = CI->getArgOperand(5)->getType();
4991 return UpgradeLegacyWMMAIUIntrinsicCall(F, CI, Builder, {T1, T2, T3, T4});
4992 }
4993
4994 switch (F->getIntrinsicID()) {
4995 default:
4996 break;
4997 case Intrinsic::amdgcn_wmma_f32_16x16x4_f32:
4998 case Intrinsic::amdgcn_wmma_f32_16x16x32_bf16:
4999 case Intrinsic::amdgcn_wmma_f32_16x16x32_f16:
5000 case Intrinsic::amdgcn_wmma_f16_16x16x32_f16:
5001 case Intrinsic::amdgcn_wmma_bf16_16x16x32_bf16:
5002 case Intrinsic::amdgcn_wmma_bf16f32_16x16x32_bf16: {
5003 // Drop src0 and src1 modifiers.
5004 const Value *Op0 = CI->getArgOperand(0);
5005 const Value *Op2 = CI->getArgOperand(2);
5006 assert(Op0->getType()->isIntegerTy() && Op2->getType()->isIntegerTy());
5007 const ConstantInt *ModA = dyn_cast<ConstantInt>(Op0);
5008 const ConstantInt *ModB = dyn_cast<ConstantInt>(Op2);
5009 if (!ModA->isZero() || !ModB->isZero())
5010 reportFatalUsageError(Name + " matrix A and B modifiers shall be zero");
5011
5013 for (int I = 4, E = CI->arg_size(); I < E; ++I)
5014 Args.push_back(CI->getArgOperand(I));
5015
5016 SmallVector<Type *, 3> Overloads{F->getReturnType(), Args[0]->getType()};
5017 if (F->getIntrinsicID() == Intrinsic::amdgcn_wmma_bf16f32_16x16x32_bf16)
5018 Overloads.push_back(Args[3]->getType());
5020 F->getParent(), F->getIntrinsicID(), Overloads);
5021
5023 CI->getOperandBundlesAsDefs(Bundles);
5024
5025 auto *NewCall = cast<CallInst>(Builder.CreateCall(NewDecl, Args, Bundles));
5026 NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
5027 NewCall->setCallingConv(CI->getCallingConv());
5028 NewCall->setAttributes(CI->getAttributes());
5029 NewCall->setDebugLoc(CI->getDebugLoc());
5030 NewCall->copyMetadata(*CI);
5031 NewCall->takeName(CI);
5032 return NewCall;
5033 }
5034 }
5035
5036 AtomicRMWInst::BinOp RMWOp =
5038 .StartsWith("ds.fadd", AtomicRMWInst::FAdd)
5039 .StartsWith("ds.fmin", AtomicRMWInst::FMin)
5040 .StartsWith("ds.fmax", AtomicRMWInst::FMax)
5041 .StartsWith("atomic.inc.", AtomicRMWInst::UIncWrap)
5042 .StartsWith("atomic.dec.", AtomicRMWInst::UDecWrap)
5043 .StartsWith("global.atomic.fadd", AtomicRMWInst::FAdd)
5044 .StartsWith("flat.atomic.fadd", AtomicRMWInst::FAdd)
5045 .StartsWith("global.atomic.fmin", AtomicRMWInst::FMin)
5046 .StartsWith("flat.atomic.fmin", AtomicRMWInst::FMin)
5047 .StartsWith("global.atomic.fmax", AtomicRMWInst::FMax)
5048 .StartsWith("flat.atomic.fmax", AtomicRMWInst::FMax)
5049 .StartsWith("atomic.cond.sub", AtomicRMWInst::USubCond)
5050 .StartsWith("atomic.csub", AtomicRMWInst::USubSat);
5051
5052 unsigned NumOperands = CI->getNumOperands();
5053 if (NumOperands < 3) // Malformed bitcode.
5054 return nullptr;
5055
5056 Value *Ptr = CI->getArgOperand(0);
5057 PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType());
5058 if (!PtrTy) // Malformed.
5059 return nullptr;
5060
5061 Value *Val = CI->getArgOperand(1);
5062 if (Val->getType() != CI->getType()) // Malformed.
5063 return nullptr;
5064
5065 ConstantInt *OrderArg = nullptr;
5066 bool IsVolatile = false;
5067
5068 // These should have 5 arguments (plus the callee). A separate version of the
5069 // ds_fadd intrinsic was defined for bf16 which was missing arguments.
5070 if (NumOperands > 3)
5071 OrderArg = dyn_cast<ConstantInt>(CI->getArgOperand(2));
5072
5073 // Ignore scope argument at 3
5074
5075 if (NumOperands > 5) {
5076 ConstantInt *VolatileArg = dyn_cast<ConstantInt>(CI->getArgOperand(4));
5077 IsVolatile = !VolatileArg || !VolatileArg->isZero();
5078 }
5079
5081 if (OrderArg && isValidAtomicOrdering(OrderArg->getZExtValue()))
5082 Order = static_cast<AtomicOrdering>(OrderArg->getZExtValue());
5085
5086 LLVMContext &Ctx = F->getContext();
5087
5088 // Handle the v2bf16 intrinsic which used <2 x i16> instead of <2 x bfloat>
5089 Type *RetTy = CI->getType();
5090 if (VectorType *VT = dyn_cast<VectorType>(RetTy)) {
5091 if (VT->getElementType()->isIntegerTy(16)) {
5092 VectorType *AsBF16 =
5093 VectorType::get(Type::getBFloatTy(Ctx), VT->getElementCount());
5094 Val = Builder.CreateBitCast(Val, AsBF16);
5095 }
5096 }
5097
5098 // The scope argument never really worked correctly. Use agent as the most
5099 // conservative option which should still always produce the instruction.
5100 SyncScope::ID SSID = Ctx.getOrInsertSyncScopeID("agent");
5101 AtomicRMWInst *RMW =
5102 Builder.CreateAtomicRMW(RMWOp, Ptr, Val, std::nullopt, Order, SSID);
5103
5104 unsigned AddrSpace = PtrTy->getAddressSpace();
5105 if (AddrSpace != AMDGPUAS::LOCAL_ADDRESS) {
5106 MDNode *EmptyMD = MDNode::get(F->getContext(), {});
5107 RMW->setMetadata("amdgpu.no.fine.grained.memory", EmptyMD);
5108 if (RMWOp == AtomicRMWInst::FAdd && RetTy->isFloatTy())
5109 RMW->setMetadata("amdgpu.ignore.denormal.mode", EmptyMD);
5110 }
5111
5112 if (AddrSpace == AMDGPUAS::FLAT_ADDRESS) {
5113 MDBuilder MDB(F->getContext());
5114 MDNode *RangeNotPrivate =
5117 RMW->setMetadata(LLVMContext::MD_noalias_addrspace, RangeNotPrivate);
5118 }
5119
5120 if (IsVolatile)
5121 RMW->setVolatile(true);
5122
5123 return Builder.CreateBitCast(RMW, RetTy);
5124}
5125
5126/// Helper to unwrap intrinsic call MetadataAsValue operands. Return as a
5127/// plain MDNode, as it's the verifier's job to check these are the correct
5128/// types later.
5129static MDNode *unwrapMAVOp(CallBase *CI, unsigned Op) {
5130 if (Op < CI->arg_size()) {
5131 if (MetadataAsValue *MAV =
5133 Metadata *MD = MAV->getMetadata();
5134 return dyn_cast_if_present<MDNode>(MD);
5135 }
5136 }
5137 return nullptr;
5138}
5139
5140/// Helper to unwrap Metadata MetadataAsValue operands, such as the Value field.
5141static Metadata *unwrapMAVMetadataOp(CallBase *CI, unsigned Op) {
5142 if (Op < CI->arg_size())
5144 return MAV->getMetadata();
5145 return nullptr;
5146}
5147
5148/// Convert debug intrinsic calls to non-instruction debug records.
5149/// \p Name - Final part of the intrinsic name, e.g. 'value' in llvm.dbg.value.
5150/// \p CI - The debug intrinsic call.
5152 DbgRecord *DR = nullptr;
5153 if (Name == "label") {
5155 } else if (Name == "assign") {
5158 unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2), unwrapMAVOp(CI, 3),
5159 unwrapMAVMetadataOp(CI, 4),
5160 /*The address is a Value ref, it will be stored as a Metadata */
5161 unwrapMAVOp(CI, 5));
5162 } else if (Name == "declare") {
5165 unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2), nullptr, nullptr, nullptr);
5166 } else if (Name == "addr") {
5167 // Upgrade dbg.addr to dbg.value with DW_OP_deref.
5168 MDNode *ExprNode = unwrapMAVOp(CI, 2);
5169 // Don't try to add something to the expression if it's not an expression.
5170 // Instead, allow the verifier to fail later.
5171 if (DIExpression *Expr = dyn_cast<DIExpression>(ExprNode)) {
5172 ExprNode = DIExpression::append(Expr, dwarf::DW_OP_deref);
5173 }
5176 unwrapMAVOp(CI, 1), ExprNode, nullptr, nullptr, nullptr);
5177 } else if (Name == "value") {
5178 // An old version of dbg.value had an extra offset argument.
5179 unsigned VarOp = 1;
5180 unsigned ExprOp = 2;
5181 if (CI->arg_size() == 4) {
5183 // Nonzero offset dbg.values get dropped without a replacement.
5184 if (!Offset || !Offset->isNullValue())
5185 return;
5186 VarOp = 2;
5187 ExprOp = 3;
5188 }
5191 unwrapMAVOp(CI, VarOp), unwrapMAVOp(CI, ExprOp), nullptr, nullptr,
5192 nullptr);
5193 }
5194 DR->setDebugLoc(CI->getDebugLoc());
5195 assert(DR && "Unhandled intrinsic kind in upgrade to DbgRecord");
5196 CI->getParent()->insertDbgRecordBefore(DR, CI->getIterator());
5197}
5198
5201 if (!Offset)
5202 reportFatalUsageError("Invalid llvm.vector.splice offset argument");
5203 int64_t OffsetVal = Offset->getSExtValue();
5204 return Builder.CreateIntrinsic(OffsetVal >= 0
5205 ? Intrinsic::vector_splice_left
5206 : Intrinsic::vector_splice_right,
5207 CI->getType(),
5208 {CI->getArgOperand(0), CI->getArgOperand(1),
5209 Builder.getInt32(std::abs(OffsetVal))});
5210}
5211
5213 Function *F, IRBuilder<> &Builder) {
5214 if (Name.starts_with("to.fp16")) {
5215 Value *Cast =
5216 Builder.CreateFPTrunc(CI->getArgOperand(0), Builder.getHalfTy());
5217 return Builder.CreateBitCast(Cast, CI->getType());
5218 }
5219
5220 if (Name.starts_with("from.fp16")) {
5221 Value *Cast =
5222 Builder.CreateBitCast(CI->getArgOperand(0), Builder.getHalfTy());
5223 return Builder.CreateFPExt(Cast, CI->getType());
5224 }
5225
5226 return nullptr;
5227}
5228
5230 IRBuilder<> &Builder) {
5231 Intrinsic::ID IID = NewFn->getIntrinsicID();
5232
5233 auto [FirstDefault, Defaults] = Intrinsic::getAllDefaultArgValues(IID);
5234 if (Defaults.empty())
5235 return false;
5236
5237 unsigned OldArgCount = CI->arg_size();
5238 unsigned NewArgCount = NewFn->arg_size();
5239
5240 // If the caller already supplied all arguments (or more), nothing to do.
5241 // This mirrors C++ semantics: an explicitly-passed value is never overridden.
5242 if (OldArgCount >= NewArgCount)
5243 return false;
5244
5245 // Start with the existing arguments from the old call.
5246 SmallVector<Value *, 8> NewArgs(CI->args());
5247
5248 // Defaults are a contiguous trailing block, so checking the first missing
5249 // argument is enough.
5250 if (OldArgCount < FirstDefault)
5251 return false;
5252
5253 // Fill in each missing trailing argument from the table.
5254 FunctionType *NewFT = NewFn->getFunctionType();
5255 for (unsigned Idx = OldArgCount; Idx < NewArgCount; ++Idx) {
5256 assert(Idx >= FirstDefault && Idx - FirstDefault < Defaults.size() &&
5257 "missing argument outside the default range");
5258 Type *ParamTy = NewFT->getParamType(Idx);
5259
5260 // Only integer types are supported (i1, i8, i16, i32, i64).
5261 if (!ParamTy->isIntegerTy())
5262 return false;
5263 NewArgs.push_back(ConstantInt::get(ParamTy, Defaults[Idx - FirstDefault]));
5264 }
5265
5266 // Preserve operand bundles by creating the call with them.
5268 CI->getOperandBundlesAsDefs(OpBundles);
5269 CallInst *NewCall = Builder.CreateCall(NewFn, NewArgs, OpBundles);
5270
5271 NewCall->takeName(CI);
5272 NewCall->setCallingConv(CI->getCallingConv());
5273 NewCall->copyMetadata(*CI);
5274 if (auto *OldCI = dyn_cast<CallInst>(CI))
5275 NewCall->setTailCallKind(OldCI->getTailCallKind());
5276
5277 CI->replaceAllUsesWith(NewCall);
5278 CI->eraseFromParent();
5279 return true;
5280}
5281
5282/// Upgrade a call to an old intrinsic. All argument and return casting must be
5283/// provided to seamlessly integrate with existing context.
5285 // Note dyn_cast to Function is not quite the same as getCalledFunction, which
5286 // checks the callee's function type matches. It's likely we need to handle
5287 // type changes here.
5289 if (!F)
5290 return;
5291
5292 LLVMContext &C = CI->getContext();
5293 IRBuilder<> Builder(C);
5294 if (isa<FPMathOperator>(CI))
5295 Builder.setFastMathFlags(CI->getFastMathFlags());
5296 Builder.SetInsertPoint(CI->getParent(), CI->getIterator());
5297
5298 if (!NewFn) {
5299 // Get the Function's name.
5300 StringRef Name = F->getName();
5301 if (!Name.consume_front("llvm."))
5302 llvm_unreachable("intrinsic doesn't start with 'llvm.'");
5303
5304 bool IsX86 = Name.consume_front("x86.");
5305 bool IsNVVM = Name.consume_front("nvvm.");
5306 bool IsAArch64 = Name.consume_front("aarch64.");
5307 bool IsARM = Name.consume_front("arm.");
5308 bool IsAMDGCN = Name.consume_front("amdgcn.");
5309 bool IsDbg = Name.consume_front("dbg.");
5310 bool IsOldSplice =
5311 (Name.consume_front("experimental.vector.splice") ||
5312 Name.consume_front("vector.splice")) &&
5313 !(Name.starts_with(".left") || Name.starts_with(".right"));
5314 Value *Rep = nullptr;
5315
5316 if (!IsX86 && Name == "stackprotectorcheck") {
5317 Rep = nullptr;
5318 } else if (IsNVVM) {
5319 Rep = upgradeNVVMIntrinsicCall(Name, CI, F, Builder);
5320 } else if (IsX86) {
5321 Rep = upgradeX86IntrinsicCall(Name, CI, F, Builder);
5322 } else if (IsAArch64) {
5323 Rep = upgradeAArch64IntrinsicCall(Name, CI, F, Builder);
5324 } else if (IsARM) {
5325 Rep = upgradeARMIntrinsicCall(Name, CI, F, Builder);
5326 } else if (IsAMDGCN) {
5327 Rep = upgradeAMDGCNIntrinsicCall(Name, CI, F, Builder);
5328 } else if (IsDbg) {
5330 } else if (IsOldSplice) {
5331 Rep = upgradeVectorSplice(CI, Builder);
5332 } else if (Name.consume_front("convert.")) {
5333 Rep = upgradeConvertIntrinsicCall(Name, CI, F, Builder);
5334 } else if (Name == "lifetime.start.i64" || Name == "lifetime.end.i64") {
5335 // Delete calls to invalid @llvm.lifetime.{start,end}.i64 intrinsics.
5336 Rep = nullptr;
5337 } else {
5338 llvm_unreachable("Unknown function for CallBase upgrade.");
5339 }
5340
5341 if (Rep)
5342 CI->replaceAllUsesWith(Rep);
5343 CI->eraseFromParent();
5344 return;
5345 }
5346
5347 const auto &DefaultCase = [&]() -> void {
5348 if (F == NewFn)
5349 return;
5350
5351 if (CI->getFunctionType() == NewFn->getFunctionType()) {
5352 // Handle generic mangling change.
5353 assert(
5354 (CI->getCalledFunction()->getName() != NewFn->getName()) &&
5355 "Unknown function for CallBase upgrade and isn't just a name change");
5356 CI->setCalledFunction(NewFn);
5357 return;
5358 }
5359
5360 // This must be an upgrade from a named to a literal struct.
5361 if (auto *OldST = dyn_cast<StructType>(CI->getType())) {
5362 assert(OldST != NewFn->getReturnType() &&
5363 "Return type must have changed");
5364 assert(OldST->getNumElements() ==
5365 cast<StructType>(NewFn->getReturnType())->getNumElements() &&
5366 "Must have same number of elements");
5367
5368 SmallVector<Value *> Args(CI->args());
5369 CallInst *NewCI = Builder.CreateCall(NewFn, Args);
5370 NewCI->setAttributes(CI->getAttributes());
5371 Value *Res = PoisonValue::get(OldST);
5372 for (unsigned Idx = 0; Idx < OldST->getNumElements(); ++Idx) {
5373 Value *Elem = Builder.CreateExtractValue(NewCI, Idx);
5374 Res = Builder.CreateInsertValue(Res, Elem, Idx);
5375 }
5376 CI->replaceAllUsesWith(Res);
5377 CI->eraseFromParent();
5378 return;
5379 }
5380
5381 // We're probably about to produce something invalid. Let the verifier catch
5382 // it instead of dying here.
5383 CI->setCalledOperand(
5385 return;
5386 };
5387 CallInst *NewCall = nullptr;
5388 switch (NewFn->getIntrinsicID()) {
5389 default: {
5390 // Last resort: try the data-driven default-arg upgrade.
5391 // Handles any intrinsic annotated with ImmArg<..., DefaultValue<...>>
5392 // in its .td definition, without needing a dedicated case.
5393 if (upgradeIntrinsicCallWithDefaultArgs(CI, NewFn, Builder))
5394 return;
5395 DefaultCase();
5396 return;
5397 }
5398 case Intrinsic::arm_neon_vst1:
5399 case Intrinsic::arm_neon_vst2:
5400 case Intrinsic::arm_neon_vst3:
5401 case Intrinsic::arm_neon_vst4:
5402 case Intrinsic::arm_neon_vst2lane:
5403 case Intrinsic::arm_neon_vst3lane:
5404 case Intrinsic::arm_neon_vst4lane: {
5405 SmallVector<Value *, 4> Args(CI->args());
5406 NewCall = Builder.CreateCall(NewFn, Args);
5407 break;
5408 }
5409 case Intrinsic::aarch64_sve_bfmlalb_lane_v2:
5410 case Intrinsic::aarch64_sve_bfmlalt_lane_v2:
5411 case Intrinsic::aarch64_sve_bfdot_lane_v2: {
5412 LLVMContext &Ctx = F->getParent()->getContext();
5413 SmallVector<Value *, 4> Args(CI->args());
5414 Args[3] = ConstantInt::get(Type::getInt32Ty(Ctx),
5415 cast<ConstantInt>(Args[3])->getZExtValue());
5416 NewCall = Builder.CreateCall(NewFn, Args);
5417 break;
5418 }
5419 case Intrinsic::aarch64_sve_ld3_sret:
5420 case Intrinsic::aarch64_sve_ld4_sret:
5421 case Intrinsic::aarch64_sve_ld2_sret: {
5422 // Is this a trivial remangle of the name to support ptr address spaces?
5423 if (isa<StructType>(F->getReturnType())) {
5424 DefaultCase();
5425 return;
5426 }
5427
5428 StringRef Name = F->getName();
5429 Name = Name.substr(5);
5430 unsigned N = StringSwitch<unsigned>(Name)
5431 .StartsWith("aarch64.sve.ld2", 2)
5432 .StartsWith("aarch64.sve.ld3", 3)
5433 .StartsWith("aarch64.sve.ld4", 4)
5434 .Default(0);
5435 auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
5436 unsigned MinElts = RetTy->getMinNumElements() / N;
5437 SmallVector<Value *, 2> Args(CI->args());
5438 Value *NewLdCall = Builder.CreateCall(NewFn, Args);
5439 Value *Ret = llvm::PoisonValue::get(RetTy);
5440 for (unsigned I = 0; I < N; I++) {
5441 Value *SRet = Builder.CreateExtractValue(NewLdCall, I);
5442 Ret = Builder.CreateInsertVector(RetTy, Ret, SRet, I * MinElts);
5443 }
5444 NewCall = dyn_cast<CallInst>(Ret);
5445 break;
5446 }
5447
5448 case Intrinsic::coro_end_async:
5449 case Intrinsic::coro_end: {
5450 SmallVector<Value *, 3> Args(CI->args());
5451 if (NewFn->getIntrinsicID() == Intrinsic::coro_end && Args.size() == 2)
5452 Args.push_back(ConstantTokenNone::get(CI->getContext()));
5453 NewCall = Builder.CreateCall(NewFn, Args);
5454
5455 if (!CI->getType()->isVoidTy()) {
5456 if (!CI->use_empty()) {
5458 CI->getModule(), Intrinsic::coro_is_in_ramp);
5459 Value *InRamp = Builder.CreateCall(IsInRamp);
5460 CI->replaceAllUsesWith(Builder.CreateNot(InRamp));
5461 }
5462 CI->eraseFromParent();
5463 return;
5464 }
5465
5466 break;
5467 }
5468
5469 case Intrinsic::vector_extract: {
5470 StringRef Name = F->getName();
5471 Name = Name.substr(5); // Strip llvm
5472 if (!Name.starts_with("aarch64.sve.tuple.get")) {
5473 DefaultCase();
5474 return;
5475 }
5476 auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
5477 unsigned MinElts = RetTy->getMinNumElements();
5478 unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
5479 Value *NewIdx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
5480 NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0), NewIdx});
5481 break;
5482 }
5483
5484 case Intrinsic::vector_insert: {
5485 StringRef Name = F->getName();
5486 Name = Name.substr(5);
5487 if (!Name.starts_with("aarch64.sve.tuple")) {
5488 DefaultCase();
5489 return;
5490 }
5491 if (Name.starts_with("aarch64.sve.tuple.set")) {
5492 unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
5493 auto *Ty = cast<ScalableVectorType>(CI->getArgOperand(2)->getType());
5494 Value *NewIdx =
5495 ConstantInt::get(Type::getInt64Ty(C), I * Ty->getMinNumElements());
5496 NewCall = Builder.CreateCall(
5497 NewFn, {CI->getArgOperand(0), CI->getArgOperand(2), NewIdx});
5498 break;
5499 }
5500 if (Name.starts_with("aarch64.sve.tuple.create")) {
5501 unsigned N = StringSwitch<unsigned>(Name)
5502 .StartsWith("aarch64.sve.tuple.create2", 2)
5503 .StartsWith("aarch64.sve.tuple.create3", 3)
5504 .StartsWith("aarch64.sve.tuple.create4", 4)
5505 .Default(0);
5506 assert(N > 1 && "Create is expected to be between 2-4");
5507 auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
5508 Value *Ret = llvm::PoisonValue::get(RetTy);
5509 unsigned MinElts = RetTy->getMinNumElements() / N;
5510 for (unsigned I = 0; I < N; I++) {
5511 Value *V = CI->getArgOperand(I);
5512 Ret = Builder.CreateInsertVector(RetTy, Ret, V, I * MinElts);
5513 }
5514 NewCall = dyn_cast<CallInst>(Ret);
5515 }
5516 break;
5517 }
5518
5519 case Intrinsic::arm_neon_bfdot:
5520 case Intrinsic::arm_neon_bfmmla:
5521 case Intrinsic::arm_neon_bfmlalb:
5522 case Intrinsic::arm_neon_bfmlalt:
5523 case Intrinsic::aarch64_neon_bfdot:
5524 case Intrinsic::aarch64_neon_bfmmla:
5525 case Intrinsic::aarch64_neon_bfmlalb:
5526 case Intrinsic::aarch64_neon_bfmlalt: {
5528 assert(CI->arg_size() == 3 &&
5529 "Mismatch between function args and call args");
5530 size_t OperandWidth =
5532 assert((OperandWidth == 64 || OperandWidth == 128) &&
5533 "Unexpected operand width");
5534 Type *NewTy = FixedVectorType::get(Type::getBFloatTy(C), OperandWidth / 16);
5535 auto Iter = CI->args().begin();
5536 Args.push_back(*Iter++);
5537 Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
5538 Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
5539 NewCall = Builder.CreateCall(NewFn, Args);
5540 break;
5541 }
5542
5543 case Intrinsic::bitreverse:
5544 NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
5545 break;
5546
5547 case Intrinsic::ctlz:
5548 case Intrinsic::cttz: {
5549 if (CI->arg_size() != 1) {
5550 DefaultCase();
5551 return;
5552 }
5553
5554 NewCall =
5555 Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()});
5556 break;
5557 }
5558
5559 case Intrinsic::objectsize: {
5560 Value *NullIsUnknownSize =
5561 CI->arg_size() == 2 ? Builder.getFalse() : CI->getArgOperand(2);
5562 Value *Dynamic =
5563 CI->arg_size() < 4 ? Builder.getFalse() : CI->getArgOperand(3);
5564 NewCall = Builder.CreateCall(
5565 NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic});
5566 break;
5567 }
5568
5569 case Intrinsic::ctpop:
5570 NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
5571 break;
5572 case Intrinsic::dbg_value: {
5573 StringRef Name = F->getName();
5574 Name = Name.substr(5); // Strip llvm.
5575 // Upgrade `dbg.addr` to `dbg.value` with `DW_OP_deref`.
5576 if (Name.starts_with("dbg.addr")) {
5578 cast<MetadataAsValue>(CI->getArgOperand(2))->getMetadata());
5579 Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
5580 NewCall =
5581 Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
5582 MetadataAsValue::get(C, Expr)});
5583 break;
5584 }
5585
5586 // Upgrade from the old version that had an extra offset argument.
5587 assert(CI->arg_size() == 4);
5588 // Drop nonzero offsets instead of attempting to upgrade them.
5590 if (Offset->isNullValue()) {
5591 NewCall = Builder.CreateCall(
5592 NewFn,
5593 {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
5594 break;
5595 }
5596 CI->eraseFromParent();
5597 return;
5598 }
5599
5600 case Intrinsic::ptr_annotation:
5601 // Upgrade from versions that lacked the annotation attribute argument.
5602 if (CI->arg_size() != 4) {
5603 DefaultCase();
5604 return;
5605 }
5606
5607 // Create a new call with an added null annotation attribute argument.
5608 NewCall = Builder.CreateCall(
5609 NewFn,
5610 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
5611 CI->getArgOperand(3), ConstantPointerNull::get(Builder.getPtrTy())});
5612 NewCall->takeName(CI);
5613 CI->replaceAllUsesWith(NewCall);
5614 CI->eraseFromParent();
5615 return;
5616
5617 case Intrinsic::var_annotation:
5618 // Upgrade from versions that lacked the annotation attribute argument.
5619 if (CI->arg_size() != 4) {
5620 DefaultCase();
5621 return;
5622 }
5623 // Create a new call with an added null annotation attribute argument.
5624 NewCall = Builder.CreateCall(
5625 NewFn,
5626 {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
5627 CI->getArgOperand(3), ConstantPointerNull::get(Builder.getPtrTy())});
5628 NewCall->takeName(CI);
5629 CI->replaceAllUsesWith(NewCall);
5630 CI->eraseFromParent();
5631 return;
5632
5633 case Intrinsic::riscv_aes32dsi:
5634 case Intrinsic::riscv_aes32dsmi:
5635 case Intrinsic::riscv_aes32esi:
5636 case Intrinsic::riscv_aes32esmi:
5637 case Intrinsic::riscv_sm4ks:
5638 case Intrinsic::riscv_sm4ed: {
5639 // The last argument to these intrinsics used to be i8 and changed to i32.
5640 // The type overload for sm4ks and sm4ed was removed.
5641 Value *Arg2 = CI->getArgOperand(2);
5642 if (Arg2->getType()->isIntegerTy(32) && !CI->getType()->isIntegerTy(64))
5643 return;
5644
5645 Value *Arg0 = CI->getArgOperand(0);
5646 Value *Arg1 = CI->getArgOperand(1);
5647 if (CI->getType()->isIntegerTy(64)) {
5648 Arg0 = Builder.CreateTrunc(Arg0, Builder.getInt32Ty());
5649 Arg1 = Builder.CreateTrunc(Arg1, Builder.getInt32Ty());
5650 }
5651
5652 Arg2 = ConstantInt::get(Type::getInt32Ty(C),
5653 cast<ConstantInt>(Arg2)->getZExtValue());
5654
5655 NewCall = Builder.CreateCall(NewFn, {Arg0, Arg1, Arg2});
5656 Value *Res = NewCall;
5657 if (Res->getType() != CI->getType())
5658 Res = Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
5659 NewCall->takeName(CI);
5660 CI->replaceAllUsesWith(Res);
5661 CI->eraseFromParent();
5662 return;
5663 }
5664 case Intrinsic::nvvm_mapa_shared_cluster: {
5665 // Create a new call with the correct address space.
5666 NewCall =
5667 Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1)});
5668 Value *Res = NewCall;
5669 Res = Builder.CreateAddrSpaceCast(
5670 Res, Builder.getPtrTy(NVPTXAS::ADDRESS_SPACE_SHARED));
5671 NewCall->takeName(CI);
5672 CI->replaceAllUsesWith(Res);
5673 CI->eraseFromParent();
5674 return;
5675 }
5676 case Intrinsic::nvvm_cp_async_bulk_global_to_shared_cluster:
5677 case Intrinsic::nvvm_cp_async_bulk_shared_cta_to_cluster: {
5678 // Create a new call with the correct address space.
5679 SmallVector<Value *, 4> Args(CI->args());
5680 Args[0] = Builder.CreateAddrSpaceCast(
5681 Args[0], Builder.getPtrTy(NVPTXAS::ADDRESS_SPACE_SHARED_CLUSTER));
5682
5683 NewCall = Builder.CreateCall(NewFn, Args);
5684 NewCall->takeName(CI);
5685 CI->replaceAllUsesWith(NewCall);
5686 CI->eraseFromParent();
5687 return;
5688 }
5689 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_3d:
5690 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_4d:
5691 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_im2col_5d:
5692 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_1d:
5693 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_2d:
5694 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_3d:
5695 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_4d:
5696 case Intrinsic::nvvm_cp_async_bulk_tensor_g2s_tile_5d: {
5697 SmallVector<Value *, 16> Args(CI->args());
5698
5699 // Create AddrSpaceCast to shared_cluster if needed.
5700 // This handles case (1) in shouldUpgradeNVPTXTMAG2SIntrinsics().
5701 unsigned AS = CI->getArgOperand(0)->getType()->getPointerAddressSpace();
5703 Args[0] = Builder.CreateAddrSpaceCast(
5704 Args[0], Builder.getPtrTy(NVPTXAS::ADDRESS_SPACE_SHARED_CLUSTER));
5705
5706 // Attach the flag argument for cta_group, with a
5707 // default value of 0. This handles case (2) in
5708 // shouldUpgradeNVPTXTMAG2SIntrinsics().
5709 size_t NumArgs = CI->arg_size();
5710 Value *FlagArg = CI->getArgOperand(NumArgs - 3);
5711 if (!FlagArg->getType()->isIntegerTy(1))
5712 Args.push_back(ConstantInt::get(Builder.getInt32Ty(), 0));
5713
5714 NewCall = Builder.CreateCall(NewFn, Args);
5715 NewCall->takeName(CI);
5716 CI->replaceAllUsesWith(NewCall);
5717 CI->eraseFromParent();
5718 return;
5719 }
5720 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_1d:
5721 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_2d:
5722 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_3d:
5723 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_4d:
5724 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_tile_5d:
5725 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_3d:
5726 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_4d:
5727 case Intrinsic::nvvm_cp_async_bulk_tensor_reduce_im2col_5d: {
5728 StringRef Name = F->getName();
5729 Name.consume_front("llvm.nvvm.cp.async.bulk.tensor.reduce.");
5730 auto RedOp = getNVPTXTMAReductionOp(Name.split('.').first);
5731
5732 SmallVector<Value *, 16> Args(CI->args());
5733 Args.insert(Args.end() - 1, Builder.getInt32(*RedOp));
5734 NewCall = Builder.CreateCall(NewFn, Args);
5735 break;
5736 }
5737 case Intrinsic::nvvm_tcgen05_mma_shared:
5738 case Intrinsic::nvvm_tcgen05_mma_shared_disable_output_lane_cg1:
5739 case Intrinsic::nvvm_tcgen05_mma_shared_disable_output_lane_cg2:
5740 case Intrinsic::nvvm_tcgen05_mma_shared_mxf4_block_scale:
5741 case Intrinsic::nvvm_tcgen05_mma_shared_mxf4_block_scale_block32:
5742 case Intrinsic::nvvm_tcgen05_mma_shared_mxf4nvf4_block_scale_block16:
5743 case Intrinsic::nvvm_tcgen05_mma_shared_mxf4nvf4_block_scale_block32:
5744 case Intrinsic::nvvm_tcgen05_mma_shared_mxf8f6f4_block_scale:
5745 case Intrinsic::nvvm_tcgen05_mma_shared_mxf8f6f4_block_scale_block32:
5746 case Intrinsic::nvvm_tcgen05_mma_shared_scale_d:
5747 case Intrinsic::nvvm_tcgen05_mma_shared_scale_d_disable_output_lane_cg1:
5748 case Intrinsic::nvvm_tcgen05_mma_shared_scale_d_disable_output_lane_cg2:
5749 case Intrinsic::nvvm_tcgen05_mma_sp_shared:
5750 case Intrinsic::nvvm_tcgen05_mma_sp_shared_disable_output_lane_cg1:
5751 case Intrinsic::nvvm_tcgen05_mma_sp_shared_disable_output_lane_cg2:
5752 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf4_block_scale:
5753 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf4_block_scale_block32:
5754 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf4nvf4_block_scale_block16:
5755 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf4nvf4_block_scale_block32:
5756 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf8f6f4_block_scale:
5757 case Intrinsic::nvvm_tcgen05_mma_sp_shared_mxf8f6f4_block_scale_block32:
5758 case Intrinsic::nvvm_tcgen05_mma_sp_shared_scale_d:
5759 case Intrinsic::nvvm_tcgen05_mma_sp_shared_scale_d_disable_output_lane_cg1:
5760 case Intrinsic::nvvm_tcgen05_mma_sp_shared_scale_d_disable_output_lane_cg2:
5761 case Intrinsic::nvvm_tcgen05_mma_sp_tensor:
5762 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_ashift:
5763 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_disable_output_lane_cg1:
5764 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_disable_output_lane_cg1_ashift:
5765 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_disable_output_lane_cg2:
5766 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_disable_output_lane_cg2_ashift:
5767 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf4_block_scale:
5768 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf4_block_scale_block32:
5769 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf4nvf4_block_scale_block16:
5770 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf4nvf4_block_scale_block32:
5771 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf8f6f4_block_scale:
5772 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_mxf8f6f4_block_scale_block32:
5773 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_scale_d:
5774 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_scale_d_ashift:
5775 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_scale_d_disable_output_lane_cg1:
5776 case Intrinsic::
5777 nvvm_tcgen05_mma_sp_tensor_scale_d_disable_output_lane_cg1_ashift:
5778 case Intrinsic::nvvm_tcgen05_mma_sp_tensor_scale_d_disable_output_lane_cg2:
5779 case Intrinsic::
5780 nvvm_tcgen05_mma_sp_tensor_scale_d_disable_output_lane_cg2_ashift:
5781 case Intrinsic::nvvm_tcgen05_mma_tensor:
5782 case Intrinsic::nvvm_tcgen05_mma_tensor_ashift:
5783 case Intrinsic::nvvm_tcgen05_mma_tensor_disable_output_lane_cg1:
5784 case Intrinsic::nvvm_tcgen05_mma_tensor_disable_output_lane_cg1_ashift:
5785 case Intrinsic::nvvm_tcgen05_mma_tensor_disable_output_lane_cg2:
5786 case Intrinsic::nvvm_tcgen05_mma_tensor_disable_output_lane_cg2_ashift:
5787 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf4_block_scale:
5788 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf4_block_scale_block32:
5789 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf4nvf4_block_scale_block16:
5790 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf4nvf4_block_scale_block32:
5791 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf8f6f4_block_scale:
5792 case Intrinsic::nvvm_tcgen05_mma_tensor_mxf8f6f4_block_scale_block32:
5793 case Intrinsic::nvvm_tcgen05_mma_tensor_scale_d:
5794 case Intrinsic::nvvm_tcgen05_mma_tensor_scale_d_ashift:
5795 case Intrinsic::nvvm_tcgen05_mma_tensor_scale_d_disable_output_lane_cg1:
5796 case Intrinsic::
5797 nvvm_tcgen05_mma_tensor_scale_d_disable_output_lane_cg1_ashift:
5798 case Intrinsic::nvvm_tcgen05_mma_tensor_scale_d_disable_output_lane_cg2:
5799 case Intrinsic::
5800 nvvm_tcgen05_mma_tensor_scale_d_disable_output_lane_cg2_ashift: {
5801 SmallVector<Value *, 12> Args(CI->args());
5802 Args.push_back(Builder.getInt32(0)); // collector_usage_b = discard(0)
5803 NewCall = Builder.CreateCall(NewFn, Args);
5804 break;
5805 }
5806 case Intrinsic::riscv_sha256sig0:
5807 case Intrinsic::riscv_sha256sig1:
5808 case Intrinsic::riscv_sha256sum0:
5809 case Intrinsic::riscv_sha256sum1:
5810 case Intrinsic::riscv_sm3p0:
5811 case Intrinsic::riscv_sm3p1: {
5812 // The last argument to these intrinsics used to be i8 and changed to i32.
5813 // The type overload for sm4ks and sm4ed was removed.
5814 if (!CI->getType()->isIntegerTy(64))
5815 return;
5816
5817 Value *Arg =
5818 Builder.CreateTrunc(CI->getArgOperand(0), Builder.getInt32Ty());
5819
5820 NewCall = Builder.CreateCall(NewFn, Arg);
5821 Value *Res =
5822 Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
5823 NewCall->takeName(CI);
5824 CI->replaceAllUsesWith(Res);
5825 CI->eraseFromParent();
5826 return;
5827 }
5828
5829 case Intrinsic::x86_xop_vfrcz_ss:
5830 case Intrinsic::x86_xop_vfrcz_sd:
5831 NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)});
5832 break;
5833
5834 case Intrinsic::x86_xop_vpermil2pd:
5835 case Intrinsic::x86_xop_vpermil2ps:
5836 case Intrinsic::x86_xop_vpermil2pd_256:
5837 case Intrinsic::x86_xop_vpermil2ps_256: {
5838 SmallVector<Value *, 4> Args(CI->args());
5839 VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType());
5840 VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy);
5841 Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy);
5842 NewCall = Builder.CreateCall(NewFn, Args);
5843 break;
5844 }
5845
5846 case Intrinsic::x86_sse41_ptestc:
5847 case Intrinsic::x86_sse41_ptestz:
5848 case Intrinsic::x86_sse41_ptestnzc: {
5849 // The arguments for these intrinsics used to be v4f32, and changed
5850 // to v2i64. This is purely a nop, since those are bitwise intrinsics.
5851 // So, the only thing required is a bitcast for both arguments.
5852 // First, check the arguments have the old type.
5853 Value *Arg0 = CI->getArgOperand(0);
5854 if (Arg0->getType() != FixedVectorType::get(Type::getFloatTy(C), 4))
5855 return;
5856
5857 // Old intrinsic, add bitcasts
5858 Value *Arg1 = CI->getArgOperand(1);
5859
5860 auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
5861
5862 Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast");
5863 Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
5864
5865 NewCall = Builder.CreateCall(NewFn, {BC0, BC1});
5866 break;
5867 }
5868
5869 case Intrinsic::x86_rdtscp: {
5870 // This used to take 1 arguments. If we have no arguments, it is already
5871 // upgraded.
5872 if (CI->getNumOperands() == 0)
5873 return;
5874
5875 NewCall = Builder.CreateCall(NewFn);
5876 // Extract the second result and store it.
5877 Value *Data = Builder.CreateExtractValue(NewCall, 1);
5878 Builder.CreateAlignedStore(Data, CI->getArgOperand(0), Align(1));
5879 // Replace the original call result with the first result of the new call.
5880 Value *TSC = Builder.CreateExtractValue(NewCall, 0);
5881
5882 NewCall->takeName(CI);
5883 CI->replaceAllUsesWith(TSC);
5884 CI->eraseFromParent();
5885 return;
5886 }
5887
5888 case Intrinsic::x86_sse41_insertps:
5889 case Intrinsic::x86_sse41_dppd:
5890 case Intrinsic::x86_sse41_dpps:
5891 case Intrinsic::x86_sse41_mpsadbw:
5892 case Intrinsic::x86_avx_dp_ps_256:
5893 case Intrinsic::x86_avx2_mpsadbw: {
5894 // Need to truncate the last argument from i32 to i8 -- this argument models
5895 // an inherently 8-bit immediate operand to these x86 instructions.
5896 SmallVector<Value *, 4> Args(CI->args());
5897
5898 // Replace the last argument with a trunc.
5899 Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
5900 NewCall = Builder.CreateCall(NewFn, Args);
5901 break;
5902 }
5903
5904 case Intrinsic::x86_avx512_mask_cmp_pd_128:
5905 case Intrinsic::x86_avx512_mask_cmp_pd_256:
5906 case Intrinsic::x86_avx512_mask_cmp_pd_512:
5907 case Intrinsic::x86_avx512_mask_cmp_ps_128:
5908 case Intrinsic::x86_avx512_mask_cmp_ps_256:
5909 case Intrinsic::x86_avx512_mask_cmp_ps_512: {
5910 SmallVector<Value *, 4> Args(CI->args());
5911 unsigned NumElts =
5912 cast<FixedVectorType>(Args[0]->getType())->getNumElements();
5913 Args[3] = getX86MaskVec(Builder, Args[3], NumElts);
5914
5915 NewCall = Builder.CreateCall(NewFn, Args);
5916 Value *Res = applyX86MaskOn1BitsVec(Builder, NewCall, nullptr);
5917
5918 NewCall->takeName(CI);
5919 CI->replaceAllUsesWith(Res);
5920 CI->eraseFromParent();
5921 return;
5922 }
5923
5924 case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128:
5925 case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256:
5926 case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512:
5927 case Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128:
5928 case Intrinsic::x86_avx512bf16_cvtneps2bf16_256:
5929 case Intrinsic::x86_avx512bf16_cvtneps2bf16_512: {
5930 SmallVector<Value *, 4> Args(CI->args());
5931 unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
5932 if (NewFn->getIntrinsicID() ==
5933 Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
5934 Args[1] = Builder.CreateBitCast(
5935 Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
5936
5937 NewCall = Builder.CreateCall(NewFn, Args);
5938 Value *Res = Builder.CreateBitCast(
5939 NewCall, FixedVectorType::get(Builder.getInt16Ty(), NumElts));
5940
5941 NewCall->takeName(CI);
5942 CI->replaceAllUsesWith(Res);
5943 CI->eraseFromParent();
5944 return;
5945 }
5946 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
5947 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
5948 case Intrinsic::x86_avx512bf16_dpbf16ps_512:{
5949 SmallVector<Value *, 4> Args(CI->args());
5950 unsigned NumElts =
5951 cast<FixedVectorType>(CI->getType())->getNumElements() * 2;
5952 Args[1] = Builder.CreateBitCast(
5953 Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
5954 Args[2] = Builder.CreateBitCast(
5955 Args[2], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
5956
5957 NewCall = Builder.CreateCall(NewFn, Args);
5958 break;
5959 }
5960
5961 case Intrinsic::thread_pointer: {
5962 NewCall = Builder.CreateCall(NewFn, {});
5963 break;
5964 }
5965
5966 case Intrinsic::memcpy:
5967 case Intrinsic::memmove:
5968 case Intrinsic::memset: {
5969 // We have to make sure that the call signature is what we're expecting.
5970 // We only want to change the old signatures by removing the alignment arg:
5971 // @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i32, i1)
5972 // -> @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i1)
5973 // @llvm.memset...(i8*, i8, i[32|64], i32, i1)
5974 // -> @llvm.memset...(i8*, i8, i[32|64], i1)
5975 // Note: i8*'s in the above can be any pointer type
5976 if (CI->arg_size() != 5) {
5977 DefaultCase();
5978 return;
5979 }
5980 // Remove alignment argument (3), and add alignment attributes to the
5981 // dest/src pointers.
5982 Value *Args[4] = {CI->getArgOperand(0), CI->getArgOperand(1),
5983 CI->getArgOperand(2), CI->getArgOperand(4)};
5984 NewCall = Builder.CreateCall(NewFn, Args);
5985 AttributeList OldAttrs = CI->getAttributes();
5986 AttributeList NewAttrs = AttributeList::get(
5987 C, OldAttrs.getFnAttrs(), OldAttrs.getRetAttrs(),
5988 {OldAttrs.getParamAttrs(0), OldAttrs.getParamAttrs(1),
5989 OldAttrs.getParamAttrs(2), OldAttrs.getParamAttrs(4)});
5990 NewCall->setAttributes(NewAttrs);
5991 auto *MemCI = cast<MemIntrinsic>(NewCall);
5992 // All mem intrinsics support dest alignment.
5994 MemCI->setDestAlignment(Align->getMaybeAlignValue());
5995 // Memcpy/Memmove also support source alignment.
5996 if (auto *MTI = dyn_cast<MemTransferInst>(MemCI))
5997 MTI->setSourceAlignment(Align->getMaybeAlignValue());
5998 break;
5999 }
6000
6001 case Intrinsic::masked_load:
6002 case Intrinsic::masked_gather:
6003 case Intrinsic::masked_store:
6004 case Intrinsic::masked_scatter: {
6005 if (CI->arg_size() != 4) {
6006 DefaultCase();
6007 return;
6008 }
6009
6010 auto GetMaybeAlign = [](Value *Op) {
6011 if (auto *CI = dyn_cast<ConstantInt>(Op)) {
6012 uint64_t Val = CI->getZExtValue();
6013 if (Val == 0)
6014 return MaybeAlign();
6015 if (isPowerOf2_64(Val))
6016 return MaybeAlign(Val);
6017 }
6018 reportFatalUsageError("Invalid alignment argument");
6019 };
6020 auto GetAlign = [&](Value *Op) {
6021 MaybeAlign Align = GetMaybeAlign(Op);
6022 if (Align)
6023 return *Align;
6024 reportFatalUsageError("Invalid zero alignment argument");
6025 };
6026
6027 const DataLayout &DL = CI->getDataLayout();
6028 switch (NewFn->getIntrinsicID()) {
6029 case Intrinsic::masked_load:
6030 NewCall = Builder.CreateMaskedLoad(
6031 CI->getType(), CI->getArgOperand(0), GetAlign(CI->getArgOperand(1)),
6032 CI->getArgOperand(2), CI->getArgOperand(3));
6033 break;
6034 case Intrinsic::masked_gather:
6035 NewCall = Builder.CreateMaskedGather(
6036 CI->getType(), CI->getArgOperand(0),
6037 DL.getValueOrABITypeAlignment(GetMaybeAlign(CI->getArgOperand(1)),
6038 CI->getType()->getScalarType()),
6039 CI->getArgOperand(2), CI->getArgOperand(3));
6040 break;
6041 case Intrinsic::masked_store:
6042 NewCall = Builder.CreateMaskedStore(
6043 CI->getArgOperand(0), CI->getArgOperand(1),
6044 GetAlign(CI->getArgOperand(2)), CI->getArgOperand(3));
6045 break;
6046 case Intrinsic::masked_scatter:
6047 NewCall = Builder.CreateMaskedScatter(
6048 CI->getArgOperand(0), CI->getArgOperand(1),
6049 DL.getValueOrABITypeAlignment(
6050 GetMaybeAlign(CI->getArgOperand(2)),
6051 CI->getArgOperand(0)->getType()->getScalarType()),
6052 CI->getArgOperand(3));
6053 break;
6054 default:
6055 llvm_unreachable("Unexpected intrinsic ID");
6056 }
6057 // Previous metadata is still valid.
6058 NewCall->copyMetadata(*CI);
6059 NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
6060 break;
6061 }
6062
6063 case Intrinsic::lifetime_start:
6064 case Intrinsic::lifetime_end: {
6065 if (CI->arg_size() != 2) {
6066 DefaultCase();
6067 return;
6068 }
6069
6070 Value *Ptr = CI->getArgOperand(1);
6071 // Try to strip pointer casts, such that the lifetime works on an alloca.
6072 Ptr = Ptr->stripPointerCasts();
6073 if (isa<AllocaInst>(Ptr)) {
6074 // Don't use NewFn, as we might have looked through an addrspacecast.
6075 if (NewFn->getIntrinsicID() == Intrinsic::lifetime_start)
6076 NewCall = Builder.CreateLifetimeStart(Ptr);
6077 else
6078 NewCall = Builder.CreateLifetimeEnd(Ptr);
6079 break;
6080 }
6081
6082 // Otherwise remove the lifetime marker.
6083 CI->eraseFromParent();
6084 return;
6085 }
6086
6087 case Intrinsic::x86_avx512_vpdpbusd_128:
6088 case Intrinsic::x86_avx512_vpdpbusd_256:
6089 case Intrinsic::x86_avx512_vpdpbusd_512:
6090 case Intrinsic::x86_avx512_vpdpbusds_128:
6091 case Intrinsic::x86_avx512_vpdpbusds_256:
6092 case Intrinsic::x86_avx512_vpdpbusds_512:
6093 case Intrinsic::x86_avx2_vpdpbssd_128:
6094 case Intrinsic::x86_avx2_vpdpbssd_256:
6095 case Intrinsic::x86_avx10_vpdpbssd_512:
6096 case Intrinsic::x86_avx2_vpdpbssds_128:
6097 case Intrinsic::x86_avx2_vpdpbssds_256:
6098 case Intrinsic::x86_avx10_vpdpbssds_512:
6099 case Intrinsic::x86_avx2_vpdpbsud_128:
6100 case Intrinsic::x86_avx2_vpdpbsud_256:
6101 case Intrinsic::x86_avx10_vpdpbsud_512:
6102 case Intrinsic::x86_avx2_vpdpbsuds_128:
6103 case Intrinsic::x86_avx2_vpdpbsuds_256:
6104 case Intrinsic::x86_avx10_vpdpbsuds_512:
6105 case Intrinsic::x86_avx2_vpdpbuud_128:
6106 case Intrinsic::x86_avx2_vpdpbuud_256:
6107 case Intrinsic::x86_avx10_vpdpbuud_512:
6108 case Intrinsic::x86_avx2_vpdpbuuds_128:
6109 case Intrinsic::x86_avx2_vpdpbuuds_256:
6110 case Intrinsic::x86_avx10_vpdpbuuds_512: {
6111 unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() / 8;
6112 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
6113 CI->getArgOperand(2)};
6114 Type *NewArgType = VectorType::get(Builder.getInt8Ty(), NumElts, false);
6115 Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
6116 Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
6117
6118 NewCall = Builder.CreateCall(NewFn, Args);
6119 break;
6120 }
6121 case Intrinsic::x86_avx512_vpdpwssd_128:
6122 case Intrinsic::x86_avx512_vpdpwssd_256:
6123 case Intrinsic::x86_avx512_vpdpwssd_512:
6124 case Intrinsic::x86_avx512_vpdpwssds_128:
6125 case Intrinsic::x86_avx512_vpdpwssds_256:
6126 case Intrinsic::x86_avx512_vpdpwssds_512:
6127 case Intrinsic::x86_avx2_vpdpwsud_128:
6128 case Intrinsic::x86_avx2_vpdpwsud_256:
6129 case Intrinsic::x86_avx10_vpdpwsud_512:
6130 case Intrinsic::x86_avx2_vpdpwsuds_128:
6131 case Intrinsic::x86_avx2_vpdpwsuds_256:
6132 case Intrinsic::x86_avx10_vpdpwsuds_512:
6133 case Intrinsic::x86_avx2_vpdpwusd_128:
6134 case Intrinsic::x86_avx2_vpdpwusd_256:
6135 case Intrinsic::x86_avx10_vpdpwusd_512:
6136 case Intrinsic::x86_avx2_vpdpwusds_128:
6137 case Intrinsic::x86_avx2_vpdpwusds_256:
6138 case Intrinsic::x86_avx10_vpdpwusds_512:
6139 case Intrinsic::x86_avx2_vpdpwuud_128:
6140 case Intrinsic::x86_avx2_vpdpwuud_256:
6141 case Intrinsic::x86_avx10_vpdpwuud_512:
6142 case Intrinsic::x86_avx2_vpdpwuuds_128:
6143 case Intrinsic::x86_avx2_vpdpwuuds_256:
6144 case Intrinsic::x86_avx10_vpdpwuuds_512:
6145 unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() / 16;
6146 Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
6147 CI->getArgOperand(2)};
6148 Type *NewArgType = VectorType::get(Builder.getInt16Ty(), NumElts, false);
6149 Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
6150 Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
6151
6152 NewCall = Builder.CreateCall(NewFn, Args);
6153 break;
6154 }
6155 assert(NewCall && "Should have either set this variable or returned through "
6156 "the default case");
6157 NewCall->takeName(CI);
6158 CI->replaceAllUsesWith(NewCall);
6159 CI->eraseFromParent();
6160}
6161
6163 assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
6164
6165 // Check if this function should be upgraded and get the replacement function
6166 // if there is one.
6167 Function *NewFn;
6168 if (UpgradeIntrinsicFunction(F, NewFn)) {
6169 // Replace all users of the old function with the new function or new
6170 // instructions. This is not a range loop because the call is deleted.
6171 for (User *U : make_early_inc_range(F->users()))
6172 if (CallBase *CB = dyn_cast<CallBase>(U))
6173 UpgradeIntrinsicCall(CB, NewFn);
6174
6175 // Remove old function, no longer used, from the module.
6176 if (F != NewFn)
6177 F->eraseFromParent();
6178 }
6179}
6180
6182 const unsigned NumOperands = MD.getNumOperands();
6183 if (NumOperands == 0)
6184 return &MD; // Invalid, punt to a verifier error.
6185
6186 // Check if the tag uses struct-path aware TBAA format.
6187 if (isa<MDNode>(MD.getOperand(0)) && NumOperands >= 3)
6188 return &MD;
6189
6190 auto &Context = MD.getContext();
6191 if (NumOperands == 3) {
6192 Metadata *Elts[] = {MD.getOperand(0), MD.getOperand(1)};
6193 MDNode *ScalarType = MDNode::get(Context, Elts);
6194 // Create a MDNode <ScalarType, ScalarType, offset 0, const>
6195 Metadata *Elts2[] = {ScalarType, ScalarType,
6198 MD.getOperand(2)};
6199 return MDNode::get(Context, Elts2);
6200 }
6201 // Create a MDNode <MD, MD, offset 0>
6203 Type::getInt64Ty(Context)))};
6204 return MDNode::get(Context, Elts);
6205}
6206
6208 Instruction *&Temp) {
6209 if (Opc != Instruction::BitCast)
6210 return nullptr;
6211
6212 Temp = nullptr;
6213 Type *SrcTy = V->getType();
6214 if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
6215 SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
6216 LLVMContext &Context = V->getContext();
6217
6218 // We have no information about target data layout, so we assume that
6219 // the maximum pointer size is 64bit.
6220 Type *MidTy = Type::getInt64Ty(Context);
6221 Temp = CastInst::Create(Instruction::PtrToInt, V, MidTy);
6222
6223 return CastInst::Create(Instruction::IntToPtr, Temp, DestTy);
6224 }
6225
6226 return nullptr;
6227}
6228
6230 if (Opc != Instruction::BitCast)
6231 return nullptr;
6232
6233 Type *SrcTy = C->getType();
6234 if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
6235 SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
6236 LLVMContext &Context = C->getContext();
6237
6238 // We have no information about target data layout, so we assume that
6239 // the maximum pointer size is 64bit.
6240 Type *MidTy = Type::getInt64Ty(Context);
6241
6243 DestTy);
6244 }
6245
6246 return nullptr;
6247}
6248
6249static std::optional<StringRef> getModuleFlagNameSafely(const MDNode &Flag) {
6250 if (Flag.getNumOperands() < 3)
6251 return std::nullopt;
6252 if (MDString *Name = dyn_cast_or_null<MDString>(Flag.getOperand(1)))
6253 return Name->getString();
6254 return std::nullopt;
6255}
6256
6257/// Check the debug info version number, if it is out-dated, drop the debug
6258/// info. Return true if module is modified.
6261 return false;
6262
6263 llvm::TimeTraceScope timeScope("Upgrade debug info");
6264 // We need to get metadata before the module is verified (i.e., getModuleFlag
6265 // makes assumptions that we haven't verified yet). Carefully extract the flag
6266 // from the metadata.
6267 unsigned Version = 0;
6268 if (NamedMDNode *ModFlags = M.getModuleFlagsMetadata()) {
6269 auto OpIt = find_if(ModFlags->operands(), [](const MDNode *Flag) {
6270 if (auto Name = getModuleFlagNameSafely(*Flag))
6271 return *Name == "Debug Info Version";
6272 return false;
6273 });
6274 if (OpIt != ModFlags->op_end()) {
6275 const MDOperand &ValOp = (*OpIt)->getOperand(2);
6276 if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(ValOp))
6277 Version = CI->getZExtValue();
6278 }
6279 }
6280
6282 bool BrokenDebugInfo = false;
6283 if (verifyModule(M, &llvm::errs(), &BrokenDebugInfo))
6284 report_fatal_error("Broken module found, compilation aborted!");
6285 if (!BrokenDebugInfo)
6286 // Everything is ok.
6287 return false;
6288 else {
6289 // Diagnose malformed debug info.
6291 M.getContext().diagnose(Diag);
6292 }
6293 }
6294 bool Modified = StripDebugInfo(M);
6296 // Diagnose a version mismatch.
6298 M.getContext().diagnose(DiagVersion);
6299 }
6300 return Modified;
6301}
6302
6303static void upgradeNVVMFnVectorAttr(const StringRef Attr, const char DimC,
6304 GlobalValue *GV, const Metadata *V) {
6305 Function *F = cast<Function>(GV);
6306
6307 constexpr StringLiteral DefaultValue = "1";
6308 StringRef Vect3[3] = {DefaultValue, DefaultValue, DefaultValue};
6309 unsigned Length = 0;
6310
6311 if (F->hasFnAttribute(Attr)) {
6312 // We expect the existing attribute to have the form "x[,y[,z]]". Here we
6313 // parse these elements placing them into Vect3
6314 StringRef S = F->getFnAttribute(Attr).getValueAsString();
6315 for (; Length < 3 && !S.empty(); Length++) {
6316 auto [Part, Rest] = S.split(',');
6317 Vect3[Length] = Part.trim();
6318 S = Rest;
6319 }
6320 }
6321
6322 const unsigned Dim = DimC - 'x';
6323 assert(Dim < 3 && "Unexpected dim char");
6324
6325 const uint64_t VInt = mdconst::extract<ConstantInt>(V)->getZExtValue();
6326
6327 // local variable required for StringRef in Vect3 to point to.
6328 const std::string VStr = llvm::utostr(VInt);
6329 Vect3[Dim] = VStr;
6330 Length = std::max(Length, Dim + 1);
6331
6332 const std::string NewAttr = llvm::join(ArrayRef(Vect3, Length), ",");
6333 F->addFnAttr(Attr, NewAttr);
6334}
6335
6336static inline bool isXYZ(StringRef S) {
6337 return S == "x" || S == "y" || S == "z";
6338}
6339
6341 const Metadata *V) {
6342 if (K == "kernel") {
6344 cast<Function>(GV)->setCallingConv(CallingConv::PTX_Kernel);
6345 return true;
6346 }
6347 if (K == "align") {
6348 // V is a bitfeild specifying two 16-bit values. The alignment value is
6349 // specfied in low 16-bits, The index is specified in the high bits. For the
6350 // index, 0 indicates the return value while higher values correspond to
6351 // each parameter (idx = param + 1).
6352 const uint64_t AlignIdxValuePair =
6353 mdconst::extract<ConstantInt>(V)->getZExtValue();
6354 const unsigned Idx = (AlignIdxValuePair >> 16);
6355 const Align StackAlign = Align(AlignIdxValuePair & 0xFFFF);
6356 cast<Function>(GV)->addAttributeAtIndex(
6357 Idx, Attribute::getWithStackAlignment(GV->getContext(), StackAlign));
6358 return true;
6359 }
6360 if (K == "maxclusterrank" || K == "cluster_max_blocks") {
6361 const auto CV = mdconst::extract<ConstantInt>(V)->getZExtValue();
6363 return true;
6364 }
6365 if (K == "minctasm") {
6366 const auto CV = mdconst::extract<ConstantInt>(V)->getZExtValue();
6367 cast<Function>(GV)->addFnAttr(NVVMAttr::MinCTASm, llvm::utostr(CV));
6368 return true;
6369 }
6370 if (K == "maxnreg") {
6371 const auto CV = mdconst::extract<ConstantInt>(V)->getZExtValue();
6372 cast<Function>(GV)->addFnAttr(NVVMAttr::MaxNReg, llvm::utostr(CV));
6373 return true;
6374 }
6375 if (K.consume_front("maxntid") && isXYZ(K)) {
6377 return true;
6378 }
6379 if (K.consume_front("reqntid") && isXYZ(K)) {
6381 return true;
6382 }
6383 if (K.consume_front("cluster_dim_") && isXYZ(K)) {
6385 return true;
6386 }
6387 if (K == "grid_constant") {
6388 const auto Attr = Attribute::get(GV->getContext(), NVVMAttr::GridConstant);
6389 for (const auto &Op : cast<MDNode>(V)->operands()) {
6390 // For some reason, the index is 1-based in the metadata. Good thing we're
6391 // able to auto-upgrade it!
6392 const auto Index = mdconst::extract<ConstantInt>(Op)->getZExtValue() - 1;
6393 cast<Function>(GV)->addParamAttr(Index, Attr);
6394 }
6395 return true;
6396 }
6397
6398 return false;
6399}
6400
6402 NamedMDNode *NamedMD = M.getNamedMetadata("nvvm.annotations");
6403 if (!NamedMD)
6404 return;
6405
6406 SmallVector<MDNode *, 8> NewNodes;
6408 for (MDNode *MD : NamedMD->operands()) {
6409 if (!SeenNodes.insert(MD).second)
6410 continue;
6411
6412 auto *GV = mdconst::dyn_extract_or_null<GlobalValue>(MD->getOperand(0));
6413 if (!GV)
6414 continue;
6415
6416 assert((MD->getNumOperands() % 2) == 1 && "Invalid number of operands");
6417
6418 SmallVector<Metadata *, 8> NewOperands{MD->getOperand(0)};
6419 // Each nvvm.annotations metadata entry will be of the following form:
6420 // !{ ptr @gv, !"key1", value1, !"key2", value2, ... }
6421 // start index = 1, to skip the global variable key
6422 // increment = 2, to skip the value for each property-value pairs
6423 for (unsigned j = 1, je = MD->getNumOperands(); j < je; j += 2) {
6424 MDString *K = cast<MDString>(MD->getOperand(j));
6425 const MDOperand &V = MD->getOperand(j + 1);
6426 bool Upgraded = upgradeSingleNVVMAnnotation(GV, K->getString(), V);
6427 if (!Upgraded)
6428 NewOperands.append({K, V});
6429 }
6430
6431 if (NewOperands.size() > 1)
6432 NewNodes.push_back(MDNode::get(M.getContext(), NewOperands));
6433 }
6434
6435 NamedMD->clearOperands();
6436 for (MDNode *N : NewNodes)
6437 NamedMD->addOperand(N);
6438}
6439
6440/// This checks for objc retain release marker which should be upgraded. It
6441/// returns true if module is modified.
6443 bool Changed = false;
6444 const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
6445 NamedMDNode *ModRetainReleaseMarker = M.getNamedMetadata(MarkerKey);
6446 if (ModRetainReleaseMarker) {
6447 MDNode *Op = ModRetainReleaseMarker->getOperand(0);
6448 if (Op) {
6449 MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(0));
6450 if (ID) {
6451 SmallVector<StringRef, 4> ValueComp;
6452 ID->getString().split(ValueComp, "#");
6453 if (ValueComp.size() == 2) {
6454 std::string NewValue = ValueComp[0].str() + ";" + ValueComp[1].str();
6455 ID = MDString::get(M.getContext(), NewValue);
6456 }
6457 M.addModuleFlag(Module::Error, MarkerKey, ID);
6458 M.eraseNamedMetadata(ModRetainReleaseMarker);
6459 Changed = true;
6460 }
6461 }
6462 }
6463 return Changed;
6464}
6465
6467 // This lambda converts normal function calls to ARC runtime functions to
6468 // intrinsic calls.
6469 auto UpgradeToIntrinsic = [&](const char *OldFunc,
6470 llvm::Intrinsic::ID IntrinsicFunc) {
6471 Function *Fn = M.getFunction(OldFunc);
6472
6473 if (!Fn)
6474 return;
6475
6476 Function *NewFn =
6477 llvm::Intrinsic::getOrInsertDeclaration(&M, IntrinsicFunc);
6478
6479 for (User *U : make_early_inc_range(Fn->users())) {
6481 if (!CI || CI->getCalledFunction() != Fn)
6482 continue;
6483
6484 IRBuilder<> Builder(CI->getParent(), CI->getIterator());
6485 FunctionType *NewFuncTy = NewFn->getFunctionType();
6487
6488 // Don't upgrade the intrinsic if it's not valid to bitcast the return
6489 // value to the return type of the old function.
6490 if (NewFuncTy->getReturnType() != CI->getType() &&
6491 !CastInst::castIsValid(Instruction::BitCast, CI,
6492 NewFuncTy->getReturnType()))
6493 continue;
6494
6495 bool InvalidCast = false;
6496
6497 for (unsigned I = 0, E = CI->arg_size(); I != E; ++I) {
6498 Value *Arg = CI->getArgOperand(I);
6499
6500 // Bitcast argument to the parameter type of the new function if it's
6501 // not a variadic argument.
6502 if (I < NewFuncTy->getNumParams()) {
6503 // Don't upgrade the intrinsic if it's not valid to bitcast the argument
6504 // to the parameter type of the new function.
6505 if (!CastInst::castIsValid(Instruction::BitCast, Arg,
6506 NewFuncTy->getParamType(I))) {
6507 InvalidCast = true;
6508 break;
6509 }
6510 Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
6511 }
6512 Args.push_back(Arg);
6513 }
6514
6515 if (InvalidCast)
6516 continue;
6517
6518 // Create a call instruction that calls the new function.
6519 CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
6520 NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
6521 NewCall->takeName(CI);
6522
6523 // Bitcast the return value back to the type of the old call.
6524 Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType());
6525
6526 if (!CI->use_empty())
6527 CI->replaceAllUsesWith(NewRetVal);
6528 CI->eraseFromParent();
6529 }
6530
6531 if (Fn->use_empty())
6532 Fn->eraseFromParent();
6533 };
6534
6535 // Unconditionally convert a call to "clang.arc.use" to a call to
6536 // "llvm.objc.clang.arc.use".
6537 UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use);
6538
6539 // Upgrade the retain release marker. If there is no need to upgrade
6540 // the marker, that means either the module is already new enough to contain
6541 // new intrinsics or it is not ARC. There is no need to upgrade runtime call.
6543 return;
6544
6545 std::pair<const char *, llvm::Intrinsic::ID> RuntimeFuncs[] = {
6546 {"objc_autorelease", llvm::Intrinsic::objc_autorelease},
6547 {"objc_autoreleasePoolPop", llvm::Intrinsic::objc_autoreleasePoolPop},
6548 {"objc_autoreleasePoolPush", llvm::Intrinsic::objc_autoreleasePoolPush},
6549 {"objc_autoreleaseReturnValue",
6550 llvm::Intrinsic::objc_autoreleaseReturnValue},
6551 {"objc_copyWeak", llvm::Intrinsic::objc_copyWeak},
6552 {"objc_destroyWeak", llvm::Intrinsic::objc_destroyWeak},
6553 {"objc_initWeak", llvm::Intrinsic::objc_initWeak},
6554 {"objc_loadWeak", llvm::Intrinsic::objc_loadWeak},
6555 {"objc_loadWeakRetained", llvm::Intrinsic::objc_loadWeakRetained},
6556 {"objc_moveWeak", llvm::Intrinsic::objc_moveWeak},
6557 {"objc_release", llvm::Intrinsic::objc_release},
6558 {"objc_retain", llvm::Intrinsic::objc_retain},
6559 {"objc_retainAutorelease", llvm::Intrinsic::objc_retainAutorelease},
6560 {"objc_retainAutoreleaseReturnValue",
6561 llvm::Intrinsic::objc_retainAutoreleaseReturnValue},
6562 {"objc_retainAutoreleasedReturnValue",
6563 llvm::Intrinsic::objc_retainAutoreleasedReturnValue},
6564 {"objc_retainBlock", llvm::Intrinsic::objc_retainBlock},
6565 {"objc_storeStrong", llvm::Intrinsic::objc_storeStrong},
6566 {"objc_storeWeak", llvm::Intrinsic::objc_storeWeak},
6567 {"objc_unsafeClaimAutoreleasedReturnValue",
6568 llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue},
6569 {"objc_retainedObject", llvm::Intrinsic::objc_retainedObject},
6570 {"objc_unretainedObject", llvm::Intrinsic::objc_unretainedObject},
6571 {"objc_unretainedPointer", llvm::Intrinsic::objc_unretainedPointer},
6572 {"objc_retain_autorelease", llvm::Intrinsic::objc_retain_autorelease},
6573 {"objc_sync_enter", llvm::Intrinsic::objc_sync_enter},
6574 {"objc_sync_exit", llvm::Intrinsic::objc_sync_exit},
6575 {"objc_arc_annotation_topdown_bbstart",
6576 llvm::Intrinsic::objc_arc_annotation_topdown_bbstart},
6577 {"objc_arc_annotation_topdown_bbend",
6578 llvm::Intrinsic::objc_arc_annotation_topdown_bbend},
6579 {"objc_arc_annotation_bottomup_bbstart",
6580 llvm::Intrinsic::objc_arc_annotation_bottomup_bbstart},
6581 {"objc_arc_annotation_bottomup_bbend",
6582 llvm::Intrinsic::objc_arc_annotation_bottomup_bbend}};
6583
6584 for (auto &I : RuntimeFuncs)
6585 UpgradeToIntrinsic(I.first, I.second);
6586}
6587
6588// Upgrade the way signing of pointers to init/fini functions is described.
6589//
6590// Originally, the `@llvm.global_(ctors|dtors)` arrays contained `ptrauth`
6591// constants, if signing was requested. After the upgrade, these arrays contain
6592// plain function pointers and the desired signing schema is described via a
6593// pair of module flags.
6594//
6595// Note that the upgrade is only performed if all elements of *both* arrays
6596// agree on a common signing schema.
6598 // As we cannot always decide whether the particular module should have
6599 // ptrauth-init-fini flags, we have to treat absent flags as having zero
6600 // values for compatibility reasons. Thus, upgradePtrauthInitFiniArrays
6601 // returns as soon as it spots any non-signed init/fini pointer: either we
6602 // should request non-signed pointers (safe to omit both flags) or there is
6603 // no common schema (and thus we do not modify anything).
6604 //
6605 // UseAddressDisc's value either represents "not decided yet" state (nullopt)
6606 // or whether we should request address diversity in addition to the basic
6607 // constant diversity. There is no value representing "decided not to sign"
6608 // for the reasons explained above.
6609 std::optional<bool> UseAddressDisc;
6610
6611 // Do not attempt upgrading if the new module flags already exist.
6612 if (const NamedMDNode *ModFlags = M.getModuleFlagsMetadata()) {
6613 for (const MDNode *Flag : ModFlags->operands()) {
6614 std::optional<StringRef> Name = getModuleFlagNameSafely(*Flag);
6615 if (Name && (*Name == "ptrauth-init-fini" ||
6616 *Name == "ptrauth-init-fini-address-discrimination"))
6617 return false;
6618 }
6619 }
6620
6621 auto UpgradeSinglePointer = [&UseAddressDisc](Constant *CV) -> Constant * {
6622 constexpr unsigned ExpectedConstDisc = 0xD9D4;
6623 constexpr unsigned ExpectedAddressMarker = 1;
6624
6625 auto *CPA = dyn_cast<ConstantPtrAuth>(CV);
6626 if (!CPA || !CPA->getDiscriminator()->equalsInt(ExpectedConstDisc))
6627 return nullptr; // Nothing to upgrade or unknown pattern found.
6628
6629 bool HasAddressDisc;
6630 if (!CPA->hasAddressDiscriminator())
6631 HasAddressDisc = false;
6632 else if (CPA->hasSpecialAddressDiscriminator(ExpectedAddressMarker))
6633 HasAddressDisc = true;
6634 else
6635 return nullptr; // Unknown pattern.
6636
6637 if (UseAddressDisc && *UseAddressDisc != HasAddressDisc)
6638 return nullptr; // Disagreement with the decided mode.
6639
6640 UseAddressDisc = HasAddressDisc;
6641 return CPA->getPointer();
6642 };
6643
6644 // Do not apply any changes until we know the upgrade is non-ambiguous.
6645 using PendingUpgrade = std::pair<GlobalVariable *, Constant *>;
6646 SmallVector<PendingUpgrade, 2> GlobalArraysToUpgrade;
6647
6648 for (const char *Name : {"llvm.global_ctors", "llvm.global_dtors"}) {
6649 auto *GV = dyn_cast_if_present<GlobalVariable>(M.getNamedValue(Name));
6650 if (!GV || !GV->hasInitializer())
6651 continue; // Skip, but it is okay to upgrade the other variable.
6652
6653 auto *OldStructorsArray = dyn_cast<ConstantArray>(GV->getInitializer());
6654 if (!OldStructorsArray || OldStructorsArray->getNumOperands() == 0)
6655 return false;
6656
6657 std::vector<Constant *> NewStructors;
6658 NewStructors.reserve(OldStructorsArray->getNumOperands());
6659
6660 for (Use &U : OldStructorsArray->operands()) {
6661 ConstantStruct *Structor = dyn_cast<ConstantStruct>(U.get());
6662 if (!Structor || Structor->getNumOperands() != 3)
6663 return false;
6664
6665 Constant *Prio = Structor->getOperand(0);
6666 Constant *Func = Structor->getOperand(1);
6667 Constant *Arg = Structor->getOperand(2);
6668
6669 Func = UpgradeSinglePointer(Func);
6670 if (!Func)
6671 return false;
6672
6673 NewStructors.push_back(
6674 ConstantStruct::get(Structor->getType(), {Prio, Func, Arg}));
6675 }
6676
6677 Constant *NewInit =
6678 ConstantArray::get(OldStructorsArray->getType(), NewStructors);
6679 GlobalArraysToUpgrade.emplace_back(GV, NewInit);
6680 }
6681
6682 if (GlobalArraysToUpgrade.empty())
6683 return false;
6684 assert(UseAddressDisc.has_value());
6685
6686 for (auto [GV, NewInit] : GlobalArraysToUpgrade)
6687 GV->setInitializer(NewInit);
6688
6689 M.addModuleFlag(Module::Error, "ptrauth-init-fini", 1);
6690 M.addModuleFlag(Module::Error, "ptrauth-init-fini-address-discrimination",
6691 *UseAddressDisc);
6692
6693 return true;
6694}
6695
6697 bool Changed = false;
6699
6700 NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
6701 if (!ModFlags)
6702 return Changed;
6703
6704 bool HasObjCFlag = false, HasClassProperties = false;
6705 bool HasSwiftVersionFlag = false;
6706 uint8_t SwiftMajorVersion, SwiftMinorVersion;
6707 uint32_t SwiftABIVersion;
6708 auto Int8Ty = Type::getInt8Ty(M.getContext());
6709 auto Int32Ty = Type::getInt32Ty(M.getContext());
6710
6711 for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
6712 MDNode *Op = ModFlags->getOperand(I);
6713 if (Op->getNumOperands() != 3)
6714 continue;
6715 MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
6716 if (!ID)
6717 continue;
6718 auto SetBehavior = [&](Module::ModFlagBehavior B) {
6719 Metadata *Ops[3] = {ConstantAsMetadata::get(ConstantInt::get(
6720 Type::getInt32Ty(M.getContext()), B)),
6721 MDString::get(M.getContext(), ID->getString()),
6722 Op->getOperand(2)};
6723 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6724 Changed = true;
6725 };
6726
6727 if (ID->getString() == "Objective-C Image Info Version")
6728 HasObjCFlag = true;
6729 if (ID->getString() == "Objective-C Class Properties")
6730 HasClassProperties = true;
6731 // Upgrade PIC from Error/Max to Min.
6732 if (ID->getString() == "PIC Level") {
6733 if (auto *Behavior =
6735 uint64_t V = Behavior->getLimitedValue();
6736 if (V == Module::Error || V == Module::Max)
6737 SetBehavior(Module::Min);
6738 }
6739 }
6740 // Upgrade "PIE Level" from Error to Max.
6741 if (ID->getString() == "PIE Level")
6742 if (auto *Behavior =
6744 if (Behavior->getLimitedValue() == Module::Error)
6745 SetBehavior(Module::Max);
6746
6747 // Upgrade branch protection and return address signing module flags. The
6748 // module flag behavior for these fields were Error and now they are Min.
6749 if (ID->getString() == "branch-target-enforcement" ||
6750 ID->getString().starts_with("sign-return-address")) {
6751 if (auto *Behavior =
6753 if (Behavior->getLimitedValue() == Module::Error) {
6754 Type *Int32Ty = Type::getInt32Ty(M.getContext());
6755 Metadata *Ops[3] = {
6756 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Min)),
6757 Op->getOperand(1), Op->getOperand(2)};
6758 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6759 Changed = true;
6760 }
6761 }
6762 }
6763
6764 // Upgrade Objective-C Image Info Section. Removed the whitespce in the
6765 // section name so that llvm-lto will not complain about mismatching
6766 // module flags that is functionally the same.
6767 if (ID->getString() == "Objective-C Image Info Section") {
6768 if (auto *Value = dyn_cast_or_null<MDString>(Op->getOperand(2))) {
6769 SmallVector<StringRef, 4> ValueComp;
6770 Value->getString().split(ValueComp, " ");
6771 if (ValueComp.size() != 1) {
6772 std::string NewValue;
6773 for (auto &S : ValueComp)
6774 NewValue += S.str();
6775 Metadata *Ops[3] = {Op->getOperand(0), Op->getOperand(1),
6776 MDString::get(M.getContext(), NewValue)};
6777 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6778 Changed = true;
6779 }
6780 }
6781 }
6782
6783 // IRUpgrader turns a i32 type "Objective-C Garbage Collection" into i8 value.
6784 // If the higher bits are set, it adds new module flag for swift info.
6785 if (ID->getString() == "Objective-C Garbage Collection") {
6786 auto Md = dyn_cast<ConstantAsMetadata>(Op->getOperand(2));
6787 if (Md) {
6788 assert(Md->getValue() && "Expected non-empty metadata");
6789 auto Type = Md->getValue()->getType();
6790 if (Type == Int8Ty)
6791 continue;
6792 unsigned Val = Md->getValue()->getUniqueInteger().getZExtValue();
6793 if ((Val & 0xff) != Val) {
6794 HasSwiftVersionFlag = true;
6795 SwiftABIVersion = (Val & 0xff00) >> 8;
6796 SwiftMajorVersion = (Val & 0xff000000) >> 24;
6797 SwiftMinorVersion = (Val & 0xff0000) >> 16;
6798 }
6799 Metadata *Ops[3] = {
6800 ConstantAsMetadata::get(ConstantInt::get(Int32Ty,Module::Error)),
6801 Op->getOperand(1),
6802 ConstantAsMetadata::get(ConstantInt::get(Int8Ty,Val & 0xff))};
6803 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6804 Changed = true;
6805 }
6806 }
6807
6808 if (ID->getString() == "amdgpu_code_object_version") {
6809 Metadata *Ops[3] = {
6810 Op->getOperand(0),
6811 MDString::get(M.getContext(), "amdhsa_code_object_version"),
6812 Op->getOperand(2)};
6813 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6814 Changed = true;
6815 }
6816
6817 // clang/PowerPC used to use "float-abi" to describe the long double format;
6818 // it has been renamed to "long-double-type", with its values changed to the
6819 // corresponding IR floating-point type names.
6820 if (M.getTargetTriple().isPPC() && ID->getString() == "float-abi") {
6822 if (auto *S = dyn_cast_or_null<MDString>(Op->getOperand(2)))
6823 Format = S->getString();
6824
6825 // The "float-abi" key is now reserved for the target-independent
6826 // soft/hard ABI flag, so leave a valid value alone. Map any other value
6827 // (including unrecognized ones, which were never valid) to the default.
6829 LongDoubleFormat NewFormat =
6831 .Case("ieeequad", LongDoubleFormat::IEEEquad)
6832 .Case("ieeedouble", LongDoubleFormat::IEEEdouble)
6834 Metadata *Ops[3] = {
6835 Op->getOperand(0),
6836 MDString::get(M.getContext(), "long-double-type"),
6837 MDString::get(M.getContext(), getLongDoubleFormatName(NewFormat))};
6838 ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
6839 Changed = true;
6840 }
6841 }
6842 }
6843
6844 // "Objective-C Class Properties" is recently added for Objective-C. We
6845 // upgrade ObjC bitcodes to contain a "Objective-C Class Properties" module
6846 // flag of value 0, so we can correclty downgrade this flag when trying to
6847 // link an ObjC bitcode without this module flag with an ObjC bitcode with
6848 // this module flag.
6849 if (HasObjCFlag && !HasClassProperties) {
6850 M.addModuleFlag(llvm::Module::Override, "Objective-C Class Properties",
6851 (uint32_t)0);
6852 Changed = true;
6853 }
6854
6855 if (HasSwiftVersionFlag) {
6856 M.addModuleFlag(Module::Error, "Swift ABI Version",
6857 SwiftABIVersion);
6858 M.addModuleFlag(Module::Error, "Swift Major Version",
6859 ConstantInt::get(Int8Ty, SwiftMajorVersion));
6860 M.addModuleFlag(Module::Error, "Swift Minor Version",
6861 ConstantInt::get(Int8Ty, SwiftMinorVersion));
6862 Changed = true;
6863 }
6864
6865 return Changed;
6866}
6867
6869 NamedMDNode *CFIConsts = M.getNamedMetadata("cfi.functions");
6870 // If this metadata has operands, we expect all of them to be either from
6871 // before or from after the format change handled here, so we can bail out
6872 // fast if the first (if any) operands is of the new format.
6873 auto MatchesVersion = [](const MDNode *Op) {
6874 return Op->getNumOperands() >= 3 &&
6875 isa<ConstantAsMetadata>(Op->getOperand(2)) &&
6876 cast<ConstantAsMetadata>(Op->getOperand(2))
6877 ->getType()
6878 ->isIntegerTy(64);
6879 };
6880
6881 if (!CFIConsts || !CFIConsts->getNumOperands() ||
6882 MatchesVersion(CFIConsts->getOperand(0)))
6883 return false;
6884
6885 bool Changed = false;
6886 for (unsigned I = 0, E = CFIConsts->getNumOperands(); I != E; ++I) {
6887 MDNode *Op = CFIConsts->getOperand(I);
6888 assert(!MatchesVersion(Op) && "Unexpected mix of CFIConstant formats");
6889 assert(Op->getNumOperands() >= 2 &&
6890 "Expected at least 2 operands - name and linkage type");
6891 MDString *NameMD = dyn_cast<MDString>(Op->getOperand(0));
6892 StringRef Name = NameMD->getString();
6895
6897 Elts.push_back(Op->getOperand(0));
6898 Elts.push_back(Op->getOperand(1));
6900 ConstantInt::get(Type::getInt64Ty(M.getContext()), GUID)));
6901
6902 for (unsigned J = 2, EJ = Op->getNumOperands(); J != EJ; ++J)
6903 Elts.push_back(Op->getOperand(J));
6904
6905 CFIConsts->setOperand(I, MDNode::get(M.getContext(), Elts));
6906 Changed = true;
6907 }
6908
6909 return Changed;
6910}
6911
6913 auto TrimSpaces = [](StringRef Section) -> std::string {
6914 SmallVector<StringRef, 5> Components;
6915 Section.split(Components, ',');
6916
6917 SmallString<32> Buffer;
6918 raw_svector_ostream OS(Buffer);
6919
6920 for (auto Component : Components)
6921 OS << ',' << Component.trim();
6922
6923 return std::string(OS.str().substr(1));
6924 };
6925
6926 for (auto &GV : M.globals()) {
6927 if (!GV.hasSection())
6928 continue;
6929
6930 StringRef Section = GV.getSection();
6931
6932 if (!Section.starts_with("__DATA, __objc_catlist"))
6933 continue;
6934
6935 // __DATA, __objc_catlist, regular, no_dead_strip
6936 // __DATA,__objc_catlist,regular,no_dead_strip
6937 GV.setSection(TrimSpaces(Section));
6938 }
6939}
6940
6941namespace {
6942// Prior to LLVM 10.0, the strictfp attribute could be used on individual
6943// callsites within a function that did not also have the strictfp attribute.
6944// Since 10.0, if strict FP semantics are needed within a function, the
6945// function must have the strictfp attribute and all calls within the function
6946// must also have the strictfp attribute. This latter restriction is
6947// necessary to prevent unwanted libcall simplification when a function is
6948// being cloned (such as for inlining).
6949//
6950// The "dangling" strictfp attribute usage was only used to prevent constant
6951// folding and other libcall simplification. The nobuiltin attribute on the
6952// callsite has the same effect.
6953struct StrictFPUpgradeVisitor : public InstVisitor<StrictFPUpgradeVisitor> {
6954 StrictFPUpgradeVisitor() = default;
6955
6956 void visitCallBase(CallBase &Call) {
6957 if (!Call.isStrictFP())
6958 return;
6960 return;
6961 // If we get here, the caller doesn't have the strictfp attribute
6962 // but this callsite does. Replace the strictfp attribute with nobuiltin.
6963 Call.removeFnAttr(Attribute::StrictFP);
6964 Call.addFnAttr(Attribute::NoBuiltin);
6965 }
6966};
6967
6968/// Replace "amdgpu-unsafe-fp-atomics" metadata with atomicrmw metadata
6969struct AMDGPUUnsafeFPAtomicsUpgradeVisitor
6970 : public InstVisitor<AMDGPUUnsafeFPAtomicsUpgradeVisitor> {
6971 AMDGPUUnsafeFPAtomicsUpgradeVisitor() = default;
6972
6973 void visitAtomicRMWInst(AtomicRMWInst &RMW) {
6974 if (!RMW.isFloatingPointOperation())
6975 return;
6976
6977 MDNode *Empty = MDNode::get(RMW.getContext(), {});
6978 RMW.setMetadata("amdgpu.no.fine.grained.host.memory", Empty);
6979 RMW.setMetadata("amdgpu.no.remote.memory.access", Empty);
6980 RMW.setMetadata("amdgpu.ignore.denormal.mode", Empty);
6981 }
6982};
6983} // namespace
6984
6986 // If a function definition doesn't have the strictfp attribute,
6987 // convert any callsite strictfp attributes to nobuiltin.
6988 if (!F.isDeclaration() && !F.hasFnAttribute(Attribute::StrictFP)) {
6989 StrictFPUpgradeVisitor SFPV;
6990 SFPV.visit(F);
6991 }
6992
6993 // Remove all incompatibile attributes from function.
6994 F.removeRetAttrs(AttributeFuncs::typeIncompatible(
6995 F.getReturnType(), F.getAttributes().getRetAttrs()));
6996 for (auto &Arg : F.args())
6997 Arg.removeAttrs(
6998 AttributeFuncs::typeIncompatible(Arg.getType(), Arg.getAttributes()));
6999
7000 bool AddingAttrs = false, RemovingAttrs = false;
7001 AttrBuilder AttrsToAdd(F.getContext());
7002 AttributeMask AttrsToRemove;
7003
7004 // Older versions of LLVM treated an "implicit-section-name" attribute
7005 // similarly to directly setting the section on a Function.
7006 if (Attribute A = F.getFnAttribute("implicit-section-name");
7007 A.isValid() && A.isStringAttribute()) {
7008 F.setSection(A.getValueAsString());
7009 AttrsToRemove.addAttribute("implicit-section-name");
7010 RemovingAttrs = true;
7011 }
7012
7013 if (Attribute A = F.getFnAttribute("nooutline");
7014 A.isValid() && A.isStringAttribute()) {
7015 AttrsToRemove.addAttribute("nooutline");
7016 AttrsToAdd.addAttribute(Attribute::NoOutline);
7017 AddingAttrs = RemovingAttrs = true;
7018 }
7019
7020 if (Attribute A = F.getFnAttribute("uniform-work-group-size");
7021 A.isValid() && A.isStringAttribute() && !A.getValueAsString().empty()) {
7022 AttrsToRemove.addAttribute("uniform-work-group-size");
7023 RemovingAttrs = true;
7024 if (A.getValueAsString() == "true") {
7025 AttrsToAdd.addAttribute("uniform-work-group-size");
7026 AddingAttrs = true;
7027 }
7028 }
7029
7030 if (!F.empty()) {
7031 // For some reason this is called twice, and the first time is before any
7032 // instructions are loaded into the body.
7033
7034 if (Attribute A = F.getFnAttribute("amdgpu-unsafe-fp-atomics");
7035 A.isValid()) {
7036
7037 if (A.getValueAsBool()) {
7038 AMDGPUUnsafeFPAtomicsUpgradeVisitor Visitor;
7039 Visitor.visit(F);
7040 }
7041
7042 // We will leave behind dead attribute uses on external declarations, but
7043 // clang never added these to declarations anyway.
7044 AttrsToRemove.addAttribute("amdgpu-unsafe-fp-atomics");
7045 RemovingAttrs = true;
7046 }
7047 }
7048
7049 DenormalMode DenormalFPMath = DenormalMode::getIEEE();
7050 DenormalMode DenormalFPMathF32 = DenormalMode::getInvalid();
7051
7052 bool HandleDenormalMode = false;
7053
7054 if (Attribute Attr = F.getFnAttribute("denormal-fp-math"); Attr.isValid()) {
7055 DenormalMode ParsedMode = parseDenormalFPAttribute(Attr.getValueAsString());
7056 if (ParsedMode.isValid()) {
7057 DenormalFPMath = ParsedMode;
7058 AttrsToRemove.addAttribute("denormal-fp-math");
7059 AddingAttrs = RemovingAttrs = true;
7060 HandleDenormalMode = true;
7061 }
7062 }
7063
7064 if (Attribute Attr = F.getFnAttribute("denormal-fp-math-f32");
7065 Attr.isValid()) {
7066 DenormalMode ParsedMode = parseDenormalFPAttribute(Attr.getValueAsString());
7067 if (ParsedMode.isValid()) {
7068 DenormalFPMathF32 = ParsedMode;
7069 AttrsToRemove.addAttribute("denormal-fp-math-f32");
7070 AddingAttrs = RemovingAttrs = true;
7071 HandleDenormalMode = true;
7072 }
7073 }
7074
7075 if (HandleDenormalMode)
7076 AttrsToAdd.addDenormalFPEnvAttr(
7077 DenormalFPEnv(DenormalFPMath, DenormalFPMathF32));
7078
7079 if (RemovingAttrs)
7080 F.removeFnAttrs(AttrsToRemove);
7081
7082 if (AddingAttrs)
7083 F.addFnAttrs(AttrsToAdd);
7084}
7085
7086// Check if the function attribute is not present and set it.
7088 StringRef Value) {
7089 if (!F.hasFnAttribute(FnAttrName))
7090 F.addFnAttr(FnAttrName, Value);
7091}
7092
7093// Check if the function attribute is not present and set it if needed.
7094// If the attribute is "false" then removes it.
7095// If the attribute is "true" resets it to a valueless attribute.
7096static void ConvertFunctionAttr(Function &F, bool Set, StringRef FnAttrName) {
7097 if (!F.hasFnAttribute(FnAttrName)) {
7098 if (Set)
7099 F.addFnAttr(FnAttrName);
7100 } else {
7101 auto A = F.getFnAttribute(FnAttrName);
7102 if ("false" == A.getValueAsString())
7103 F.removeFnAttr(FnAttrName);
7104 else if ("true" == A.getValueAsString()) {
7105 F.removeFnAttr(FnAttrName);
7106 F.addFnAttr(FnAttrName);
7107 }
7108 }
7109}
7110
7112 Triple T(M.getTargetTriple());
7113 if (!T.isThumb() && !T.isARM() && !T.isAArch64())
7114 return;
7115
7116 uint64_t BTEValue = 0;
7117 uint64_t BPPLRValue = 0;
7118 uint64_t GCSValue = 0;
7119 uint64_t SRAValue = 0;
7120 uint64_t SRAALLValue = 0;
7121 uint64_t SRABKeyValue = 0;
7122
7123 NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
7124 if (ModFlags) {
7125 for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
7126 MDNode *Op = ModFlags->getOperand(I);
7127 if (Op->getNumOperands() != 3)
7128 continue;
7129
7130 MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
7131 auto *CI = mdconst::dyn_extract<ConstantInt>(Op->getOperand(2));
7132 if (!ID || !CI)
7133 continue;
7134
7135 StringRef IDStr = ID->getString();
7136 uint64_t *ValPtr = IDStr == "branch-target-enforcement" ? &BTEValue
7137 : IDStr == "branch-protection-pauth-lr" ? &BPPLRValue
7138 : IDStr == "guarded-control-stack" ? &GCSValue
7139 : IDStr == "sign-return-address" ? &SRAValue
7140 : IDStr == "sign-return-address-all" ? &SRAALLValue
7141 : IDStr == "sign-return-address-with-bkey"
7142 ? &SRABKeyValue
7143 : nullptr;
7144 if (!ValPtr)
7145 continue;
7146
7147 *ValPtr = CI->getZExtValue();
7148 if (*ValPtr == 2)
7149 return;
7150 }
7151 }
7152
7153 bool BTE = BTEValue == 1;
7154 bool BPPLR = BPPLRValue == 1;
7155 bool GCS = GCSValue == 1;
7156 bool SRA = SRAValue == 1;
7157
7158 StringRef SignTypeValue = "non-leaf";
7159 if (SRA && SRAALLValue == 1)
7160 SignTypeValue = "all";
7161
7162 StringRef SignKeyValue = "a_key";
7163 if (SRA && SRABKeyValue == 1)
7164 SignKeyValue = "b_key";
7165
7166 for (Function &F : M.getFunctionList()) {
7167 if (F.isDeclaration())
7168 continue;
7169
7170 if (SRA) {
7171 setFunctionAttrIfNotSet(F, "sign-return-address", SignTypeValue);
7172 setFunctionAttrIfNotSet(F, "sign-return-address-key", SignKeyValue);
7173 } else {
7174 if (auto A = F.getFnAttribute("sign-return-address");
7175 A.isValid() && "none" == A.getValueAsString()) {
7176 F.removeFnAttr("sign-return-address");
7177 F.removeFnAttr("sign-return-address-key");
7178 }
7179 }
7180 ConvertFunctionAttr(F, BTE, "branch-target-enforcement");
7181 ConvertFunctionAttr(F, BPPLR, "branch-protection-pauth-lr");
7182 ConvertFunctionAttr(F, GCS, "guarded-control-stack");
7183 }
7184
7185 if (BTE)
7186 M.setModuleFlag(llvm::Module::Min, "branch-target-enforcement", 2);
7187 if (BPPLR)
7188 M.setModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr", 2);
7189 if (GCS)
7190 M.setModuleFlag(llvm::Module::Min, "guarded-control-stack", 2);
7191 if (SRA) {
7192 M.setModuleFlag(llvm::Module::Min, "sign-return-address", 2);
7193 if (SRAALLValue == 1)
7194 M.setModuleFlag(llvm::Module::Min, "sign-return-address-all", 2);
7195 if (SRABKeyValue == 1)
7196 M.setModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", 2);
7197 }
7198}
7199
7200/// Return the replacement tags if \p T still uses a removed two-operand form.
7202 if (T->getNumOperands() != 2 || !mdconst::hasa<ConstantInt>(T->getOperand(1)))
7203 return nullptr;
7204 auto *Tag = dyn_cast_or_null<MDString>(T->getOperand(0));
7205 return Tag ? findBooleanLoopTags(Tag->getString()) : nullptr;
7206}
7207
7208/// Build the single-operand node that replaces a boolean operand: nonzero
7209/// selects the enable tag, zero the disable tag.
7211 const BooleanLoopTags &Tags,
7212 const MDOperand &Op) {
7213 bool Enable = !mdconst::extract<ConstantInt>(Op)->isZero();
7214 return MDTuple::get(C,
7215 {MDString::get(C, Enable ? Tags.Enable : Tags.Disable)});
7216}
7217
7218static bool isOldLoopArgument(Metadata *MD) {
7219 auto *T = dyn_cast_or_null<MDTuple>(MD);
7220 if (!T)
7221 return false;
7222 if (T->getNumOperands() < 1)
7223 return false;
7224 auto *S = dyn_cast_or_null<MDString>(T->getOperand(0));
7225 if (!S)
7226 return false;
7227 if (S->getString().starts_with("llvm.vectorizer."))
7228 return true;
7229 return getOldBooleanLoopTags(T) != nullptr;
7230}
7231
7233 StringRef OldPrefix = "llvm.vectorizer.";
7234 assert(OldTag.starts_with(OldPrefix) && "Expected old prefix");
7235
7236 if (OldTag == "llvm.vectorizer.unroll")
7237 return MDString::get(C, "llvm.loop.interleave.count");
7238
7239 return MDString::get(
7240 C, (Twine("llvm.loop.vectorize.") + OldTag.drop_front(OldPrefix.size()))
7241 .str());
7242}
7243
7245 auto *T = dyn_cast_or_null<MDTuple>(MD);
7246 if (!T)
7247 return MD;
7248 if (T->getNumOperands() < 1)
7249 return MD;
7250 auto *OldTag = dyn_cast_or_null<MDString>(T->getOperand(0));
7251 if (!OldTag)
7252 return MD;
7253
7254 LLVMContext &C = T->getContext();
7255
7256 /// Rewrite a removed two-operand boolean form to the single-operand pair.
7257 if (const BooleanLoopTags *Tags = getOldBooleanLoopTags(T))
7258 return makeBooleanLoopNode(C, *Tags, T->getOperand(1));
7259
7260 if (!OldTag->getString().starts_with("llvm.vectorizer."))
7261 return MD;
7262
7263 // This has an old tag. Upgrade it.
7264 MDString *NewTag = upgradeLoopTag(C, OldTag->getString());
7265
7266 // The legacy !{!"llvm.vectorizer.enable", i1 X} maps onto the single-operand
7267 // vectorize.enable/disable pair, not a two-operand enable node.
7268 if (T->getNumOperands() == 2 && mdconst::hasa<ConstantInt>(T->getOperand(1)))
7269 if (const BooleanLoopTags *Tags = findBooleanLoopTags(NewTag->getString()))
7270 return makeBooleanLoopNode(C, *Tags, T->getOperand(1));
7271
7273 Ops.reserve(T->getNumOperands());
7274 Ops.push_back(NewTag);
7275 for (unsigned I = 1, E = T->getNumOperands(); I != E; ++I)
7276 Ops.push_back(T->getOperand(I));
7277
7278 return MDTuple::get(C, Ops);
7279}
7280
7282 auto *T = dyn_cast<MDTuple>(&N);
7283 if (!T)
7284 return &N;
7285
7286 if (none_of(T->operands(), isOldLoopArgument))
7287 return &N;
7288
7289 // Fix the removed two-operand boolean nodes in place: the Verifier rejects
7290 // any MDNode carrying those tags with more than one operand, so a leftover
7291 // reference (from the distinct loop-ID) would still trigger a diagnostic.
7292 // In-place mutation is safe on distinct MDNodes.
7293 if (T->isDistinct()) {
7294 for (unsigned I = 0, E = T->getNumOperands(); I < E; ++I) {
7295 auto *OpT = dyn_cast_or_null<MDTuple>(T->getOperand(I));
7296 if (OpT && getOldBooleanLoopTags(OpT))
7297 T->replaceOperandWith(I, upgradeLoopArgument(OpT));
7298 }
7299 if (none_of(T->operands(), isOldLoopArgument))
7300 return &N;
7301 }
7302
7303 // Remaining old arguments (e.g. llvm.vectorizer.*) are handled via a wrapper
7304 // attachment; the original distinct loop-ID is kept as the first operand.
7306 Ops.reserve(T->getNumOperands());
7307 for (Metadata *MD : T->operands())
7308 Ops.push_back(upgradeLoopArgument(MD));
7309
7310 return MDTuple::get(T->getContext(), Ops);
7311}
7312
7314 Triple T(TT);
7315 // The only data layout upgrades needed for pre-GCN, SPIR or SPIRV are setting
7316 // the address space of globals to 1. This does not apply to SPIRV Logical.
7317 if ((T.isSPIR() || (T.isSPIRV() && !T.isSPIRVLogical())) &&
7318 !DL.contains("-G") && !DL.starts_with("G")) {
7319 return DL.empty() ? std::string("G1") : (DL + "-G1").str();
7320 }
7321
7322 if (T.isLoongArch64() || T.isRISCV64()) {
7323 // Make i32 a native type for 64-bit LoongArch and RISC-V.
7324 auto I = DL.find("-n64-");
7325 if (I != StringRef::npos)
7326 return (DL.take_front(I) + "-n32:64-" + DL.drop_front(I + 5)).str();
7327 return DL.str();
7328 }
7329
7330 // AMDGPU data layout upgrades.
7331 std::string Res = DL.str();
7332 if (T.isAMDGPU()) {
7333 // Define address spaces for constants.
7334 if (!DL.contains("-G") && !DL.starts_with("G"))
7335 Res.append(Res.empty() ? "G1" : "-G1");
7336
7337 // AMDGCN data layout upgrades.
7338 if (T.isAMDGCN()) {
7339
7340 // Add missing non-integral declarations.
7341 // This goes before adding new address spaces to prevent incoherent string
7342 // values.
7343 if (!DL.contains("-ni") && !DL.starts_with("ni"))
7344 Res.append("-ni:7:8:9");
7345 // Update ni:7 to ni:7:8:9.
7346 if (DL.ends_with("ni:7"))
7347 Res.append(":8:9");
7348 if (DL.ends_with("ni:7:8"))
7349 Res.append(":9");
7350
7351 // Add sizing for address spaces 7 and 8 (fat raw buffers and buffer
7352 // resources) An empty data layout has already been upgraded to G1 by now.
7353 if (!DL.contains("-p7") && !DL.starts_with("p7"))
7354 Res.append("-p7:160:256:256:32");
7355 if (!DL.contains("-p8") && !DL.starts_with("p8"))
7356 Res.append("-p8:128:128:128:48");
7357 constexpr StringRef OldP8("-p8:128:128-");
7358 if (DL.contains(OldP8))
7359 Res.replace(Res.find(OldP8), OldP8.size(), "-p8:128:128:128:48-");
7360 if (!DL.contains("-p9") && !DL.starts_with("p9"))
7361 Res.append("-p9:192:256:256:32");
7362 }
7363
7364 // Upgrade the ELF mangling mode.
7365 if (!DL.contains("m:e"))
7366 Res = Res.empty() ? "m:e" : "m:e-" + Res;
7367
7368 return Res;
7369 }
7370
7371 if (T.isSystemZ() && !DL.empty()) {
7372 // Make sure the stack alignment is present.
7373 if (!DL.contains("-S64"))
7374 return "E-S64" + DL.drop_front(1).str();
7375 return DL.str();
7376 }
7377
7378 auto AddPtr32Ptr64AddrSpaces = [&DL, &Res]() {
7379 // If the datalayout matches the expected format, add pointer size address
7380 // spaces to the datalayout.
7381 StringRef AddrSpaces{"-p270:32:32-p271:32:32-p272:64:64"};
7382 if (!DL.contains(AddrSpaces)) {
7384 Regex R("^([Ee]-m:[a-z](-p:32:32)?)(-.*)$");
7385 if (R.match(Res, &Groups))
7386 Res = (Groups[1] + AddrSpaces + Groups[3]).str();
7387 }
7388 };
7389
7390 // AArch64 data layout upgrades.
7391 if (T.isAArch64()) {
7392 // Add "-Fn32"
7393 if (!DL.empty() && !DL.contains("-Fn32"))
7394 Res.append("-Fn32");
7395 AddPtr32Ptr64AddrSpaces();
7396 return Res;
7397 }
7398
7399 if (T.isSPARC() || (T.isMIPS64() && !DL.contains("m:m")) || T.isPPC64() ||
7400 T.isWasm()) {
7401 // Mips64 with o32 ABI did not add "-i128:128".
7402 // Add "-i128:128"
7403 std::string I64 = "-i64:64";
7404 std::string I128 = "-i128:128";
7405 if (!StringRef(Res).contains(I128)) {
7406 size_t Pos = Res.find(I64);
7407 if (Pos != size_t(-1))
7408 Res.insert(Pos + I64.size(), I128);
7409 }
7410 }
7411
7412 if (T.isPPC() && T.isOSAIX() && !DL.contains("f64:32:64") && !DL.empty()) {
7413 size_t Pos = Res.find("-S128");
7414 if (Pos == StringRef::npos)
7415 Pos = Res.size();
7416 Res.insert(Pos, "-f64:32:64");
7417 }
7418
7419 if (!T.isX86())
7420 return Res;
7421
7422 AddPtr32Ptr64AddrSpaces();
7423
7424 // i128 values need to be 16-byte-aligned. LLVM already called into libgcc
7425 // for i128 operations prior to this being reflected in the data layout, and
7426 // clang mostly produced LLVM IR that already aligned i128 to 16 byte
7427 // boundaries, so although this is a breaking change, the upgrade is expected
7428 // to fix more IR than it breaks.
7429 // Intel MCU is an exception and uses 4-byte-alignment.
7430 if (!T.isOSIAMCU()) {
7431 std::string I128 = "-i128:128";
7432 if (StringRef Ref = Res; !Ref.contains(I128)) {
7434 Regex R("^(e(-[mpi][^-]*)*)((-[^mpi][^-]*)*)$");
7435 if (R.match(Res, &Groups))
7436 Res = (Groups[1] + I128 + Groups[3]).str();
7437 }
7438 }
7439
7440 // For 32-bit MSVC targets, raise the alignment of f80 values to 16 bytes.
7441 // Raising the alignment is safe because Clang did not produce f80 values in
7442 // the MSVC environment before this upgrade was added.
7443 if (T.isWindowsMSVCEnvironment() && !T.isArch64Bit()) {
7444 StringRef Ref = Res;
7445 auto I = Ref.find("-f80:32-");
7446 if (I != StringRef::npos)
7447 Res = (Ref.take_front(I) + "-f80:128-" + Ref.drop_front(I + 8)).str();
7448 }
7449
7450 return Res;
7451}
7452
7453void llvm::UpgradeAttributes(AttrBuilder &B) {
7454 StringRef FramePointer;
7455 Attribute A = B.getAttribute("no-frame-pointer-elim");
7456 if (A.isValid()) {
7457 // The value can be "true" or "false".
7458 FramePointer = A.getValueAsString() == "true" ? "all" : "none";
7459 B.removeAttribute("no-frame-pointer-elim");
7460 }
7461 if (B.contains("no-frame-pointer-elim-non-leaf")) {
7462 // The value is ignored. "no-frame-pointer-elim"="true" takes priority.
7463 if (FramePointer != "all")
7464 FramePointer = "non-leaf";
7465 B.removeAttribute("no-frame-pointer-elim-non-leaf");
7466 }
7467 if (!FramePointer.empty())
7468 B.addAttribute("frame-pointer", FramePointer);
7469
7470 A = B.getAttribute("null-pointer-is-valid");
7471 if (A.isValid()) {
7472 // The value can be "true" or "false".
7473 bool NullPointerIsValid = A.getValueAsString() == "true";
7474 B.removeAttribute("null-pointer-is-valid");
7475 if (NullPointerIsValid)
7476 B.addAttribute(Attribute::NullPointerIsValid);
7477 }
7478
7479 A = B.getAttribute("uniform-work-group-size");
7480 if (A.isValid()) {
7481 StringRef Val = A.getValueAsString();
7482 if (!Val.empty()) {
7483 bool IsTrue = Val == "true";
7484 B.removeAttribute("uniform-work-group-size");
7485 if (IsTrue)
7486 B.addAttribute("uniform-work-group-size");
7487 }
7488 }
7489}
7490
7491void llvm::UpgradeOperandBundles(std::vector<OperandBundleDef> &Bundles) {
7492 // clang.arc.attachedcall bundles are now required to have an operand.
7493 // If they don't, it's okay to drop them entirely: when there is an operand,
7494 // the "attachedcall" is meaningful and required, but without an operand,
7495 // it's just a marker NOP. Dropping it merely prevents an optimization.
7496 erase_if(Bundles, [&](OperandBundleDef &OBD) {
7497 return OBD.getTag() == "clang.arc.attachedcall" &&
7498 OBD.inputs().empty();
7499 });
7500}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU address space definition.
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static bool upgradeIntrinsicDeclWithDefaultArgs(Function *F, Function *&NewFn)
static Value * upgradeX86VPERMT2Intrinsics(IRBuilder<> &Builder, CallBase &CI, bool ZeroMask, bool IndexForm)
static Metadata * upgradeLoopArgument(Metadata *MD)
static bool isXYZ(StringRef S)
static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn, bool CanUpgradeDebugIntrinsicsToRecords)
static Value * upgradeX86PSLLDQIntrinsics(IRBuilder<> &Builder, Value *Op, unsigned Shift)
static Intrinsic::ID shouldUpgradeNVPTXSharedClusterIntrinsic(Function *F, StringRef Name)
static std::optional< unsigned > getNVPTXTMAReductionOp(StringRef Name)
static Intrinsic::ID shouldUpgradeNVPTXTMAReductionIntrinsics(StringRef Name)
static bool upgradeRetainReleaseMarker(Module &M)
This checks for objc retain release marker which should be upgraded.
static Value * upgradeX86vpcom(IRBuilder<> &Builder, CallBase &CI, unsigned Imm, bool IsSigned)
static Value * upgradeMaskToInt(IRBuilder<> &Builder, CallBase &CI)
static bool convertIntrinsicValidType(StringRef Name, const FunctionType *FuncTy)
static Value * upgradeX86Rotate(IRBuilder<> &Builder, CallBase &CI, bool IsRotateRight)
static bool upgradeX86MultiplyAddBytes(Function *F, Intrinsic::ID IID, Function *&NewFn)
static void setFunctionAttrIfNotSet(Function &F, StringRef FnAttrName, StringRef Value)
static Intrinsic::ID shouldUpgradeNVPTXBF16Intrinsic(StringRef Name)
static bool upgradeSingleNVVMAnnotation(GlobalValue *GV, StringRef K, const Metadata *V)
static MDNode * unwrapMAVOp(CallBase *CI, unsigned Op)
Helper to unwrap intrinsic call MetadataAsValue operands.
static MDString * upgradeLoopTag(LLVMContext &C, StringRef OldTag)
static void upgradeNVVMFnVectorAttr(const StringRef Attr, const char DimC, GlobalValue *GV, const Metadata *V)
static bool upgradeX86MaskedFPCompare(Function *F, Intrinsic::ID IID, Function *&NewFn)
static Value * upgradeX86ALIGNIntrinsics(IRBuilder<> &Builder, Value *Op0, Value *Op1, Value *Shift, Value *Passthru, Value *Mask, bool IsVALIGN)
static Value * upgradeAbs(IRBuilder<> &Builder, CallBase &CI)
static Value * emitX86Select(IRBuilder<> &Builder, Value *Mask, Value *Op0, Value *Op1)
static Value * upgradeAArch64IntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static Value * upgradeMaskedMove(IRBuilder<> &Builder, CallBase &CI)
static const BooleanLoopTags * getOldBooleanLoopTags(const MDTuple *T)
Return the replacement tags if T still uses a removed two-operand form.
static bool upgradeX86IntrinsicFunction(Function *F, StringRef Name, Function *&NewFn)
static Value * applyX86MaskOn1BitsVec(IRBuilder<> &Builder, Value *Vec, Value *Mask)
static std::optional< StringRef > getModuleFlagNameSafely(const MDNode &Flag)
static bool consumeNVVMPtrAddrSpace(StringRef &Name)
static Metadata * makeBooleanLoopNode(LLVMContext &C, const BooleanLoopTags &Tags, const MDOperand &Op)
Build the single-operand node that replaces a boolean operand: nonzero selects the enable tag,...
static bool shouldUpgradeX86Intrinsic(Function *F, StringRef Name)
static Value * upgradeX86PSRLDQIntrinsics(IRBuilder<> &Builder, Value *Op, unsigned Shift)
static Intrinsic::ID shouldUpgradeNVPTXTcgen05CommitSharedIntrinsic(Function *F, StringRef Name)
static Intrinsic::ID shouldUpgradeNVPTXTMAG2SIntrinsics(Function *F, StringRef Name)
static bool isOldLoopArgument(Metadata *MD)
static Value * upgradeARMIntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static bool upgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID, Function *&NewFn)
static Value * upgradeVectorSplice(CallBase *CI, IRBuilder<> &Builder)
static Value * upgradeAMDGCNIntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static Value * upgradeMaskedLoad(IRBuilder<> &Builder, Value *Ptr, Value *Passthru, Value *Mask, bool Aligned)
static Metadata * unwrapMAVMetadataOp(CallBase *CI, unsigned Op)
Helper to unwrap Metadata MetadataAsValue operands, such as the Value field.
static bool upgradeX86BF16Intrinsic(Function *F, Intrinsic::ID IID, Function *&NewFn)
static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F, StringRef Name, Function *&NewFn)
static bool upgradeIntrinsicCallWithDefaultArgs(CallBase *CI, Function *NewFn, IRBuilder<> &Builder)
static Value * getX86MaskVec(IRBuilder<> &Builder, Value *Mask, unsigned NumElts)
static Value * emitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask, Value *Op0, Value *Op1)
static Value * upgradeX86ConcatShift(IRBuilder<> &Builder, CallBase &CI, bool IsShiftRight, bool ZeroMask)
static Intrinsic::ID shouldUpgradeNVPTXTcgen05MMAIntrinsic(Function *F, StringRef Name)
static void rename(GlobalValue *GV)
static bool upgradePTESTIntrinsic(Function *F, Intrinsic::ID IID, Function *&NewFn)
static bool upgradeX86BF16DPIntrinsic(Function *F, Intrinsic::ID IID, Function *&NewFn)
static cl::opt< bool > DisableAutoUpgradeDebugInfo("disable-auto-upgrade-debug-info", cl::desc("Disable autoupgrade of debug info"))
static Value * upgradeMaskedCompare(IRBuilder<> &Builder, CallBase &CI, unsigned CC, bool Signed)
static Value * upgradeX86BinaryIntrinsics(IRBuilder<> &Builder, CallBase &CI, Intrinsic::ID IID)
static Value * upgradeNVVMIntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static Value * upgradeX86MaskedShift(IRBuilder<> &Builder, CallBase &CI, Intrinsic::ID IID)
static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder, CallBase &CI, Value *&Rep)
static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI)
Convert debug intrinsic calls to non-instruction debug records.
static void ConvertFunctionAttr(Function &F, bool Set, StringRef FnAttrName)
static Value * upgradePMULDQ(IRBuilder<> &Builder, CallBase &CI, bool IsSigned)
static void reportFatalUsageErrorWithCI(StringRef reason, CallBase *CI)
static Value * upgradeMaskedStore(IRBuilder<> &Builder, Value *Ptr, Value *Data, Value *Mask, bool Aligned)
static Value * upgradeConvertIntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static bool upgradeX86MultiplyAddWords(Function *F, Intrinsic::ID IID, Function *&NewFn)
static bool upgradePtrauthInitFiniArrays(Module &M)
static Value * upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F, IRBuilder<> &Builder)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
@ Enable
This file contains constants used for implementing Dwarf debug support.
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Definition Lint.cpp:539
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define R2(n)
This file contains the declarations for metadata subclasses.
#define T
#define T1
NVPTX address space definition.
uint64_t High
This file contains the definitions of the enumerations and flags associated with NVVM Intrinsics,...
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file contains some functions that are useful when dealing with strings.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
static const X86InstrFMA3Group Groups[]
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Type * getElementType() const
an instruction that atomically reads a memory location, combines it with another value,...
void setVolatile(bool V)
Specify whether this is a volatile RMW or not.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Add
*p = old + v
@ FAdd
*p = old + v
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ And
*p = old & v
@ Xor
*p = old ^ v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
bool isFloatingPointOperation() const
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
static LLVM_ABI Attribute getWithStackAlignment(LLVMContext &Context, Align Alignment)
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
LLVM_ABI void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void setCalledOperand(Value *V)
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
static LLVM_ABI CastInst * Create(Instruction::CastOps, Value *S, Type *Ty, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Provides a way to construct any of the CastInst subclasses using an opcode instead of the subclass's ...
static LLVM_ABI bool castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy)
This method can be used to determine if a cast from SrcTy to DstTy using Opcode op is valid or not.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
StructType * getType() const
Specialization - reduce amount of casting.
Definition Constants.h:661
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DWARF expression.
static LLVM_ABI DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static LLVM_ABI DbgLabelRecord * createUnresolvedDbgLabelRecord(MDNode *Label)
For use during parsing; creates a DbgLabelRecord from as-of-yet unresolved MDNodes.
Base class for non-instruction debug metadata records that have positions within IR.
void setDebugLoc(DebugLoc Loc)
static LLVM_ABI DbgVariableRecord * createUnresolvedDbgVariableRecord(LocationType Type, Metadata *Val, MDNode *Variable, MDNode *Expression, MDNode *AssignID, Metadata *Address, MDNode *AddressExpression)
Used to create DbgVariableRecords during parsing, where some metadata references may still be unresol...
Diagnostic information for debug metadata version reporting.
Diagnostic information for stripping invalid debug metadata.
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
void setApproxFunc(bool B=true)
Definition FMF.h:93
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
Type * getReturnType() const
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:246
const Function & getFunction() const
Definition Function.h:166
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition Function.cpp:448
size_t arg_size() const
Definition Function.h:885
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
Argument * getArg(unsigned i) const
Definition Function.h:870
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
Definition Globals.cpp:80
LinkageTypes getLinkage() const
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Definition IRBuilder.h:577
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
Base class for instruction visitors.
Definition InstVisitor.h:78
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY
Convenience function for getting all the fast-math flags, which must be an operator which supports th...
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI SyncScope::ID getOrInsertSyncScopeID(StringRef SSN)
getOrInsertSyncScopeID - Maps synchronization scope name to synchronization scope ID.
An instruction for reading from memory.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
Definition MDBuilder.cpp:96
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
LLVMContext & getContext() const
Definition Metadata.h:1233
Tracking metadata reference owned by Metadata.
Definition Metadata.h:891
A single uniqued string.
Definition Metadata.h:722
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:633
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:615
Tuple of metadata.
Definition Metadata.h:1484
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1513
Metadata wrapper in the Value hierarchy.
Definition Metadata.h:184
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:111
Root of the metadata hierarchy.
Definition Metadata.h:64
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
ModFlagBehavior
This enumeration defines the supported behaviors of module flags.
Definition Module.h:117
@ Override
Uses the specified value, regardless of the behavior or value of the other module.
Definition Module.h:138
@ Error
Emits an error if two values disagree, otherwise the resulting value is that of the operands.
Definition Module.h:120
@ Min
Takes the min of the two values, which are required to be integers.
Definition Module.h:152
@ Max
Takes the max of the two values, which are required to be integers.
Definition Module.h:149
A tuple of MDNodes.
Definition Metadata.h:1755
LLVM_ABI void setOperand(unsigned I, MDNode *New)
LLVM_ABI MDNode * getOperand(unsigned i) const
LLVM_ABI unsigned getNumOperands() const
LLVM_ABI void clearOperands()
Drop all references to this node's operands.
iterator_range< op_iterator > operands()
Definition Metadata.h:1851
LLVM_ABI void addOperand(MDNode *M)
ArrayRef< InputTy > inputs() const
StringRef getTag() const
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI bool match(StringRef String, SmallVectorImpl< StringRef > *Matches=nullptr, std::string *Error=nullptr) const
matches - Match the regex against a given String.
Definition Regex.cpp:83
static LLVM_ABI ScalableVectorType * get(Type *ElementType, unsigned MinNumElts)
Definition Type.cpp:889
ArrayRef< int > getShuffleMask() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
reference emplace_back(ArgTypes &&... Args)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
Definition StringRef.h:888
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
static constexpr size_t npos
Definition StringRef.h:58
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:597
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
Definition StringRef.h:850
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
StringSwitch & StartsWith(StringLiteral S, T Value)
StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:477
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:310
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
Definition Type.h:147
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
static LLVM_ABI IntegerType * getInt16Ty(LLVMContext &C)
Definition Type.cpp:308
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition Type.h:285
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition Type.h:227
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:286
static LLVM_ABI Type * getBFloatTy(LLVMContext &C)
Definition Type.cpp:285
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:284
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:713
bool use_empty() const
Definition Value.h:346
bool hasName() const
Definition Value.h:261
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
Base class of all SIMD vector types.
static VectorType * getInteger(VectorType *VTy)
This static method gets a VectorType with the same number of elements as the input type,...
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ PRIVATE_ADDRESS
Address space for private memory.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
std::optional< ABIType > parseABIType(StringRef S)
Parse the string spelling used by the "float-abi" IR module flag into an ABIType.
Definition CodeGen.h:117
LLVM_ABI std::optional< Function * > remangleIntrinsicFunction(Function *F)
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI ID lookupIntrinsicID(StringRef Name)
This does the actual lookup of an intrinsic ID which matches the given function name.
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LLVM_ABI bool isOverloaded(ID id)
Returns true if the intrinsic can be overloaded.
LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT, SmallVectorImpl< Type * > &OverloadTys, raw_ostream &OS=nulls())
Returns true if FT is a valid function type for intrinsic ID.
LLVM_ABI bool hasStructReturnType(ID id)
Returns true if id has a struct return type.
LLVM_ABI std::pair< unsigned, ArrayRef< uint64_t > > getAllDefaultArgValues(ID IID)
Returns the first default argument index and an ArrayRef of all default values for the trailing param...
constexpr StringLiteral GridConstant("nvvm.grid_constant")
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxNReg("nvvm.maxnreg")
constexpr StringLiteral MinCTASm("nvvm.minctasm")
constexpr StringLiteral ReqNTID("nvvm.reqntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
constexpr StringLiteral ClusterDim("nvvm.cluster_dim")
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:709
std::enable_if_t< detail::IsValidPointer< X, Y >::value, bool > hasa(Y &&MD)
Check whether Metadata has a Value.
Definition Metadata.h:651
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:696
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
@ Length
Definition DWP.cpp:578
LLVM_ABI void UpgradeIntrinsicCall(CallBase *CB, Function *NewFn)
This is the complement to the above, replacing a specific call to an intrinsic function with a call t...
LLVM_ABI void UpgradeSectionAttributes(Module &M)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
LLVM_ABI void UpgradeInlineAsmString(std::string *AsmStr)
Upgrade comment in call to inline asm that represents an objc retain release marker.
bool isValidAtomicOrdering(Int I)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
StringRef getLongDoubleFormatName(LongDoubleFormat Format)
Returns the IR floating-point type name for a LongDoubleFormat.
Definition CodeGen.h:76
LongDoubleFormat
The floating-point format used for the target's "long double" type.
Definition CodeGen.h:67
LLVM_ABI bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn, bool CanUpgradeDebugIntrinsicsToRecords=true)
This is a more granular function that simply checks an intrinsic function for upgrading,...
LLVM_ABI MDNode * upgradeInstructionLoopAttachment(MDNode &N)
Upgrade the loop attachment metadata node.
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI void UpgradeAttributes(AttrBuilder &B)
Upgrade attributes that changed format or kind.
LLVM_ABI void UpgradeCallsToIntrinsic(Function *F)
This is an auto-upgrade hook for any old intrinsic function syntaxes which need to have both the func...
LLVM_ABI void UpgradeNVVMAnnotations(Module &M)
Convert legacy nvvm.annotations metadata to appropriate function attributes.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
LLVM_ABI bool UpgradeModuleFlags(Module &M)
This checks for module flags which should be upgraded.
std::string utostr(uint64_t X, bool isNeg=false)
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
LLVM_ABI bool UpgradeCFIFunctionsMetadata(Module &M)
Upgrade the cfi.functions metadata node by calculating and inserting the GUID for each function entry...
LLVM_ABI void copyModuleAttrToFunctions(Module &M)
Copies module attributes to the functions in the module.
LLVM_ABI void UpgradeOperandBundles(std::vector< OperandBundleDef > &OperandBundles)
Upgrade operand bundles (without knowing about their user instruction).
LLVM_ABI Constant * UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy)
This is an auto-upgrade for bitcast constant expression between pointers with different address space...
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI std::string UpgradeDataLayoutString(StringRef DL, StringRef Triple)
Upgrade the datalayout string by adding a section for address space pointers.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI GlobalVariable * UpgradeGlobalVariable(GlobalVariable *GV)
This checks for global variables which should be upgraded.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
const BooleanLoopTags * findBooleanLoopTags(StringRef Name)
Return the replacement tags for the enable tag Name, or nullptr.
OperandBundleDefT< Value * > OperandBundleDef
Definition AutoUpgrade.h:34
LLVM_ABI Instruction * UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy, Instruction *&Temp)
This is an auto-upgrade for bitcast between pointers with different address spaces: the instruction i...
DWARFExpression::Operation Op
@ Dynamic
Denotes mode unknown at compile time.
ArrayRef(const T &OneElt) -> ArrayRef< T >
DenormalMode parseDenormalFPAttribute(StringRef Str)
Returns the denormal mode to use for inputs and outputs.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2192
LLVM_ABI bool UpgradeDebugInfo(Module &M)
Check the debug info version number, if it is out-dated, drop the debug info.
LLVM_ABI void UpgradeFunctionAttributes(Function &F)
Correct any IR that is relying on old function attribute behavior.
LLVM_ABI MDNode * UpgradeTBAANode(MDNode &TBAANode)
If the given TBAA tag uses the scalar TBAA format, create a new node corresponding to the upgrade to ...
LLVM_ABI void UpgradeARCRuntime(Module &M)
Convert calls to ARC runtime functions to intrinsic calls and upgrade the old retain release marker t...
@ DEBUG_METADATA_VERSION
Definition Metadata.h:54
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Single-operand tags replacing a removed two-operand form !
StringLiteral Disable
StringLiteral Enable
Represents the full denormal controls for a function, including the default mode and the f32 specific...
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getInvalid()
constexpr bool isValid() const
static constexpr DenormalMode getIEEE()
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106