109467b48Spatrick //===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the auto-upgrade helper functions.
1009467b48Spatrick // This is where deprecated IR intrinsics and other IR features are updated to
1109467b48Spatrick // current specifications.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick
1509467b48Spatrick #include "llvm/IR/AutoUpgrade.h"
1609467b48Spatrick #include "llvm/ADT/StringSwitch.h"
17*d415bd75Srobert #include "llvm/ADT/Triple.h"
1809467b48Spatrick #include "llvm/IR/Constants.h"
1909467b48Spatrick #include "llvm/IR/DebugInfo.h"
2009467b48Spatrick #include "llvm/IR/DiagnosticInfo.h"
2109467b48Spatrick #include "llvm/IR/Function.h"
2209467b48Spatrick #include "llvm/IR/IRBuilder.h"
23097a140dSpatrick #include "llvm/IR/InstVisitor.h"
2473471bf0Spatrick #include "llvm/IR/Instruction.h"
2509467b48Spatrick #include "llvm/IR/IntrinsicInst.h"
2673471bf0Spatrick #include "llvm/IR/Intrinsics.h"
2709467b48Spatrick #include "llvm/IR/IntrinsicsAArch64.h"
2809467b48Spatrick #include "llvm/IR/IntrinsicsARM.h"
29*d415bd75Srobert #include "llvm/IR/IntrinsicsWebAssembly.h"
3009467b48Spatrick #include "llvm/IR/IntrinsicsX86.h"
3109467b48Spatrick #include "llvm/IR/LLVMContext.h"
3209467b48Spatrick #include "llvm/IR/Module.h"
3309467b48Spatrick #include "llvm/IR/Verifier.h"
3409467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3509467b48Spatrick #include "llvm/Support/Regex.h"
3609467b48Spatrick #include <cstring>
3709467b48Spatrick using namespace llvm;
3809467b48Spatrick
rename(GlobalValue * GV)3909467b48Spatrick static void rename(GlobalValue *GV) { GV->setName(GV->getName() + ".old"); }
4009467b48Spatrick
4109467b48Spatrick // Upgrade the declarations of the SSE4.1 ptest intrinsics whose arguments have
4209467b48Spatrick // changed their type from v4f32 to v2i64.
UpgradePTESTIntrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)4309467b48Spatrick static bool UpgradePTESTIntrinsic(Function* F, Intrinsic::ID IID,
4409467b48Spatrick Function *&NewFn) {
4509467b48Spatrick // Check whether this is an old version of the function, which received
4609467b48Spatrick // v4f32 arguments.
4709467b48Spatrick Type *Arg0Type = F->getFunctionType()->getParamType(0);
48097a140dSpatrick if (Arg0Type != FixedVectorType::get(Type::getFloatTy(F->getContext()), 4))
4909467b48Spatrick return false;
5009467b48Spatrick
5109467b48Spatrick // Yes, it's old, replace it with new version.
5209467b48Spatrick rename(F);
5309467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
5409467b48Spatrick return true;
5509467b48Spatrick }
5609467b48Spatrick
5709467b48Spatrick // Upgrade the declarations of intrinsic functions whose 8-bit immediate mask
5809467b48Spatrick // arguments have changed their type from i32 to i8.
UpgradeX86IntrinsicsWith8BitMask(Function * F,Intrinsic::ID IID,Function * & NewFn)5909467b48Spatrick static bool UpgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID,
6009467b48Spatrick Function *&NewFn) {
6109467b48Spatrick // Check that the last argument is an i32.
6209467b48Spatrick Type *LastArgType = F->getFunctionType()->getParamType(
6309467b48Spatrick F->getFunctionType()->getNumParams() - 1);
6409467b48Spatrick if (!LastArgType->isIntegerTy(32))
6509467b48Spatrick return false;
6609467b48Spatrick
6709467b48Spatrick // Move this function aside and map down.
6809467b48Spatrick rename(F);
6909467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
7009467b48Spatrick return true;
7109467b48Spatrick }
7209467b48Spatrick
7373471bf0Spatrick // Upgrade the declaration of fp compare intrinsics that change return type
7473471bf0Spatrick // from scalar to vXi1 mask.
UpgradeX86MaskedFPCompare(Function * F,Intrinsic::ID IID,Function * & NewFn)7573471bf0Spatrick static bool UpgradeX86MaskedFPCompare(Function *F, Intrinsic::ID IID,
7673471bf0Spatrick Function *&NewFn) {
7773471bf0Spatrick // Check if the return type is a vector.
7873471bf0Spatrick if (F->getReturnType()->isVectorTy())
7973471bf0Spatrick return false;
8073471bf0Spatrick
8173471bf0Spatrick rename(F);
8273471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
8373471bf0Spatrick return true;
8473471bf0Spatrick }
8573471bf0Spatrick
UpgradeX86BF16Intrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)86*d415bd75Srobert static bool UpgradeX86BF16Intrinsic(Function *F, Intrinsic::ID IID,
87*d415bd75Srobert Function *&NewFn) {
88*d415bd75Srobert if (F->getReturnType()->getScalarType()->isBFloatTy())
89*d415bd75Srobert return false;
90*d415bd75Srobert
91*d415bd75Srobert rename(F);
92*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
93*d415bd75Srobert return true;
94*d415bd75Srobert }
95*d415bd75Srobert
UpgradeX86BF16DPIntrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)96*d415bd75Srobert static bool UpgradeX86BF16DPIntrinsic(Function *F, Intrinsic::ID IID,
97*d415bd75Srobert Function *&NewFn) {
98*d415bd75Srobert if (F->getFunctionType()->getParamType(1)->getScalarType()->isBFloatTy())
99*d415bd75Srobert return false;
100*d415bd75Srobert
101*d415bd75Srobert rename(F);
102*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
103*d415bd75Srobert return true;
104*d415bd75Srobert }
105*d415bd75Srobert
ShouldUpgradeX86Intrinsic(Function * F,StringRef Name)10609467b48Spatrick static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
10709467b48Spatrick // All of the intrinsics matches below should be marked with which llvm
10809467b48Spatrick // version started autoupgrading them. At some point in the future we would
10909467b48Spatrick // like to use this information to remove upgrade code for some older
11009467b48Spatrick // intrinsics. It is currently undecided how we will determine that future
11109467b48Spatrick // point.
11209467b48Spatrick if (Name == "addcarryx.u32" || // Added in 8.0
11309467b48Spatrick Name == "addcarryx.u64" || // Added in 8.0
11409467b48Spatrick Name == "addcarry.u32" || // Added in 8.0
11509467b48Spatrick Name == "addcarry.u64" || // Added in 8.0
11609467b48Spatrick Name == "subborrow.u32" || // Added in 8.0
11709467b48Spatrick Name == "subborrow.u64" || // Added in 8.0
11809467b48Spatrick Name.startswith("sse2.padds.") || // Added in 8.0
11909467b48Spatrick Name.startswith("sse2.psubs.") || // Added in 8.0
12009467b48Spatrick Name.startswith("sse2.paddus.") || // Added in 8.0
12109467b48Spatrick Name.startswith("sse2.psubus.") || // Added in 8.0
12209467b48Spatrick Name.startswith("avx2.padds.") || // Added in 8.0
12309467b48Spatrick Name.startswith("avx2.psubs.") || // Added in 8.0
12409467b48Spatrick Name.startswith("avx2.paddus.") || // Added in 8.0
12509467b48Spatrick Name.startswith("avx2.psubus.") || // Added in 8.0
12609467b48Spatrick Name.startswith("avx512.padds.") || // Added in 8.0
12709467b48Spatrick Name.startswith("avx512.psubs.") || // Added in 8.0
12809467b48Spatrick Name.startswith("avx512.mask.padds.") || // Added in 8.0
12909467b48Spatrick Name.startswith("avx512.mask.psubs.") || // Added in 8.0
13009467b48Spatrick Name.startswith("avx512.mask.paddus.") || // Added in 8.0
13109467b48Spatrick Name.startswith("avx512.mask.psubus.") || // Added in 8.0
13209467b48Spatrick Name=="ssse3.pabs.b.128" || // Added in 6.0
13309467b48Spatrick Name=="ssse3.pabs.w.128" || // Added in 6.0
13409467b48Spatrick Name=="ssse3.pabs.d.128" || // Added in 6.0
13509467b48Spatrick Name.startswith("fma4.vfmadd.s") || // Added in 7.0
13609467b48Spatrick Name.startswith("fma.vfmadd.") || // Added in 7.0
13709467b48Spatrick Name.startswith("fma.vfmsub.") || // Added in 7.0
13809467b48Spatrick Name.startswith("fma.vfmsubadd.") || // Added in 7.0
13909467b48Spatrick Name.startswith("fma.vfnmadd.") || // Added in 7.0
14009467b48Spatrick Name.startswith("fma.vfnmsub.") || // Added in 7.0
14109467b48Spatrick Name.startswith("avx512.mask.vfmadd.") || // Added in 7.0
14209467b48Spatrick Name.startswith("avx512.mask.vfnmadd.") || // Added in 7.0
14309467b48Spatrick Name.startswith("avx512.mask.vfnmsub.") || // Added in 7.0
14409467b48Spatrick Name.startswith("avx512.mask3.vfmadd.") || // Added in 7.0
14509467b48Spatrick Name.startswith("avx512.maskz.vfmadd.") || // Added in 7.0
14609467b48Spatrick Name.startswith("avx512.mask3.vfmsub.") || // Added in 7.0
14709467b48Spatrick Name.startswith("avx512.mask3.vfnmsub.") || // Added in 7.0
14809467b48Spatrick Name.startswith("avx512.mask.vfmaddsub.") || // Added in 7.0
14909467b48Spatrick Name.startswith("avx512.maskz.vfmaddsub.") || // Added in 7.0
15009467b48Spatrick Name.startswith("avx512.mask3.vfmaddsub.") || // Added in 7.0
15109467b48Spatrick Name.startswith("avx512.mask3.vfmsubadd.") || // Added in 7.0
15209467b48Spatrick Name.startswith("avx512.mask.shuf.i") || // Added in 6.0
15309467b48Spatrick Name.startswith("avx512.mask.shuf.f") || // Added in 6.0
15409467b48Spatrick Name.startswith("avx512.kunpck") || //added in 6.0
15509467b48Spatrick Name.startswith("avx2.pabs.") || // Added in 6.0
15609467b48Spatrick Name.startswith("avx512.mask.pabs.") || // Added in 6.0
15709467b48Spatrick Name.startswith("avx512.broadcastm") || // Added in 6.0
15809467b48Spatrick Name == "sse.sqrt.ss" || // Added in 7.0
15909467b48Spatrick Name == "sse2.sqrt.sd" || // Added in 7.0
16009467b48Spatrick Name.startswith("avx512.mask.sqrt.p") || // Added in 7.0
16109467b48Spatrick Name.startswith("avx.sqrt.p") || // Added in 7.0
16209467b48Spatrick Name.startswith("sse2.sqrt.p") || // Added in 7.0
16309467b48Spatrick Name.startswith("sse.sqrt.p") || // Added in 7.0
16409467b48Spatrick Name.startswith("avx512.mask.pbroadcast") || // Added in 6.0
16509467b48Spatrick Name.startswith("sse2.pcmpeq.") || // Added in 3.1
16609467b48Spatrick Name.startswith("sse2.pcmpgt.") || // Added in 3.1
16709467b48Spatrick Name.startswith("avx2.pcmpeq.") || // Added in 3.1
16809467b48Spatrick Name.startswith("avx2.pcmpgt.") || // Added in 3.1
16909467b48Spatrick Name.startswith("avx512.mask.pcmpeq.") || // Added in 3.9
17009467b48Spatrick Name.startswith("avx512.mask.pcmpgt.") || // Added in 3.9
17109467b48Spatrick Name.startswith("avx.vperm2f128.") || // Added in 6.0
17209467b48Spatrick Name == "avx2.vperm2i128" || // Added in 6.0
17309467b48Spatrick Name == "sse.add.ss" || // Added in 4.0
17409467b48Spatrick Name == "sse2.add.sd" || // Added in 4.0
17509467b48Spatrick Name == "sse.sub.ss" || // Added in 4.0
17609467b48Spatrick Name == "sse2.sub.sd" || // Added in 4.0
17709467b48Spatrick Name == "sse.mul.ss" || // Added in 4.0
17809467b48Spatrick Name == "sse2.mul.sd" || // Added in 4.0
17909467b48Spatrick Name == "sse.div.ss" || // Added in 4.0
18009467b48Spatrick Name == "sse2.div.sd" || // Added in 4.0
18109467b48Spatrick Name == "sse41.pmaxsb" || // Added in 3.9
18209467b48Spatrick Name == "sse2.pmaxs.w" || // Added in 3.9
18309467b48Spatrick Name == "sse41.pmaxsd" || // Added in 3.9
18409467b48Spatrick Name == "sse2.pmaxu.b" || // Added in 3.9
18509467b48Spatrick Name == "sse41.pmaxuw" || // Added in 3.9
18609467b48Spatrick Name == "sse41.pmaxud" || // Added in 3.9
18709467b48Spatrick Name == "sse41.pminsb" || // Added in 3.9
18809467b48Spatrick Name == "sse2.pmins.w" || // Added in 3.9
18909467b48Spatrick Name == "sse41.pminsd" || // Added in 3.9
19009467b48Spatrick Name == "sse2.pminu.b" || // Added in 3.9
19109467b48Spatrick Name == "sse41.pminuw" || // Added in 3.9
19209467b48Spatrick Name == "sse41.pminud" || // Added in 3.9
19309467b48Spatrick Name == "avx512.kand.w" || // Added in 7.0
19409467b48Spatrick Name == "avx512.kandn.w" || // Added in 7.0
19509467b48Spatrick Name == "avx512.knot.w" || // Added in 7.0
19609467b48Spatrick Name == "avx512.kor.w" || // Added in 7.0
19709467b48Spatrick Name == "avx512.kxor.w" || // Added in 7.0
19809467b48Spatrick Name == "avx512.kxnor.w" || // Added in 7.0
19909467b48Spatrick Name == "avx512.kortestc.w" || // Added in 7.0
20009467b48Spatrick Name == "avx512.kortestz.w" || // Added in 7.0
20109467b48Spatrick Name.startswith("avx512.mask.pshuf.b.") || // Added in 4.0
20209467b48Spatrick Name.startswith("avx2.pmax") || // Added in 3.9
20309467b48Spatrick Name.startswith("avx2.pmin") || // Added in 3.9
20409467b48Spatrick Name.startswith("avx512.mask.pmax") || // Added in 4.0
20509467b48Spatrick Name.startswith("avx512.mask.pmin") || // Added in 4.0
20609467b48Spatrick Name.startswith("avx2.vbroadcast") || // Added in 3.8
20709467b48Spatrick Name.startswith("avx2.pbroadcast") || // Added in 3.8
20809467b48Spatrick Name.startswith("avx.vpermil.") || // Added in 3.1
20909467b48Spatrick Name.startswith("sse2.pshuf") || // Added in 3.9
21009467b48Spatrick Name.startswith("avx512.pbroadcast") || // Added in 3.9
21109467b48Spatrick Name.startswith("avx512.mask.broadcast.s") || // Added in 3.9
21209467b48Spatrick Name.startswith("avx512.mask.movddup") || // Added in 3.9
21309467b48Spatrick Name.startswith("avx512.mask.movshdup") || // Added in 3.9
21409467b48Spatrick Name.startswith("avx512.mask.movsldup") || // Added in 3.9
21509467b48Spatrick Name.startswith("avx512.mask.pshuf.d.") || // Added in 3.9
21609467b48Spatrick Name.startswith("avx512.mask.pshufl.w.") || // Added in 3.9
21709467b48Spatrick Name.startswith("avx512.mask.pshufh.w.") || // Added in 3.9
21809467b48Spatrick Name.startswith("avx512.mask.shuf.p") || // Added in 4.0
21909467b48Spatrick Name.startswith("avx512.mask.vpermil.p") || // Added in 3.9
22009467b48Spatrick Name.startswith("avx512.mask.perm.df.") || // Added in 3.9
22109467b48Spatrick Name.startswith("avx512.mask.perm.di.") || // Added in 3.9
22209467b48Spatrick Name.startswith("avx512.mask.punpckl") || // Added in 3.9
22309467b48Spatrick Name.startswith("avx512.mask.punpckh") || // Added in 3.9
22409467b48Spatrick Name.startswith("avx512.mask.unpckl.") || // Added in 3.9
22509467b48Spatrick Name.startswith("avx512.mask.unpckh.") || // Added in 3.9
22609467b48Spatrick Name.startswith("avx512.mask.pand.") || // Added in 3.9
22709467b48Spatrick Name.startswith("avx512.mask.pandn.") || // Added in 3.9
22809467b48Spatrick Name.startswith("avx512.mask.por.") || // Added in 3.9
22909467b48Spatrick Name.startswith("avx512.mask.pxor.") || // Added in 3.9
23009467b48Spatrick Name.startswith("avx512.mask.and.") || // Added in 3.9
23109467b48Spatrick Name.startswith("avx512.mask.andn.") || // Added in 3.9
23209467b48Spatrick Name.startswith("avx512.mask.or.") || // Added in 3.9
23309467b48Spatrick Name.startswith("avx512.mask.xor.") || // Added in 3.9
23409467b48Spatrick Name.startswith("avx512.mask.padd.") || // Added in 4.0
23509467b48Spatrick Name.startswith("avx512.mask.psub.") || // Added in 4.0
23609467b48Spatrick Name.startswith("avx512.mask.pmull.") || // Added in 4.0
23709467b48Spatrick Name.startswith("avx512.mask.cvtdq2pd.") || // Added in 4.0
23809467b48Spatrick Name.startswith("avx512.mask.cvtudq2pd.") || // Added in 4.0
23909467b48Spatrick Name.startswith("avx512.mask.cvtudq2ps.") || // Added in 7.0 updated 9.0
24009467b48Spatrick Name.startswith("avx512.mask.cvtqq2pd.") || // Added in 7.0 updated 9.0
24109467b48Spatrick Name.startswith("avx512.mask.cvtuqq2pd.") || // Added in 7.0 updated 9.0
24209467b48Spatrick Name.startswith("avx512.mask.cvtdq2ps.") || // Added in 7.0 updated 9.0
243097a140dSpatrick Name == "avx512.mask.vcvtph2ps.128" || // Added in 11.0
244097a140dSpatrick Name == "avx512.mask.vcvtph2ps.256" || // Added in 11.0
24509467b48Spatrick Name == "avx512.mask.cvtqq2ps.256" || // Added in 9.0
24609467b48Spatrick Name == "avx512.mask.cvtqq2ps.512" || // Added in 9.0
24709467b48Spatrick Name == "avx512.mask.cvtuqq2ps.256" || // Added in 9.0
24809467b48Spatrick Name == "avx512.mask.cvtuqq2ps.512" || // Added in 9.0
24909467b48Spatrick Name == "avx512.mask.cvtpd2dq.256" || // Added in 7.0
25009467b48Spatrick Name == "avx512.mask.cvtpd2ps.256" || // Added in 7.0
25109467b48Spatrick Name == "avx512.mask.cvttpd2dq.256" || // Added in 7.0
25209467b48Spatrick Name == "avx512.mask.cvttps2dq.128" || // Added in 7.0
25309467b48Spatrick Name == "avx512.mask.cvttps2dq.256" || // Added in 7.0
25409467b48Spatrick Name == "avx512.mask.cvtps2pd.128" || // Added in 7.0
25509467b48Spatrick Name == "avx512.mask.cvtps2pd.256" || // Added in 7.0
25609467b48Spatrick Name == "avx512.cvtusi2sd" || // Added in 7.0
25709467b48Spatrick Name.startswith("avx512.mask.permvar.") || // Added in 7.0
25809467b48Spatrick Name == "sse2.pmulu.dq" || // Added in 7.0
25909467b48Spatrick Name == "sse41.pmuldq" || // Added in 7.0
26009467b48Spatrick Name == "avx2.pmulu.dq" || // Added in 7.0
26109467b48Spatrick Name == "avx2.pmul.dq" || // Added in 7.0
26209467b48Spatrick Name == "avx512.pmulu.dq.512" || // Added in 7.0
26309467b48Spatrick Name == "avx512.pmul.dq.512" || // Added in 7.0
26409467b48Spatrick Name.startswith("avx512.mask.pmul.dq.") || // Added in 4.0
26509467b48Spatrick Name.startswith("avx512.mask.pmulu.dq.") || // Added in 4.0
26609467b48Spatrick Name.startswith("avx512.mask.pmul.hr.sw.") || // Added in 7.0
26709467b48Spatrick Name.startswith("avx512.mask.pmulh.w.") || // Added in 7.0
26809467b48Spatrick Name.startswith("avx512.mask.pmulhu.w.") || // Added in 7.0
26909467b48Spatrick Name.startswith("avx512.mask.pmaddw.d.") || // Added in 7.0
27009467b48Spatrick Name.startswith("avx512.mask.pmaddubs.w.") || // Added in 7.0
27109467b48Spatrick Name.startswith("avx512.mask.packsswb.") || // Added in 5.0
27209467b48Spatrick Name.startswith("avx512.mask.packssdw.") || // Added in 5.0
27309467b48Spatrick Name.startswith("avx512.mask.packuswb.") || // Added in 5.0
27409467b48Spatrick Name.startswith("avx512.mask.packusdw.") || // Added in 5.0
27509467b48Spatrick Name.startswith("avx512.mask.cmp.b") || // Added in 5.0
27609467b48Spatrick Name.startswith("avx512.mask.cmp.d") || // Added in 5.0
27709467b48Spatrick Name.startswith("avx512.mask.cmp.q") || // Added in 5.0
27809467b48Spatrick Name.startswith("avx512.mask.cmp.w") || // Added in 5.0
27973471bf0Spatrick Name.startswith("avx512.cmp.p") || // Added in 12.0
28009467b48Spatrick Name.startswith("avx512.mask.ucmp.") || // Added in 5.0
28109467b48Spatrick Name.startswith("avx512.cvtb2mask.") || // Added in 7.0
28209467b48Spatrick Name.startswith("avx512.cvtw2mask.") || // Added in 7.0
28309467b48Spatrick Name.startswith("avx512.cvtd2mask.") || // Added in 7.0
28409467b48Spatrick Name.startswith("avx512.cvtq2mask.") || // Added in 7.0
28509467b48Spatrick Name.startswith("avx512.mask.vpermilvar.") || // Added in 4.0
28609467b48Spatrick Name.startswith("avx512.mask.psll.d") || // Added in 4.0
28709467b48Spatrick Name.startswith("avx512.mask.psll.q") || // Added in 4.0
28809467b48Spatrick Name.startswith("avx512.mask.psll.w") || // Added in 4.0
28909467b48Spatrick Name.startswith("avx512.mask.psra.d") || // Added in 4.0
29009467b48Spatrick Name.startswith("avx512.mask.psra.q") || // Added in 4.0
29109467b48Spatrick Name.startswith("avx512.mask.psra.w") || // Added in 4.0
29209467b48Spatrick Name.startswith("avx512.mask.psrl.d") || // Added in 4.0
29309467b48Spatrick Name.startswith("avx512.mask.psrl.q") || // Added in 4.0
29409467b48Spatrick Name.startswith("avx512.mask.psrl.w") || // Added in 4.0
29509467b48Spatrick Name.startswith("avx512.mask.pslli") || // Added in 4.0
29609467b48Spatrick Name.startswith("avx512.mask.psrai") || // Added in 4.0
29709467b48Spatrick Name.startswith("avx512.mask.psrli") || // Added in 4.0
29809467b48Spatrick Name.startswith("avx512.mask.psllv") || // Added in 4.0
29909467b48Spatrick Name.startswith("avx512.mask.psrav") || // Added in 4.0
30009467b48Spatrick Name.startswith("avx512.mask.psrlv") || // Added in 4.0
30109467b48Spatrick Name.startswith("sse41.pmovsx") || // Added in 3.8
30209467b48Spatrick Name.startswith("sse41.pmovzx") || // Added in 3.9
30309467b48Spatrick Name.startswith("avx2.pmovsx") || // Added in 3.9
30409467b48Spatrick Name.startswith("avx2.pmovzx") || // Added in 3.9
30509467b48Spatrick Name.startswith("avx512.mask.pmovsx") || // Added in 4.0
30609467b48Spatrick Name.startswith("avx512.mask.pmovzx") || // Added in 4.0
30709467b48Spatrick Name.startswith("avx512.mask.lzcnt.") || // Added in 5.0
30809467b48Spatrick Name.startswith("avx512.mask.pternlog.") || // Added in 7.0
30909467b48Spatrick Name.startswith("avx512.maskz.pternlog.") || // Added in 7.0
31009467b48Spatrick Name.startswith("avx512.mask.vpmadd52") || // Added in 7.0
31109467b48Spatrick Name.startswith("avx512.maskz.vpmadd52") || // Added in 7.0
31209467b48Spatrick Name.startswith("avx512.mask.vpermi2var.") || // Added in 7.0
31309467b48Spatrick Name.startswith("avx512.mask.vpermt2var.") || // Added in 7.0
31409467b48Spatrick Name.startswith("avx512.maskz.vpermt2var.") || // Added in 7.0
31509467b48Spatrick Name.startswith("avx512.mask.vpdpbusd.") || // Added in 7.0
31609467b48Spatrick Name.startswith("avx512.maskz.vpdpbusd.") || // Added in 7.0
31709467b48Spatrick Name.startswith("avx512.mask.vpdpbusds.") || // Added in 7.0
31809467b48Spatrick Name.startswith("avx512.maskz.vpdpbusds.") || // Added in 7.0
31909467b48Spatrick Name.startswith("avx512.mask.vpdpwssd.") || // Added in 7.0
32009467b48Spatrick Name.startswith("avx512.maskz.vpdpwssd.") || // Added in 7.0
32109467b48Spatrick Name.startswith("avx512.mask.vpdpwssds.") || // Added in 7.0
32209467b48Spatrick Name.startswith("avx512.maskz.vpdpwssds.") || // Added in 7.0
32309467b48Spatrick Name.startswith("avx512.mask.dbpsadbw.") || // Added in 7.0
32409467b48Spatrick Name.startswith("avx512.mask.vpshld.") || // Added in 7.0
32509467b48Spatrick Name.startswith("avx512.mask.vpshrd.") || // Added in 7.0
32609467b48Spatrick Name.startswith("avx512.mask.vpshldv.") || // Added in 8.0
32709467b48Spatrick Name.startswith("avx512.mask.vpshrdv.") || // Added in 8.0
32809467b48Spatrick Name.startswith("avx512.maskz.vpshldv.") || // Added in 8.0
32909467b48Spatrick Name.startswith("avx512.maskz.vpshrdv.") || // Added in 8.0
33009467b48Spatrick Name.startswith("avx512.vpshld.") || // Added in 8.0
33109467b48Spatrick Name.startswith("avx512.vpshrd.") || // Added in 8.0
33209467b48Spatrick Name.startswith("avx512.mask.add.p") || // Added in 7.0. 128/256 in 4.0
33309467b48Spatrick Name.startswith("avx512.mask.sub.p") || // Added in 7.0. 128/256 in 4.0
33409467b48Spatrick Name.startswith("avx512.mask.mul.p") || // Added in 7.0. 128/256 in 4.0
33509467b48Spatrick Name.startswith("avx512.mask.div.p") || // Added in 7.0. 128/256 in 4.0
33609467b48Spatrick Name.startswith("avx512.mask.max.p") || // Added in 7.0. 128/256 in 5.0
33709467b48Spatrick Name.startswith("avx512.mask.min.p") || // Added in 7.0. 128/256 in 5.0
33809467b48Spatrick Name.startswith("avx512.mask.fpclass.p") || // Added in 7.0
33909467b48Spatrick Name.startswith("avx512.mask.vpshufbitqmb.") || // Added in 8.0
34009467b48Spatrick Name.startswith("avx512.mask.pmultishift.qb.") || // Added in 8.0
34109467b48Spatrick Name.startswith("avx512.mask.conflict.") || // Added in 9.0
34209467b48Spatrick Name == "avx512.mask.pmov.qd.256" || // Added in 9.0
34309467b48Spatrick Name == "avx512.mask.pmov.qd.512" || // Added in 9.0
34409467b48Spatrick Name == "avx512.mask.pmov.wb.256" || // Added in 9.0
34509467b48Spatrick Name == "avx512.mask.pmov.wb.512" || // Added in 9.0
34609467b48Spatrick Name == "sse.cvtsi2ss" || // Added in 7.0
34709467b48Spatrick Name == "sse.cvtsi642ss" || // Added in 7.0
34809467b48Spatrick Name == "sse2.cvtsi2sd" || // Added in 7.0
34909467b48Spatrick Name == "sse2.cvtsi642sd" || // Added in 7.0
35009467b48Spatrick Name == "sse2.cvtss2sd" || // Added in 7.0
35109467b48Spatrick Name == "sse2.cvtdq2pd" || // Added in 3.9
35209467b48Spatrick Name == "sse2.cvtdq2ps" || // Added in 7.0
35309467b48Spatrick Name == "sse2.cvtps2pd" || // Added in 3.9
35409467b48Spatrick Name == "avx.cvtdq2.pd.256" || // Added in 3.9
35509467b48Spatrick Name == "avx.cvtdq2.ps.256" || // Added in 7.0
35609467b48Spatrick Name == "avx.cvt.ps2.pd.256" || // Added in 3.9
357097a140dSpatrick Name.startswith("vcvtph2ps.") || // Added in 11.0
35809467b48Spatrick Name.startswith("avx.vinsertf128.") || // Added in 3.7
35909467b48Spatrick Name == "avx2.vinserti128" || // Added in 3.7
36009467b48Spatrick Name.startswith("avx512.mask.insert") || // Added in 4.0
36109467b48Spatrick Name.startswith("avx.vextractf128.") || // Added in 3.7
36209467b48Spatrick Name == "avx2.vextracti128" || // Added in 3.7
36309467b48Spatrick Name.startswith("avx512.mask.vextract") || // Added in 4.0
36409467b48Spatrick Name.startswith("sse4a.movnt.") || // Added in 3.9
36509467b48Spatrick Name.startswith("avx.movnt.") || // Added in 3.2
36609467b48Spatrick Name.startswith("avx512.storent.") || // Added in 3.9
36709467b48Spatrick Name == "sse41.movntdqa" || // Added in 5.0
36809467b48Spatrick Name == "avx2.movntdqa" || // Added in 5.0
36909467b48Spatrick Name == "avx512.movntdqa" || // Added in 5.0
37009467b48Spatrick Name == "sse2.storel.dq" || // Added in 3.9
37109467b48Spatrick Name.startswith("sse.storeu.") || // Added in 3.9
37209467b48Spatrick Name.startswith("sse2.storeu.") || // Added in 3.9
37309467b48Spatrick Name.startswith("avx.storeu.") || // Added in 3.9
37409467b48Spatrick Name.startswith("avx512.mask.storeu.") || // Added in 3.9
37509467b48Spatrick Name.startswith("avx512.mask.store.p") || // Added in 3.9
37609467b48Spatrick Name.startswith("avx512.mask.store.b.") || // Added in 3.9
37709467b48Spatrick Name.startswith("avx512.mask.store.w.") || // Added in 3.9
37809467b48Spatrick Name.startswith("avx512.mask.store.d.") || // Added in 3.9
37909467b48Spatrick Name.startswith("avx512.mask.store.q.") || // Added in 3.9
38009467b48Spatrick Name == "avx512.mask.store.ss" || // Added in 7.0
38109467b48Spatrick Name.startswith("avx512.mask.loadu.") || // Added in 3.9
38209467b48Spatrick Name.startswith("avx512.mask.load.") || // Added in 3.9
38309467b48Spatrick Name.startswith("avx512.mask.expand.load.") || // Added in 7.0
38409467b48Spatrick Name.startswith("avx512.mask.compress.store.") || // Added in 7.0
38509467b48Spatrick Name.startswith("avx512.mask.expand.b") || // Added in 9.0
38609467b48Spatrick Name.startswith("avx512.mask.expand.w") || // Added in 9.0
38709467b48Spatrick Name.startswith("avx512.mask.expand.d") || // Added in 9.0
38809467b48Spatrick Name.startswith("avx512.mask.expand.q") || // Added in 9.0
38909467b48Spatrick Name.startswith("avx512.mask.expand.p") || // Added in 9.0
39009467b48Spatrick Name.startswith("avx512.mask.compress.b") || // Added in 9.0
39109467b48Spatrick Name.startswith("avx512.mask.compress.w") || // Added in 9.0
39209467b48Spatrick Name.startswith("avx512.mask.compress.d") || // Added in 9.0
39309467b48Spatrick Name.startswith("avx512.mask.compress.q") || // Added in 9.0
39409467b48Spatrick Name.startswith("avx512.mask.compress.p") || // Added in 9.0
39509467b48Spatrick Name == "sse42.crc32.64.8" || // Added in 3.4
39609467b48Spatrick Name.startswith("avx.vbroadcast.s") || // Added in 3.5
39709467b48Spatrick Name.startswith("avx512.vbroadcast.s") || // Added in 7.0
39809467b48Spatrick Name.startswith("avx512.mask.palignr.") || // Added in 3.9
39909467b48Spatrick Name.startswith("avx512.mask.valign.") || // Added in 4.0
40009467b48Spatrick Name.startswith("sse2.psll.dq") || // Added in 3.7
40109467b48Spatrick Name.startswith("sse2.psrl.dq") || // Added in 3.7
40209467b48Spatrick Name.startswith("avx2.psll.dq") || // Added in 3.7
40309467b48Spatrick Name.startswith("avx2.psrl.dq") || // Added in 3.7
40409467b48Spatrick Name.startswith("avx512.psll.dq") || // Added in 3.9
40509467b48Spatrick Name.startswith("avx512.psrl.dq") || // Added in 3.9
40609467b48Spatrick Name == "sse41.pblendw" || // Added in 3.7
40709467b48Spatrick Name.startswith("sse41.blendp") || // Added in 3.7
40809467b48Spatrick Name.startswith("avx.blend.p") || // Added in 3.7
40909467b48Spatrick Name == "avx2.pblendw" || // Added in 3.7
41009467b48Spatrick Name.startswith("avx2.pblendd.") || // Added in 3.7
41109467b48Spatrick Name.startswith("avx.vbroadcastf128") || // Added in 4.0
41209467b48Spatrick Name == "avx2.vbroadcasti128" || // Added in 3.7
413097a140dSpatrick Name.startswith("avx512.mask.broadcastf32x4.") || // Added in 6.0
414097a140dSpatrick Name.startswith("avx512.mask.broadcastf64x2.") || // Added in 6.0
415097a140dSpatrick Name.startswith("avx512.mask.broadcastf32x8.") || // Added in 6.0
416097a140dSpatrick Name.startswith("avx512.mask.broadcastf64x4.") || // Added in 6.0
417097a140dSpatrick Name.startswith("avx512.mask.broadcasti32x4.") || // Added in 6.0
418097a140dSpatrick Name.startswith("avx512.mask.broadcasti64x2.") || // Added in 6.0
419097a140dSpatrick Name.startswith("avx512.mask.broadcasti32x8.") || // Added in 6.0
420097a140dSpatrick Name.startswith("avx512.mask.broadcasti64x4.") || // Added in 6.0
42109467b48Spatrick Name == "xop.vpcmov" || // Added in 3.8
42209467b48Spatrick Name == "xop.vpcmov.256" || // Added in 5.0
42309467b48Spatrick Name.startswith("avx512.mask.move.s") || // Added in 4.0
42409467b48Spatrick Name.startswith("avx512.cvtmask2") || // Added in 5.0
42509467b48Spatrick Name.startswith("xop.vpcom") || // Added in 3.2, Updated in 9.0
42609467b48Spatrick Name.startswith("xop.vprot") || // Added in 8.0
42709467b48Spatrick Name.startswith("avx512.prol") || // Added in 8.0
42809467b48Spatrick Name.startswith("avx512.pror") || // Added in 8.0
42909467b48Spatrick Name.startswith("avx512.mask.prorv.") || // Added in 8.0
43009467b48Spatrick Name.startswith("avx512.mask.pror.") || // Added in 8.0
43109467b48Spatrick Name.startswith("avx512.mask.prolv.") || // Added in 8.0
43209467b48Spatrick Name.startswith("avx512.mask.prol.") || // Added in 8.0
43309467b48Spatrick Name.startswith("avx512.ptestm") || //Added in 6.0
43409467b48Spatrick Name.startswith("avx512.ptestnm") || //Added in 6.0
43509467b48Spatrick Name.startswith("avx512.mask.pavg")) // Added in 6.0
43609467b48Spatrick return true;
43709467b48Spatrick
43809467b48Spatrick return false;
43909467b48Spatrick }
44009467b48Spatrick
UpgradeX86IntrinsicFunction(Function * F,StringRef Name,Function * & NewFn)44109467b48Spatrick static bool UpgradeX86IntrinsicFunction(Function *F, StringRef Name,
44209467b48Spatrick Function *&NewFn) {
44309467b48Spatrick // Only handle intrinsics that start with "x86.".
44409467b48Spatrick if (!Name.startswith("x86."))
44509467b48Spatrick return false;
44609467b48Spatrick // Remove "x86." prefix.
44709467b48Spatrick Name = Name.substr(4);
44809467b48Spatrick
44909467b48Spatrick if (ShouldUpgradeX86Intrinsic(F, Name)) {
45009467b48Spatrick NewFn = nullptr;
45109467b48Spatrick return true;
45209467b48Spatrick }
45309467b48Spatrick
45409467b48Spatrick if (Name == "rdtscp") { // Added in 8.0
45509467b48Spatrick // If this intrinsic has 0 operands, it's the new version.
45609467b48Spatrick if (F->getFunctionType()->getNumParams() == 0)
45709467b48Spatrick return false;
45809467b48Spatrick
45909467b48Spatrick rename(F);
46009467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
46109467b48Spatrick Intrinsic::x86_rdtscp);
46209467b48Spatrick return true;
46309467b48Spatrick }
46409467b48Spatrick
46509467b48Spatrick // SSE4.1 ptest functions may have an old signature.
46609467b48Spatrick if (Name.startswith("sse41.ptest")) { // Added in 3.2
46709467b48Spatrick if (Name.substr(11) == "c")
46809467b48Spatrick return UpgradePTESTIntrinsic(F, Intrinsic::x86_sse41_ptestc, NewFn);
46909467b48Spatrick if (Name.substr(11) == "z")
47009467b48Spatrick return UpgradePTESTIntrinsic(F, Intrinsic::x86_sse41_ptestz, NewFn);
47109467b48Spatrick if (Name.substr(11) == "nzc")
47209467b48Spatrick return UpgradePTESTIntrinsic(F, Intrinsic::x86_sse41_ptestnzc, NewFn);
47309467b48Spatrick }
47409467b48Spatrick // Several blend and other instructions with masks used the wrong number of
47509467b48Spatrick // bits.
47609467b48Spatrick if (Name == "sse41.insertps") // Added in 3.6
47709467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_insertps,
47809467b48Spatrick NewFn);
47909467b48Spatrick if (Name == "sse41.dppd") // Added in 3.6
48009467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dppd,
48109467b48Spatrick NewFn);
48209467b48Spatrick if (Name == "sse41.dpps") // Added in 3.6
48309467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dpps,
48409467b48Spatrick NewFn);
48509467b48Spatrick if (Name == "sse41.mpsadbw") // Added in 3.6
48609467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_mpsadbw,
48709467b48Spatrick NewFn);
48809467b48Spatrick if (Name == "avx.dp.ps.256") // Added in 3.6
48909467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx_dp_ps_256,
49009467b48Spatrick NewFn);
49109467b48Spatrick if (Name == "avx2.mpsadbw") // Added in 3.6
49209467b48Spatrick return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_mpsadbw,
49309467b48Spatrick NewFn);
49473471bf0Spatrick if (Name == "avx512.mask.cmp.pd.128") // Added in 7.0
49573471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_pd_128,
49673471bf0Spatrick NewFn);
49773471bf0Spatrick if (Name == "avx512.mask.cmp.pd.256") // Added in 7.0
49873471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_pd_256,
49973471bf0Spatrick NewFn);
50073471bf0Spatrick if (Name == "avx512.mask.cmp.pd.512") // Added in 7.0
50173471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_pd_512,
50273471bf0Spatrick NewFn);
50373471bf0Spatrick if (Name == "avx512.mask.cmp.ps.128") // Added in 7.0
50473471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_ps_128,
50573471bf0Spatrick NewFn);
50673471bf0Spatrick if (Name == "avx512.mask.cmp.ps.256") // Added in 7.0
50773471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_ps_256,
50873471bf0Spatrick NewFn);
50973471bf0Spatrick if (Name == "avx512.mask.cmp.ps.512") // Added in 7.0
51073471bf0Spatrick return UpgradeX86MaskedFPCompare(F, Intrinsic::x86_avx512_mask_cmp_ps_512,
51173471bf0Spatrick NewFn);
512*d415bd75Srobert if (Name == "avx512bf16.cvtne2ps2bf16.128") // Added in 9.0
513*d415bd75Srobert return UpgradeX86BF16Intrinsic(
514*d415bd75Srobert F, Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128, NewFn);
515*d415bd75Srobert if (Name == "avx512bf16.cvtne2ps2bf16.256") // Added in 9.0
516*d415bd75Srobert return UpgradeX86BF16Intrinsic(
517*d415bd75Srobert F, Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256, NewFn);
518*d415bd75Srobert if (Name == "avx512bf16.cvtne2ps2bf16.512") // Added in 9.0
519*d415bd75Srobert return UpgradeX86BF16Intrinsic(
520*d415bd75Srobert F, Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512, NewFn);
521*d415bd75Srobert if (Name == "avx512bf16.mask.cvtneps2bf16.128") // Added in 9.0
522*d415bd75Srobert return UpgradeX86BF16Intrinsic(
523*d415bd75Srobert F, Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128, NewFn);
524*d415bd75Srobert if (Name == "avx512bf16.cvtneps2bf16.256") // Added in 9.0
525*d415bd75Srobert return UpgradeX86BF16Intrinsic(
526*d415bd75Srobert F, Intrinsic::x86_avx512bf16_cvtneps2bf16_256, NewFn);
527*d415bd75Srobert if (Name == "avx512bf16.cvtneps2bf16.512") // Added in 9.0
528*d415bd75Srobert return UpgradeX86BF16Intrinsic(
529*d415bd75Srobert F, Intrinsic::x86_avx512bf16_cvtneps2bf16_512, NewFn);
530*d415bd75Srobert if (Name == "avx512bf16.dpbf16ps.128") // Added in 9.0
531*d415bd75Srobert return UpgradeX86BF16DPIntrinsic(
532*d415bd75Srobert F, Intrinsic::x86_avx512bf16_dpbf16ps_128, NewFn);
533*d415bd75Srobert if (Name == "avx512bf16.dpbf16ps.256") // Added in 9.0
534*d415bd75Srobert return UpgradeX86BF16DPIntrinsic(
535*d415bd75Srobert F, Intrinsic::x86_avx512bf16_dpbf16ps_256, NewFn);
536*d415bd75Srobert if (Name == "avx512bf16.dpbf16ps.512") // Added in 9.0
537*d415bd75Srobert return UpgradeX86BF16DPIntrinsic(
538*d415bd75Srobert F, Intrinsic::x86_avx512bf16_dpbf16ps_512, NewFn);
53909467b48Spatrick
54009467b48Spatrick // frcz.ss/sd may need to have an argument dropped. Added in 3.2
54109467b48Spatrick if (Name.startswith("xop.vfrcz.ss") && F->arg_size() == 2) {
54209467b48Spatrick rename(F);
54309467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
54409467b48Spatrick Intrinsic::x86_xop_vfrcz_ss);
54509467b48Spatrick return true;
54609467b48Spatrick }
54709467b48Spatrick if (Name.startswith("xop.vfrcz.sd") && F->arg_size() == 2) {
54809467b48Spatrick rename(F);
54909467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
55009467b48Spatrick Intrinsic::x86_xop_vfrcz_sd);
55109467b48Spatrick return true;
55209467b48Spatrick }
55309467b48Spatrick // Upgrade any XOP PERMIL2 index operand still using a float/double vector.
55409467b48Spatrick if (Name.startswith("xop.vpermil2")) { // Added in 3.9
55509467b48Spatrick auto Idx = F->getFunctionType()->getParamType(2);
55609467b48Spatrick if (Idx->isFPOrFPVectorTy()) {
55709467b48Spatrick rename(F);
55809467b48Spatrick unsigned IdxSize = Idx->getPrimitiveSizeInBits();
55909467b48Spatrick unsigned EltSize = Idx->getScalarSizeInBits();
56009467b48Spatrick Intrinsic::ID Permil2ID;
56109467b48Spatrick if (EltSize == 64 && IdxSize == 128)
56209467b48Spatrick Permil2ID = Intrinsic::x86_xop_vpermil2pd;
56309467b48Spatrick else if (EltSize == 32 && IdxSize == 128)
56409467b48Spatrick Permil2ID = Intrinsic::x86_xop_vpermil2ps;
56509467b48Spatrick else if (EltSize == 64 && IdxSize == 256)
56609467b48Spatrick Permil2ID = Intrinsic::x86_xop_vpermil2pd_256;
56709467b48Spatrick else
56809467b48Spatrick Permil2ID = Intrinsic::x86_xop_vpermil2ps_256;
56909467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Permil2ID);
57009467b48Spatrick return true;
57109467b48Spatrick }
57209467b48Spatrick }
57309467b48Spatrick
57409467b48Spatrick if (Name == "seh.recoverfp") {
57509467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
57609467b48Spatrick return true;
57709467b48Spatrick }
57809467b48Spatrick
57909467b48Spatrick return false;
58009467b48Spatrick }
58109467b48Spatrick
UpgradeIntrinsicFunction1(Function * F,Function * & NewFn)58209467b48Spatrick static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
58309467b48Spatrick assert(F && "Illegal to upgrade a non-existent Function.");
58409467b48Spatrick
58509467b48Spatrick // Quickly eliminate it, if it's not a candidate.
58609467b48Spatrick StringRef Name = F->getName();
587*d415bd75Srobert if (Name.size() <= 7 || !Name.startswith("llvm."))
58809467b48Spatrick return false;
58909467b48Spatrick Name = Name.substr(5); // Strip off "llvm."
59009467b48Spatrick
59109467b48Spatrick switch (Name[0]) {
59209467b48Spatrick default: break;
59309467b48Spatrick case 'a': {
59409467b48Spatrick if (Name.startswith("arm.rbit") || Name.startswith("aarch64.rbit")) {
59509467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse,
59609467b48Spatrick F->arg_begin()->getType());
59709467b48Spatrick return true;
59809467b48Spatrick }
59973471bf0Spatrick if (Name.startswith("aarch64.neon.frintn")) {
60073471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::roundeven,
60173471bf0Spatrick F->arg_begin()->getType());
60273471bf0Spatrick return true;
60373471bf0Spatrick }
60473471bf0Spatrick if (Name.startswith("aarch64.neon.rbit")) {
60573471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse,
60673471bf0Spatrick F->arg_begin()->getType());
60773471bf0Spatrick return true;
60873471bf0Spatrick }
609*d415bd75Srobert if (Name == "aarch64.sve.bfdot.lane") {
610*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
611*d415bd75Srobert Intrinsic::aarch64_sve_bfdot_lane_v2);
612*d415bd75Srobert return true;
613*d415bd75Srobert }
614*d415bd75Srobert if (Name == "aarch64.sve.bfmlalb.lane") {
615*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
616*d415bd75Srobert Intrinsic::aarch64_sve_bfmlalb_lane_v2);
617*d415bd75Srobert return true;
618*d415bd75Srobert }
619*d415bd75Srobert if (Name == "aarch64.sve.bfmlalt.lane") {
620*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
621*d415bd75Srobert Intrinsic::aarch64_sve_bfmlalt_lane_v2);
622*d415bd75Srobert return true;
623*d415bd75Srobert }
624*d415bd75Srobert static const Regex LdRegex("^aarch64\\.sve\\.ld[234](.nxv[a-z0-9]+|$)");
625*d415bd75Srobert if (LdRegex.match(Name)) {
626*d415bd75Srobert Type *ScalarTy =
627*d415bd75Srobert dyn_cast<VectorType>(F->getReturnType())->getElementType();
628*d415bd75Srobert ElementCount EC =
629*d415bd75Srobert dyn_cast<VectorType>(F->arg_begin()->getType())->getElementCount();
630*d415bd75Srobert Type *Ty = VectorType::get(ScalarTy, EC);
631*d415bd75Srobert Intrinsic::ID ID =
632*d415bd75Srobert StringSwitch<Intrinsic::ID>(Name)
633*d415bd75Srobert .StartsWith("aarch64.sve.ld2", Intrinsic::aarch64_sve_ld2_sret)
634*d415bd75Srobert .StartsWith("aarch64.sve.ld3", Intrinsic::aarch64_sve_ld3_sret)
635*d415bd75Srobert .StartsWith("aarch64.sve.ld4", Intrinsic::aarch64_sve_ld4_sret)
636*d415bd75Srobert .Default(Intrinsic::not_intrinsic);
637*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Ty);
638*d415bd75Srobert return true;
639*d415bd75Srobert }
640*d415bd75Srobert if (Name.startswith("aarch64.sve.tuple.get")) {
641*d415bd75Srobert Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
642*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
643*d415bd75Srobert Intrinsic::vector_extract, Tys);
644*d415bd75Srobert return true;
645*d415bd75Srobert }
646*d415bd75Srobert if (Name.startswith("aarch64.sve.tuple.set")) {
647*d415bd75Srobert auto Args = F->getFunctionType()->params();
648*d415bd75Srobert Type *Tys[] = {Args[0], Args[2], Args[1]};
649*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
650*d415bd75Srobert Intrinsic::vector_insert, Tys);
651*d415bd75Srobert return true;
652*d415bd75Srobert }
653*d415bd75Srobert static const Regex CreateTupleRegex(
654*d415bd75Srobert "^aarch64\\.sve\\.tuple\\.create[234](.nxv[a-z0-9]+|$)");
655*d415bd75Srobert if (CreateTupleRegex.match(Name)) {
656*d415bd75Srobert auto Args = F->getFunctionType()->params();
657*d415bd75Srobert Type *Tys[] = {F->getReturnType(), Args[1]};
658*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
659*d415bd75Srobert Intrinsic::vector_insert, Tys);
660*d415bd75Srobert return true;
661*d415bd75Srobert }
66209467b48Spatrick if (Name.startswith("arm.neon.vclz")) {
66309467b48Spatrick Type* args[2] = {
66409467b48Spatrick F->arg_begin()->getType(),
66509467b48Spatrick Type::getInt1Ty(F->getContext())
66609467b48Spatrick };
66709467b48Spatrick // Can't use Intrinsic::getDeclaration here as it adds a ".i1" to
66809467b48Spatrick // the end of the name. Change name from llvm.arm.neon.vclz.* to
66909467b48Spatrick // llvm.ctlz.*
67009467b48Spatrick FunctionType* fType = FunctionType::get(F->getReturnType(), args, false);
67109467b48Spatrick NewFn = Function::Create(fType, F->getLinkage(), F->getAddressSpace(),
67209467b48Spatrick "llvm.ctlz." + Name.substr(14), F->getParent());
67309467b48Spatrick return true;
67409467b48Spatrick }
67509467b48Spatrick if (Name.startswith("arm.neon.vcnt")) {
67609467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop,
67709467b48Spatrick F->arg_begin()->getType());
67809467b48Spatrick return true;
67909467b48Spatrick }
68009467b48Spatrick static const Regex vstRegex("^arm\\.neon\\.vst([1234]|[234]lane)\\.v[a-z0-9]*$");
68109467b48Spatrick if (vstRegex.match(Name)) {
68209467b48Spatrick static const Intrinsic::ID StoreInts[] = {Intrinsic::arm_neon_vst1,
68309467b48Spatrick Intrinsic::arm_neon_vst2,
68409467b48Spatrick Intrinsic::arm_neon_vst3,
68509467b48Spatrick Intrinsic::arm_neon_vst4};
68609467b48Spatrick
68709467b48Spatrick static const Intrinsic::ID StoreLaneInts[] = {
68809467b48Spatrick Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane,
68909467b48Spatrick Intrinsic::arm_neon_vst4lane
69009467b48Spatrick };
69109467b48Spatrick
69209467b48Spatrick auto fArgs = F->getFunctionType()->params();
69309467b48Spatrick Type *Tys[] = {fArgs[0], fArgs[1]};
694*d415bd75Srobert if (!Name.contains("lane"))
69509467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
69609467b48Spatrick StoreInts[fArgs.size() - 3], Tys);
69709467b48Spatrick else
69809467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
69909467b48Spatrick StoreLaneInts[fArgs.size() - 5], Tys);
70009467b48Spatrick return true;
70109467b48Spatrick }
70209467b48Spatrick if (Name == "aarch64.thread.pointer" || Name == "arm.thread.pointer") {
70309467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer);
70409467b48Spatrick return true;
70509467b48Spatrick }
70609467b48Spatrick if (Name.startswith("arm.neon.vqadds.")) {
70709467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::sadd_sat,
70809467b48Spatrick F->arg_begin()->getType());
70909467b48Spatrick return true;
71009467b48Spatrick }
71109467b48Spatrick if (Name.startswith("arm.neon.vqaddu.")) {
71209467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::uadd_sat,
71309467b48Spatrick F->arg_begin()->getType());
71409467b48Spatrick return true;
71509467b48Spatrick }
71609467b48Spatrick if (Name.startswith("arm.neon.vqsubs.")) {
71709467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ssub_sat,
71809467b48Spatrick F->arg_begin()->getType());
71909467b48Spatrick return true;
72009467b48Spatrick }
72109467b48Spatrick if (Name.startswith("arm.neon.vqsubu.")) {
72209467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::usub_sat,
72309467b48Spatrick F->arg_begin()->getType());
72409467b48Spatrick return true;
72509467b48Spatrick }
72609467b48Spatrick if (Name.startswith("aarch64.neon.addp")) {
72709467b48Spatrick if (F->arg_size() != 2)
72809467b48Spatrick break; // Invalid IR.
72909467b48Spatrick VectorType *Ty = dyn_cast<VectorType>(F->getReturnType());
73009467b48Spatrick if (Ty && Ty->getElementType()->isFloatingPointTy()) {
73109467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
73209467b48Spatrick Intrinsic::aarch64_neon_faddp, Ty);
73309467b48Spatrick return true;
73409467b48Spatrick }
73509467b48Spatrick }
73673471bf0Spatrick
73773471bf0Spatrick // Changed in 12.0: bfdot accept v4bf16 and v8bf16 instead of v8i8 and v16i8
73873471bf0Spatrick // respectively
73973471bf0Spatrick if ((Name.startswith("arm.neon.bfdot.") ||
74073471bf0Spatrick Name.startswith("aarch64.neon.bfdot.")) &&
74173471bf0Spatrick Name.endswith("i8")) {
74273471bf0Spatrick Intrinsic::ID IID =
74373471bf0Spatrick StringSwitch<Intrinsic::ID>(Name)
74473471bf0Spatrick .Cases("arm.neon.bfdot.v2f32.v8i8",
74573471bf0Spatrick "arm.neon.bfdot.v4f32.v16i8",
74673471bf0Spatrick Intrinsic::arm_neon_bfdot)
74773471bf0Spatrick .Cases("aarch64.neon.bfdot.v2f32.v8i8",
74873471bf0Spatrick "aarch64.neon.bfdot.v4f32.v16i8",
74973471bf0Spatrick Intrinsic::aarch64_neon_bfdot)
75073471bf0Spatrick .Default(Intrinsic::not_intrinsic);
75173471bf0Spatrick if (IID == Intrinsic::not_intrinsic)
75273471bf0Spatrick break;
75373471bf0Spatrick
75473471bf0Spatrick size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits();
75573471bf0Spatrick assert((OperandWidth == 64 || OperandWidth == 128) &&
75673471bf0Spatrick "Unexpected operand width");
75773471bf0Spatrick LLVMContext &Ctx = F->getParent()->getContext();
75873471bf0Spatrick std::array<Type *, 2> Tys {{
75973471bf0Spatrick F->getReturnType(),
76073471bf0Spatrick FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16)
76173471bf0Spatrick }};
76273471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID, Tys);
76373471bf0Spatrick return true;
76473471bf0Spatrick }
76573471bf0Spatrick
76673471bf0Spatrick // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic anymore
76773471bf0Spatrick // and accept v8bf16 instead of v16i8
76873471bf0Spatrick if ((Name.startswith("arm.neon.bfm") ||
76973471bf0Spatrick Name.startswith("aarch64.neon.bfm")) &&
77073471bf0Spatrick Name.endswith(".v4f32.v16i8")) {
77173471bf0Spatrick Intrinsic::ID IID =
77273471bf0Spatrick StringSwitch<Intrinsic::ID>(Name)
77373471bf0Spatrick .Case("arm.neon.bfmmla.v4f32.v16i8",
77473471bf0Spatrick Intrinsic::arm_neon_bfmmla)
77573471bf0Spatrick .Case("arm.neon.bfmlalb.v4f32.v16i8",
77673471bf0Spatrick Intrinsic::arm_neon_bfmlalb)
77773471bf0Spatrick .Case("arm.neon.bfmlalt.v4f32.v16i8",
77873471bf0Spatrick Intrinsic::arm_neon_bfmlalt)
77973471bf0Spatrick .Case("aarch64.neon.bfmmla.v4f32.v16i8",
78073471bf0Spatrick Intrinsic::aarch64_neon_bfmmla)
78173471bf0Spatrick .Case("aarch64.neon.bfmlalb.v4f32.v16i8",
78273471bf0Spatrick Intrinsic::aarch64_neon_bfmlalb)
78373471bf0Spatrick .Case("aarch64.neon.bfmlalt.v4f32.v16i8",
78473471bf0Spatrick Intrinsic::aarch64_neon_bfmlalt)
78573471bf0Spatrick .Default(Intrinsic::not_intrinsic);
78673471bf0Spatrick if (IID == Intrinsic::not_intrinsic)
78773471bf0Spatrick break;
78873471bf0Spatrick
78973471bf0Spatrick std::array<Type *, 0> Tys;
79073471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID, Tys);
79173471bf0Spatrick return true;
79273471bf0Spatrick }
793*d415bd75Srobert
794*d415bd75Srobert if (Name == "arm.mve.vctp64" &&
795*d415bd75Srobert cast<FixedVectorType>(F->getReturnType())->getNumElements() == 4) {
796*d415bd75Srobert // A vctp64 returning a v4i1 is converted to return a v2i1. Rename the
797*d415bd75Srobert // function and deal with it below in UpgradeIntrinsicCall.
798*d415bd75Srobert rename(F);
799*d415bd75Srobert return true;
800*d415bd75Srobert }
801*d415bd75Srobert // These too are changed to accept a v2i1 insteead of the old v4i1.
802*d415bd75Srobert if (Name == "arm.mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
803*d415bd75Srobert Name == "arm.mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
804*d415bd75Srobert Name == "arm.mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
805*d415bd75Srobert Name == "arm.mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
806*d415bd75Srobert Name == "arm.mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
807*d415bd75Srobert Name == "arm.mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
808*d415bd75Srobert Name == "arm.mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
809*d415bd75Srobert Name == "arm.mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
810*d415bd75Srobert Name == "arm.cde.vcx1q.predicated.v2i64.v4i1" ||
811*d415bd75Srobert Name == "arm.cde.vcx1qa.predicated.v2i64.v4i1" ||
812*d415bd75Srobert Name == "arm.cde.vcx2q.predicated.v2i64.v4i1" ||
813*d415bd75Srobert Name == "arm.cde.vcx2qa.predicated.v2i64.v4i1" ||
814*d415bd75Srobert Name == "arm.cde.vcx3q.predicated.v2i64.v4i1" ||
815*d415bd75Srobert Name == "arm.cde.vcx3qa.predicated.v2i64.v4i1")
816*d415bd75Srobert return true;
817*d415bd75Srobert
818*d415bd75Srobert if (Name == "amdgcn.alignbit") {
819*d415bd75Srobert // Target specific intrinsic became redundant
820*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::fshr,
821*d415bd75Srobert {F->getReturnType()});
822*d415bd75Srobert return true;
823*d415bd75Srobert }
824*d415bd75Srobert
82509467b48Spatrick break;
82609467b48Spatrick }
82709467b48Spatrick
82809467b48Spatrick case 'c': {
82909467b48Spatrick if (Name.startswith("ctlz.") && F->arg_size() == 1) {
83009467b48Spatrick rename(F);
83109467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
83209467b48Spatrick F->arg_begin()->getType());
83309467b48Spatrick return true;
83409467b48Spatrick }
83509467b48Spatrick if (Name.startswith("cttz.") && F->arg_size() == 1) {
83609467b48Spatrick rename(F);
83709467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::cttz,
83809467b48Spatrick F->arg_begin()->getType());
83909467b48Spatrick return true;
84009467b48Spatrick }
84109467b48Spatrick break;
84209467b48Spatrick }
84309467b48Spatrick case 'd': {
84409467b48Spatrick if (Name == "dbg.value" && F->arg_size() == 4) {
84509467b48Spatrick rename(F);
84609467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value);
84709467b48Spatrick return true;
84809467b48Spatrick }
84909467b48Spatrick break;
85009467b48Spatrick }
85109467b48Spatrick case 'e': {
852*d415bd75Srobert if (Name.startswith("experimental.vector.extract.")) {
853*d415bd75Srobert rename(F);
854*d415bd75Srobert Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
855*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
856*d415bd75Srobert Intrinsic::vector_extract, Tys);
857*d415bd75Srobert return true;
858*d415bd75Srobert }
859*d415bd75Srobert
860*d415bd75Srobert if (Name.startswith("experimental.vector.insert.")) {
861*d415bd75Srobert rename(F);
862*d415bd75Srobert auto Args = F->getFunctionType()->params();
863*d415bd75Srobert Type *Tys[] = {Args[0], Args[1]};
864*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(),
865*d415bd75Srobert Intrinsic::vector_insert, Tys);
866*d415bd75Srobert return true;
867*d415bd75Srobert }
868*d415bd75Srobert
86909467b48Spatrick SmallVector<StringRef, 2> Groups;
87073471bf0Spatrick static const Regex R("^experimental.vector.reduce.([a-z]+)\\.[a-z][0-9]+");
87109467b48Spatrick if (R.match(Name, &Groups)) {
87273471bf0Spatrick Intrinsic::ID ID;
87373471bf0Spatrick ID = StringSwitch<Intrinsic::ID>(Groups[1])
87473471bf0Spatrick .Case("add", Intrinsic::vector_reduce_add)
87573471bf0Spatrick .Case("mul", Intrinsic::vector_reduce_mul)
87673471bf0Spatrick .Case("and", Intrinsic::vector_reduce_and)
87773471bf0Spatrick .Case("or", Intrinsic::vector_reduce_or)
87873471bf0Spatrick .Case("xor", Intrinsic::vector_reduce_xor)
87973471bf0Spatrick .Case("smax", Intrinsic::vector_reduce_smax)
88073471bf0Spatrick .Case("smin", Intrinsic::vector_reduce_smin)
88173471bf0Spatrick .Case("umax", Intrinsic::vector_reduce_umax)
88273471bf0Spatrick .Case("umin", Intrinsic::vector_reduce_umin)
88373471bf0Spatrick .Case("fmax", Intrinsic::vector_reduce_fmax)
88473471bf0Spatrick .Case("fmin", Intrinsic::vector_reduce_fmin)
88573471bf0Spatrick .Default(Intrinsic::not_intrinsic);
88609467b48Spatrick if (ID != Intrinsic::not_intrinsic) {
88709467b48Spatrick rename(F);
88809467b48Spatrick auto Args = F->getFunctionType()->params();
88973471bf0Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), ID, {Args[0]});
89073471bf0Spatrick return true;
89173471bf0Spatrick }
89273471bf0Spatrick }
89373471bf0Spatrick static const Regex R2(
89473471bf0Spatrick "^experimental.vector.reduce.v2.([a-z]+)\\.[fi][0-9]+");
89573471bf0Spatrick Groups.clear();
89673471bf0Spatrick if (R2.match(Name, &Groups)) {
89773471bf0Spatrick Intrinsic::ID ID = Intrinsic::not_intrinsic;
89873471bf0Spatrick if (Groups[1] == "fadd")
89973471bf0Spatrick ID = Intrinsic::vector_reduce_fadd;
90073471bf0Spatrick if (Groups[1] == "fmul")
90173471bf0Spatrick ID = Intrinsic::vector_reduce_fmul;
90273471bf0Spatrick if (ID != Intrinsic::not_intrinsic) {
90373471bf0Spatrick rename(F);
90473471bf0Spatrick auto Args = F->getFunctionType()->params();
90573471bf0Spatrick Type *Tys[] = {Args[1]};
90609467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
90709467b48Spatrick return true;
90809467b48Spatrick }
90909467b48Spatrick }
91009467b48Spatrick break;
91109467b48Spatrick }
912*d415bd75Srobert case 'f':
913*d415bd75Srobert if (Name.startswith("flt.rounds")) {
914*d415bd75Srobert rename(F);
915*d415bd75Srobert NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::get_rounding);
916*d415bd75Srobert return true;
917*d415bd75Srobert }
918*d415bd75Srobert break;
91909467b48Spatrick case 'i':
92009467b48Spatrick case 'l': {
92109467b48Spatrick bool IsLifetimeStart = Name.startswith("lifetime.start");
92209467b48Spatrick if (IsLifetimeStart || Name.startswith("invariant.start")) {
92309467b48Spatrick Intrinsic::ID ID = IsLifetimeStart ?
92409467b48Spatrick Intrinsic::lifetime_start : Intrinsic::invariant_start;
92509467b48Spatrick auto Args = F->getFunctionType()->params();
92609467b48Spatrick Type* ObjectPtr[1] = {Args[1]};
92773471bf0Spatrick if (F->getName() != Intrinsic::getName(ID, ObjectPtr, F->getParent())) {
92809467b48Spatrick rename(F);
92909467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), ID, ObjectPtr);
93009467b48Spatrick return true;
93109467b48Spatrick }
93209467b48Spatrick }
93309467b48Spatrick
93409467b48Spatrick bool IsLifetimeEnd = Name.startswith("lifetime.end");
93509467b48Spatrick if (IsLifetimeEnd || Name.startswith("invariant.end")) {
93609467b48Spatrick Intrinsic::ID ID = IsLifetimeEnd ?
93709467b48Spatrick Intrinsic::lifetime_end : Intrinsic::invariant_end;
93809467b48Spatrick
93909467b48Spatrick auto Args = F->getFunctionType()->params();
94009467b48Spatrick Type* ObjectPtr[1] = {Args[IsLifetimeEnd ? 1 : 2]};
94173471bf0Spatrick if (F->getName() != Intrinsic::getName(ID, ObjectPtr, F->getParent())) {
94209467b48Spatrick rename(F);
94309467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), ID, ObjectPtr);
94409467b48Spatrick return true;
94509467b48Spatrick }
94609467b48Spatrick }
94709467b48Spatrick if (Name.startswith("invariant.group.barrier")) {
94809467b48Spatrick // Rename invariant.group.barrier to launder.invariant.group
94909467b48Spatrick auto Args = F->getFunctionType()->params();
95009467b48Spatrick Type* ObjectPtr[1] = {Args[0]};
95109467b48Spatrick rename(F);
95209467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
95309467b48Spatrick Intrinsic::launder_invariant_group, ObjectPtr);
95409467b48Spatrick return true;
95509467b48Spatrick
95609467b48Spatrick }
95709467b48Spatrick
95809467b48Spatrick break;
95909467b48Spatrick }
96009467b48Spatrick case 'm': {
96109467b48Spatrick if (Name.startswith("masked.load.")) {
96209467b48Spatrick Type *Tys[] = { F->getReturnType(), F->arg_begin()->getType() };
96373471bf0Spatrick if (F->getName() !=
96473471bf0Spatrick Intrinsic::getName(Intrinsic::masked_load, Tys, F->getParent())) {
96509467b48Spatrick rename(F);
96609467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
96709467b48Spatrick Intrinsic::masked_load,
96809467b48Spatrick Tys);
96909467b48Spatrick return true;
97009467b48Spatrick }
97109467b48Spatrick }
97209467b48Spatrick if (Name.startswith("masked.store.")) {
97309467b48Spatrick auto Args = F->getFunctionType()->params();
97409467b48Spatrick Type *Tys[] = { Args[0], Args[1] };
97573471bf0Spatrick if (F->getName() !=
97673471bf0Spatrick Intrinsic::getName(Intrinsic::masked_store, Tys, F->getParent())) {
97709467b48Spatrick rename(F);
97809467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
97909467b48Spatrick Intrinsic::masked_store,
98009467b48Spatrick Tys);
98109467b48Spatrick return true;
98209467b48Spatrick }
98309467b48Spatrick }
98409467b48Spatrick // Renaming gather/scatter intrinsics with no address space overloading
98509467b48Spatrick // to the new overload which includes an address space
98609467b48Spatrick if (Name.startswith("masked.gather.")) {
98709467b48Spatrick Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
98873471bf0Spatrick if (F->getName() !=
98973471bf0Spatrick Intrinsic::getName(Intrinsic::masked_gather, Tys, F->getParent())) {
99009467b48Spatrick rename(F);
99109467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
99209467b48Spatrick Intrinsic::masked_gather, Tys);
99309467b48Spatrick return true;
99409467b48Spatrick }
99509467b48Spatrick }
99609467b48Spatrick if (Name.startswith("masked.scatter.")) {
99709467b48Spatrick auto Args = F->getFunctionType()->params();
99809467b48Spatrick Type *Tys[] = {Args[0], Args[1]};
99973471bf0Spatrick if (F->getName() !=
100073471bf0Spatrick Intrinsic::getName(Intrinsic::masked_scatter, Tys, F->getParent())) {
100109467b48Spatrick rename(F);
100209467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(),
100309467b48Spatrick Intrinsic::masked_scatter, Tys);
100409467b48Spatrick return true;
100509467b48Spatrick }
100609467b48Spatrick }
100709467b48Spatrick // Updating the memory intrinsics (memcpy/memmove/memset) that have an
100809467b48Spatrick // alignment parameter to embedding the alignment as an attribute of
100909467b48Spatrick // the pointer args.
101009467b48Spatrick if (Name.startswith("memcpy.") && F->arg_size() == 5) {
101109467b48Spatrick rename(F);
101209467b48Spatrick // Get the types of dest, src, and len
101309467b48Spatrick ArrayRef<Type *> ParamTypes = F->getFunctionType()->params().slice(0, 3);
101409467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memcpy,
101509467b48Spatrick ParamTypes);
101609467b48Spatrick return true;
101709467b48Spatrick }
101809467b48Spatrick if (Name.startswith("memmove.") && F->arg_size() == 5) {
101909467b48Spatrick rename(F);
102009467b48Spatrick // Get the types of dest, src, and len
102109467b48Spatrick ArrayRef<Type *> ParamTypes = F->getFunctionType()->params().slice(0, 3);
102209467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memmove,
102309467b48Spatrick ParamTypes);
102409467b48Spatrick return true;
102509467b48Spatrick }
102609467b48Spatrick if (Name.startswith("memset.") && F->arg_size() == 5) {
102709467b48Spatrick rename(F);
102809467b48Spatrick // Get the types of dest, and len
102909467b48Spatrick const auto *FT = F->getFunctionType();
103009467b48Spatrick Type *ParamTypes[2] = {
103109467b48Spatrick FT->getParamType(0), // Dest
103209467b48Spatrick FT->getParamType(2) // len
103309467b48Spatrick };
103409467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memset,
103509467b48Spatrick ParamTypes);
103609467b48Spatrick return true;
103709467b48Spatrick }
103809467b48Spatrick break;
103909467b48Spatrick }
104009467b48Spatrick case 'n': {
104109467b48Spatrick if (Name.startswith("nvvm.")) {
104209467b48Spatrick Name = Name.substr(5);
104309467b48Spatrick
104409467b48Spatrick // The following nvvm intrinsics correspond exactly to an LLVM intrinsic.
104509467b48Spatrick Intrinsic::ID IID = StringSwitch<Intrinsic::ID>(Name)
104609467b48Spatrick .Cases("brev32", "brev64", Intrinsic::bitreverse)
104709467b48Spatrick .Case("clz.i", Intrinsic::ctlz)
104809467b48Spatrick .Case("popc.i", Intrinsic::ctpop)
104909467b48Spatrick .Default(Intrinsic::not_intrinsic);
105009467b48Spatrick if (IID != Intrinsic::not_intrinsic && F->arg_size() == 1) {
105109467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), IID,
105209467b48Spatrick {F->getReturnType()});
105309467b48Spatrick return true;
105409467b48Spatrick }
105509467b48Spatrick
105609467b48Spatrick // The following nvvm intrinsics correspond exactly to an LLVM idiom, but
105709467b48Spatrick // not to an intrinsic alone. We expand them in UpgradeIntrinsicCall.
105809467b48Spatrick //
105909467b48Spatrick // TODO: We could add lohi.i2d.
106009467b48Spatrick bool Expand = StringSwitch<bool>(Name)
106109467b48Spatrick .Cases("abs.i", "abs.ll", true)
106209467b48Spatrick .Cases("clz.ll", "popc.ll", "h2f", true)
106309467b48Spatrick .Cases("max.i", "max.ll", "max.ui", "max.ull", true)
106409467b48Spatrick .Cases("min.i", "min.ll", "min.ui", "min.ull", true)
106509467b48Spatrick .StartsWith("atomic.load.add.f32.p", true)
106609467b48Spatrick .StartsWith("atomic.load.add.f64.p", true)
106709467b48Spatrick .Default(false);
106809467b48Spatrick if (Expand) {
106909467b48Spatrick NewFn = nullptr;
107009467b48Spatrick return true;
107109467b48Spatrick }
107209467b48Spatrick }
107309467b48Spatrick break;
107409467b48Spatrick }
107509467b48Spatrick case 'o':
107609467b48Spatrick // We only need to change the name to match the mangling including the
107709467b48Spatrick // address space.
107809467b48Spatrick if (Name.startswith("objectsize.")) {
107909467b48Spatrick Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
108009467b48Spatrick if (F->arg_size() == 2 || F->arg_size() == 3 ||
108173471bf0Spatrick F->getName() !=
108273471bf0Spatrick Intrinsic::getName(Intrinsic::objectsize, Tys, F->getParent())) {
108309467b48Spatrick rename(F);
108409467b48Spatrick NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::objectsize,
108509467b48Spatrick Tys);
108609467b48Spatrick return true;
108709467b48Spatrick }
108809467b48Spatrick }
108909467b48Spatrick break;
109009467b48Spatrick
109109467b48Spatrick case 'p':
109209467b48Spatrick if (Name == "prefetch") {
109309467b48Spatrick // Handle address space overloading.
109409467b48Spatrick Type *Tys[] = {F->arg_begin()->getType()};
109573471bf0Spatrick if (F->getName() !=
109673471bf0Spatrick Intrinsic::getName(Intrinsic::prefetch, Tys, F->getParent())) {
109709467b48Spatrick rename(F);
109809467b48Spatrick NewFn =
109909467b48Spatrick Intrinsic::getDeclaration(F->getParent(), Intrinsic::prefetch, Tys);
110009467b48Spatrick return true;
110109467b48Spatrick }
110273471bf0Spatrick } else if (Name.startswith("ptr.annotation.") && F->arg_size() == 4) {
110373471bf0Spatrick rename(F);
1104*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1105*d415bd75Srobert F->getParent(), Intrinsic::ptr_annotation,
1106*d415bd75Srobert {F->arg_begin()->getType(), F->getArg(1)->getType()});
110773471bf0Spatrick return true;
110809467b48Spatrick }
110909467b48Spatrick break;
111009467b48Spatrick
111109467b48Spatrick case 's':
111209467b48Spatrick if (Name == "stackprotectorcheck") {
111309467b48Spatrick NewFn = nullptr;
111409467b48Spatrick return true;
111509467b48Spatrick }
111609467b48Spatrick break;
111709467b48Spatrick
111873471bf0Spatrick case 'v': {
111973471bf0Spatrick if (Name == "var.annotation" && F->arg_size() == 4) {
112073471bf0Spatrick rename(F);
1121*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1122*d415bd75Srobert F->getParent(), Intrinsic::var_annotation,
1123*d415bd75Srobert {{F->arg_begin()->getType(), F->getArg(1)->getType()}});
112473471bf0Spatrick return true;
112573471bf0Spatrick }
112673471bf0Spatrick break;
112773471bf0Spatrick }
112873471bf0Spatrick
1129*d415bd75Srobert case 'w':
1130*d415bd75Srobert if (Name.startswith("wasm.fma.")) {
1131*d415bd75Srobert rename(F);
1132*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1133*d415bd75Srobert F->getParent(), Intrinsic::wasm_relaxed_madd, F->getReturnType());
1134*d415bd75Srobert return true;
1135*d415bd75Srobert }
1136*d415bd75Srobert if (Name.startswith("wasm.fms.")) {
1137*d415bd75Srobert rename(F);
1138*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1139*d415bd75Srobert F->getParent(), Intrinsic::wasm_relaxed_nmadd, F->getReturnType());
1140*d415bd75Srobert return true;
1141*d415bd75Srobert }
1142*d415bd75Srobert if (Name.startswith("wasm.laneselect.")) {
1143*d415bd75Srobert rename(F);
1144*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1145*d415bd75Srobert F->getParent(), Intrinsic::wasm_relaxed_laneselect,
1146*d415bd75Srobert F->getReturnType());
1147*d415bd75Srobert return true;
1148*d415bd75Srobert }
1149*d415bd75Srobert if (Name == "wasm.dot.i8x16.i7x16.signed") {
1150*d415bd75Srobert rename(F);
1151*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1152*d415bd75Srobert F->getParent(), Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed);
1153*d415bd75Srobert return true;
1154*d415bd75Srobert }
1155*d415bd75Srobert if (Name == "wasm.dot.i8x16.i7x16.add.signed") {
1156*d415bd75Srobert rename(F);
1157*d415bd75Srobert NewFn = Intrinsic::getDeclaration(
1158*d415bd75Srobert F->getParent(), Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed);
1159*d415bd75Srobert return true;
1160*d415bd75Srobert }
1161*d415bd75Srobert break;
1162*d415bd75Srobert
116309467b48Spatrick case 'x':
116409467b48Spatrick if (UpgradeX86IntrinsicFunction(F, Name, NewFn))
116509467b48Spatrick return true;
116609467b48Spatrick }
1167*d415bd75Srobert
1168*d415bd75Srobert auto *ST = dyn_cast<StructType>(F->getReturnType());
1169*d415bd75Srobert if (ST && (!ST->isLiteral() || ST->isPacked())) {
1170*d415bd75Srobert // Replace return type with literal non-packed struct. Only do this for
1171*d415bd75Srobert // intrinsics declared to return a struct, not for intrinsics with
1172*d415bd75Srobert // overloaded return type, in which case the exact struct type will be
1173*d415bd75Srobert // mangled into the name.
1174*d415bd75Srobert SmallVector<Intrinsic::IITDescriptor> Desc;
1175*d415bd75Srobert Intrinsic::getIntrinsicInfoTableEntries(F->getIntrinsicID(), Desc);
1176*d415bd75Srobert if (Desc.front().Kind == Intrinsic::IITDescriptor::Struct) {
1177*d415bd75Srobert auto *FT = F->getFunctionType();
1178*d415bd75Srobert auto *NewST = StructType::get(ST->getContext(), ST->elements());
1179*d415bd75Srobert auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());
1180*d415bd75Srobert std::string Name = F->getName().str();
1181*d415bd75Srobert rename(F);
1182*d415bd75Srobert NewFn = Function::Create(NewFT, F->getLinkage(), F->getAddressSpace(),
1183*d415bd75Srobert Name, F->getParent());
1184*d415bd75Srobert
1185*d415bd75Srobert // The new function may also need remangling.
1186*d415bd75Srobert if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn))
1187*d415bd75Srobert NewFn = *Result;
1188*d415bd75Srobert return true;
1189*d415bd75Srobert }
1190*d415bd75Srobert }
1191*d415bd75Srobert
119209467b48Spatrick // Remangle our intrinsic since we upgrade the mangling
119309467b48Spatrick auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F);
1194*d415bd75Srobert if (Result != std::nullopt) {
1195*d415bd75Srobert NewFn = *Result;
119609467b48Spatrick return true;
119709467b48Spatrick }
119809467b48Spatrick
119909467b48Spatrick // This may not belong here. This function is effectively being overloaded
120009467b48Spatrick // to both detect an intrinsic which needs upgrading, and to provide the
120109467b48Spatrick // upgraded form of the intrinsic. We should perhaps have two separate
120209467b48Spatrick // functions for this.
120309467b48Spatrick return false;
120409467b48Spatrick }
120509467b48Spatrick
UpgradeIntrinsicFunction(Function * F,Function * & NewFn)120609467b48Spatrick bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
120709467b48Spatrick NewFn = nullptr;
120809467b48Spatrick bool Upgraded = UpgradeIntrinsicFunction1(F, NewFn);
120909467b48Spatrick assert(F != NewFn && "Intrinsic function upgraded to the same function");
121009467b48Spatrick
121109467b48Spatrick // Upgrade intrinsic attributes. This does not change the function.
121209467b48Spatrick if (NewFn)
121309467b48Spatrick F = NewFn;
121409467b48Spatrick if (Intrinsic::ID id = F->getIntrinsicID())
121509467b48Spatrick F->setAttributes(Intrinsic::getAttributes(F->getContext(), id));
121609467b48Spatrick return Upgraded;
121709467b48Spatrick }
121809467b48Spatrick
UpgradeGlobalVariable(GlobalVariable * GV)121909467b48Spatrick GlobalVariable *llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
122009467b48Spatrick if (!(GV->hasName() && (GV->getName() == "llvm.global_ctors" ||
122109467b48Spatrick GV->getName() == "llvm.global_dtors")) ||
122209467b48Spatrick !GV->hasInitializer())
122309467b48Spatrick return nullptr;
122409467b48Spatrick ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType());
122509467b48Spatrick if (!ATy)
122609467b48Spatrick return nullptr;
122709467b48Spatrick StructType *STy = dyn_cast<StructType>(ATy->getElementType());
122809467b48Spatrick if (!STy || STy->getNumElements() != 2)
122909467b48Spatrick return nullptr;
123009467b48Spatrick
123109467b48Spatrick LLVMContext &C = GV->getContext();
123209467b48Spatrick IRBuilder<> IRB(C);
123309467b48Spatrick auto EltTy = StructType::get(STy->getElementType(0), STy->getElementType(1),
123409467b48Spatrick IRB.getInt8PtrTy());
123509467b48Spatrick Constant *Init = GV->getInitializer();
123609467b48Spatrick unsigned N = Init->getNumOperands();
123709467b48Spatrick std::vector<Constant *> NewCtors(N);
123809467b48Spatrick for (unsigned i = 0; i != N; ++i) {
123909467b48Spatrick auto Ctor = cast<Constant>(Init->getOperand(i));
124009467b48Spatrick NewCtors[i] = ConstantStruct::get(
124109467b48Spatrick EltTy, Ctor->getAggregateElement(0u), Ctor->getAggregateElement(1),
124209467b48Spatrick Constant::getNullValue(IRB.getInt8PtrTy()));
124309467b48Spatrick }
124409467b48Spatrick Constant *NewInit = ConstantArray::get(ArrayType::get(EltTy, N), NewCtors);
124509467b48Spatrick
124609467b48Spatrick return new GlobalVariable(NewInit->getType(), false, GV->getLinkage(),
124709467b48Spatrick NewInit, GV->getName());
124809467b48Spatrick }
124909467b48Spatrick
125009467b48Spatrick // Handles upgrading SSE2/AVX2/AVX512BW PSLLDQ intrinsics by converting them
125109467b48Spatrick // to byte shuffles.
UpgradeX86PSLLDQIntrinsics(IRBuilder<> & Builder,Value * Op,unsigned Shift)125209467b48Spatrick static Value *UpgradeX86PSLLDQIntrinsics(IRBuilder<> &Builder,
125309467b48Spatrick Value *Op, unsigned Shift) {
125473471bf0Spatrick auto *ResultTy = cast<FixedVectorType>(Op->getType());
1255097a140dSpatrick unsigned NumElts = ResultTy->getNumElements() * 8;
125609467b48Spatrick
125709467b48Spatrick // Bitcast from a 64-bit element type to a byte element type.
1258097a140dSpatrick Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
125909467b48Spatrick Op = Builder.CreateBitCast(Op, VecTy, "cast");
126009467b48Spatrick
126109467b48Spatrick // We'll be shuffling in zeroes.
126209467b48Spatrick Value *Res = Constant::getNullValue(VecTy);
126309467b48Spatrick
126409467b48Spatrick // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
126509467b48Spatrick // we'll just return the zero vector.
126609467b48Spatrick if (Shift < 16) {
1267097a140dSpatrick int Idxs[64];
126809467b48Spatrick // 256/512-bit version is split into 2/4 16-byte lanes.
126909467b48Spatrick for (unsigned l = 0; l != NumElts; l += 16)
127009467b48Spatrick for (unsigned i = 0; i != 16; ++i) {
127109467b48Spatrick unsigned Idx = NumElts + i - Shift;
127209467b48Spatrick if (Idx < NumElts)
127309467b48Spatrick Idx -= NumElts - 16; // end of lane, switch operand.
127409467b48Spatrick Idxs[l + i] = Idx + l;
127509467b48Spatrick }
127609467b48Spatrick
1277*d415bd75Srobert Res = Builder.CreateShuffleVector(Res, Op, ArrayRef(Idxs, NumElts));
127809467b48Spatrick }
127909467b48Spatrick
128009467b48Spatrick // Bitcast back to a 64-bit element type.
128109467b48Spatrick return Builder.CreateBitCast(Res, ResultTy, "cast");
128209467b48Spatrick }
128309467b48Spatrick
128409467b48Spatrick // Handles upgrading SSE2/AVX2/AVX512BW PSRLDQ intrinsics by converting them
128509467b48Spatrick // to byte shuffles.
UpgradeX86PSRLDQIntrinsics(IRBuilder<> & Builder,Value * Op,unsigned Shift)128609467b48Spatrick static Value *UpgradeX86PSRLDQIntrinsics(IRBuilder<> &Builder, Value *Op,
128709467b48Spatrick unsigned Shift) {
128873471bf0Spatrick auto *ResultTy = cast<FixedVectorType>(Op->getType());
1289097a140dSpatrick unsigned NumElts = ResultTy->getNumElements() * 8;
129009467b48Spatrick
129109467b48Spatrick // Bitcast from a 64-bit element type to a byte element type.
1292097a140dSpatrick Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
129309467b48Spatrick Op = Builder.CreateBitCast(Op, VecTy, "cast");
129409467b48Spatrick
129509467b48Spatrick // We'll be shuffling in zeroes.
129609467b48Spatrick Value *Res = Constant::getNullValue(VecTy);
129709467b48Spatrick
129809467b48Spatrick // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
129909467b48Spatrick // we'll just return the zero vector.
130009467b48Spatrick if (Shift < 16) {
1301097a140dSpatrick int Idxs[64];
130209467b48Spatrick // 256/512-bit version is split into 2/4 16-byte lanes.
130309467b48Spatrick for (unsigned l = 0; l != NumElts; l += 16)
130409467b48Spatrick for (unsigned i = 0; i != 16; ++i) {
130509467b48Spatrick unsigned Idx = i + Shift;
130609467b48Spatrick if (Idx >= 16)
130709467b48Spatrick Idx += NumElts - 16; // end of lane, switch operand.
130809467b48Spatrick Idxs[l + i] = Idx + l;
130909467b48Spatrick }
131009467b48Spatrick
1311*d415bd75Srobert Res = Builder.CreateShuffleVector(Op, Res, ArrayRef(Idxs, NumElts));
131209467b48Spatrick }
131309467b48Spatrick
131409467b48Spatrick // Bitcast back to a 64-bit element type.
131509467b48Spatrick return Builder.CreateBitCast(Res, ResultTy, "cast");
131609467b48Spatrick }
131709467b48Spatrick
getX86MaskVec(IRBuilder<> & Builder,Value * Mask,unsigned NumElts)131809467b48Spatrick static Value *getX86MaskVec(IRBuilder<> &Builder, Value *Mask,
131909467b48Spatrick unsigned NumElts) {
132073471bf0Spatrick assert(isPowerOf2_32(NumElts) && "Expected power-of-2 mask elements");
1321097a140dSpatrick llvm::VectorType *MaskTy = FixedVectorType::get(
1322097a140dSpatrick Builder.getInt1Ty(), cast<IntegerType>(Mask->getType())->getBitWidth());
132309467b48Spatrick Mask = Builder.CreateBitCast(Mask, MaskTy);
132409467b48Spatrick
132573471bf0Spatrick // If we have less than 8 elements (1, 2 or 4), then the starting mask was an
132673471bf0Spatrick // i8 and we need to extract down to the right number of elements.
132773471bf0Spatrick if (NumElts <= 4) {
1328097a140dSpatrick int Indices[4];
132909467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
133009467b48Spatrick Indices[i] = i;
1331*d415bd75Srobert Mask = Builder.CreateShuffleVector(Mask, Mask, ArrayRef(Indices, NumElts),
1332*d415bd75Srobert "extract");
133309467b48Spatrick }
133409467b48Spatrick
133509467b48Spatrick return Mask;
133609467b48Spatrick }
133709467b48Spatrick
EmitX86Select(IRBuilder<> & Builder,Value * Mask,Value * Op0,Value * Op1)133809467b48Spatrick static Value *EmitX86Select(IRBuilder<> &Builder, Value *Mask,
133909467b48Spatrick Value *Op0, Value *Op1) {
134009467b48Spatrick // If the mask is all ones just emit the first operation.
134109467b48Spatrick if (const auto *C = dyn_cast<Constant>(Mask))
134209467b48Spatrick if (C->isAllOnesValue())
134309467b48Spatrick return Op0;
134409467b48Spatrick
1345097a140dSpatrick Mask = getX86MaskVec(Builder, Mask,
134673471bf0Spatrick cast<FixedVectorType>(Op0->getType())->getNumElements());
134709467b48Spatrick return Builder.CreateSelect(Mask, Op0, Op1);
134809467b48Spatrick }
134909467b48Spatrick
EmitX86ScalarSelect(IRBuilder<> & Builder,Value * Mask,Value * Op0,Value * Op1)135009467b48Spatrick static Value *EmitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask,
135109467b48Spatrick Value *Op0, Value *Op1) {
135209467b48Spatrick // If the mask is all ones just emit the first operation.
135309467b48Spatrick if (const auto *C = dyn_cast<Constant>(Mask))
135409467b48Spatrick if (C->isAllOnesValue())
135509467b48Spatrick return Op0;
135609467b48Spatrick
1357097a140dSpatrick auto *MaskTy = FixedVectorType::get(Builder.getInt1Ty(),
135809467b48Spatrick Mask->getType()->getIntegerBitWidth());
135909467b48Spatrick Mask = Builder.CreateBitCast(Mask, MaskTy);
136009467b48Spatrick Mask = Builder.CreateExtractElement(Mask, (uint64_t)0);
136109467b48Spatrick return Builder.CreateSelect(Mask, Op0, Op1);
136209467b48Spatrick }
136309467b48Spatrick
136409467b48Spatrick // Handle autoupgrade for masked PALIGNR and VALIGND/Q intrinsics.
136509467b48Spatrick // PALIGNR handles large immediates by shifting while VALIGN masks the immediate
136609467b48Spatrick // so we need to handle both cases. VALIGN also doesn't have 128-bit lanes.
UpgradeX86ALIGNIntrinsics(IRBuilder<> & Builder,Value * Op0,Value * Op1,Value * Shift,Value * Passthru,Value * Mask,bool IsVALIGN)136709467b48Spatrick static Value *UpgradeX86ALIGNIntrinsics(IRBuilder<> &Builder, Value *Op0,
136809467b48Spatrick Value *Op1, Value *Shift,
136909467b48Spatrick Value *Passthru, Value *Mask,
137009467b48Spatrick bool IsVALIGN) {
137109467b48Spatrick unsigned ShiftVal = cast<llvm::ConstantInt>(Shift)->getZExtValue();
137209467b48Spatrick
137373471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
137409467b48Spatrick assert((IsVALIGN || NumElts % 16 == 0) && "Illegal NumElts for PALIGNR!");
137509467b48Spatrick assert((!IsVALIGN || NumElts <= 16) && "NumElts too large for VALIGN!");
137609467b48Spatrick assert(isPowerOf2_32(NumElts) && "NumElts not a power of 2!");
137709467b48Spatrick
137809467b48Spatrick // Mask the immediate for VALIGN.
137909467b48Spatrick if (IsVALIGN)
138009467b48Spatrick ShiftVal &= (NumElts - 1);
138109467b48Spatrick
138209467b48Spatrick // If palignr is shifting the pair of vectors more than the size of two
138309467b48Spatrick // lanes, emit zero.
138409467b48Spatrick if (ShiftVal >= 32)
138509467b48Spatrick return llvm::Constant::getNullValue(Op0->getType());
138609467b48Spatrick
138709467b48Spatrick // If palignr is shifting the pair of input vectors more than one lane,
138809467b48Spatrick // but less than two lanes, convert to shifting in zeroes.
138909467b48Spatrick if (ShiftVal > 16) {
139009467b48Spatrick ShiftVal -= 16;
139109467b48Spatrick Op1 = Op0;
139209467b48Spatrick Op0 = llvm::Constant::getNullValue(Op0->getType());
139309467b48Spatrick }
139409467b48Spatrick
1395097a140dSpatrick int Indices[64];
139609467b48Spatrick // 256-bit palignr operates on 128-bit lanes so we need to handle that
139709467b48Spatrick for (unsigned l = 0; l < NumElts; l += 16) {
139809467b48Spatrick for (unsigned i = 0; i != 16; ++i) {
139909467b48Spatrick unsigned Idx = ShiftVal + i;
140009467b48Spatrick if (!IsVALIGN && Idx >= 16) // Disable wrap for VALIGN.
140109467b48Spatrick Idx += NumElts - 16; // End of lane, switch operand.
140209467b48Spatrick Indices[l + i] = Idx + l;
140309467b48Spatrick }
140409467b48Spatrick }
140509467b48Spatrick
1406*d415bd75Srobert Value *Align = Builder.CreateShuffleVector(
1407*d415bd75Srobert Op1, Op0, ArrayRef(Indices, NumElts), "palignr");
140809467b48Spatrick
140909467b48Spatrick return EmitX86Select(Builder, Mask, Align, Passthru);
141009467b48Spatrick }
141109467b48Spatrick
UpgradeX86VPERMT2Intrinsics(IRBuilder<> & Builder,CallBase & CI,bool ZeroMask,bool IndexForm)1412*d415bd75Srobert static Value *UpgradeX86VPERMT2Intrinsics(IRBuilder<> &Builder, CallBase &CI,
141309467b48Spatrick bool ZeroMask, bool IndexForm) {
141409467b48Spatrick Type *Ty = CI.getType();
141509467b48Spatrick unsigned VecWidth = Ty->getPrimitiveSizeInBits();
141609467b48Spatrick unsigned EltWidth = Ty->getScalarSizeInBits();
141709467b48Spatrick bool IsFloat = Ty->isFPOrFPVectorTy();
141809467b48Spatrick Intrinsic::ID IID;
141909467b48Spatrick if (VecWidth == 128 && EltWidth == 32 && IsFloat)
142009467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_ps_128;
142109467b48Spatrick else if (VecWidth == 128 && EltWidth == 32 && !IsFloat)
142209467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_d_128;
142309467b48Spatrick else if (VecWidth == 128 && EltWidth == 64 && IsFloat)
142409467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_pd_128;
142509467b48Spatrick else if (VecWidth == 128 && EltWidth == 64 && !IsFloat)
142609467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_q_128;
142709467b48Spatrick else if (VecWidth == 256 && EltWidth == 32 && IsFloat)
142809467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_ps_256;
142909467b48Spatrick else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
143009467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_d_256;
143109467b48Spatrick else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
143209467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_pd_256;
143309467b48Spatrick else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
143409467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_q_256;
143509467b48Spatrick else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
143609467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_ps_512;
143709467b48Spatrick else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
143809467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_d_512;
143909467b48Spatrick else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
144009467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_pd_512;
144109467b48Spatrick else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
144209467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_q_512;
144309467b48Spatrick else if (VecWidth == 128 && EltWidth == 16)
144409467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_hi_128;
144509467b48Spatrick else if (VecWidth == 256 && EltWidth == 16)
144609467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_hi_256;
144709467b48Spatrick else if (VecWidth == 512 && EltWidth == 16)
144809467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_hi_512;
144909467b48Spatrick else if (VecWidth == 128 && EltWidth == 8)
145009467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_qi_128;
145109467b48Spatrick else if (VecWidth == 256 && EltWidth == 8)
145209467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_qi_256;
145309467b48Spatrick else if (VecWidth == 512 && EltWidth == 8)
145409467b48Spatrick IID = Intrinsic::x86_avx512_vpermi2var_qi_512;
145509467b48Spatrick else
145609467b48Spatrick llvm_unreachable("Unexpected intrinsic");
145709467b48Spatrick
145809467b48Spatrick Value *Args[] = { CI.getArgOperand(0) , CI.getArgOperand(1),
145909467b48Spatrick CI.getArgOperand(2) };
146009467b48Spatrick
146109467b48Spatrick // If this isn't index form we need to swap operand 0 and 1.
146209467b48Spatrick if (!IndexForm)
146309467b48Spatrick std::swap(Args[0], Args[1]);
146409467b48Spatrick
146509467b48Spatrick Value *V = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
146609467b48Spatrick Args);
146709467b48Spatrick Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty)
146809467b48Spatrick : Builder.CreateBitCast(CI.getArgOperand(1),
146909467b48Spatrick Ty);
147009467b48Spatrick return EmitX86Select(Builder, CI.getArgOperand(3), V, PassThru);
147109467b48Spatrick }
147209467b48Spatrick
UpgradeX86BinaryIntrinsics(IRBuilder<> & Builder,CallBase & CI,Intrinsic::ID IID)1473*d415bd75Srobert static Value *UpgradeX86BinaryIntrinsics(IRBuilder<> &Builder, CallBase &CI,
147473471bf0Spatrick Intrinsic::ID IID) {
147509467b48Spatrick Type *Ty = CI.getType();
147609467b48Spatrick Value *Op0 = CI.getOperand(0);
147709467b48Spatrick Value *Op1 = CI.getOperand(1);
147809467b48Spatrick Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
147909467b48Spatrick Value *Res = Builder.CreateCall(Intrin, {Op0, Op1});
148009467b48Spatrick
1481*d415bd75Srobert if (CI.arg_size() == 4) { // For masked intrinsics.
148209467b48Spatrick Value *VecSrc = CI.getOperand(2);
148309467b48Spatrick Value *Mask = CI.getOperand(3);
148409467b48Spatrick Res = EmitX86Select(Builder, Mask, Res, VecSrc);
148509467b48Spatrick }
148609467b48Spatrick return Res;
148709467b48Spatrick }
148809467b48Spatrick
upgradeX86Rotate(IRBuilder<> & Builder,CallBase & CI,bool IsRotateRight)1489*d415bd75Srobert static Value *upgradeX86Rotate(IRBuilder<> &Builder, CallBase &CI,
149009467b48Spatrick bool IsRotateRight) {
149109467b48Spatrick Type *Ty = CI.getType();
149209467b48Spatrick Value *Src = CI.getArgOperand(0);
149309467b48Spatrick Value *Amt = CI.getArgOperand(1);
149409467b48Spatrick
149509467b48Spatrick // Amount may be scalar immediate, in which case create a splat vector.
149609467b48Spatrick // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
149709467b48Spatrick // we only care about the lowest log2 bits anyway.
149809467b48Spatrick if (Amt->getType() != Ty) {
149973471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
150009467b48Spatrick Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
150109467b48Spatrick Amt = Builder.CreateVectorSplat(NumElts, Amt);
150209467b48Spatrick }
150309467b48Spatrick
150409467b48Spatrick Intrinsic::ID IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl;
150509467b48Spatrick Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
150609467b48Spatrick Value *Res = Builder.CreateCall(Intrin, {Src, Src, Amt});
150709467b48Spatrick
1508*d415bd75Srobert if (CI.arg_size() == 4) { // For masked intrinsics.
150909467b48Spatrick Value *VecSrc = CI.getOperand(2);
151009467b48Spatrick Value *Mask = CI.getOperand(3);
151109467b48Spatrick Res = EmitX86Select(Builder, Mask, Res, VecSrc);
151209467b48Spatrick }
151309467b48Spatrick return Res;
151409467b48Spatrick }
151509467b48Spatrick
upgradeX86vpcom(IRBuilder<> & Builder,CallBase & CI,unsigned Imm,bool IsSigned)1516*d415bd75Srobert static Value *upgradeX86vpcom(IRBuilder<> &Builder, CallBase &CI, unsigned Imm,
151709467b48Spatrick bool IsSigned) {
151809467b48Spatrick Type *Ty = CI.getType();
151909467b48Spatrick Value *LHS = CI.getArgOperand(0);
152009467b48Spatrick Value *RHS = CI.getArgOperand(1);
152109467b48Spatrick
152209467b48Spatrick CmpInst::Predicate Pred;
152309467b48Spatrick switch (Imm) {
152409467b48Spatrick case 0x0:
152509467b48Spatrick Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
152609467b48Spatrick break;
152709467b48Spatrick case 0x1:
152809467b48Spatrick Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
152909467b48Spatrick break;
153009467b48Spatrick case 0x2:
153109467b48Spatrick Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
153209467b48Spatrick break;
153309467b48Spatrick case 0x3:
153409467b48Spatrick Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
153509467b48Spatrick break;
153609467b48Spatrick case 0x4:
153709467b48Spatrick Pred = ICmpInst::ICMP_EQ;
153809467b48Spatrick break;
153909467b48Spatrick case 0x5:
154009467b48Spatrick Pred = ICmpInst::ICMP_NE;
154109467b48Spatrick break;
154209467b48Spatrick case 0x6:
154309467b48Spatrick return Constant::getNullValue(Ty); // FALSE
154409467b48Spatrick case 0x7:
154509467b48Spatrick return Constant::getAllOnesValue(Ty); // TRUE
154609467b48Spatrick default:
154709467b48Spatrick llvm_unreachable("Unknown XOP vpcom/vpcomu predicate");
154809467b48Spatrick }
154909467b48Spatrick
155009467b48Spatrick Value *Cmp = Builder.CreateICmp(Pred, LHS, RHS);
155109467b48Spatrick Value *Ext = Builder.CreateSExt(Cmp, Ty);
155209467b48Spatrick return Ext;
155309467b48Spatrick }
155409467b48Spatrick
upgradeX86ConcatShift(IRBuilder<> & Builder,CallBase & CI,bool IsShiftRight,bool ZeroMask)1555*d415bd75Srobert static Value *upgradeX86ConcatShift(IRBuilder<> &Builder, CallBase &CI,
155609467b48Spatrick bool IsShiftRight, bool ZeroMask) {
155709467b48Spatrick Type *Ty = CI.getType();
155809467b48Spatrick Value *Op0 = CI.getArgOperand(0);
155909467b48Spatrick Value *Op1 = CI.getArgOperand(1);
156009467b48Spatrick Value *Amt = CI.getArgOperand(2);
156109467b48Spatrick
156209467b48Spatrick if (IsShiftRight)
156309467b48Spatrick std::swap(Op0, Op1);
156409467b48Spatrick
156509467b48Spatrick // Amount may be scalar immediate, in which case create a splat vector.
156609467b48Spatrick // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
156709467b48Spatrick // we only care about the lowest log2 bits anyway.
156809467b48Spatrick if (Amt->getType() != Ty) {
156973471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
157009467b48Spatrick Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
157109467b48Spatrick Amt = Builder.CreateVectorSplat(NumElts, Amt);
157209467b48Spatrick }
157309467b48Spatrick
157409467b48Spatrick Intrinsic::ID IID = IsShiftRight ? Intrinsic::fshr : Intrinsic::fshl;
157509467b48Spatrick Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
157609467b48Spatrick Value *Res = Builder.CreateCall(Intrin, {Op0, Op1, Amt});
157709467b48Spatrick
1578*d415bd75Srobert unsigned NumArgs = CI.arg_size();
157909467b48Spatrick if (NumArgs >= 4) { // For masked intrinsics.
158009467b48Spatrick Value *VecSrc = NumArgs == 5 ? CI.getArgOperand(3) :
158109467b48Spatrick ZeroMask ? ConstantAggregateZero::get(CI.getType()) :
158209467b48Spatrick CI.getArgOperand(0);
158309467b48Spatrick Value *Mask = CI.getOperand(NumArgs - 1);
158409467b48Spatrick Res = EmitX86Select(Builder, Mask, Res, VecSrc);
158509467b48Spatrick }
158609467b48Spatrick return Res;
158709467b48Spatrick }
158809467b48Spatrick
UpgradeMaskedStore(IRBuilder<> & Builder,Value * Ptr,Value * Data,Value * Mask,bool Aligned)158909467b48Spatrick static Value *UpgradeMaskedStore(IRBuilder<> &Builder,
159009467b48Spatrick Value *Ptr, Value *Data, Value *Mask,
159109467b48Spatrick bool Aligned) {
159209467b48Spatrick // Cast the pointer to the right type.
159309467b48Spatrick Ptr = Builder.CreateBitCast(Ptr,
159409467b48Spatrick llvm::PointerType::getUnqual(Data->getType()));
1595097a140dSpatrick const Align Alignment =
1596097a140dSpatrick Aligned
1597*d415bd75Srobert ? Align(Data->getType()->getPrimitiveSizeInBits().getFixedValue() / 8)
1598097a140dSpatrick : Align(1);
159909467b48Spatrick
160009467b48Spatrick // If the mask is all ones just emit a regular store.
160109467b48Spatrick if (const auto *C = dyn_cast<Constant>(Mask))
160209467b48Spatrick if (C->isAllOnesValue())
1603097a140dSpatrick return Builder.CreateAlignedStore(Data, Ptr, Alignment);
160409467b48Spatrick
160509467b48Spatrick // Convert the mask from an integer type to a vector of i1.
160673471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Data->getType())->getNumElements();
160709467b48Spatrick Mask = getX86MaskVec(Builder, Mask, NumElts);
1608097a140dSpatrick return Builder.CreateMaskedStore(Data, Ptr, Alignment, Mask);
160909467b48Spatrick }
161009467b48Spatrick
UpgradeMaskedLoad(IRBuilder<> & Builder,Value * Ptr,Value * Passthru,Value * Mask,bool Aligned)161109467b48Spatrick static Value *UpgradeMaskedLoad(IRBuilder<> &Builder,
161209467b48Spatrick Value *Ptr, Value *Passthru, Value *Mask,
161309467b48Spatrick bool Aligned) {
161409467b48Spatrick Type *ValTy = Passthru->getType();
161509467b48Spatrick // Cast the pointer to the right type.
161609467b48Spatrick Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(ValTy));
1617097a140dSpatrick const Align Alignment =
1618097a140dSpatrick Aligned
1619*d415bd75Srobert ? Align(
1620*d415bd75Srobert Passthru->getType()->getPrimitiveSizeInBits().getFixedValue() /
1621097a140dSpatrick 8)
1622097a140dSpatrick : Align(1);
162309467b48Spatrick
162409467b48Spatrick // If the mask is all ones just emit a regular store.
162509467b48Spatrick if (const auto *C = dyn_cast<Constant>(Mask))
162609467b48Spatrick if (C->isAllOnesValue())
1627097a140dSpatrick return Builder.CreateAlignedLoad(ValTy, Ptr, Alignment);
162809467b48Spatrick
162909467b48Spatrick // Convert the mask from an integer type to a vector of i1.
163073471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(ValTy)->getNumElements();
163109467b48Spatrick Mask = getX86MaskVec(Builder, Mask, NumElts);
163273471bf0Spatrick return Builder.CreateMaskedLoad(ValTy, Ptr, Alignment, Mask, Passthru);
163309467b48Spatrick }
163409467b48Spatrick
upgradeAbs(IRBuilder<> & Builder,CallBase & CI)1635*d415bd75Srobert static Value *upgradeAbs(IRBuilder<> &Builder, CallBase &CI) {
163673471bf0Spatrick Type *Ty = CI.getType();
163709467b48Spatrick Value *Op0 = CI.getArgOperand(0);
163873471bf0Spatrick Function *F = Intrinsic::getDeclaration(CI.getModule(), Intrinsic::abs, Ty);
163973471bf0Spatrick Value *Res = Builder.CreateCall(F, {Op0, Builder.getInt1(false)});
1640*d415bd75Srobert if (CI.arg_size() == 3)
164109467b48Spatrick Res = EmitX86Select(Builder, CI.getArgOperand(2), Res, CI.getArgOperand(1));
164209467b48Spatrick return Res;
164309467b48Spatrick }
164409467b48Spatrick
upgradePMULDQ(IRBuilder<> & Builder,CallBase & CI,bool IsSigned)1645*d415bd75Srobert static Value *upgradePMULDQ(IRBuilder<> &Builder, CallBase &CI, bool IsSigned) {
164609467b48Spatrick Type *Ty = CI.getType();
164709467b48Spatrick
164809467b48Spatrick // Arguments have a vXi32 type so cast to vXi64.
164909467b48Spatrick Value *LHS = Builder.CreateBitCast(CI.getArgOperand(0), Ty);
165009467b48Spatrick Value *RHS = Builder.CreateBitCast(CI.getArgOperand(1), Ty);
165109467b48Spatrick
165209467b48Spatrick if (IsSigned) {
165309467b48Spatrick // Shift left then arithmetic shift right.
165409467b48Spatrick Constant *ShiftAmt = ConstantInt::get(Ty, 32);
165509467b48Spatrick LHS = Builder.CreateShl(LHS, ShiftAmt);
165609467b48Spatrick LHS = Builder.CreateAShr(LHS, ShiftAmt);
165709467b48Spatrick RHS = Builder.CreateShl(RHS, ShiftAmt);
165809467b48Spatrick RHS = Builder.CreateAShr(RHS, ShiftAmt);
165909467b48Spatrick } else {
166009467b48Spatrick // Clear the upper bits.
166109467b48Spatrick Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
166209467b48Spatrick LHS = Builder.CreateAnd(LHS, Mask);
166309467b48Spatrick RHS = Builder.CreateAnd(RHS, Mask);
166409467b48Spatrick }
166509467b48Spatrick
166609467b48Spatrick Value *Res = Builder.CreateMul(LHS, RHS);
166709467b48Spatrick
1668*d415bd75Srobert if (CI.arg_size() == 4)
166909467b48Spatrick Res = EmitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2));
167009467b48Spatrick
167109467b48Spatrick return Res;
167209467b48Spatrick }
167309467b48Spatrick
167409467b48Spatrick // Applying mask on vector of i1's and make sure result is at least 8 bits wide.
ApplyX86MaskOn1BitsVec(IRBuilder<> & Builder,Value * Vec,Value * Mask)167509467b48Spatrick static Value *ApplyX86MaskOn1BitsVec(IRBuilder<> &Builder, Value *Vec,
167609467b48Spatrick Value *Mask) {
167773471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
167809467b48Spatrick if (Mask) {
167909467b48Spatrick const auto *C = dyn_cast<Constant>(Mask);
168009467b48Spatrick if (!C || !C->isAllOnesValue())
168109467b48Spatrick Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
168209467b48Spatrick }
168309467b48Spatrick
168409467b48Spatrick if (NumElts < 8) {
1685097a140dSpatrick int Indices[8];
168609467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
168709467b48Spatrick Indices[i] = i;
168809467b48Spatrick for (unsigned i = NumElts; i != 8; ++i)
168909467b48Spatrick Indices[i] = NumElts + i % NumElts;
169009467b48Spatrick Vec = Builder.CreateShuffleVector(Vec,
169109467b48Spatrick Constant::getNullValue(Vec->getType()),
169209467b48Spatrick Indices);
169309467b48Spatrick }
169409467b48Spatrick return Builder.CreateBitCast(Vec, Builder.getIntNTy(std::max(NumElts, 8U)));
169509467b48Spatrick }
169609467b48Spatrick
upgradeMaskedCompare(IRBuilder<> & Builder,CallBase & CI,unsigned CC,bool Signed)1697*d415bd75Srobert static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallBase &CI,
169809467b48Spatrick unsigned CC, bool Signed) {
169909467b48Spatrick Value *Op0 = CI.getArgOperand(0);
170073471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
170109467b48Spatrick
170209467b48Spatrick Value *Cmp;
170309467b48Spatrick if (CC == 3) {
1704097a140dSpatrick Cmp = Constant::getNullValue(
1705097a140dSpatrick FixedVectorType::get(Builder.getInt1Ty(), NumElts));
170609467b48Spatrick } else if (CC == 7) {
1707097a140dSpatrick Cmp = Constant::getAllOnesValue(
1708097a140dSpatrick FixedVectorType::get(Builder.getInt1Ty(), NumElts));
170909467b48Spatrick } else {
171009467b48Spatrick ICmpInst::Predicate Pred;
171109467b48Spatrick switch (CC) {
171209467b48Spatrick default: llvm_unreachable("Unknown condition code");
171309467b48Spatrick case 0: Pred = ICmpInst::ICMP_EQ; break;
171409467b48Spatrick case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
171509467b48Spatrick case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
171609467b48Spatrick case 4: Pred = ICmpInst::ICMP_NE; break;
171709467b48Spatrick case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
171809467b48Spatrick case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
171909467b48Spatrick }
172009467b48Spatrick Cmp = Builder.CreateICmp(Pred, Op0, CI.getArgOperand(1));
172109467b48Spatrick }
172209467b48Spatrick
1723*d415bd75Srobert Value *Mask = CI.getArgOperand(CI.arg_size() - 1);
172409467b48Spatrick
172509467b48Spatrick return ApplyX86MaskOn1BitsVec(Builder, Cmp, Mask);
172609467b48Spatrick }
172709467b48Spatrick
172809467b48Spatrick // Replace a masked intrinsic with an older unmasked intrinsic.
UpgradeX86MaskedShift(IRBuilder<> & Builder,CallBase & CI,Intrinsic::ID IID)1729*d415bd75Srobert static Value *UpgradeX86MaskedShift(IRBuilder<> &Builder, CallBase &CI,
173009467b48Spatrick Intrinsic::ID IID) {
173109467b48Spatrick Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID);
173209467b48Spatrick Value *Rep = Builder.CreateCall(Intrin,
173309467b48Spatrick { CI.getArgOperand(0), CI.getArgOperand(1) });
173409467b48Spatrick return EmitX86Select(Builder, CI.getArgOperand(3), Rep, CI.getArgOperand(2));
173509467b48Spatrick }
173609467b48Spatrick
upgradeMaskedMove(IRBuilder<> & Builder,CallBase & CI)1737*d415bd75Srobert static Value* upgradeMaskedMove(IRBuilder<> &Builder, CallBase &CI) {
173809467b48Spatrick Value* A = CI.getArgOperand(0);
173909467b48Spatrick Value* B = CI.getArgOperand(1);
174009467b48Spatrick Value* Src = CI.getArgOperand(2);
174109467b48Spatrick Value* Mask = CI.getArgOperand(3);
174209467b48Spatrick
174309467b48Spatrick Value* AndNode = Builder.CreateAnd(Mask, APInt(8, 1));
174409467b48Spatrick Value* Cmp = Builder.CreateIsNotNull(AndNode);
174509467b48Spatrick Value* Extract1 = Builder.CreateExtractElement(B, (uint64_t)0);
174609467b48Spatrick Value* Extract2 = Builder.CreateExtractElement(Src, (uint64_t)0);
174709467b48Spatrick Value* Select = Builder.CreateSelect(Cmp, Extract1, Extract2);
174809467b48Spatrick return Builder.CreateInsertElement(A, Select, (uint64_t)0);
174909467b48Spatrick }
175009467b48Spatrick
175109467b48Spatrick
UpgradeMaskToInt(IRBuilder<> & Builder,CallBase & CI)1752*d415bd75Srobert static Value* UpgradeMaskToInt(IRBuilder<> &Builder, CallBase &CI) {
175309467b48Spatrick Value* Op = CI.getArgOperand(0);
175409467b48Spatrick Type* ReturnOp = CI.getType();
175573471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI.getType())->getNumElements();
175609467b48Spatrick Value *Mask = getX86MaskVec(Builder, Op, NumElts);
175709467b48Spatrick return Builder.CreateSExt(Mask, ReturnOp, "vpmovm2");
175809467b48Spatrick }
175909467b48Spatrick
176009467b48Spatrick // Replace intrinsic with unmasked version and a select.
upgradeAVX512MaskToSelect(StringRef Name,IRBuilder<> & Builder,CallBase & CI,Value * & Rep)176109467b48Spatrick static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder,
1762*d415bd75Srobert CallBase &CI, Value *&Rep) {
176309467b48Spatrick Name = Name.substr(12); // Remove avx512.mask.
176409467b48Spatrick
176509467b48Spatrick unsigned VecWidth = CI.getType()->getPrimitiveSizeInBits();
176609467b48Spatrick unsigned EltWidth = CI.getType()->getScalarSizeInBits();
176709467b48Spatrick Intrinsic::ID IID;
176809467b48Spatrick if (Name.startswith("max.p")) {
176909467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
177009467b48Spatrick IID = Intrinsic::x86_sse_max_ps;
177109467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
177209467b48Spatrick IID = Intrinsic::x86_sse2_max_pd;
177309467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
177409467b48Spatrick IID = Intrinsic::x86_avx_max_ps_256;
177509467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
177609467b48Spatrick IID = Intrinsic::x86_avx_max_pd_256;
177709467b48Spatrick else
177809467b48Spatrick llvm_unreachable("Unexpected intrinsic");
177909467b48Spatrick } else if (Name.startswith("min.p")) {
178009467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
178109467b48Spatrick IID = Intrinsic::x86_sse_min_ps;
178209467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
178309467b48Spatrick IID = Intrinsic::x86_sse2_min_pd;
178409467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
178509467b48Spatrick IID = Intrinsic::x86_avx_min_ps_256;
178609467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
178709467b48Spatrick IID = Intrinsic::x86_avx_min_pd_256;
178809467b48Spatrick else
178909467b48Spatrick llvm_unreachable("Unexpected intrinsic");
179009467b48Spatrick } else if (Name.startswith("pshuf.b.")) {
179109467b48Spatrick if (VecWidth == 128)
179209467b48Spatrick IID = Intrinsic::x86_ssse3_pshuf_b_128;
179309467b48Spatrick else if (VecWidth == 256)
179409467b48Spatrick IID = Intrinsic::x86_avx2_pshuf_b;
179509467b48Spatrick else if (VecWidth == 512)
179609467b48Spatrick IID = Intrinsic::x86_avx512_pshuf_b_512;
179709467b48Spatrick else
179809467b48Spatrick llvm_unreachable("Unexpected intrinsic");
179909467b48Spatrick } else if (Name.startswith("pmul.hr.sw.")) {
180009467b48Spatrick if (VecWidth == 128)
180109467b48Spatrick IID = Intrinsic::x86_ssse3_pmul_hr_sw_128;
180209467b48Spatrick else if (VecWidth == 256)
180309467b48Spatrick IID = Intrinsic::x86_avx2_pmul_hr_sw;
180409467b48Spatrick else if (VecWidth == 512)
180509467b48Spatrick IID = Intrinsic::x86_avx512_pmul_hr_sw_512;
180609467b48Spatrick else
180709467b48Spatrick llvm_unreachable("Unexpected intrinsic");
180809467b48Spatrick } else if (Name.startswith("pmulh.w.")) {
180909467b48Spatrick if (VecWidth == 128)
181009467b48Spatrick IID = Intrinsic::x86_sse2_pmulh_w;
181109467b48Spatrick else if (VecWidth == 256)
181209467b48Spatrick IID = Intrinsic::x86_avx2_pmulh_w;
181309467b48Spatrick else if (VecWidth == 512)
181409467b48Spatrick IID = Intrinsic::x86_avx512_pmulh_w_512;
181509467b48Spatrick else
181609467b48Spatrick llvm_unreachable("Unexpected intrinsic");
181709467b48Spatrick } else if (Name.startswith("pmulhu.w.")) {
181809467b48Spatrick if (VecWidth == 128)
181909467b48Spatrick IID = Intrinsic::x86_sse2_pmulhu_w;
182009467b48Spatrick else if (VecWidth == 256)
182109467b48Spatrick IID = Intrinsic::x86_avx2_pmulhu_w;
182209467b48Spatrick else if (VecWidth == 512)
182309467b48Spatrick IID = Intrinsic::x86_avx512_pmulhu_w_512;
182409467b48Spatrick else
182509467b48Spatrick llvm_unreachable("Unexpected intrinsic");
182609467b48Spatrick } else if (Name.startswith("pmaddw.d.")) {
182709467b48Spatrick if (VecWidth == 128)
182809467b48Spatrick IID = Intrinsic::x86_sse2_pmadd_wd;
182909467b48Spatrick else if (VecWidth == 256)
183009467b48Spatrick IID = Intrinsic::x86_avx2_pmadd_wd;
183109467b48Spatrick else if (VecWidth == 512)
183209467b48Spatrick IID = Intrinsic::x86_avx512_pmaddw_d_512;
183309467b48Spatrick else
183409467b48Spatrick llvm_unreachable("Unexpected intrinsic");
183509467b48Spatrick } else if (Name.startswith("pmaddubs.w.")) {
183609467b48Spatrick if (VecWidth == 128)
183709467b48Spatrick IID = Intrinsic::x86_ssse3_pmadd_ub_sw_128;
183809467b48Spatrick else if (VecWidth == 256)
183909467b48Spatrick IID = Intrinsic::x86_avx2_pmadd_ub_sw;
184009467b48Spatrick else if (VecWidth == 512)
184109467b48Spatrick IID = Intrinsic::x86_avx512_pmaddubs_w_512;
184209467b48Spatrick else
184309467b48Spatrick llvm_unreachable("Unexpected intrinsic");
184409467b48Spatrick } else if (Name.startswith("packsswb.")) {
184509467b48Spatrick if (VecWidth == 128)
184609467b48Spatrick IID = Intrinsic::x86_sse2_packsswb_128;
184709467b48Spatrick else if (VecWidth == 256)
184809467b48Spatrick IID = Intrinsic::x86_avx2_packsswb;
184909467b48Spatrick else if (VecWidth == 512)
185009467b48Spatrick IID = Intrinsic::x86_avx512_packsswb_512;
185109467b48Spatrick else
185209467b48Spatrick llvm_unreachable("Unexpected intrinsic");
185309467b48Spatrick } else if (Name.startswith("packssdw.")) {
185409467b48Spatrick if (VecWidth == 128)
185509467b48Spatrick IID = Intrinsic::x86_sse2_packssdw_128;
185609467b48Spatrick else if (VecWidth == 256)
185709467b48Spatrick IID = Intrinsic::x86_avx2_packssdw;
185809467b48Spatrick else if (VecWidth == 512)
185909467b48Spatrick IID = Intrinsic::x86_avx512_packssdw_512;
186009467b48Spatrick else
186109467b48Spatrick llvm_unreachable("Unexpected intrinsic");
186209467b48Spatrick } else if (Name.startswith("packuswb.")) {
186309467b48Spatrick if (VecWidth == 128)
186409467b48Spatrick IID = Intrinsic::x86_sse2_packuswb_128;
186509467b48Spatrick else if (VecWidth == 256)
186609467b48Spatrick IID = Intrinsic::x86_avx2_packuswb;
186709467b48Spatrick else if (VecWidth == 512)
186809467b48Spatrick IID = Intrinsic::x86_avx512_packuswb_512;
186909467b48Spatrick else
187009467b48Spatrick llvm_unreachable("Unexpected intrinsic");
187109467b48Spatrick } else if (Name.startswith("packusdw.")) {
187209467b48Spatrick if (VecWidth == 128)
187309467b48Spatrick IID = Intrinsic::x86_sse41_packusdw;
187409467b48Spatrick else if (VecWidth == 256)
187509467b48Spatrick IID = Intrinsic::x86_avx2_packusdw;
187609467b48Spatrick else if (VecWidth == 512)
187709467b48Spatrick IID = Intrinsic::x86_avx512_packusdw_512;
187809467b48Spatrick else
187909467b48Spatrick llvm_unreachable("Unexpected intrinsic");
188009467b48Spatrick } else if (Name.startswith("vpermilvar.")) {
188109467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
188209467b48Spatrick IID = Intrinsic::x86_avx_vpermilvar_ps;
188309467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
188409467b48Spatrick IID = Intrinsic::x86_avx_vpermilvar_pd;
188509467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
188609467b48Spatrick IID = Intrinsic::x86_avx_vpermilvar_ps_256;
188709467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
188809467b48Spatrick IID = Intrinsic::x86_avx_vpermilvar_pd_256;
188909467b48Spatrick else if (VecWidth == 512 && EltWidth == 32)
189009467b48Spatrick IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
189109467b48Spatrick else if (VecWidth == 512 && EltWidth == 64)
189209467b48Spatrick IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
189309467b48Spatrick else
189409467b48Spatrick llvm_unreachable("Unexpected intrinsic");
189509467b48Spatrick } else if (Name == "cvtpd2dq.256") {
189609467b48Spatrick IID = Intrinsic::x86_avx_cvt_pd2dq_256;
189709467b48Spatrick } else if (Name == "cvtpd2ps.256") {
189809467b48Spatrick IID = Intrinsic::x86_avx_cvt_pd2_ps_256;
189909467b48Spatrick } else if (Name == "cvttpd2dq.256") {
190009467b48Spatrick IID = Intrinsic::x86_avx_cvtt_pd2dq_256;
190109467b48Spatrick } else if (Name == "cvttps2dq.128") {
190209467b48Spatrick IID = Intrinsic::x86_sse2_cvttps2dq;
190309467b48Spatrick } else if (Name == "cvttps2dq.256") {
190409467b48Spatrick IID = Intrinsic::x86_avx_cvtt_ps2dq_256;
190509467b48Spatrick } else if (Name.startswith("permvar.")) {
190609467b48Spatrick bool IsFloat = CI.getType()->isFPOrFPVectorTy();
190709467b48Spatrick if (VecWidth == 256 && EltWidth == 32 && IsFloat)
190809467b48Spatrick IID = Intrinsic::x86_avx2_permps;
190909467b48Spatrick else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
191009467b48Spatrick IID = Intrinsic::x86_avx2_permd;
191109467b48Spatrick else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
191209467b48Spatrick IID = Intrinsic::x86_avx512_permvar_df_256;
191309467b48Spatrick else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
191409467b48Spatrick IID = Intrinsic::x86_avx512_permvar_di_256;
191509467b48Spatrick else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
191609467b48Spatrick IID = Intrinsic::x86_avx512_permvar_sf_512;
191709467b48Spatrick else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
191809467b48Spatrick IID = Intrinsic::x86_avx512_permvar_si_512;
191909467b48Spatrick else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
192009467b48Spatrick IID = Intrinsic::x86_avx512_permvar_df_512;
192109467b48Spatrick else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
192209467b48Spatrick IID = Intrinsic::x86_avx512_permvar_di_512;
192309467b48Spatrick else if (VecWidth == 128 && EltWidth == 16)
192409467b48Spatrick IID = Intrinsic::x86_avx512_permvar_hi_128;
192509467b48Spatrick else if (VecWidth == 256 && EltWidth == 16)
192609467b48Spatrick IID = Intrinsic::x86_avx512_permvar_hi_256;
192709467b48Spatrick else if (VecWidth == 512 && EltWidth == 16)
192809467b48Spatrick IID = Intrinsic::x86_avx512_permvar_hi_512;
192909467b48Spatrick else if (VecWidth == 128 && EltWidth == 8)
193009467b48Spatrick IID = Intrinsic::x86_avx512_permvar_qi_128;
193109467b48Spatrick else if (VecWidth == 256 && EltWidth == 8)
193209467b48Spatrick IID = Intrinsic::x86_avx512_permvar_qi_256;
193309467b48Spatrick else if (VecWidth == 512 && EltWidth == 8)
193409467b48Spatrick IID = Intrinsic::x86_avx512_permvar_qi_512;
193509467b48Spatrick else
193609467b48Spatrick llvm_unreachable("Unexpected intrinsic");
193709467b48Spatrick } else if (Name.startswith("dbpsadbw.")) {
193809467b48Spatrick if (VecWidth == 128)
193909467b48Spatrick IID = Intrinsic::x86_avx512_dbpsadbw_128;
194009467b48Spatrick else if (VecWidth == 256)
194109467b48Spatrick IID = Intrinsic::x86_avx512_dbpsadbw_256;
194209467b48Spatrick else if (VecWidth == 512)
194309467b48Spatrick IID = Intrinsic::x86_avx512_dbpsadbw_512;
194409467b48Spatrick else
194509467b48Spatrick llvm_unreachable("Unexpected intrinsic");
194609467b48Spatrick } else if (Name.startswith("pmultishift.qb.")) {
194709467b48Spatrick if (VecWidth == 128)
194809467b48Spatrick IID = Intrinsic::x86_avx512_pmultishift_qb_128;
194909467b48Spatrick else if (VecWidth == 256)
195009467b48Spatrick IID = Intrinsic::x86_avx512_pmultishift_qb_256;
195109467b48Spatrick else if (VecWidth == 512)
195209467b48Spatrick IID = Intrinsic::x86_avx512_pmultishift_qb_512;
195309467b48Spatrick else
195409467b48Spatrick llvm_unreachable("Unexpected intrinsic");
195509467b48Spatrick } else if (Name.startswith("conflict.")) {
195609467b48Spatrick if (Name[9] == 'd' && VecWidth == 128)
195709467b48Spatrick IID = Intrinsic::x86_avx512_conflict_d_128;
195809467b48Spatrick else if (Name[9] == 'd' && VecWidth == 256)
195909467b48Spatrick IID = Intrinsic::x86_avx512_conflict_d_256;
196009467b48Spatrick else if (Name[9] == 'd' && VecWidth == 512)
196109467b48Spatrick IID = Intrinsic::x86_avx512_conflict_d_512;
196209467b48Spatrick else if (Name[9] == 'q' && VecWidth == 128)
196309467b48Spatrick IID = Intrinsic::x86_avx512_conflict_q_128;
196409467b48Spatrick else if (Name[9] == 'q' && VecWidth == 256)
196509467b48Spatrick IID = Intrinsic::x86_avx512_conflict_q_256;
196609467b48Spatrick else if (Name[9] == 'q' && VecWidth == 512)
196709467b48Spatrick IID = Intrinsic::x86_avx512_conflict_q_512;
196809467b48Spatrick else
196909467b48Spatrick llvm_unreachable("Unexpected intrinsic");
197009467b48Spatrick } else if (Name.startswith("pavg.")) {
197109467b48Spatrick if (Name[5] == 'b' && VecWidth == 128)
197209467b48Spatrick IID = Intrinsic::x86_sse2_pavg_b;
197309467b48Spatrick else if (Name[5] == 'b' && VecWidth == 256)
197409467b48Spatrick IID = Intrinsic::x86_avx2_pavg_b;
197509467b48Spatrick else if (Name[5] == 'b' && VecWidth == 512)
197609467b48Spatrick IID = Intrinsic::x86_avx512_pavg_b_512;
197709467b48Spatrick else if (Name[5] == 'w' && VecWidth == 128)
197809467b48Spatrick IID = Intrinsic::x86_sse2_pavg_w;
197909467b48Spatrick else if (Name[5] == 'w' && VecWidth == 256)
198009467b48Spatrick IID = Intrinsic::x86_avx2_pavg_w;
198109467b48Spatrick else if (Name[5] == 'w' && VecWidth == 512)
198209467b48Spatrick IID = Intrinsic::x86_avx512_pavg_w_512;
198309467b48Spatrick else
198409467b48Spatrick llvm_unreachable("Unexpected intrinsic");
198509467b48Spatrick } else
198609467b48Spatrick return false;
198709467b48Spatrick
1988*d415bd75Srobert SmallVector<Value *, 4> Args(CI.args());
198909467b48Spatrick Args.pop_back();
199009467b48Spatrick Args.pop_back();
199109467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
199209467b48Spatrick Args);
1993*d415bd75Srobert unsigned NumArgs = CI.arg_size();
199409467b48Spatrick Rep = EmitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep,
199509467b48Spatrick CI.getArgOperand(NumArgs - 2));
199609467b48Spatrick return true;
199709467b48Spatrick }
199809467b48Spatrick
199909467b48Spatrick /// Upgrade comment in call to inline asm that represents an objc retain release
200009467b48Spatrick /// marker.
UpgradeInlineAsmString(std::string * AsmStr)200109467b48Spatrick void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
200209467b48Spatrick size_t Pos;
200309467b48Spatrick if (AsmStr->find("mov\tfp") == 0 &&
200409467b48Spatrick AsmStr->find("objc_retainAutoreleaseReturnValue") != std::string::npos &&
200509467b48Spatrick (Pos = AsmStr->find("# marker")) != std::string::npos) {
200609467b48Spatrick AsmStr->replace(Pos, 1, ";");
200709467b48Spatrick }
200809467b48Spatrick }
200909467b48Spatrick
UpgradeARMIntrinsicCall(StringRef Name,CallBase * CI,Function * F,IRBuilder<> & Builder)2010*d415bd75Srobert static Value *UpgradeARMIntrinsicCall(StringRef Name, CallBase *CI, Function *F,
2011*d415bd75Srobert IRBuilder<> &Builder) {
2012*d415bd75Srobert if (Name == "mve.vctp64.old") {
2013*d415bd75Srobert // Replace the old v4i1 vctp64 with a v2i1 vctp and predicate-casts to the
2014*d415bd75Srobert // correct type.
2015*d415bd75Srobert Value *VCTP = Builder.CreateCall(
2016*d415bd75Srobert Intrinsic::getDeclaration(F->getParent(), Intrinsic::arm_mve_vctp64),
2017*d415bd75Srobert CI->getArgOperand(0), CI->getName());
2018*d415bd75Srobert Value *C1 = Builder.CreateCall(
2019*d415bd75Srobert Intrinsic::getDeclaration(
2020*d415bd75Srobert F->getParent(), Intrinsic::arm_mve_pred_v2i,
2021*d415bd75Srobert {VectorType::get(Builder.getInt1Ty(), 2, false)}),
2022*d415bd75Srobert VCTP);
2023*d415bd75Srobert return Builder.CreateCall(
2024*d415bd75Srobert Intrinsic::getDeclaration(
2025*d415bd75Srobert F->getParent(), Intrinsic::arm_mve_pred_i2v,
2026*d415bd75Srobert {VectorType::get(Builder.getInt1Ty(), 4, false)}),
2027*d415bd75Srobert C1);
2028*d415bd75Srobert } else if (Name == "mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
2029*d415bd75Srobert Name == "mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
2030*d415bd75Srobert Name == "mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
2031*d415bd75Srobert Name == "mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
2032*d415bd75Srobert Name == "mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
2033*d415bd75Srobert Name == "mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
2034*d415bd75Srobert Name == "mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
2035*d415bd75Srobert Name == "mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
2036*d415bd75Srobert Name == "cde.vcx1q.predicated.v2i64.v4i1" ||
2037*d415bd75Srobert Name == "cde.vcx1qa.predicated.v2i64.v4i1" ||
2038*d415bd75Srobert Name == "cde.vcx2q.predicated.v2i64.v4i1" ||
2039*d415bd75Srobert Name == "cde.vcx2qa.predicated.v2i64.v4i1" ||
2040*d415bd75Srobert Name == "cde.vcx3q.predicated.v2i64.v4i1" ||
2041*d415bd75Srobert Name == "cde.vcx3qa.predicated.v2i64.v4i1") {
2042*d415bd75Srobert std::vector<Type *> Tys;
2043*d415bd75Srobert unsigned ID = CI->getIntrinsicID();
2044*d415bd75Srobert Type *V2I1Ty = FixedVectorType::get(Builder.getInt1Ty(), 2);
2045*d415bd75Srobert switch (ID) {
2046*d415bd75Srobert case Intrinsic::arm_mve_mull_int_predicated:
2047*d415bd75Srobert case Intrinsic::arm_mve_vqdmull_predicated:
2048*d415bd75Srobert case Intrinsic::arm_mve_vldr_gather_base_predicated:
2049*d415bd75Srobert Tys = {CI->getType(), CI->getOperand(0)->getType(), V2I1Ty};
2050*d415bd75Srobert break;
2051*d415bd75Srobert case Intrinsic::arm_mve_vldr_gather_base_wb_predicated:
2052*d415bd75Srobert case Intrinsic::arm_mve_vstr_scatter_base_predicated:
2053*d415bd75Srobert case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated:
2054*d415bd75Srobert Tys = {CI->getOperand(0)->getType(), CI->getOperand(0)->getType(),
2055*d415bd75Srobert V2I1Ty};
2056*d415bd75Srobert break;
2057*d415bd75Srobert case Intrinsic::arm_mve_vldr_gather_offset_predicated:
2058*d415bd75Srobert Tys = {CI->getType(), CI->getOperand(0)->getType(),
2059*d415bd75Srobert CI->getOperand(1)->getType(), V2I1Ty};
2060*d415bd75Srobert break;
2061*d415bd75Srobert case Intrinsic::arm_mve_vstr_scatter_offset_predicated:
2062*d415bd75Srobert Tys = {CI->getOperand(0)->getType(), CI->getOperand(1)->getType(),
2063*d415bd75Srobert CI->getOperand(2)->getType(), V2I1Ty};
2064*d415bd75Srobert break;
2065*d415bd75Srobert case Intrinsic::arm_cde_vcx1q_predicated:
2066*d415bd75Srobert case Intrinsic::arm_cde_vcx1qa_predicated:
2067*d415bd75Srobert case Intrinsic::arm_cde_vcx2q_predicated:
2068*d415bd75Srobert case Intrinsic::arm_cde_vcx2qa_predicated:
2069*d415bd75Srobert case Intrinsic::arm_cde_vcx3q_predicated:
2070*d415bd75Srobert case Intrinsic::arm_cde_vcx3qa_predicated:
2071*d415bd75Srobert Tys = {CI->getOperand(1)->getType(), V2I1Ty};
2072*d415bd75Srobert break;
2073*d415bd75Srobert default:
2074*d415bd75Srobert llvm_unreachable("Unhandled Intrinsic!");
2075*d415bd75Srobert }
2076*d415bd75Srobert
2077*d415bd75Srobert std::vector<Value *> Ops;
2078*d415bd75Srobert for (Value *Op : CI->args()) {
2079*d415bd75Srobert Type *Ty = Op->getType();
2080*d415bd75Srobert if (Ty->getScalarSizeInBits() == 1) {
2081*d415bd75Srobert Value *C1 = Builder.CreateCall(
2082*d415bd75Srobert Intrinsic::getDeclaration(
2083*d415bd75Srobert F->getParent(), Intrinsic::arm_mve_pred_v2i,
2084*d415bd75Srobert {VectorType::get(Builder.getInt1Ty(), 4, false)}),
2085*d415bd75Srobert Op);
2086*d415bd75Srobert Op = Builder.CreateCall(
2087*d415bd75Srobert Intrinsic::getDeclaration(F->getParent(),
2088*d415bd75Srobert Intrinsic::arm_mve_pred_i2v, {V2I1Ty}),
2089*d415bd75Srobert C1);
2090*d415bd75Srobert }
2091*d415bd75Srobert Ops.push_back(Op);
2092*d415bd75Srobert }
2093*d415bd75Srobert
2094*d415bd75Srobert Function *Fn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
2095*d415bd75Srobert return Builder.CreateCall(Fn, Ops, CI->getName());
2096*d415bd75Srobert }
2097*d415bd75Srobert llvm_unreachable("Unknown function for ARM CallBase upgrade.");
2098*d415bd75Srobert }
2099*d415bd75Srobert
210009467b48Spatrick /// Upgrade a call to an old intrinsic. All argument and return casting must be
210109467b48Spatrick /// provided to seamlessly integrate with existing context.
UpgradeIntrinsicCall(CallBase * CI,Function * NewFn)2102*d415bd75Srobert void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
2103*d415bd75Srobert // Note dyn_cast to Function is not quite the same as getCalledFunction, which
2104*d415bd75Srobert // checks the callee's function type matches. It's likely we need to handle
2105*d415bd75Srobert // type changes here.
2106*d415bd75Srobert Function *F = dyn_cast<Function>(CI->getCalledOperand());
2107*d415bd75Srobert if (!F)
2108*d415bd75Srobert return;
2109*d415bd75Srobert
211009467b48Spatrick LLVMContext &C = CI->getContext();
211109467b48Spatrick IRBuilder<> Builder(C);
211209467b48Spatrick Builder.SetInsertPoint(CI->getParent(), CI->getIterator());
211309467b48Spatrick
211409467b48Spatrick if (!NewFn) {
211509467b48Spatrick // Get the Function's name.
211609467b48Spatrick StringRef Name = F->getName();
211709467b48Spatrick
211809467b48Spatrick assert(Name.startswith("llvm.") && "Intrinsic doesn't start with 'llvm.'");
211909467b48Spatrick Name = Name.substr(5);
212009467b48Spatrick
212109467b48Spatrick bool IsX86 = Name.startswith("x86.");
212209467b48Spatrick if (IsX86)
212309467b48Spatrick Name = Name.substr(4);
212409467b48Spatrick bool IsNVVM = Name.startswith("nvvm.");
212509467b48Spatrick if (IsNVVM)
212609467b48Spatrick Name = Name.substr(5);
2127*d415bd75Srobert bool IsARM = Name.startswith("arm.");
2128*d415bd75Srobert if (IsARM)
2129*d415bd75Srobert Name = Name.substr(4);
213009467b48Spatrick
213109467b48Spatrick if (IsX86 && Name.startswith("sse4a.movnt.")) {
213209467b48Spatrick Module *M = F->getParent();
213309467b48Spatrick SmallVector<Metadata *, 1> Elts;
213409467b48Spatrick Elts.push_back(
213509467b48Spatrick ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
213609467b48Spatrick MDNode *Node = MDNode::get(C, Elts);
213709467b48Spatrick
213809467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
213909467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
214009467b48Spatrick
214109467b48Spatrick // Nontemporal (unaligned) store of the 0'th element of the float/double
214209467b48Spatrick // vector.
214309467b48Spatrick Type *SrcEltTy = cast<VectorType>(Arg1->getType())->getElementType();
214409467b48Spatrick PointerType *EltPtrTy = PointerType::getUnqual(SrcEltTy);
214509467b48Spatrick Value *Addr = Builder.CreateBitCast(Arg0, EltPtrTy, "cast");
214609467b48Spatrick Value *Extract =
214709467b48Spatrick Builder.CreateExtractElement(Arg1, (uint64_t)0, "extractelement");
214809467b48Spatrick
2149097a140dSpatrick StoreInst *SI = Builder.CreateAlignedStore(Extract, Addr, Align(1));
215009467b48Spatrick SI->setMetadata(M->getMDKindID("nontemporal"), Node);
215109467b48Spatrick
215209467b48Spatrick // Remove intrinsic.
215309467b48Spatrick CI->eraseFromParent();
215409467b48Spatrick return;
215509467b48Spatrick }
215609467b48Spatrick
215709467b48Spatrick if (IsX86 && (Name.startswith("avx.movnt.") ||
215809467b48Spatrick Name.startswith("avx512.storent."))) {
215909467b48Spatrick Module *M = F->getParent();
216009467b48Spatrick SmallVector<Metadata *, 1> Elts;
216109467b48Spatrick Elts.push_back(
216209467b48Spatrick ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
216309467b48Spatrick MDNode *Node = MDNode::get(C, Elts);
216409467b48Spatrick
216509467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
216609467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
216709467b48Spatrick
216809467b48Spatrick // Convert the type of the pointer to a pointer to the stored type.
216909467b48Spatrick Value *BC = Builder.CreateBitCast(Arg0,
217009467b48Spatrick PointerType::getUnqual(Arg1->getType()),
217109467b48Spatrick "cast");
2172097a140dSpatrick StoreInst *SI = Builder.CreateAlignedStore(
2173097a140dSpatrick Arg1, BC,
2174*d415bd75Srobert Align(Arg1->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
217509467b48Spatrick SI->setMetadata(M->getMDKindID("nontemporal"), Node);
217609467b48Spatrick
217709467b48Spatrick // Remove intrinsic.
217809467b48Spatrick CI->eraseFromParent();
217909467b48Spatrick return;
218009467b48Spatrick }
218109467b48Spatrick
218209467b48Spatrick if (IsX86 && Name == "sse2.storel.dq") {
218309467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
218409467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
218509467b48Spatrick
2186097a140dSpatrick auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
218709467b48Spatrick Value *BC0 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
218809467b48Spatrick Value *Elt = Builder.CreateExtractElement(BC0, (uint64_t)0);
218909467b48Spatrick Value *BC = Builder.CreateBitCast(Arg0,
219009467b48Spatrick PointerType::getUnqual(Elt->getType()),
219109467b48Spatrick "cast");
2192097a140dSpatrick Builder.CreateAlignedStore(Elt, BC, Align(1));
219309467b48Spatrick
219409467b48Spatrick // Remove intrinsic.
219509467b48Spatrick CI->eraseFromParent();
219609467b48Spatrick return;
219709467b48Spatrick }
219809467b48Spatrick
219909467b48Spatrick if (IsX86 && (Name.startswith("sse.storeu.") ||
220009467b48Spatrick Name.startswith("sse2.storeu.") ||
220109467b48Spatrick Name.startswith("avx.storeu."))) {
220209467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
220309467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
220409467b48Spatrick
220509467b48Spatrick Arg0 = Builder.CreateBitCast(Arg0,
220609467b48Spatrick PointerType::getUnqual(Arg1->getType()),
220709467b48Spatrick "cast");
2208097a140dSpatrick Builder.CreateAlignedStore(Arg1, Arg0, Align(1));
220909467b48Spatrick
221009467b48Spatrick // Remove intrinsic.
221109467b48Spatrick CI->eraseFromParent();
221209467b48Spatrick return;
221309467b48Spatrick }
221409467b48Spatrick
221509467b48Spatrick if (IsX86 && Name == "avx512.mask.store.ss") {
221609467b48Spatrick Value *Mask = Builder.CreateAnd(CI->getArgOperand(2), Builder.getInt8(1));
221709467b48Spatrick UpgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
221809467b48Spatrick Mask, false);
221909467b48Spatrick
222009467b48Spatrick // Remove intrinsic.
222109467b48Spatrick CI->eraseFromParent();
222209467b48Spatrick return;
222309467b48Spatrick }
222409467b48Spatrick
222509467b48Spatrick if (IsX86 && (Name.startswith("avx512.mask.store"))) {
222609467b48Spatrick // "avx512.mask.storeu." or "avx512.mask.store."
222709467b48Spatrick bool Aligned = Name[17] != 'u'; // "avx512.mask.storeu".
222809467b48Spatrick UpgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
222909467b48Spatrick CI->getArgOperand(2), Aligned);
223009467b48Spatrick
223109467b48Spatrick // Remove intrinsic.
223209467b48Spatrick CI->eraseFromParent();
223309467b48Spatrick return;
223409467b48Spatrick }
223509467b48Spatrick
223609467b48Spatrick Value *Rep;
223709467b48Spatrick // Upgrade packed integer vector compare intrinsics to compare instructions.
223809467b48Spatrick if (IsX86 && (Name.startswith("sse2.pcmp") ||
223909467b48Spatrick Name.startswith("avx2.pcmp"))) {
224009467b48Spatrick // "sse2.pcpmpeq." "sse2.pcmpgt." "avx2.pcmpeq." or "avx2.pcmpgt."
224109467b48Spatrick bool CmpEq = Name[9] == 'e';
224209467b48Spatrick Rep = Builder.CreateICmp(CmpEq ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_SGT,
224309467b48Spatrick CI->getArgOperand(0), CI->getArgOperand(1));
224409467b48Spatrick Rep = Builder.CreateSExt(Rep, CI->getType(), "");
224509467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.broadcastm"))) {
224609467b48Spatrick Type *ExtTy = Type::getInt32Ty(C);
224709467b48Spatrick if (CI->getOperand(0)->getType()->isIntegerTy(8))
224809467b48Spatrick ExtTy = Type::getInt64Ty(C);
224909467b48Spatrick unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() /
225009467b48Spatrick ExtTy->getPrimitiveSizeInBits();
225109467b48Spatrick Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy);
225209467b48Spatrick Rep = Builder.CreateVectorSplat(NumElts, Rep);
225309467b48Spatrick } else if (IsX86 && (Name == "sse.sqrt.ss" ||
225409467b48Spatrick Name == "sse2.sqrt.sd")) {
225509467b48Spatrick Value *Vec = CI->getArgOperand(0);
225609467b48Spatrick Value *Elt0 = Builder.CreateExtractElement(Vec, (uint64_t)0);
225709467b48Spatrick Function *Intr = Intrinsic::getDeclaration(F->getParent(),
225809467b48Spatrick Intrinsic::sqrt, Elt0->getType());
225909467b48Spatrick Elt0 = Builder.CreateCall(Intr, Elt0);
226009467b48Spatrick Rep = Builder.CreateInsertElement(Vec, Elt0, (uint64_t)0);
226109467b48Spatrick } else if (IsX86 && (Name.startswith("avx.sqrt.p") ||
226209467b48Spatrick Name.startswith("sse2.sqrt.p") ||
226309467b48Spatrick Name.startswith("sse.sqrt.p"))) {
226409467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
226509467b48Spatrick Intrinsic::sqrt,
226609467b48Spatrick CI->getType()),
226709467b48Spatrick {CI->getArgOperand(0)});
226809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.sqrt.p"))) {
2269*d415bd75Srobert if (CI->arg_size() == 4 &&
227009467b48Spatrick (!isa<ConstantInt>(CI->getArgOperand(3)) ||
227109467b48Spatrick cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
227209467b48Spatrick Intrinsic::ID IID = Name[18] == 's' ? Intrinsic::x86_avx512_sqrt_ps_512
227309467b48Spatrick : Intrinsic::x86_avx512_sqrt_pd_512;
227409467b48Spatrick
227509467b48Spatrick Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(3) };
227609467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
227709467b48Spatrick IID), Args);
227809467b48Spatrick } else {
227909467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
228009467b48Spatrick Intrinsic::sqrt,
228109467b48Spatrick CI->getType()),
228209467b48Spatrick {CI->getArgOperand(0)});
228309467b48Spatrick }
228409467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
228509467b48Spatrick CI->getArgOperand(1));
228609467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.ptestm") ||
228709467b48Spatrick Name.startswith("avx512.ptestnm"))) {
228809467b48Spatrick Value *Op0 = CI->getArgOperand(0);
228909467b48Spatrick Value *Op1 = CI->getArgOperand(1);
229009467b48Spatrick Value *Mask = CI->getArgOperand(2);
229109467b48Spatrick Rep = Builder.CreateAnd(Op0, Op1);
229209467b48Spatrick llvm::Type *Ty = Op0->getType();
229309467b48Spatrick Value *Zero = llvm::Constant::getNullValue(Ty);
229409467b48Spatrick ICmpInst::Predicate Pred =
229509467b48Spatrick Name.startswith("avx512.ptestm") ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
229609467b48Spatrick Rep = Builder.CreateICmp(Pred, Rep, Zero);
229709467b48Spatrick Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, Mask);
229809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.pbroadcast"))){
229973471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getArgOperand(1)->getType())
230073471bf0Spatrick ->getNumElements();
230109467b48Spatrick Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0));
230209467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
230309467b48Spatrick CI->getArgOperand(1));
230409467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.kunpck"))) {
230509467b48Spatrick unsigned NumElts = CI->getType()->getScalarSizeInBits();
230609467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), NumElts);
230709467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), NumElts);
2308097a140dSpatrick int Indices[64];
230909467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
231009467b48Spatrick Indices[i] = i;
231109467b48Spatrick
231209467b48Spatrick // First extract half of each vector. This gives better codegen than
231309467b48Spatrick // doing it in a single shuffle.
2314*d415bd75Srobert LHS =
2315*d415bd75Srobert Builder.CreateShuffleVector(LHS, LHS, ArrayRef(Indices, NumElts / 2));
2316*d415bd75Srobert RHS =
2317*d415bd75Srobert Builder.CreateShuffleVector(RHS, RHS, ArrayRef(Indices, NumElts / 2));
231809467b48Spatrick // Concat the vectors.
231909467b48Spatrick // NOTE: Operands have to be swapped to match intrinsic definition.
2320*d415bd75Srobert Rep = Builder.CreateShuffleVector(RHS, LHS, ArrayRef(Indices, NumElts));
232109467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
232209467b48Spatrick } else if (IsX86 && Name == "avx512.kand.w") {
232309467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
232409467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
232509467b48Spatrick Rep = Builder.CreateAnd(LHS, RHS);
232609467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
232709467b48Spatrick } else if (IsX86 && Name == "avx512.kandn.w") {
232809467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
232909467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
233009467b48Spatrick LHS = Builder.CreateNot(LHS);
233109467b48Spatrick Rep = Builder.CreateAnd(LHS, RHS);
233209467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
233309467b48Spatrick } else if (IsX86 && Name == "avx512.kor.w") {
233409467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
233509467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
233609467b48Spatrick Rep = Builder.CreateOr(LHS, RHS);
233709467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
233809467b48Spatrick } else if (IsX86 && Name == "avx512.kxor.w") {
233909467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
234009467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
234109467b48Spatrick Rep = Builder.CreateXor(LHS, RHS);
234209467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
234309467b48Spatrick } else if (IsX86 && Name == "avx512.kxnor.w") {
234409467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
234509467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
234609467b48Spatrick LHS = Builder.CreateNot(LHS);
234709467b48Spatrick Rep = Builder.CreateXor(LHS, RHS);
234809467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
234909467b48Spatrick } else if (IsX86 && Name == "avx512.knot.w") {
235009467b48Spatrick Rep = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
235109467b48Spatrick Rep = Builder.CreateNot(Rep);
235209467b48Spatrick Rep = Builder.CreateBitCast(Rep, CI->getType());
235309467b48Spatrick } else if (IsX86 &&
235409467b48Spatrick (Name == "avx512.kortestz.w" || Name == "avx512.kortestc.w")) {
235509467b48Spatrick Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
235609467b48Spatrick Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
235709467b48Spatrick Rep = Builder.CreateOr(LHS, RHS);
235809467b48Spatrick Rep = Builder.CreateBitCast(Rep, Builder.getInt16Ty());
235909467b48Spatrick Value *C;
236009467b48Spatrick if (Name[14] == 'c')
236109467b48Spatrick C = ConstantInt::getAllOnesValue(Builder.getInt16Ty());
236209467b48Spatrick else
236309467b48Spatrick C = ConstantInt::getNullValue(Builder.getInt16Ty());
236409467b48Spatrick Rep = Builder.CreateICmpEQ(Rep, C);
236509467b48Spatrick Rep = Builder.CreateZExt(Rep, Builder.getInt32Ty());
236609467b48Spatrick } else if (IsX86 && (Name == "sse.add.ss" || Name == "sse2.add.sd" ||
236709467b48Spatrick Name == "sse.sub.ss" || Name == "sse2.sub.sd" ||
236809467b48Spatrick Name == "sse.mul.ss" || Name == "sse2.mul.sd" ||
236909467b48Spatrick Name == "sse.div.ss" || Name == "sse2.div.sd")) {
237009467b48Spatrick Type *I32Ty = Type::getInt32Ty(C);
237109467b48Spatrick Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0),
237209467b48Spatrick ConstantInt::get(I32Ty, 0));
237309467b48Spatrick Value *Elt1 = Builder.CreateExtractElement(CI->getArgOperand(1),
237409467b48Spatrick ConstantInt::get(I32Ty, 0));
237509467b48Spatrick Value *EltOp;
237609467b48Spatrick if (Name.contains(".add."))
237709467b48Spatrick EltOp = Builder.CreateFAdd(Elt0, Elt1);
237809467b48Spatrick else if (Name.contains(".sub."))
237909467b48Spatrick EltOp = Builder.CreateFSub(Elt0, Elt1);
238009467b48Spatrick else if (Name.contains(".mul."))
238109467b48Spatrick EltOp = Builder.CreateFMul(Elt0, Elt1);
238209467b48Spatrick else
238309467b48Spatrick EltOp = Builder.CreateFDiv(Elt0, Elt1);
238409467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(0), EltOp,
238509467b48Spatrick ConstantInt::get(I32Ty, 0));
238609467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.pcmp")) {
238709467b48Spatrick // "avx512.mask.pcmpeq." or "avx512.mask.pcmpgt."
238809467b48Spatrick bool CmpEq = Name[16] == 'e';
238909467b48Spatrick Rep = upgradeMaskedCompare(Builder, *CI, CmpEq ? 0 : 6, true);
239009467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.vpshufbitqmb.")) {
239109467b48Spatrick Type *OpTy = CI->getArgOperand(0)->getType();
239209467b48Spatrick unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
239309467b48Spatrick Intrinsic::ID IID;
239409467b48Spatrick switch (VecWidth) {
239509467b48Spatrick default: llvm_unreachable("Unexpected intrinsic");
239609467b48Spatrick case 128: IID = Intrinsic::x86_avx512_vpshufbitqmb_128; break;
239709467b48Spatrick case 256: IID = Intrinsic::x86_avx512_vpshufbitqmb_256; break;
239809467b48Spatrick case 512: IID = Intrinsic::x86_avx512_vpshufbitqmb_512; break;
239909467b48Spatrick }
240009467b48Spatrick
240109467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
240209467b48Spatrick { CI->getOperand(0), CI->getArgOperand(1) });
240309467b48Spatrick Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
240409467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.fpclass.p")) {
240509467b48Spatrick Type *OpTy = CI->getArgOperand(0)->getType();
240609467b48Spatrick unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
240709467b48Spatrick unsigned EltWidth = OpTy->getScalarSizeInBits();
240809467b48Spatrick Intrinsic::ID IID;
240909467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
241009467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_ps_128;
241109467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
241209467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_ps_256;
241309467b48Spatrick else if (VecWidth == 512 && EltWidth == 32)
241409467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_ps_512;
241509467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
241609467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_pd_128;
241709467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
241809467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_pd_256;
241909467b48Spatrick else if (VecWidth == 512 && EltWidth == 64)
242009467b48Spatrick IID = Intrinsic::x86_avx512_fpclass_pd_512;
242109467b48Spatrick else
242209467b48Spatrick llvm_unreachable("Unexpected intrinsic");
242309467b48Spatrick
242409467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
242509467b48Spatrick { CI->getOperand(0), CI->getArgOperand(1) });
242609467b48Spatrick Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
242773471bf0Spatrick } else if (IsX86 && Name.startswith("avx512.cmp.p")) {
2428*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
242973471bf0Spatrick Type *OpTy = Args[0]->getType();
243009467b48Spatrick unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
243109467b48Spatrick unsigned EltWidth = OpTy->getScalarSizeInBits();
243209467b48Spatrick Intrinsic::ID IID;
243309467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
243473471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_ps_128;
243509467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
243673471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_ps_256;
243709467b48Spatrick else if (VecWidth == 512 && EltWidth == 32)
243873471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_ps_512;
243909467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
244073471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_pd_128;
244109467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
244273471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_pd_256;
244309467b48Spatrick else if (VecWidth == 512 && EltWidth == 64)
244473471bf0Spatrick IID = Intrinsic::x86_avx512_mask_cmp_pd_512;
244509467b48Spatrick else
244609467b48Spatrick llvm_unreachable("Unexpected intrinsic");
244709467b48Spatrick
244873471bf0Spatrick Value *Mask = Constant::getAllOnesValue(CI->getType());
244973471bf0Spatrick if (VecWidth == 512)
245073471bf0Spatrick std::swap(Mask, Args.back());
245173471bf0Spatrick Args.push_back(Mask);
245209467b48Spatrick
245309467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
245409467b48Spatrick Args);
245573471bf0Spatrick } else if (IsX86 && Name.startswith("avx512.mask.cmp.")) {
245609467b48Spatrick // Integer compare intrinsics.
245709467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
245809467b48Spatrick Rep = upgradeMaskedCompare(Builder, *CI, Imm, true);
245909467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.ucmp.")) {
246009467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
246109467b48Spatrick Rep = upgradeMaskedCompare(Builder, *CI, Imm, false);
246209467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.cvtb2mask.") ||
246309467b48Spatrick Name.startswith("avx512.cvtw2mask.") ||
246409467b48Spatrick Name.startswith("avx512.cvtd2mask.") ||
246509467b48Spatrick Name.startswith("avx512.cvtq2mask."))) {
246609467b48Spatrick Value *Op = CI->getArgOperand(0);
246709467b48Spatrick Value *Zero = llvm::Constant::getNullValue(Op->getType());
246809467b48Spatrick Rep = Builder.CreateICmp(ICmpInst::ICMP_SLT, Op, Zero);
246909467b48Spatrick Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, nullptr);
247009467b48Spatrick } else if(IsX86 && (Name == "ssse3.pabs.b.128" ||
247109467b48Spatrick Name == "ssse3.pabs.w.128" ||
247209467b48Spatrick Name == "ssse3.pabs.d.128" ||
247309467b48Spatrick Name.startswith("avx2.pabs") ||
247409467b48Spatrick Name.startswith("avx512.mask.pabs"))) {
247509467b48Spatrick Rep = upgradeAbs(Builder, *CI);
247609467b48Spatrick } else if (IsX86 && (Name == "sse41.pmaxsb" ||
247709467b48Spatrick Name == "sse2.pmaxs.w" ||
247809467b48Spatrick Name == "sse41.pmaxsd" ||
247909467b48Spatrick Name.startswith("avx2.pmaxs") ||
248009467b48Spatrick Name.startswith("avx512.mask.pmaxs"))) {
248173471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smax);
248209467b48Spatrick } else if (IsX86 && (Name == "sse2.pmaxu.b" ||
248309467b48Spatrick Name == "sse41.pmaxuw" ||
248409467b48Spatrick Name == "sse41.pmaxud" ||
248509467b48Spatrick Name.startswith("avx2.pmaxu") ||
248609467b48Spatrick Name.startswith("avx512.mask.pmaxu"))) {
248773471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umax);
248809467b48Spatrick } else if (IsX86 && (Name == "sse41.pminsb" ||
248909467b48Spatrick Name == "sse2.pmins.w" ||
249009467b48Spatrick Name == "sse41.pminsd" ||
249109467b48Spatrick Name.startswith("avx2.pmins") ||
249209467b48Spatrick Name.startswith("avx512.mask.pmins"))) {
249373471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smin);
249409467b48Spatrick } else if (IsX86 && (Name == "sse2.pminu.b" ||
249509467b48Spatrick Name == "sse41.pminuw" ||
249609467b48Spatrick Name == "sse41.pminud" ||
249709467b48Spatrick Name.startswith("avx2.pminu") ||
249809467b48Spatrick Name.startswith("avx512.mask.pminu"))) {
249973471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umin);
250009467b48Spatrick } else if (IsX86 && (Name == "sse2.pmulu.dq" ||
250109467b48Spatrick Name == "avx2.pmulu.dq" ||
250209467b48Spatrick Name == "avx512.pmulu.dq.512" ||
250309467b48Spatrick Name.startswith("avx512.mask.pmulu.dq."))) {
250409467b48Spatrick Rep = upgradePMULDQ(Builder, *CI, /*Signed*/false);
250509467b48Spatrick } else if (IsX86 && (Name == "sse41.pmuldq" ||
250609467b48Spatrick Name == "avx2.pmul.dq" ||
250709467b48Spatrick Name == "avx512.pmul.dq.512" ||
250809467b48Spatrick Name.startswith("avx512.mask.pmul.dq."))) {
250909467b48Spatrick Rep = upgradePMULDQ(Builder, *CI, /*Signed*/true);
251009467b48Spatrick } else if (IsX86 && (Name == "sse.cvtsi2ss" ||
251109467b48Spatrick Name == "sse2.cvtsi2sd" ||
251209467b48Spatrick Name == "sse.cvtsi642ss" ||
251309467b48Spatrick Name == "sse2.cvtsi642sd")) {
2514097a140dSpatrick Rep = Builder.CreateSIToFP(
2515097a140dSpatrick CI->getArgOperand(1),
2516097a140dSpatrick cast<VectorType>(CI->getType())->getElementType());
251709467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
251809467b48Spatrick } else if (IsX86 && Name == "avx512.cvtusi2sd") {
2519097a140dSpatrick Rep = Builder.CreateUIToFP(
2520097a140dSpatrick CI->getArgOperand(1),
2521097a140dSpatrick cast<VectorType>(CI->getType())->getElementType());
252209467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
252309467b48Spatrick } else if (IsX86 && Name == "sse2.cvtss2sd") {
252409467b48Spatrick Rep = Builder.CreateExtractElement(CI->getArgOperand(1), (uint64_t)0);
2525097a140dSpatrick Rep = Builder.CreateFPExt(
2526097a140dSpatrick Rep, cast<VectorType>(CI->getType())->getElementType());
252709467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
252809467b48Spatrick } else if (IsX86 && (Name == "sse2.cvtdq2pd" ||
252909467b48Spatrick Name == "sse2.cvtdq2ps" ||
253009467b48Spatrick Name == "avx.cvtdq2.pd.256" ||
253109467b48Spatrick Name == "avx.cvtdq2.ps.256" ||
253209467b48Spatrick Name.startswith("avx512.mask.cvtdq2pd.") ||
253309467b48Spatrick Name.startswith("avx512.mask.cvtudq2pd.") ||
253409467b48Spatrick Name.startswith("avx512.mask.cvtdq2ps.") ||
253509467b48Spatrick Name.startswith("avx512.mask.cvtudq2ps.") ||
253609467b48Spatrick Name.startswith("avx512.mask.cvtqq2pd.") ||
253709467b48Spatrick Name.startswith("avx512.mask.cvtuqq2pd.") ||
253809467b48Spatrick Name == "avx512.mask.cvtqq2ps.256" ||
253909467b48Spatrick Name == "avx512.mask.cvtqq2ps.512" ||
254009467b48Spatrick Name == "avx512.mask.cvtuqq2ps.256" ||
254109467b48Spatrick Name == "avx512.mask.cvtuqq2ps.512" ||
254209467b48Spatrick Name == "sse2.cvtps2pd" ||
254309467b48Spatrick Name == "avx.cvt.ps2.pd.256" ||
254409467b48Spatrick Name == "avx512.mask.cvtps2pd.128" ||
254509467b48Spatrick Name == "avx512.mask.cvtps2pd.256")) {
254673471bf0Spatrick auto *DstTy = cast<FixedVectorType>(CI->getType());
254709467b48Spatrick Rep = CI->getArgOperand(0);
254873471bf0Spatrick auto *SrcTy = cast<FixedVectorType>(Rep->getType());
254909467b48Spatrick
2550097a140dSpatrick unsigned NumDstElts = DstTy->getNumElements();
2551097a140dSpatrick if (NumDstElts < SrcTy->getNumElements()) {
255209467b48Spatrick assert(NumDstElts == 2 && "Unexpected vector size");
2553097a140dSpatrick Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1});
255409467b48Spatrick }
255509467b48Spatrick
2556097a140dSpatrick bool IsPS2PD = SrcTy->getElementType()->isFloatTy();
255709467b48Spatrick bool IsUnsigned = (StringRef::npos != Name.find("cvtu"));
255809467b48Spatrick if (IsPS2PD)
255909467b48Spatrick Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd");
2560*d415bd75Srobert else if (CI->arg_size() == 4 &&
256109467b48Spatrick (!isa<ConstantInt>(CI->getArgOperand(3)) ||
256209467b48Spatrick cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
256309467b48Spatrick Intrinsic::ID IID = IsUnsigned ? Intrinsic::x86_avx512_uitofp_round
256409467b48Spatrick : Intrinsic::x86_avx512_sitofp_round;
256509467b48Spatrick Function *F = Intrinsic::getDeclaration(CI->getModule(), IID,
256609467b48Spatrick { DstTy, SrcTy });
256709467b48Spatrick Rep = Builder.CreateCall(F, { Rep, CI->getArgOperand(3) });
256809467b48Spatrick } else {
256909467b48Spatrick Rep = IsUnsigned ? Builder.CreateUIToFP(Rep, DstTy, "cvt")
257009467b48Spatrick : Builder.CreateSIToFP(Rep, DstTy, "cvt");
257109467b48Spatrick }
257209467b48Spatrick
2573*d415bd75Srobert if (CI->arg_size() >= 3)
257409467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
257509467b48Spatrick CI->getArgOperand(1));
2576097a140dSpatrick } else if (IsX86 && (Name.startswith("avx512.mask.vcvtph2ps.") ||
2577097a140dSpatrick Name.startswith("vcvtph2ps."))) {
257873471bf0Spatrick auto *DstTy = cast<FixedVectorType>(CI->getType());
2579097a140dSpatrick Rep = CI->getArgOperand(0);
258073471bf0Spatrick auto *SrcTy = cast<FixedVectorType>(Rep->getType());
2581097a140dSpatrick unsigned NumDstElts = DstTy->getNumElements();
2582097a140dSpatrick if (NumDstElts != SrcTy->getNumElements()) {
2583097a140dSpatrick assert(NumDstElts == 4 && "Unexpected vector size");
2584097a140dSpatrick Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1, 2, 3});
2585097a140dSpatrick }
2586097a140dSpatrick Rep = Builder.CreateBitCast(
2587097a140dSpatrick Rep, FixedVectorType::get(Type::getHalfTy(C), NumDstElts));
2588097a140dSpatrick Rep = Builder.CreateFPExt(Rep, DstTy, "cvtph2ps");
2589*d415bd75Srobert if (CI->arg_size() >= 3)
2590097a140dSpatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
2591097a140dSpatrick CI->getArgOperand(1));
2592*d415bd75Srobert } else if (IsX86 && Name.startswith("avx512.mask.load")) {
2593*d415bd75Srobert // "avx512.mask.loadu." or "avx512.mask.load."
2594*d415bd75Srobert bool Aligned = Name[16] != 'u'; // "avx512.mask.loadu".
2595*d415bd75Srobert Rep =
2596*d415bd75Srobert UpgradeMaskedLoad(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
2597*d415bd75Srobert CI->getArgOperand(2), Aligned);
259809467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.expand.load.")) {
259973471bf0Spatrick auto *ResultTy = cast<FixedVectorType>(CI->getType());
2600097a140dSpatrick Type *PtrTy = ResultTy->getElementType();
260109467b48Spatrick
260209467b48Spatrick // Cast the pointer to element type.
260309467b48Spatrick Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
260409467b48Spatrick llvm::PointerType::getUnqual(PtrTy));
260509467b48Spatrick
260609467b48Spatrick Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
2607097a140dSpatrick ResultTy->getNumElements());
260809467b48Spatrick
260909467b48Spatrick Function *ELd = Intrinsic::getDeclaration(F->getParent(),
261009467b48Spatrick Intrinsic::masked_expandload,
261109467b48Spatrick ResultTy);
261209467b48Spatrick Rep = Builder.CreateCall(ELd, { Ptr, MaskVec, CI->getOperand(1) });
261309467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.compress.store.")) {
2614097a140dSpatrick auto *ResultTy = cast<VectorType>(CI->getArgOperand(1)->getType());
2615097a140dSpatrick Type *PtrTy = ResultTy->getElementType();
261609467b48Spatrick
261709467b48Spatrick // Cast the pointer to element type.
261809467b48Spatrick Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
261909467b48Spatrick llvm::PointerType::getUnqual(PtrTy));
262009467b48Spatrick
262173471bf0Spatrick Value *MaskVec =
262273471bf0Spatrick getX86MaskVec(Builder, CI->getArgOperand(2),
262373471bf0Spatrick cast<FixedVectorType>(ResultTy)->getNumElements());
262409467b48Spatrick
262509467b48Spatrick Function *CSt = Intrinsic::getDeclaration(F->getParent(),
262609467b48Spatrick Intrinsic::masked_compressstore,
262709467b48Spatrick ResultTy);
262809467b48Spatrick Rep = Builder.CreateCall(CSt, { CI->getArgOperand(1), Ptr, MaskVec });
262909467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.compress.") ||
263009467b48Spatrick Name.startswith("avx512.mask.expand."))) {
263173471bf0Spatrick auto *ResultTy = cast<FixedVectorType>(CI->getType());
263209467b48Spatrick
263309467b48Spatrick Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
2634097a140dSpatrick ResultTy->getNumElements());
263509467b48Spatrick
263609467b48Spatrick bool IsCompress = Name[12] == 'c';
263709467b48Spatrick Intrinsic::ID IID = IsCompress ? Intrinsic::x86_avx512_mask_compress
263809467b48Spatrick : Intrinsic::x86_avx512_mask_expand;
263909467b48Spatrick Function *Intr = Intrinsic::getDeclaration(F->getParent(), IID, ResultTy);
264009467b48Spatrick Rep = Builder.CreateCall(Intr, { CI->getOperand(0), CI->getOperand(1),
264109467b48Spatrick MaskVec });
264209467b48Spatrick } else if (IsX86 && Name.startswith("xop.vpcom")) {
264309467b48Spatrick bool IsSigned;
264409467b48Spatrick if (Name.endswith("ub") || Name.endswith("uw") || Name.endswith("ud") ||
264509467b48Spatrick Name.endswith("uq"))
264609467b48Spatrick IsSigned = false;
264709467b48Spatrick else if (Name.endswith("b") || Name.endswith("w") || Name.endswith("d") ||
264809467b48Spatrick Name.endswith("q"))
264909467b48Spatrick IsSigned = true;
265009467b48Spatrick else
265109467b48Spatrick llvm_unreachable("Unknown suffix");
265209467b48Spatrick
265309467b48Spatrick unsigned Imm;
2654*d415bd75Srobert if (CI->arg_size() == 3) {
265509467b48Spatrick Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
265609467b48Spatrick } else {
265709467b48Spatrick Name = Name.substr(9); // strip off "xop.vpcom"
265809467b48Spatrick if (Name.startswith("lt"))
265909467b48Spatrick Imm = 0;
266009467b48Spatrick else if (Name.startswith("le"))
266109467b48Spatrick Imm = 1;
266209467b48Spatrick else if (Name.startswith("gt"))
266309467b48Spatrick Imm = 2;
266409467b48Spatrick else if (Name.startswith("ge"))
266509467b48Spatrick Imm = 3;
266609467b48Spatrick else if (Name.startswith("eq"))
266709467b48Spatrick Imm = 4;
266809467b48Spatrick else if (Name.startswith("ne"))
266909467b48Spatrick Imm = 5;
267009467b48Spatrick else if (Name.startswith("false"))
267109467b48Spatrick Imm = 6;
267209467b48Spatrick else if (Name.startswith("true"))
267309467b48Spatrick Imm = 7;
267409467b48Spatrick else
267509467b48Spatrick llvm_unreachable("Unknown condition");
267609467b48Spatrick }
267709467b48Spatrick
267809467b48Spatrick Rep = upgradeX86vpcom(Builder, *CI, Imm, IsSigned);
267909467b48Spatrick } else if (IsX86 && Name.startswith("xop.vpcmov")) {
268009467b48Spatrick Value *Sel = CI->getArgOperand(2);
268109467b48Spatrick Value *NotSel = Builder.CreateNot(Sel);
268209467b48Spatrick Value *Sel0 = Builder.CreateAnd(CI->getArgOperand(0), Sel);
268309467b48Spatrick Value *Sel1 = Builder.CreateAnd(CI->getArgOperand(1), NotSel);
268409467b48Spatrick Rep = Builder.CreateOr(Sel0, Sel1);
268509467b48Spatrick } else if (IsX86 && (Name.startswith("xop.vprot") ||
268609467b48Spatrick Name.startswith("avx512.prol") ||
268709467b48Spatrick Name.startswith("avx512.mask.prol"))) {
268809467b48Spatrick Rep = upgradeX86Rotate(Builder, *CI, false);
268909467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.pror") ||
269009467b48Spatrick Name.startswith("avx512.mask.pror"))) {
269109467b48Spatrick Rep = upgradeX86Rotate(Builder, *CI, true);
269209467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.vpshld.") ||
269309467b48Spatrick Name.startswith("avx512.mask.vpshld") ||
269409467b48Spatrick Name.startswith("avx512.maskz.vpshld"))) {
269509467b48Spatrick bool ZeroMask = Name[11] == 'z';
269609467b48Spatrick Rep = upgradeX86ConcatShift(Builder, *CI, false, ZeroMask);
269709467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.vpshrd.") ||
269809467b48Spatrick Name.startswith("avx512.mask.vpshrd") ||
269909467b48Spatrick Name.startswith("avx512.maskz.vpshrd"))) {
270009467b48Spatrick bool ZeroMask = Name[11] == 'z';
270109467b48Spatrick Rep = upgradeX86ConcatShift(Builder, *CI, true, ZeroMask);
270209467b48Spatrick } else if (IsX86 && Name == "sse42.crc32.64.8") {
270309467b48Spatrick Function *CRC32 = Intrinsic::getDeclaration(F->getParent(),
270409467b48Spatrick Intrinsic::x86_sse42_crc32_32_8);
270509467b48Spatrick Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
270609467b48Spatrick Rep = Builder.CreateCall(CRC32, {Trunc0, CI->getArgOperand(1)});
270709467b48Spatrick Rep = Builder.CreateZExt(Rep, CI->getType(), "");
270809467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vbroadcast.s") ||
270909467b48Spatrick Name.startswith("avx512.vbroadcast.s"))) {
271009467b48Spatrick // Replace broadcasts with a series of insertelements.
271173471bf0Spatrick auto *VecTy = cast<FixedVectorType>(CI->getType());
2712097a140dSpatrick Type *EltTy = VecTy->getElementType();
2713097a140dSpatrick unsigned EltNum = VecTy->getNumElements();
271409467b48Spatrick Value *Cast = Builder.CreateBitCast(CI->getArgOperand(0),
271509467b48Spatrick EltTy->getPointerTo());
271609467b48Spatrick Value *Load = Builder.CreateLoad(EltTy, Cast);
271709467b48Spatrick Type *I32Ty = Type::getInt32Ty(C);
2718*d415bd75Srobert Rep = PoisonValue::get(VecTy);
271909467b48Spatrick for (unsigned I = 0; I < EltNum; ++I)
272009467b48Spatrick Rep = Builder.CreateInsertElement(Rep, Load,
272109467b48Spatrick ConstantInt::get(I32Ty, I));
272209467b48Spatrick } else if (IsX86 && (Name.startswith("sse41.pmovsx") ||
272309467b48Spatrick Name.startswith("sse41.pmovzx") ||
272409467b48Spatrick Name.startswith("avx2.pmovsx") ||
272509467b48Spatrick Name.startswith("avx2.pmovzx") ||
272609467b48Spatrick Name.startswith("avx512.mask.pmovsx") ||
272709467b48Spatrick Name.startswith("avx512.mask.pmovzx"))) {
272873471bf0Spatrick auto *DstTy = cast<FixedVectorType>(CI->getType());
272909467b48Spatrick unsigned NumDstElts = DstTy->getNumElements();
273009467b48Spatrick
273109467b48Spatrick // Extract a subvector of the first NumDstElts lanes and sign/zero extend.
2732097a140dSpatrick SmallVector<int, 8> ShuffleMask(NumDstElts);
273309467b48Spatrick for (unsigned i = 0; i != NumDstElts; ++i)
273409467b48Spatrick ShuffleMask[i] = i;
273509467b48Spatrick
273673471bf0Spatrick Value *SV =
273773471bf0Spatrick Builder.CreateShuffleVector(CI->getArgOperand(0), ShuffleMask);
273809467b48Spatrick
273909467b48Spatrick bool DoSext = (StringRef::npos != Name.find("pmovsx"));
274009467b48Spatrick Rep = DoSext ? Builder.CreateSExt(SV, DstTy)
274109467b48Spatrick : Builder.CreateZExt(SV, DstTy);
274209467b48Spatrick // If there are 3 arguments, it's a masked intrinsic so we need a select.
2743*d415bd75Srobert if (CI->arg_size() == 3)
274409467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
274509467b48Spatrick CI->getArgOperand(1));
274609467b48Spatrick } else if (Name == "avx512.mask.pmov.qd.256" ||
274709467b48Spatrick Name == "avx512.mask.pmov.qd.512" ||
274809467b48Spatrick Name == "avx512.mask.pmov.wb.256" ||
274909467b48Spatrick Name == "avx512.mask.pmov.wb.512") {
275009467b48Spatrick Type *Ty = CI->getArgOperand(1)->getType();
275109467b48Spatrick Rep = Builder.CreateTrunc(CI->getArgOperand(0), Ty);
275209467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
275309467b48Spatrick CI->getArgOperand(1));
275409467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vbroadcastf128") ||
275509467b48Spatrick Name == "avx2.vbroadcasti128")) {
275609467b48Spatrick // Replace vbroadcastf128/vbroadcasti128 with a vector load+shuffle.
2757097a140dSpatrick Type *EltTy = cast<VectorType>(CI->getType())->getElementType();
275809467b48Spatrick unsigned NumSrcElts = 128 / EltTy->getPrimitiveSizeInBits();
2759097a140dSpatrick auto *VT = FixedVectorType::get(EltTy, NumSrcElts);
276009467b48Spatrick Value *Op = Builder.CreatePointerCast(CI->getArgOperand(0),
276109467b48Spatrick PointerType::getUnqual(VT));
2762097a140dSpatrick Value *Load = Builder.CreateAlignedLoad(VT, Op, Align(1));
276309467b48Spatrick if (NumSrcElts == 2)
276473471bf0Spatrick Rep = Builder.CreateShuffleVector(Load, ArrayRef<int>{0, 1, 0, 1});
276509467b48Spatrick else
276673471bf0Spatrick Rep = Builder.CreateShuffleVector(
276773471bf0Spatrick Load, ArrayRef<int>{0, 1, 2, 3, 0, 1, 2, 3});
276809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.shuf.i") ||
276909467b48Spatrick Name.startswith("avx512.mask.shuf.f"))) {
277009467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
277109467b48Spatrick Type *VT = CI->getType();
277209467b48Spatrick unsigned NumLanes = VT->getPrimitiveSizeInBits() / 128;
277309467b48Spatrick unsigned NumElementsInLane = 128 / VT->getScalarSizeInBits();
277409467b48Spatrick unsigned ControlBitsMask = NumLanes - 1;
277509467b48Spatrick unsigned NumControlBits = NumLanes / 2;
2776097a140dSpatrick SmallVector<int, 8> ShuffleMask(0);
277709467b48Spatrick
277809467b48Spatrick for (unsigned l = 0; l != NumLanes; ++l) {
277909467b48Spatrick unsigned LaneMask = (Imm >> (l * NumControlBits)) & ControlBitsMask;
278009467b48Spatrick // We actually need the other source.
278109467b48Spatrick if (l >= NumLanes / 2)
278209467b48Spatrick LaneMask += NumLanes;
278309467b48Spatrick for (unsigned i = 0; i != NumElementsInLane; ++i)
278409467b48Spatrick ShuffleMask.push_back(LaneMask * NumElementsInLane + i);
278509467b48Spatrick }
278609467b48Spatrick Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
278709467b48Spatrick CI->getArgOperand(1), ShuffleMask);
278809467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep,
278909467b48Spatrick CI->getArgOperand(3));
279009467b48Spatrick }else if (IsX86 && (Name.startswith("avx512.mask.broadcastf") ||
279109467b48Spatrick Name.startswith("avx512.mask.broadcasti"))) {
279209467b48Spatrick unsigned NumSrcElts =
279373471bf0Spatrick cast<FixedVectorType>(CI->getArgOperand(0)->getType())
279473471bf0Spatrick ->getNumElements();
279573471bf0Spatrick unsigned NumDstElts =
279673471bf0Spatrick cast<FixedVectorType>(CI->getType())->getNumElements();
279709467b48Spatrick
2798097a140dSpatrick SmallVector<int, 8> ShuffleMask(NumDstElts);
279909467b48Spatrick for (unsigned i = 0; i != NumDstElts; ++i)
280009467b48Spatrick ShuffleMask[i] = i % NumSrcElts;
280109467b48Spatrick
280209467b48Spatrick Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
280309467b48Spatrick CI->getArgOperand(0),
280409467b48Spatrick ShuffleMask);
280509467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
280609467b48Spatrick CI->getArgOperand(1));
280709467b48Spatrick } else if (IsX86 && (Name.startswith("avx2.pbroadcast") ||
280809467b48Spatrick Name.startswith("avx2.vbroadcast") ||
280909467b48Spatrick Name.startswith("avx512.pbroadcast") ||
281009467b48Spatrick Name.startswith("avx512.mask.broadcast.s"))) {
281109467b48Spatrick // Replace vp?broadcasts with a vector shuffle.
281209467b48Spatrick Value *Op = CI->getArgOperand(0);
2813097a140dSpatrick ElementCount EC = cast<VectorType>(CI->getType())->getElementCount();
2814097a140dSpatrick Type *MaskTy = VectorType::get(Type::getInt32Ty(C), EC);
281573471bf0Spatrick SmallVector<int, 8> M;
281673471bf0Spatrick ShuffleVectorInst::getShuffleMask(Constant::getNullValue(MaskTy), M);
281773471bf0Spatrick Rep = Builder.CreateShuffleVector(Op, M);
281809467b48Spatrick
2819*d415bd75Srobert if (CI->arg_size() == 3)
282009467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
282109467b48Spatrick CI->getArgOperand(1));
282209467b48Spatrick } else if (IsX86 && (Name.startswith("sse2.padds.") ||
282309467b48Spatrick Name.startswith("avx2.padds.") ||
282409467b48Spatrick Name.startswith("avx512.padds.") ||
282573471bf0Spatrick Name.startswith("avx512.mask.padds."))) {
282673471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::sadd_sat);
282773471bf0Spatrick } else if (IsX86 && (Name.startswith("sse2.psubs.") ||
282873471bf0Spatrick Name.startswith("avx2.psubs.") ||
282909467b48Spatrick Name.startswith("avx512.psubs.") ||
283009467b48Spatrick Name.startswith("avx512.mask.psubs."))) {
283173471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::ssub_sat);
283209467b48Spatrick } else if (IsX86 && (Name.startswith("sse2.paddus.") ||
283309467b48Spatrick Name.startswith("avx2.paddus.") ||
283473471bf0Spatrick Name.startswith("avx512.mask.paddus."))) {
283573471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::uadd_sat);
283673471bf0Spatrick } else if (IsX86 && (Name.startswith("sse2.psubus.") ||
283709467b48Spatrick Name.startswith("avx2.psubus.") ||
283809467b48Spatrick Name.startswith("avx512.mask.psubus."))) {
283973471bf0Spatrick Rep = UpgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::usub_sat);
284009467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.palignr.")) {
284109467b48Spatrick Rep = UpgradeX86ALIGNIntrinsics(Builder, CI->getArgOperand(0),
284209467b48Spatrick CI->getArgOperand(1),
284309467b48Spatrick CI->getArgOperand(2),
284409467b48Spatrick CI->getArgOperand(3),
284509467b48Spatrick CI->getArgOperand(4),
284609467b48Spatrick false);
284709467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.valign.")) {
284809467b48Spatrick Rep = UpgradeX86ALIGNIntrinsics(Builder, CI->getArgOperand(0),
284909467b48Spatrick CI->getArgOperand(1),
285009467b48Spatrick CI->getArgOperand(2),
285109467b48Spatrick CI->getArgOperand(3),
285209467b48Spatrick CI->getArgOperand(4),
285309467b48Spatrick true);
285409467b48Spatrick } else if (IsX86 && (Name == "sse2.psll.dq" ||
285509467b48Spatrick Name == "avx2.psll.dq")) {
285609467b48Spatrick // 128/256-bit shift left specified in bits.
285709467b48Spatrick unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
285809467b48Spatrick Rep = UpgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0),
285909467b48Spatrick Shift / 8); // Shift is in bits.
286009467b48Spatrick } else if (IsX86 && (Name == "sse2.psrl.dq" ||
286109467b48Spatrick Name == "avx2.psrl.dq")) {
286209467b48Spatrick // 128/256-bit shift right specified in bits.
286309467b48Spatrick unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
286409467b48Spatrick Rep = UpgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0),
286509467b48Spatrick Shift / 8); // Shift is in bits.
286609467b48Spatrick } else if (IsX86 && (Name == "sse2.psll.dq.bs" ||
286709467b48Spatrick Name == "avx2.psll.dq.bs" ||
286809467b48Spatrick Name == "avx512.psll.dq.512")) {
286909467b48Spatrick // 128/256/512-bit shift left specified in bytes.
287009467b48Spatrick unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
287109467b48Spatrick Rep = UpgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
287209467b48Spatrick } else if (IsX86 && (Name == "sse2.psrl.dq.bs" ||
287309467b48Spatrick Name == "avx2.psrl.dq.bs" ||
287409467b48Spatrick Name == "avx512.psrl.dq.512")) {
287509467b48Spatrick // 128/256/512-bit shift right specified in bytes.
287609467b48Spatrick unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
287709467b48Spatrick Rep = UpgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
287809467b48Spatrick } else if (IsX86 && (Name == "sse41.pblendw" ||
287909467b48Spatrick Name.startswith("sse41.blendp") ||
288009467b48Spatrick Name.startswith("avx.blend.p") ||
288109467b48Spatrick Name == "avx2.pblendw" ||
288209467b48Spatrick Name.startswith("avx2.pblendd."))) {
288309467b48Spatrick Value *Op0 = CI->getArgOperand(0);
288409467b48Spatrick Value *Op1 = CI->getArgOperand(1);
288509467b48Spatrick unsigned Imm = cast <ConstantInt>(CI->getArgOperand(2))->getZExtValue();
288673471bf0Spatrick auto *VecTy = cast<FixedVectorType>(CI->getType());
288709467b48Spatrick unsigned NumElts = VecTy->getNumElements();
288809467b48Spatrick
2889097a140dSpatrick SmallVector<int, 16> Idxs(NumElts);
289009467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
289109467b48Spatrick Idxs[i] = ((Imm >> (i%8)) & 1) ? i + NumElts : i;
289209467b48Spatrick
289309467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
289409467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vinsertf128.") ||
289509467b48Spatrick Name == "avx2.vinserti128" ||
289609467b48Spatrick Name.startswith("avx512.mask.insert"))) {
289709467b48Spatrick Value *Op0 = CI->getArgOperand(0);
289809467b48Spatrick Value *Op1 = CI->getArgOperand(1);
289909467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
290073471bf0Spatrick unsigned DstNumElts =
290173471bf0Spatrick cast<FixedVectorType>(CI->getType())->getNumElements();
290273471bf0Spatrick unsigned SrcNumElts =
290373471bf0Spatrick cast<FixedVectorType>(Op1->getType())->getNumElements();
290409467b48Spatrick unsigned Scale = DstNumElts / SrcNumElts;
290509467b48Spatrick
290609467b48Spatrick // Mask off the high bits of the immediate value; hardware ignores those.
290709467b48Spatrick Imm = Imm % Scale;
290809467b48Spatrick
290909467b48Spatrick // Extend the second operand into a vector the size of the destination.
2910097a140dSpatrick SmallVector<int, 8> Idxs(DstNumElts);
291109467b48Spatrick for (unsigned i = 0; i != SrcNumElts; ++i)
291209467b48Spatrick Idxs[i] = i;
291309467b48Spatrick for (unsigned i = SrcNumElts; i != DstNumElts; ++i)
291409467b48Spatrick Idxs[i] = SrcNumElts;
291573471bf0Spatrick Rep = Builder.CreateShuffleVector(Op1, Idxs);
291609467b48Spatrick
291709467b48Spatrick // Insert the second operand into the first operand.
291809467b48Spatrick
291909467b48Spatrick // Note that there is no guarantee that instruction lowering will actually
292009467b48Spatrick // produce a vinsertf128 instruction for the created shuffles. In
292109467b48Spatrick // particular, the 0 immediate case involves no lane changes, so it can
292209467b48Spatrick // be handled as a blend.
292309467b48Spatrick
292409467b48Spatrick // Example of shuffle mask for 32-bit elements:
292509467b48Spatrick // Imm = 1 <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
292609467b48Spatrick // Imm = 0 <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7 >
292709467b48Spatrick
292809467b48Spatrick // First fill with identify mask.
292909467b48Spatrick for (unsigned i = 0; i != DstNumElts; ++i)
293009467b48Spatrick Idxs[i] = i;
293109467b48Spatrick // Then replace the elements where we need to insert.
293209467b48Spatrick for (unsigned i = 0; i != SrcNumElts; ++i)
293309467b48Spatrick Idxs[i + Imm * SrcNumElts] = i + DstNumElts;
293409467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Rep, Idxs);
293509467b48Spatrick
293609467b48Spatrick // If the intrinsic has a mask operand, handle that.
2937*d415bd75Srobert if (CI->arg_size() == 5)
293809467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep,
293909467b48Spatrick CI->getArgOperand(3));
294009467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vextractf128.") ||
294109467b48Spatrick Name == "avx2.vextracti128" ||
294209467b48Spatrick Name.startswith("avx512.mask.vextract"))) {
294309467b48Spatrick Value *Op0 = CI->getArgOperand(0);
294409467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
294573471bf0Spatrick unsigned DstNumElts =
294673471bf0Spatrick cast<FixedVectorType>(CI->getType())->getNumElements();
294773471bf0Spatrick unsigned SrcNumElts =
294873471bf0Spatrick cast<FixedVectorType>(Op0->getType())->getNumElements();
294909467b48Spatrick unsigned Scale = SrcNumElts / DstNumElts;
295009467b48Spatrick
295109467b48Spatrick // Mask off the high bits of the immediate value; hardware ignores those.
295209467b48Spatrick Imm = Imm % Scale;
295309467b48Spatrick
295409467b48Spatrick // Get indexes for the subvector of the input vector.
2955097a140dSpatrick SmallVector<int, 8> Idxs(DstNumElts);
295609467b48Spatrick for (unsigned i = 0; i != DstNumElts; ++i) {
295709467b48Spatrick Idxs[i] = i + (Imm * DstNumElts);
295809467b48Spatrick }
295909467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
296009467b48Spatrick
296109467b48Spatrick // If the intrinsic has a mask operand, handle that.
2962*d415bd75Srobert if (CI->arg_size() == 4)
296309467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
296409467b48Spatrick CI->getArgOperand(2));
296509467b48Spatrick } else if (!IsX86 && Name == "stackprotectorcheck") {
296609467b48Spatrick Rep = nullptr;
296709467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.perm.df.") ||
296809467b48Spatrick Name.startswith("avx512.mask.perm.di."))) {
296909467b48Spatrick Value *Op0 = CI->getArgOperand(0);
297009467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
297173471bf0Spatrick auto *VecTy = cast<FixedVectorType>(CI->getType());
297209467b48Spatrick unsigned NumElts = VecTy->getNumElements();
297309467b48Spatrick
2974097a140dSpatrick SmallVector<int, 8> Idxs(NumElts);
297509467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
297609467b48Spatrick Idxs[i] = (i & ~0x3) + ((Imm >> (2 * (i & 0x3))) & 3);
297709467b48Spatrick
297809467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
297909467b48Spatrick
2980*d415bd75Srobert if (CI->arg_size() == 4)
298109467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
298209467b48Spatrick CI->getArgOperand(2));
298309467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vperm2f128.") ||
298409467b48Spatrick Name == "avx2.vperm2i128")) {
298509467b48Spatrick // The immediate permute control byte looks like this:
298609467b48Spatrick // [1:0] - select 128 bits from sources for low half of destination
298709467b48Spatrick // [2] - ignore
298809467b48Spatrick // [3] - zero low half of destination
298909467b48Spatrick // [5:4] - select 128 bits from sources for high half of destination
299009467b48Spatrick // [6] - ignore
299109467b48Spatrick // [7] - zero high half of destination
299209467b48Spatrick
299309467b48Spatrick uint8_t Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
299409467b48Spatrick
299573471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
299609467b48Spatrick unsigned HalfSize = NumElts / 2;
2997097a140dSpatrick SmallVector<int, 8> ShuffleMask(NumElts);
299809467b48Spatrick
299909467b48Spatrick // Determine which operand(s) are actually in use for this instruction.
300009467b48Spatrick Value *V0 = (Imm & 0x02) ? CI->getArgOperand(1) : CI->getArgOperand(0);
300109467b48Spatrick Value *V1 = (Imm & 0x20) ? CI->getArgOperand(1) : CI->getArgOperand(0);
300209467b48Spatrick
300309467b48Spatrick // If needed, replace operands based on zero mask.
300409467b48Spatrick V0 = (Imm & 0x08) ? ConstantAggregateZero::get(CI->getType()) : V0;
300509467b48Spatrick V1 = (Imm & 0x80) ? ConstantAggregateZero::get(CI->getType()) : V1;
300609467b48Spatrick
300709467b48Spatrick // Permute low half of result.
300809467b48Spatrick unsigned StartIndex = (Imm & 0x01) ? HalfSize : 0;
300909467b48Spatrick for (unsigned i = 0; i < HalfSize; ++i)
301009467b48Spatrick ShuffleMask[i] = StartIndex + i;
301109467b48Spatrick
301209467b48Spatrick // Permute high half of result.
301309467b48Spatrick StartIndex = (Imm & 0x10) ? HalfSize : 0;
301409467b48Spatrick for (unsigned i = 0; i < HalfSize; ++i)
301509467b48Spatrick ShuffleMask[i + HalfSize] = NumElts + StartIndex + i;
301609467b48Spatrick
301709467b48Spatrick Rep = Builder.CreateShuffleVector(V0, V1, ShuffleMask);
301809467b48Spatrick
301909467b48Spatrick } else if (IsX86 && (Name.startswith("avx.vpermil.") ||
302009467b48Spatrick Name == "sse2.pshuf.d" ||
302109467b48Spatrick Name.startswith("avx512.mask.vpermil.p") ||
302209467b48Spatrick Name.startswith("avx512.mask.pshuf.d."))) {
302309467b48Spatrick Value *Op0 = CI->getArgOperand(0);
302409467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
302573471bf0Spatrick auto *VecTy = cast<FixedVectorType>(CI->getType());
302609467b48Spatrick unsigned NumElts = VecTy->getNumElements();
302709467b48Spatrick // Calculate the size of each index in the immediate.
302809467b48Spatrick unsigned IdxSize = 64 / VecTy->getScalarSizeInBits();
302909467b48Spatrick unsigned IdxMask = ((1 << IdxSize) - 1);
303009467b48Spatrick
3031097a140dSpatrick SmallVector<int, 8> Idxs(NumElts);
303209467b48Spatrick // Lookup the bits for this element, wrapping around the immediate every
303309467b48Spatrick // 8-bits. Elements are grouped into sets of 2 or 4 elements so we need
303409467b48Spatrick // to offset by the first index of each group.
303509467b48Spatrick for (unsigned i = 0; i != NumElts; ++i)
303609467b48Spatrick Idxs[i] = ((Imm >> ((i * IdxSize) % 8)) & IdxMask) | (i & ~IdxMask);
303709467b48Spatrick
303809467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
303909467b48Spatrick
3040*d415bd75Srobert if (CI->arg_size() == 4)
304109467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
304209467b48Spatrick CI->getArgOperand(2));
304309467b48Spatrick } else if (IsX86 && (Name == "sse2.pshufl.w" ||
304409467b48Spatrick Name.startswith("avx512.mask.pshufl.w."))) {
304509467b48Spatrick Value *Op0 = CI->getArgOperand(0);
304609467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
304773471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
304809467b48Spatrick
3049097a140dSpatrick SmallVector<int, 16> Idxs(NumElts);
305009467b48Spatrick for (unsigned l = 0; l != NumElts; l += 8) {
305109467b48Spatrick for (unsigned i = 0; i != 4; ++i)
305209467b48Spatrick Idxs[i + l] = ((Imm >> (2 * i)) & 0x3) + l;
305309467b48Spatrick for (unsigned i = 4; i != 8; ++i)
305409467b48Spatrick Idxs[i + l] = i + l;
305509467b48Spatrick }
305609467b48Spatrick
305709467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
305809467b48Spatrick
3059*d415bd75Srobert if (CI->arg_size() == 4)
306009467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
306109467b48Spatrick CI->getArgOperand(2));
306209467b48Spatrick } else if (IsX86 && (Name == "sse2.pshufh.w" ||
306309467b48Spatrick Name.startswith("avx512.mask.pshufh.w."))) {
306409467b48Spatrick Value *Op0 = CI->getArgOperand(0);
306509467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
306673471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
306709467b48Spatrick
3068097a140dSpatrick SmallVector<int, 16> Idxs(NumElts);
306909467b48Spatrick for (unsigned l = 0; l != NumElts; l += 8) {
307009467b48Spatrick for (unsigned i = 0; i != 4; ++i)
307109467b48Spatrick Idxs[i + l] = i + l;
307209467b48Spatrick for (unsigned i = 0; i != 4; ++i)
307309467b48Spatrick Idxs[i + l + 4] = ((Imm >> (2 * i)) & 0x3) + 4 + l;
307409467b48Spatrick }
307509467b48Spatrick
307609467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
307709467b48Spatrick
3078*d415bd75Srobert if (CI->arg_size() == 4)
307909467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
308009467b48Spatrick CI->getArgOperand(2));
308109467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.shuf.p")) {
308209467b48Spatrick Value *Op0 = CI->getArgOperand(0);
308309467b48Spatrick Value *Op1 = CI->getArgOperand(1);
308409467b48Spatrick unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
308573471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
308609467b48Spatrick
308709467b48Spatrick unsigned NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
308809467b48Spatrick unsigned HalfLaneElts = NumLaneElts / 2;
308909467b48Spatrick
3090097a140dSpatrick SmallVector<int, 16> Idxs(NumElts);
309109467b48Spatrick for (unsigned i = 0; i != NumElts; ++i) {
309209467b48Spatrick // Base index is the starting element of the lane.
309309467b48Spatrick Idxs[i] = i - (i % NumLaneElts);
309409467b48Spatrick // If we are half way through the lane switch to the other source.
309509467b48Spatrick if ((i % NumLaneElts) >= HalfLaneElts)
309609467b48Spatrick Idxs[i] += NumElts;
309709467b48Spatrick // Now select the specific element. By adding HalfLaneElts bits from
309809467b48Spatrick // the immediate. Wrapping around the immediate every 8-bits.
309909467b48Spatrick Idxs[i] += (Imm >> ((i * HalfLaneElts) % 8)) & ((1 << HalfLaneElts) - 1);
310009467b48Spatrick }
310109467b48Spatrick
310209467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
310309467b48Spatrick
310409467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep,
310509467b48Spatrick CI->getArgOperand(3));
310609467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.movddup") ||
310709467b48Spatrick Name.startswith("avx512.mask.movshdup") ||
310809467b48Spatrick Name.startswith("avx512.mask.movsldup"))) {
310909467b48Spatrick Value *Op0 = CI->getArgOperand(0);
311073471bf0Spatrick unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
311109467b48Spatrick unsigned NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
311209467b48Spatrick
311309467b48Spatrick unsigned Offset = 0;
311409467b48Spatrick if (Name.startswith("avx512.mask.movshdup."))
311509467b48Spatrick Offset = 1;
311609467b48Spatrick
3117097a140dSpatrick SmallVector<int, 16> Idxs(NumElts);
311809467b48Spatrick for (unsigned l = 0; l != NumElts; l += NumLaneElts)
311909467b48Spatrick for (unsigned i = 0; i != NumLaneElts; i += 2) {
312009467b48Spatrick Idxs[i + l + 0] = i + l + Offset;
312109467b48Spatrick Idxs[i + l + 1] = i + l + Offset;
312209467b48Spatrick }
312309467b48Spatrick
312409467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
312509467b48Spatrick
312609467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
312709467b48Spatrick CI->getArgOperand(1));
312809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.punpckl") ||
312909467b48Spatrick Name.startswith("avx512.mask.unpckl."))) {
313009467b48Spatrick Value *Op0 = CI->getArgOperand(0);
313109467b48Spatrick Value *Op1 = CI->getArgOperand(1);
313273471bf0Spatrick int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
313309467b48Spatrick int NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
313409467b48Spatrick
3135097a140dSpatrick SmallVector<int, 64> Idxs(NumElts);
313609467b48Spatrick for (int l = 0; l != NumElts; l += NumLaneElts)
313709467b48Spatrick for (int i = 0; i != NumLaneElts; ++i)
313809467b48Spatrick Idxs[i + l] = l + (i / 2) + NumElts * (i % 2);
313909467b48Spatrick
314009467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
314109467b48Spatrick
314209467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
314309467b48Spatrick CI->getArgOperand(2));
314409467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.punpckh") ||
314509467b48Spatrick Name.startswith("avx512.mask.unpckh."))) {
314609467b48Spatrick Value *Op0 = CI->getArgOperand(0);
314709467b48Spatrick Value *Op1 = CI->getArgOperand(1);
314873471bf0Spatrick int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
314909467b48Spatrick int NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
315009467b48Spatrick
3151097a140dSpatrick SmallVector<int, 64> Idxs(NumElts);
315209467b48Spatrick for (int l = 0; l != NumElts; l += NumLaneElts)
315309467b48Spatrick for (int i = 0; i != NumLaneElts; ++i)
315409467b48Spatrick Idxs[i + l] = (NumLaneElts / 2) + l + (i / 2) + NumElts * (i % 2);
315509467b48Spatrick
315609467b48Spatrick Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
315709467b48Spatrick
315809467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
315909467b48Spatrick CI->getArgOperand(2));
316009467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.and.") ||
316109467b48Spatrick Name.startswith("avx512.mask.pand."))) {
316209467b48Spatrick VectorType *FTy = cast<VectorType>(CI->getType());
316309467b48Spatrick VectorType *ITy = VectorType::getInteger(FTy);
316409467b48Spatrick Rep = Builder.CreateAnd(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
316509467b48Spatrick Builder.CreateBitCast(CI->getArgOperand(1), ITy));
316609467b48Spatrick Rep = Builder.CreateBitCast(Rep, FTy);
316709467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
316809467b48Spatrick CI->getArgOperand(2));
316909467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.andn.") ||
317009467b48Spatrick Name.startswith("avx512.mask.pandn."))) {
317109467b48Spatrick VectorType *FTy = cast<VectorType>(CI->getType());
317209467b48Spatrick VectorType *ITy = VectorType::getInteger(FTy);
317309467b48Spatrick Rep = Builder.CreateNot(Builder.CreateBitCast(CI->getArgOperand(0), ITy));
317409467b48Spatrick Rep = Builder.CreateAnd(Rep,
317509467b48Spatrick Builder.CreateBitCast(CI->getArgOperand(1), ITy));
317609467b48Spatrick Rep = Builder.CreateBitCast(Rep, FTy);
317709467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
317809467b48Spatrick CI->getArgOperand(2));
317909467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.or.") ||
318009467b48Spatrick Name.startswith("avx512.mask.por."))) {
318109467b48Spatrick VectorType *FTy = cast<VectorType>(CI->getType());
318209467b48Spatrick VectorType *ITy = VectorType::getInteger(FTy);
318309467b48Spatrick Rep = Builder.CreateOr(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
318409467b48Spatrick Builder.CreateBitCast(CI->getArgOperand(1), ITy));
318509467b48Spatrick Rep = Builder.CreateBitCast(Rep, FTy);
318609467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
318709467b48Spatrick CI->getArgOperand(2));
318809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.xor.") ||
318909467b48Spatrick Name.startswith("avx512.mask.pxor."))) {
319009467b48Spatrick VectorType *FTy = cast<VectorType>(CI->getType());
319109467b48Spatrick VectorType *ITy = VectorType::getInteger(FTy);
319209467b48Spatrick Rep = Builder.CreateXor(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
319309467b48Spatrick Builder.CreateBitCast(CI->getArgOperand(1), ITy));
319409467b48Spatrick Rep = Builder.CreateBitCast(Rep, FTy);
319509467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
319609467b48Spatrick CI->getArgOperand(2));
319709467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.padd.")) {
319809467b48Spatrick Rep = Builder.CreateAdd(CI->getArgOperand(0), CI->getArgOperand(1));
319909467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
320009467b48Spatrick CI->getArgOperand(2));
320109467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.psub.")) {
320209467b48Spatrick Rep = Builder.CreateSub(CI->getArgOperand(0), CI->getArgOperand(1));
320309467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
320409467b48Spatrick CI->getArgOperand(2));
320509467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.pmull.")) {
320609467b48Spatrick Rep = Builder.CreateMul(CI->getArgOperand(0), CI->getArgOperand(1));
320709467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
320809467b48Spatrick CI->getArgOperand(2));
320909467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.add.p")) {
321009467b48Spatrick if (Name.endswith(".512")) {
321109467b48Spatrick Intrinsic::ID IID;
321209467b48Spatrick if (Name[17] == 's')
321309467b48Spatrick IID = Intrinsic::x86_avx512_add_ps_512;
321409467b48Spatrick else
321509467b48Spatrick IID = Intrinsic::x86_avx512_add_pd_512;
321609467b48Spatrick
321709467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
321809467b48Spatrick { CI->getArgOperand(0), CI->getArgOperand(1),
321909467b48Spatrick CI->getArgOperand(4) });
322009467b48Spatrick } else {
322109467b48Spatrick Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
322209467b48Spatrick }
322309467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
322409467b48Spatrick CI->getArgOperand(2));
322509467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.div.p")) {
322609467b48Spatrick if (Name.endswith(".512")) {
322709467b48Spatrick Intrinsic::ID IID;
322809467b48Spatrick if (Name[17] == 's')
322909467b48Spatrick IID = Intrinsic::x86_avx512_div_ps_512;
323009467b48Spatrick else
323109467b48Spatrick IID = Intrinsic::x86_avx512_div_pd_512;
323209467b48Spatrick
323309467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
323409467b48Spatrick { CI->getArgOperand(0), CI->getArgOperand(1),
323509467b48Spatrick CI->getArgOperand(4) });
323609467b48Spatrick } else {
323709467b48Spatrick Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
323809467b48Spatrick }
323909467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
324009467b48Spatrick CI->getArgOperand(2));
324109467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.mul.p")) {
324209467b48Spatrick if (Name.endswith(".512")) {
324309467b48Spatrick Intrinsic::ID IID;
324409467b48Spatrick if (Name[17] == 's')
324509467b48Spatrick IID = Intrinsic::x86_avx512_mul_ps_512;
324609467b48Spatrick else
324709467b48Spatrick IID = Intrinsic::x86_avx512_mul_pd_512;
324809467b48Spatrick
324909467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
325009467b48Spatrick { CI->getArgOperand(0), CI->getArgOperand(1),
325109467b48Spatrick CI->getArgOperand(4) });
325209467b48Spatrick } else {
325309467b48Spatrick Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
325409467b48Spatrick }
325509467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
325609467b48Spatrick CI->getArgOperand(2));
325709467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.sub.p")) {
325809467b48Spatrick if (Name.endswith(".512")) {
325909467b48Spatrick Intrinsic::ID IID;
326009467b48Spatrick if (Name[17] == 's')
326109467b48Spatrick IID = Intrinsic::x86_avx512_sub_ps_512;
326209467b48Spatrick else
326309467b48Spatrick IID = Intrinsic::x86_avx512_sub_pd_512;
326409467b48Spatrick
326509467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
326609467b48Spatrick { CI->getArgOperand(0), CI->getArgOperand(1),
326709467b48Spatrick CI->getArgOperand(4) });
326809467b48Spatrick } else {
326909467b48Spatrick Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
327009467b48Spatrick }
327109467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
327209467b48Spatrick CI->getArgOperand(2));
327309467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.max.p") ||
327409467b48Spatrick Name.startswith("avx512.mask.min.p")) &&
327509467b48Spatrick Name.drop_front(18) == ".512") {
327609467b48Spatrick bool IsDouble = Name[17] == 'd';
327709467b48Spatrick bool IsMin = Name[13] == 'i';
327809467b48Spatrick static const Intrinsic::ID MinMaxTbl[2][2] = {
327909467b48Spatrick { Intrinsic::x86_avx512_max_ps_512, Intrinsic::x86_avx512_max_pd_512 },
328009467b48Spatrick { Intrinsic::x86_avx512_min_ps_512, Intrinsic::x86_avx512_min_pd_512 }
328109467b48Spatrick };
328209467b48Spatrick Intrinsic::ID IID = MinMaxTbl[IsMin][IsDouble];
328309467b48Spatrick
328409467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
328509467b48Spatrick { CI->getArgOperand(0), CI->getArgOperand(1),
328609467b48Spatrick CI->getArgOperand(4) });
328709467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
328809467b48Spatrick CI->getArgOperand(2));
328909467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.lzcnt.")) {
329009467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
329109467b48Spatrick Intrinsic::ctlz,
329209467b48Spatrick CI->getType()),
329309467b48Spatrick { CI->getArgOperand(0), Builder.getInt1(false) });
329409467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
329509467b48Spatrick CI->getArgOperand(1));
329609467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.psll")) {
329709467b48Spatrick bool IsImmediate = Name[16] == 'i' ||
329809467b48Spatrick (Name.size() > 18 && Name[18] == 'i');
329909467b48Spatrick bool IsVariable = Name[16] == 'v';
330009467b48Spatrick char Size = Name[16] == '.' ? Name[17] :
330109467b48Spatrick Name[17] == '.' ? Name[18] :
330209467b48Spatrick Name[18] == '.' ? Name[19] :
330309467b48Spatrick Name[20];
330409467b48Spatrick
330509467b48Spatrick Intrinsic::ID IID;
330609467b48Spatrick if (IsVariable && Name[17] != '.') {
330709467b48Spatrick if (Size == 'd' && Name[17] == '2') // avx512.mask.psllv2.di
330809467b48Spatrick IID = Intrinsic::x86_avx2_psllv_q;
330909467b48Spatrick else if (Size == 'd' && Name[17] == '4') // avx512.mask.psllv4.di
331009467b48Spatrick IID = Intrinsic::x86_avx2_psllv_q_256;
331109467b48Spatrick else if (Size == 's' && Name[17] == '4') // avx512.mask.psllv4.si
331209467b48Spatrick IID = Intrinsic::x86_avx2_psllv_d;
331309467b48Spatrick else if (Size == 's' && Name[17] == '8') // avx512.mask.psllv8.si
331409467b48Spatrick IID = Intrinsic::x86_avx2_psllv_d_256;
331509467b48Spatrick else if (Size == 'h' && Name[17] == '8') // avx512.mask.psllv8.hi
331609467b48Spatrick IID = Intrinsic::x86_avx512_psllv_w_128;
331709467b48Spatrick else if (Size == 'h' && Name[17] == '1') // avx512.mask.psllv16.hi
331809467b48Spatrick IID = Intrinsic::x86_avx512_psllv_w_256;
331909467b48Spatrick else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psllv32hi
332009467b48Spatrick IID = Intrinsic::x86_avx512_psllv_w_512;
332109467b48Spatrick else
332209467b48Spatrick llvm_unreachable("Unexpected size");
332309467b48Spatrick } else if (Name.endswith(".128")) {
332409467b48Spatrick if (Size == 'd') // avx512.mask.psll.d.128, avx512.mask.psll.di.128
332509467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_pslli_d
332609467b48Spatrick : Intrinsic::x86_sse2_psll_d;
332709467b48Spatrick else if (Size == 'q') // avx512.mask.psll.q.128, avx512.mask.psll.qi.128
332809467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_pslli_q
332909467b48Spatrick : Intrinsic::x86_sse2_psll_q;
333009467b48Spatrick else if (Size == 'w') // avx512.mask.psll.w.128, avx512.mask.psll.wi.128
333109467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_pslli_w
333209467b48Spatrick : Intrinsic::x86_sse2_psll_w;
333309467b48Spatrick else
333409467b48Spatrick llvm_unreachable("Unexpected size");
333509467b48Spatrick } else if (Name.endswith(".256")) {
333609467b48Spatrick if (Size == 'd') // avx512.mask.psll.d.256, avx512.mask.psll.di.256
333709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_pslli_d
333809467b48Spatrick : Intrinsic::x86_avx2_psll_d;
333909467b48Spatrick else if (Size == 'q') // avx512.mask.psll.q.256, avx512.mask.psll.qi.256
334009467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_pslli_q
334109467b48Spatrick : Intrinsic::x86_avx2_psll_q;
334209467b48Spatrick else if (Size == 'w') // avx512.mask.psll.w.256, avx512.mask.psll.wi.256
334309467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_pslli_w
334409467b48Spatrick : Intrinsic::x86_avx2_psll_w;
334509467b48Spatrick else
334609467b48Spatrick llvm_unreachable("Unexpected size");
334709467b48Spatrick } else {
334809467b48Spatrick if (Size == 'd') // psll.di.512, pslli.d, psll.d, psllv.d.512
334909467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_pslli_d_512 :
335009467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psllv_d_512 :
335109467b48Spatrick Intrinsic::x86_avx512_psll_d_512;
335209467b48Spatrick else if (Size == 'q') // psll.qi.512, pslli.q, psll.q, psllv.q.512
335309467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_pslli_q_512 :
335409467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psllv_q_512 :
335509467b48Spatrick Intrinsic::x86_avx512_psll_q_512;
335609467b48Spatrick else if (Size == 'w') // psll.wi.512, pslli.w, psll.w
335709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_pslli_w_512
335809467b48Spatrick : Intrinsic::x86_avx512_psll_w_512;
335909467b48Spatrick else
336009467b48Spatrick llvm_unreachable("Unexpected size");
336109467b48Spatrick }
336209467b48Spatrick
336309467b48Spatrick Rep = UpgradeX86MaskedShift(Builder, *CI, IID);
336409467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.psrl")) {
336509467b48Spatrick bool IsImmediate = Name[16] == 'i' ||
336609467b48Spatrick (Name.size() > 18 && Name[18] == 'i');
336709467b48Spatrick bool IsVariable = Name[16] == 'v';
336809467b48Spatrick char Size = Name[16] == '.' ? Name[17] :
336909467b48Spatrick Name[17] == '.' ? Name[18] :
337009467b48Spatrick Name[18] == '.' ? Name[19] :
337109467b48Spatrick Name[20];
337209467b48Spatrick
337309467b48Spatrick Intrinsic::ID IID;
337409467b48Spatrick if (IsVariable && Name[17] != '.') {
337509467b48Spatrick if (Size == 'd' && Name[17] == '2') // avx512.mask.psrlv2.di
337609467b48Spatrick IID = Intrinsic::x86_avx2_psrlv_q;
337709467b48Spatrick else if (Size == 'd' && Name[17] == '4') // avx512.mask.psrlv4.di
337809467b48Spatrick IID = Intrinsic::x86_avx2_psrlv_q_256;
337909467b48Spatrick else if (Size == 's' && Name[17] == '4') // avx512.mask.psrlv4.si
338009467b48Spatrick IID = Intrinsic::x86_avx2_psrlv_d;
338109467b48Spatrick else if (Size == 's' && Name[17] == '8') // avx512.mask.psrlv8.si
338209467b48Spatrick IID = Intrinsic::x86_avx2_psrlv_d_256;
338309467b48Spatrick else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrlv8.hi
338409467b48Spatrick IID = Intrinsic::x86_avx512_psrlv_w_128;
338509467b48Spatrick else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrlv16.hi
338609467b48Spatrick IID = Intrinsic::x86_avx512_psrlv_w_256;
338709467b48Spatrick else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrlv32hi
338809467b48Spatrick IID = Intrinsic::x86_avx512_psrlv_w_512;
338909467b48Spatrick else
339009467b48Spatrick llvm_unreachable("Unexpected size");
339109467b48Spatrick } else if (Name.endswith(".128")) {
339209467b48Spatrick if (Size == 'd') // avx512.mask.psrl.d.128, avx512.mask.psrl.di.128
339309467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_psrli_d
339409467b48Spatrick : Intrinsic::x86_sse2_psrl_d;
339509467b48Spatrick else if (Size == 'q') // avx512.mask.psrl.q.128, avx512.mask.psrl.qi.128
339609467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_psrli_q
339709467b48Spatrick : Intrinsic::x86_sse2_psrl_q;
339809467b48Spatrick else if (Size == 'w') // avx512.mask.psrl.w.128, avx512.mask.psrl.wi.128
339909467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_psrli_w
340009467b48Spatrick : Intrinsic::x86_sse2_psrl_w;
340109467b48Spatrick else
340209467b48Spatrick llvm_unreachable("Unexpected size");
340309467b48Spatrick } else if (Name.endswith(".256")) {
340409467b48Spatrick if (Size == 'd') // avx512.mask.psrl.d.256, avx512.mask.psrl.di.256
340509467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_psrli_d
340609467b48Spatrick : Intrinsic::x86_avx2_psrl_d;
340709467b48Spatrick else if (Size == 'q') // avx512.mask.psrl.q.256, avx512.mask.psrl.qi.256
340809467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_psrli_q
340909467b48Spatrick : Intrinsic::x86_avx2_psrl_q;
341009467b48Spatrick else if (Size == 'w') // avx512.mask.psrl.w.256, avx512.mask.psrl.wi.256
341109467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_psrli_w
341209467b48Spatrick : Intrinsic::x86_avx2_psrl_w;
341309467b48Spatrick else
341409467b48Spatrick llvm_unreachable("Unexpected size");
341509467b48Spatrick } else {
341609467b48Spatrick if (Size == 'd') // psrl.di.512, psrli.d, psrl.d, psrl.d.512
341709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrli_d_512 :
341809467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrlv_d_512 :
341909467b48Spatrick Intrinsic::x86_avx512_psrl_d_512;
342009467b48Spatrick else if (Size == 'q') // psrl.qi.512, psrli.q, psrl.q, psrl.q.512
342109467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrli_q_512 :
342209467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrlv_q_512 :
342309467b48Spatrick Intrinsic::x86_avx512_psrl_q_512;
342409467b48Spatrick else if (Size == 'w') // psrl.wi.512, psrli.w, psrl.w)
342509467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrli_w_512
342609467b48Spatrick : Intrinsic::x86_avx512_psrl_w_512;
342709467b48Spatrick else
342809467b48Spatrick llvm_unreachable("Unexpected size");
342909467b48Spatrick }
343009467b48Spatrick
343109467b48Spatrick Rep = UpgradeX86MaskedShift(Builder, *CI, IID);
343209467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.psra")) {
343309467b48Spatrick bool IsImmediate = Name[16] == 'i' ||
343409467b48Spatrick (Name.size() > 18 && Name[18] == 'i');
343509467b48Spatrick bool IsVariable = Name[16] == 'v';
343609467b48Spatrick char Size = Name[16] == '.' ? Name[17] :
343709467b48Spatrick Name[17] == '.' ? Name[18] :
343809467b48Spatrick Name[18] == '.' ? Name[19] :
343909467b48Spatrick Name[20];
344009467b48Spatrick
344109467b48Spatrick Intrinsic::ID IID;
344209467b48Spatrick if (IsVariable && Name[17] != '.') {
344309467b48Spatrick if (Size == 's' && Name[17] == '4') // avx512.mask.psrav4.si
344409467b48Spatrick IID = Intrinsic::x86_avx2_psrav_d;
344509467b48Spatrick else if (Size == 's' && Name[17] == '8') // avx512.mask.psrav8.si
344609467b48Spatrick IID = Intrinsic::x86_avx2_psrav_d_256;
344709467b48Spatrick else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrav8.hi
344809467b48Spatrick IID = Intrinsic::x86_avx512_psrav_w_128;
344909467b48Spatrick else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrav16.hi
345009467b48Spatrick IID = Intrinsic::x86_avx512_psrav_w_256;
345109467b48Spatrick else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrav32hi
345209467b48Spatrick IID = Intrinsic::x86_avx512_psrav_w_512;
345309467b48Spatrick else
345409467b48Spatrick llvm_unreachable("Unexpected size");
345509467b48Spatrick } else if (Name.endswith(".128")) {
345609467b48Spatrick if (Size == 'd') // avx512.mask.psra.d.128, avx512.mask.psra.di.128
345709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_psrai_d
345809467b48Spatrick : Intrinsic::x86_sse2_psra_d;
345909467b48Spatrick else if (Size == 'q') // avx512.mask.psra.q.128, avx512.mask.psra.qi.128
346009467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_128 :
346109467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrav_q_128 :
346209467b48Spatrick Intrinsic::x86_avx512_psra_q_128;
346309467b48Spatrick else if (Size == 'w') // avx512.mask.psra.w.128, avx512.mask.psra.wi.128
346409467b48Spatrick IID = IsImmediate ? Intrinsic::x86_sse2_psrai_w
346509467b48Spatrick : Intrinsic::x86_sse2_psra_w;
346609467b48Spatrick else
346709467b48Spatrick llvm_unreachable("Unexpected size");
346809467b48Spatrick } else if (Name.endswith(".256")) {
346909467b48Spatrick if (Size == 'd') // avx512.mask.psra.d.256, avx512.mask.psra.di.256
347009467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_psrai_d
347109467b48Spatrick : Intrinsic::x86_avx2_psra_d;
347209467b48Spatrick else if (Size == 'q') // avx512.mask.psra.q.256, avx512.mask.psra.qi.256
347309467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_256 :
347409467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrav_q_256 :
347509467b48Spatrick Intrinsic::x86_avx512_psra_q_256;
347609467b48Spatrick else if (Size == 'w') // avx512.mask.psra.w.256, avx512.mask.psra.wi.256
347709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx2_psrai_w
347809467b48Spatrick : Intrinsic::x86_avx2_psra_w;
347909467b48Spatrick else
348009467b48Spatrick llvm_unreachable("Unexpected size");
348109467b48Spatrick } else {
348209467b48Spatrick if (Size == 'd') // psra.di.512, psrai.d, psra.d, psrav.d.512
348309467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrai_d_512 :
348409467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrav_d_512 :
348509467b48Spatrick Intrinsic::x86_avx512_psra_d_512;
348609467b48Spatrick else if (Size == 'q') // psra.qi.512, psrai.q, psra.q
348709467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_512 :
348809467b48Spatrick IsVariable ? Intrinsic::x86_avx512_psrav_q_512 :
348909467b48Spatrick Intrinsic::x86_avx512_psra_q_512;
349009467b48Spatrick else if (Size == 'w') // psra.wi.512, psrai.w, psra.w
349109467b48Spatrick IID = IsImmediate ? Intrinsic::x86_avx512_psrai_w_512
349209467b48Spatrick : Intrinsic::x86_avx512_psra_w_512;
349309467b48Spatrick else
349409467b48Spatrick llvm_unreachable("Unexpected size");
349509467b48Spatrick }
349609467b48Spatrick
349709467b48Spatrick Rep = UpgradeX86MaskedShift(Builder, *CI, IID);
349809467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.move.s")) {
349909467b48Spatrick Rep = upgradeMaskedMove(Builder, *CI);
350009467b48Spatrick } else if (IsX86 && Name.startswith("avx512.cvtmask2")) {
350109467b48Spatrick Rep = UpgradeMaskToInt(Builder, *CI);
350209467b48Spatrick } else if (IsX86 && Name.endswith(".movntdqa")) {
350309467b48Spatrick Module *M = F->getParent();
350409467b48Spatrick MDNode *Node = MDNode::get(
350509467b48Spatrick C, ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
350609467b48Spatrick
350709467b48Spatrick Value *Ptr = CI->getArgOperand(0);
350809467b48Spatrick
350909467b48Spatrick // Convert the type of the pointer to a pointer to the stored type.
3510097a140dSpatrick Value *BC = Builder.CreateBitCast(
3511097a140dSpatrick Ptr, PointerType::getUnqual(CI->getType()), "cast");
3512097a140dSpatrick LoadInst *LI = Builder.CreateAlignedLoad(
3513097a140dSpatrick CI->getType(), BC,
3514*d415bd75Srobert Align(CI->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
351509467b48Spatrick LI->setMetadata(M->getMDKindID("nontemporal"), Node);
351609467b48Spatrick Rep = LI;
351709467b48Spatrick } else if (IsX86 && (Name.startswith("fma.vfmadd.") ||
351809467b48Spatrick Name.startswith("fma.vfmsub.") ||
351909467b48Spatrick Name.startswith("fma.vfnmadd.") ||
352009467b48Spatrick Name.startswith("fma.vfnmsub."))) {
352109467b48Spatrick bool NegMul = Name[6] == 'n';
352209467b48Spatrick bool NegAcc = NegMul ? Name[8] == 's' : Name[7] == 's';
352309467b48Spatrick bool IsScalar = NegMul ? Name[12] == 's' : Name[11] == 's';
352409467b48Spatrick
352509467b48Spatrick Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
352609467b48Spatrick CI->getArgOperand(2) };
352709467b48Spatrick
352809467b48Spatrick if (IsScalar) {
352909467b48Spatrick Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
353009467b48Spatrick Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
353109467b48Spatrick Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
353209467b48Spatrick }
353309467b48Spatrick
353409467b48Spatrick if (NegMul && !IsScalar)
353509467b48Spatrick Ops[0] = Builder.CreateFNeg(Ops[0]);
353609467b48Spatrick if (NegMul && IsScalar)
353709467b48Spatrick Ops[1] = Builder.CreateFNeg(Ops[1]);
353809467b48Spatrick if (NegAcc)
353909467b48Spatrick Ops[2] = Builder.CreateFNeg(Ops[2]);
354009467b48Spatrick
354109467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
354209467b48Spatrick Intrinsic::fma,
354309467b48Spatrick Ops[0]->getType()),
354409467b48Spatrick Ops);
354509467b48Spatrick
354609467b48Spatrick if (IsScalar)
354709467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep,
354809467b48Spatrick (uint64_t)0);
354909467b48Spatrick } else if (IsX86 && Name.startswith("fma4.vfmadd.s")) {
355009467b48Spatrick Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
355109467b48Spatrick CI->getArgOperand(2) };
355209467b48Spatrick
355309467b48Spatrick Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
355409467b48Spatrick Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
355509467b48Spatrick Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
355609467b48Spatrick
355709467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
355809467b48Spatrick Intrinsic::fma,
355909467b48Spatrick Ops[0]->getType()),
356009467b48Spatrick Ops);
356109467b48Spatrick
356209467b48Spatrick Rep = Builder.CreateInsertElement(Constant::getNullValue(CI->getType()),
356309467b48Spatrick Rep, (uint64_t)0);
356409467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vfmadd.s") ||
356509467b48Spatrick Name.startswith("avx512.maskz.vfmadd.s") ||
356609467b48Spatrick Name.startswith("avx512.mask3.vfmadd.s") ||
356709467b48Spatrick Name.startswith("avx512.mask3.vfmsub.s") ||
356809467b48Spatrick Name.startswith("avx512.mask3.vfnmsub.s"))) {
356909467b48Spatrick bool IsMask3 = Name[11] == '3';
357009467b48Spatrick bool IsMaskZ = Name[11] == 'z';
357109467b48Spatrick // Drop the "avx512.mask." to make it easier.
357209467b48Spatrick Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
357309467b48Spatrick bool NegMul = Name[2] == 'n';
357409467b48Spatrick bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
357509467b48Spatrick
357609467b48Spatrick Value *A = CI->getArgOperand(0);
357709467b48Spatrick Value *B = CI->getArgOperand(1);
357809467b48Spatrick Value *C = CI->getArgOperand(2);
357909467b48Spatrick
358009467b48Spatrick if (NegMul && (IsMask3 || IsMaskZ))
358109467b48Spatrick A = Builder.CreateFNeg(A);
358209467b48Spatrick if (NegMul && !(IsMask3 || IsMaskZ))
358309467b48Spatrick B = Builder.CreateFNeg(B);
358409467b48Spatrick if (NegAcc)
358509467b48Spatrick C = Builder.CreateFNeg(C);
358609467b48Spatrick
358709467b48Spatrick A = Builder.CreateExtractElement(A, (uint64_t)0);
358809467b48Spatrick B = Builder.CreateExtractElement(B, (uint64_t)0);
358909467b48Spatrick C = Builder.CreateExtractElement(C, (uint64_t)0);
359009467b48Spatrick
359109467b48Spatrick if (!isa<ConstantInt>(CI->getArgOperand(4)) ||
359209467b48Spatrick cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4) {
359309467b48Spatrick Value *Ops[] = { A, B, C, CI->getArgOperand(4) };
359409467b48Spatrick
359509467b48Spatrick Intrinsic::ID IID;
359609467b48Spatrick if (Name.back() == 'd')
359709467b48Spatrick IID = Intrinsic::x86_avx512_vfmadd_f64;
359809467b48Spatrick else
359909467b48Spatrick IID = Intrinsic::x86_avx512_vfmadd_f32;
360009467b48Spatrick Function *FMA = Intrinsic::getDeclaration(CI->getModule(), IID);
360109467b48Spatrick Rep = Builder.CreateCall(FMA, Ops);
360209467b48Spatrick } else {
360309467b48Spatrick Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
360409467b48Spatrick Intrinsic::fma,
360509467b48Spatrick A->getType());
360609467b48Spatrick Rep = Builder.CreateCall(FMA, { A, B, C });
360709467b48Spatrick }
360809467b48Spatrick
360909467b48Spatrick Value *PassThru = IsMaskZ ? Constant::getNullValue(Rep->getType()) :
361009467b48Spatrick IsMask3 ? C : A;
361109467b48Spatrick
361209467b48Spatrick // For Mask3 with NegAcc, we need to create a new extractelement that
361309467b48Spatrick // avoids the negation above.
361409467b48Spatrick if (NegAcc && IsMask3)
361509467b48Spatrick PassThru = Builder.CreateExtractElement(CI->getArgOperand(2),
361609467b48Spatrick (uint64_t)0);
361709467b48Spatrick
361809467b48Spatrick Rep = EmitX86ScalarSelect(Builder, CI->getArgOperand(3),
361909467b48Spatrick Rep, PassThru);
362009467b48Spatrick Rep = Builder.CreateInsertElement(CI->getArgOperand(IsMask3 ? 2 : 0),
362109467b48Spatrick Rep, (uint64_t)0);
362209467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vfmadd.p") ||
362309467b48Spatrick Name.startswith("avx512.mask.vfnmadd.p") ||
362409467b48Spatrick Name.startswith("avx512.mask.vfnmsub.p") ||
362509467b48Spatrick Name.startswith("avx512.mask3.vfmadd.p") ||
362609467b48Spatrick Name.startswith("avx512.mask3.vfmsub.p") ||
362709467b48Spatrick Name.startswith("avx512.mask3.vfnmsub.p") ||
362809467b48Spatrick Name.startswith("avx512.maskz.vfmadd.p"))) {
362909467b48Spatrick bool IsMask3 = Name[11] == '3';
363009467b48Spatrick bool IsMaskZ = Name[11] == 'z';
363109467b48Spatrick // Drop the "avx512.mask." to make it easier.
363209467b48Spatrick Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
363309467b48Spatrick bool NegMul = Name[2] == 'n';
363409467b48Spatrick bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
363509467b48Spatrick
363609467b48Spatrick Value *A = CI->getArgOperand(0);
363709467b48Spatrick Value *B = CI->getArgOperand(1);
363809467b48Spatrick Value *C = CI->getArgOperand(2);
363909467b48Spatrick
364009467b48Spatrick if (NegMul && (IsMask3 || IsMaskZ))
364109467b48Spatrick A = Builder.CreateFNeg(A);
364209467b48Spatrick if (NegMul && !(IsMask3 || IsMaskZ))
364309467b48Spatrick B = Builder.CreateFNeg(B);
364409467b48Spatrick if (NegAcc)
364509467b48Spatrick C = Builder.CreateFNeg(C);
364609467b48Spatrick
3647*d415bd75Srobert if (CI->arg_size() == 5 &&
364809467b48Spatrick (!isa<ConstantInt>(CI->getArgOperand(4)) ||
364909467b48Spatrick cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
365009467b48Spatrick Intrinsic::ID IID;
365109467b48Spatrick // Check the character before ".512" in string.
365209467b48Spatrick if (Name[Name.size()-5] == 's')
365309467b48Spatrick IID = Intrinsic::x86_avx512_vfmadd_ps_512;
365409467b48Spatrick else
365509467b48Spatrick IID = Intrinsic::x86_avx512_vfmadd_pd_512;
365609467b48Spatrick
365709467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
365809467b48Spatrick { A, B, C, CI->getArgOperand(4) });
365909467b48Spatrick } else {
366009467b48Spatrick Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
366109467b48Spatrick Intrinsic::fma,
366209467b48Spatrick A->getType());
366309467b48Spatrick Rep = Builder.CreateCall(FMA, { A, B, C });
366409467b48Spatrick }
366509467b48Spatrick
366609467b48Spatrick Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
366709467b48Spatrick IsMask3 ? CI->getArgOperand(2) :
366809467b48Spatrick CI->getArgOperand(0);
366909467b48Spatrick
367009467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3671097a140dSpatrick } else if (IsX86 && Name.startswith("fma.vfmsubadd.p")) {
3672097a140dSpatrick unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3673097a140dSpatrick unsigned EltWidth = CI->getType()->getScalarSizeInBits();
3674097a140dSpatrick Intrinsic::ID IID;
3675097a140dSpatrick if (VecWidth == 128 && EltWidth == 32)
3676097a140dSpatrick IID = Intrinsic::x86_fma_vfmaddsub_ps;
3677097a140dSpatrick else if (VecWidth == 256 && EltWidth == 32)
3678097a140dSpatrick IID = Intrinsic::x86_fma_vfmaddsub_ps_256;
3679097a140dSpatrick else if (VecWidth == 128 && EltWidth == 64)
3680097a140dSpatrick IID = Intrinsic::x86_fma_vfmaddsub_pd;
3681097a140dSpatrick else if (VecWidth == 256 && EltWidth == 64)
3682097a140dSpatrick IID = Intrinsic::x86_fma_vfmaddsub_pd_256;
3683097a140dSpatrick else
3684097a140dSpatrick llvm_unreachable("Unexpected intrinsic");
368509467b48Spatrick
368609467b48Spatrick Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
368709467b48Spatrick CI->getArgOperand(2) };
368809467b48Spatrick Ops[2] = Builder.CreateFNeg(Ops[2]);
3689097a140dSpatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
3690097a140dSpatrick Ops);
369109467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vfmaddsub.p") ||
369209467b48Spatrick Name.startswith("avx512.mask3.vfmaddsub.p") ||
369309467b48Spatrick Name.startswith("avx512.maskz.vfmaddsub.p") ||
369409467b48Spatrick Name.startswith("avx512.mask3.vfmsubadd.p"))) {
369509467b48Spatrick bool IsMask3 = Name[11] == '3';
369609467b48Spatrick bool IsMaskZ = Name[11] == 'z';
369709467b48Spatrick // Drop the "avx512.mask." to make it easier.
369809467b48Spatrick Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
369909467b48Spatrick bool IsSubAdd = Name[3] == 's';
3700*d415bd75Srobert if (CI->arg_size() == 5) {
370109467b48Spatrick Intrinsic::ID IID;
370209467b48Spatrick // Check the character before ".512" in string.
370309467b48Spatrick if (Name[Name.size()-5] == 's')
370409467b48Spatrick IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;
370509467b48Spatrick else
370609467b48Spatrick IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;
370709467b48Spatrick
370809467b48Spatrick Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
370909467b48Spatrick CI->getArgOperand(2), CI->getArgOperand(4) };
371009467b48Spatrick if (IsSubAdd)
371109467b48Spatrick Ops[2] = Builder.CreateFNeg(Ops[2]);
371209467b48Spatrick
371309467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
3714097a140dSpatrick Ops);
371509467b48Spatrick } else {
371673471bf0Spatrick int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
371709467b48Spatrick
371809467b48Spatrick Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
371909467b48Spatrick CI->getArgOperand(2) };
372009467b48Spatrick
372109467b48Spatrick Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
372209467b48Spatrick Ops[0]->getType());
372309467b48Spatrick Value *Odd = Builder.CreateCall(FMA, Ops);
372409467b48Spatrick Ops[2] = Builder.CreateFNeg(Ops[2]);
372509467b48Spatrick Value *Even = Builder.CreateCall(FMA, Ops);
372609467b48Spatrick
372709467b48Spatrick if (IsSubAdd)
372809467b48Spatrick std::swap(Even, Odd);
372909467b48Spatrick
3730097a140dSpatrick SmallVector<int, 32> Idxs(NumElts);
373109467b48Spatrick for (int i = 0; i != NumElts; ++i)
373209467b48Spatrick Idxs[i] = i + (i % 2) * NumElts;
373309467b48Spatrick
373409467b48Spatrick Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
373509467b48Spatrick }
373609467b48Spatrick
373709467b48Spatrick Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
373809467b48Spatrick IsMask3 ? CI->getArgOperand(2) :
373909467b48Spatrick CI->getArgOperand(0);
374009467b48Spatrick
374109467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
374209467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.pternlog.") ||
374309467b48Spatrick Name.startswith("avx512.maskz.pternlog."))) {
374409467b48Spatrick bool ZeroMask = Name[11] == 'z';
374509467b48Spatrick unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
374609467b48Spatrick unsigned EltWidth = CI->getType()->getScalarSizeInBits();
374709467b48Spatrick Intrinsic::ID IID;
374809467b48Spatrick if (VecWidth == 128 && EltWidth == 32)
374909467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_d_128;
375009467b48Spatrick else if (VecWidth == 256 && EltWidth == 32)
375109467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_d_256;
375209467b48Spatrick else if (VecWidth == 512 && EltWidth == 32)
375309467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_d_512;
375409467b48Spatrick else if (VecWidth == 128 && EltWidth == 64)
375509467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_q_128;
375609467b48Spatrick else if (VecWidth == 256 && EltWidth == 64)
375709467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_q_256;
375809467b48Spatrick else if (VecWidth == 512 && EltWidth == 64)
375909467b48Spatrick IID = Intrinsic::x86_avx512_pternlog_q_512;
376009467b48Spatrick else
376109467b48Spatrick llvm_unreachable("Unexpected intrinsic");
376209467b48Spatrick
376309467b48Spatrick Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
376409467b48Spatrick CI->getArgOperand(2), CI->getArgOperand(3) };
376509467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
376609467b48Spatrick Args);
376709467b48Spatrick Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
376809467b48Spatrick : CI->getArgOperand(0);
376909467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep, PassThru);
377009467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vpmadd52") ||
377109467b48Spatrick Name.startswith("avx512.maskz.vpmadd52"))) {
377209467b48Spatrick bool ZeroMask = Name[11] == 'z';
377309467b48Spatrick bool High = Name[20] == 'h' || Name[21] == 'h';
377409467b48Spatrick unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
377509467b48Spatrick Intrinsic::ID IID;
377609467b48Spatrick if (VecWidth == 128 && !High)
377709467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52l_uq_128;
377809467b48Spatrick else if (VecWidth == 256 && !High)
377909467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52l_uq_256;
378009467b48Spatrick else if (VecWidth == 512 && !High)
378109467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52l_uq_512;
378209467b48Spatrick else if (VecWidth == 128 && High)
378309467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52h_uq_128;
378409467b48Spatrick else if (VecWidth == 256 && High)
378509467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52h_uq_256;
378609467b48Spatrick else if (VecWidth == 512 && High)
378709467b48Spatrick IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
378809467b48Spatrick else
378909467b48Spatrick llvm_unreachable("Unexpected intrinsic");
379009467b48Spatrick
379109467b48Spatrick Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
379209467b48Spatrick CI->getArgOperand(2) };
379309467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
379409467b48Spatrick Args);
379509467b48Spatrick Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
379609467b48Spatrick : CI->getArgOperand(0);
379709467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
379809467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vpermi2var.") ||
379909467b48Spatrick Name.startswith("avx512.mask.vpermt2var.") ||
380009467b48Spatrick Name.startswith("avx512.maskz.vpermt2var."))) {
380109467b48Spatrick bool ZeroMask = Name[11] == 'z';
380209467b48Spatrick bool IndexForm = Name[17] == 'i';
380309467b48Spatrick Rep = UpgradeX86VPERMT2Intrinsics(Builder, *CI, ZeroMask, IndexForm);
380409467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vpdpbusd.") ||
380509467b48Spatrick Name.startswith("avx512.maskz.vpdpbusd.") ||
380609467b48Spatrick Name.startswith("avx512.mask.vpdpbusds.") ||
380709467b48Spatrick Name.startswith("avx512.maskz.vpdpbusds."))) {
380809467b48Spatrick bool ZeroMask = Name[11] == 'z';
380909467b48Spatrick bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
381009467b48Spatrick unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
381109467b48Spatrick Intrinsic::ID IID;
381209467b48Spatrick if (VecWidth == 128 && !IsSaturating)
381309467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusd_128;
381409467b48Spatrick else if (VecWidth == 256 && !IsSaturating)
381509467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusd_256;
381609467b48Spatrick else if (VecWidth == 512 && !IsSaturating)
381709467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusd_512;
381809467b48Spatrick else if (VecWidth == 128 && IsSaturating)
381909467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusds_128;
382009467b48Spatrick else if (VecWidth == 256 && IsSaturating)
382109467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusds_256;
382209467b48Spatrick else if (VecWidth == 512 && IsSaturating)
382309467b48Spatrick IID = Intrinsic::x86_avx512_vpdpbusds_512;
382409467b48Spatrick else
382509467b48Spatrick llvm_unreachable("Unexpected intrinsic");
382609467b48Spatrick
382709467b48Spatrick Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
382809467b48Spatrick CI->getArgOperand(2) };
382909467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
383009467b48Spatrick Args);
383109467b48Spatrick Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
383209467b48Spatrick : CI->getArgOperand(0);
383309467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
383409467b48Spatrick } else if (IsX86 && (Name.startswith("avx512.mask.vpdpwssd.") ||
383509467b48Spatrick Name.startswith("avx512.maskz.vpdpwssd.") ||
383609467b48Spatrick Name.startswith("avx512.mask.vpdpwssds.") ||
383709467b48Spatrick Name.startswith("avx512.maskz.vpdpwssds."))) {
383809467b48Spatrick bool ZeroMask = Name[11] == 'z';
383909467b48Spatrick bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
384009467b48Spatrick unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
384109467b48Spatrick Intrinsic::ID IID;
384209467b48Spatrick if (VecWidth == 128 && !IsSaturating)
384309467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssd_128;
384409467b48Spatrick else if (VecWidth == 256 && !IsSaturating)
384509467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssd_256;
384609467b48Spatrick else if (VecWidth == 512 && !IsSaturating)
384709467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssd_512;
384809467b48Spatrick else if (VecWidth == 128 && IsSaturating)
384909467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssds_128;
385009467b48Spatrick else if (VecWidth == 256 && IsSaturating)
385109467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssds_256;
385209467b48Spatrick else if (VecWidth == 512 && IsSaturating)
385309467b48Spatrick IID = Intrinsic::x86_avx512_vpdpwssds_512;
385409467b48Spatrick else
385509467b48Spatrick llvm_unreachable("Unexpected intrinsic");
385609467b48Spatrick
385709467b48Spatrick Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
385809467b48Spatrick CI->getArgOperand(2) };
385909467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
386009467b48Spatrick Args);
386109467b48Spatrick Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
386209467b48Spatrick : CI->getArgOperand(0);
386309467b48Spatrick Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
386409467b48Spatrick } else if (IsX86 && (Name == "addcarryx.u32" || Name == "addcarryx.u64" ||
386509467b48Spatrick Name == "addcarry.u32" || Name == "addcarry.u64" ||
386609467b48Spatrick Name == "subborrow.u32" || Name == "subborrow.u64")) {
386709467b48Spatrick Intrinsic::ID IID;
386809467b48Spatrick if (Name[0] == 'a' && Name.back() == '2')
386909467b48Spatrick IID = Intrinsic::x86_addcarry_32;
387009467b48Spatrick else if (Name[0] == 'a' && Name.back() == '4')
387109467b48Spatrick IID = Intrinsic::x86_addcarry_64;
387209467b48Spatrick else if (Name[0] == 's' && Name.back() == '2')
387309467b48Spatrick IID = Intrinsic::x86_subborrow_32;
387409467b48Spatrick else if (Name[0] == 's' && Name.back() == '4')
387509467b48Spatrick IID = Intrinsic::x86_subborrow_64;
387609467b48Spatrick else
387709467b48Spatrick llvm_unreachable("Unexpected intrinsic");
387809467b48Spatrick
387909467b48Spatrick // Make a call with 3 operands.
388009467b48Spatrick Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
388109467b48Spatrick CI->getArgOperand(2)};
388209467b48Spatrick Value *NewCall = Builder.CreateCall(
388309467b48Spatrick Intrinsic::getDeclaration(CI->getModule(), IID),
388409467b48Spatrick Args);
388509467b48Spatrick
388609467b48Spatrick // Extract the second result and store it.
388709467b48Spatrick Value *Data = Builder.CreateExtractValue(NewCall, 1);
388809467b48Spatrick // Cast the pointer to the right type.
388909467b48Spatrick Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(3),
389009467b48Spatrick llvm::PointerType::getUnqual(Data->getType()));
3891097a140dSpatrick Builder.CreateAlignedStore(Data, Ptr, Align(1));
389209467b48Spatrick // Replace the original call result with the first result of the new call.
389309467b48Spatrick Value *CF = Builder.CreateExtractValue(NewCall, 0);
389409467b48Spatrick
389509467b48Spatrick CI->replaceAllUsesWith(CF);
389609467b48Spatrick Rep = nullptr;
389709467b48Spatrick } else if (IsX86 && Name.startswith("avx512.mask.") &&
389809467b48Spatrick upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
389909467b48Spatrick // Rep will be updated by the call in the condition.
390009467b48Spatrick } else if (IsNVVM && (Name == "abs.i" || Name == "abs.ll")) {
390109467b48Spatrick Value *Arg = CI->getArgOperand(0);
390209467b48Spatrick Value *Neg = Builder.CreateNeg(Arg, "neg");
390309467b48Spatrick Value *Cmp = Builder.CreateICmpSGE(
390409467b48Spatrick Arg, llvm::Constant::getNullValue(Arg->getType()), "abs.cond");
390509467b48Spatrick Rep = Builder.CreateSelect(Cmp, Arg, Neg, "abs");
390609467b48Spatrick } else if (IsNVVM && (Name.startswith("atomic.load.add.f32.p") ||
390709467b48Spatrick Name.startswith("atomic.load.add.f64.p"))) {
390809467b48Spatrick Value *Ptr = CI->getArgOperand(0);
390909467b48Spatrick Value *Val = CI->getArgOperand(1);
391073471bf0Spatrick Rep = Builder.CreateAtomicRMW(AtomicRMWInst::FAdd, Ptr, Val, MaybeAlign(),
391109467b48Spatrick AtomicOrdering::SequentiallyConsistent);
391209467b48Spatrick } else if (IsNVVM && (Name == "max.i" || Name == "max.ll" ||
391309467b48Spatrick Name == "max.ui" || Name == "max.ull")) {
391409467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
391509467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
391609467b48Spatrick Value *Cmp = Name.endswith(".ui") || Name.endswith(".ull")
391709467b48Spatrick ? Builder.CreateICmpUGE(Arg0, Arg1, "max.cond")
391809467b48Spatrick : Builder.CreateICmpSGE(Arg0, Arg1, "max.cond");
391909467b48Spatrick Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "max");
392009467b48Spatrick } else if (IsNVVM && (Name == "min.i" || Name == "min.ll" ||
392109467b48Spatrick Name == "min.ui" || Name == "min.ull")) {
392209467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
392309467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
392409467b48Spatrick Value *Cmp = Name.endswith(".ui") || Name.endswith(".ull")
392509467b48Spatrick ? Builder.CreateICmpULE(Arg0, Arg1, "min.cond")
392609467b48Spatrick : Builder.CreateICmpSLE(Arg0, Arg1, "min.cond");
392709467b48Spatrick Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "min");
392809467b48Spatrick } else if (IsNVVM && Name == "clz.ll") {
392909467b48Spatrick // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 and returns an i64.
393009467b48Spatrick Value *Arg = CI->getArgOperand(0);
393109467b48Spatrick Value *Ctlz = Builder.CreateCall(
393209467b48Spatrick Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
393309467b48Spatrick {Arg->getType()}),
393409467b48Spatrick {Arg, Builder.getFalse()}, "ctlz");
393509467b48Spatrick Rep = Builder.CreateTrunc(Ctlz, Builder.getInt32Ty(), "ctlz.trunc");
393609467b48Spatrick } else if (IsNVVM && Name == "popc.ll") {
393709467b48Spatrick // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 and returns an
393809467b48Spatrick // i64.
393909467b48Spatrick Value *Arg = CI->getArgOperand(0);
394009467b48Spatrick Value *Popc = Builder.CreateCall(
394109467b48Spatrick Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop,
394209467b48Spatrick {Arg->getType()}),
394309467b48Spatrick Arg, "ctpop");
394409467b48Spatrick Rep = Builder.CreateTrunc(Popc, Builder.getInt32Ty(), "ctpop.trunc");
394509467b48Spatrick } else if (IsNVVM && Name == "h2f") {
394609467b48Spatrick Rep = Builder.CreateCall(Intrinsic::getDeclaration(
394709467b48Spatrick F->getParent(), Intrinsic::convert_from_fp16,
394809467b48Spatrick {Builder.getFloatTy()}),
394909467b48Spatrick CI->getArgOperand(0), "h2f");
3950*d415bd75Srobert } else if (IsARM) {
3951*d415bd75Srobert Rep = UpgradeARMIntrinsicCall(Name, CI, F, Builder);
395209467b48Spatrick } else {
3953*d415bd75Srobert llvm_unreachable("Unknown function for CallBase upgrade.");
395409467b48Spatrick }
395509467b48Spatrick
395609467b48Spatrick if (Rep)
395709467b48Spatrick CI->replaceAllUsesWith(Rep);
395809467b48Spatrick CI->eraseFromParent();
395909467b48Spatrick return;
396009467b48Spatrick }
396109467b48Spatrick
3962*d415bd75Srobert const auto &DefaultCase = [&]() -> void {
3963*d415bd75Srobert if (CI->getFunctionType() == NewFn->getFunctionType()) {
3964*d415bd75Srobert // Handle generic mangling change.
396509467b48Spatrick assert(
396609467b48Spatrick (CI->getCalledFunction()->getName() != NewFn->getName()) &&
3967*d415bd75Srobert "Unknown function for CallBase upgrade and isn't just a name change");
396809467b48Spatrick CI->setCalledFunction(NewFn);
3969*d415bd75Srobert return;
3970*d415bd75Srobert }
3971*d415bd75Srobert
3972*d415bd75Srobert // This must be an upgrade from a named to a literal struct.
3973*d415bd75Srobert if (auto *OldST = dyn_cast<StructType>(CI->getType())) {
3974*d415bd75Srobert assert(OldST != NewFn->getReturnType() &&
3975*d415bd75Srobert "Return type must have changed");
3976*d415bd75Srobert assert(OldST->getNumElements() ==
3977*d415bd75Srobert cast<StructType>(NewFn->getReturnType())->getNumElements() &&
3978*d415bd75Srobert "Must have same number of elements");
3979*d415bd75Srobert
3980*d415bd75Srobert SmallVector<Value *> Args(CI->args());
3981*d415bd75Srobert Value *NewCI = Builder.CreateCall(NewFn, Args);
3982*d415bd75Srobert Value *Res = PoisonValue::get(OldST);
3983*d415bd75Srobert for (unsigned Idx = 0; Idx < OldST->getNumElements(); ++Idx) {
3984*d415bd75Srobert Value *Elem = Builder.CreateExtractValue(NewCI, Idx);
3985*d415bd75Srobert Res = Builder.CreateInsertValue(Res, Elem, Idx);
3986*d415bd75Srobert }
3987*d415bd75Srobert CI->replaceAllUsesWith(Res);
3988*d415bd75Srobert CI->eraseFromParent();
3989*d415bd75Srobert return;
3990*d415bd75Srobert }
3991*d415bd75Srobert
3992*d415bd75Srobert // We're probably about to produce something invalid. Let the verifier catch
3993*d415bd75Srobert // it instead of dying here.
3994*d415bd75Srobert CI->setCalledOperand(
3995*d415bd75Srobert ConstantExpr::getPointerCast(NewFn, CI->getCalledOperand()->getType()));
3996*d415bd75Srobert return;
399709467b48Spatrick };
399809467b48Spatrick CallInst *NewCall = nullptr;
399909467b48Spatrick switch (NewFn->getIntrinsicID()) {
400009467b48Spatrick default: {
400109467b48Spatrick DefaultCase();
400209467b48Spatrick return;
400309467b48Spatrick }
400409467b48Spatrick case Intrinsic::arm_neon_vst1:
400509467b48Spatrick case Intrinsic::arm_neon_vst2:
400609467b48Spatrick case Intrinsic::arm_neon_vst3:
400709467b48Spatrick case Intrinsic::arm_neon_vst4:
400809467b48Spatrick case Intrinsic::arm_neon_vst2lane:
400909467b48Spatrick case Intrinsic::arm_neon_vst3lane:
401009467b48Spatrick case Intrinsic::arm_neon_vst4lane: {
4011*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
401209467b48Spatrick NewCall = Builder.CreateCall(NewFn, Args);
401309467b48Spatrick break;
401409467b48Spatrick }
4015*d415bd75Srobert case Intrinsic::aarch64_sve_bfmlalb_lane_v2:
4016*d415bd75Srobert case Intrinsic::aarch64_sve_bfmlalt_lane_v2:
4017*d415bd75Srobert case Intrinsic::aarch64_sve_bfdot_lane_v2: {
4018*d415bd75Srobert LLVMContext &Ctx = F->getParent()->getContext();
4019*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
4020*d415bd75Srobert Args[3] = ConstantInt::get(Type::getInt32Ty(Ctx),
4021*d415bd75Srobert cast<ConstantInt>(Args[3])->getZExtValue());
4022*d415bd75Srobert NewCall = Builder.CreateCall(NewFn, Args);
4023*d415bd75Srobert break;
4024*d415bd75Srobert }
4025*d415bd75Srobert case Intrinsic::aarch64_sve_ld3_sret:
4026*d415bd75Srobert case Intrinsic::aarch64_sve_ld4_sret:
4027*d415bd75Srobert case Intrinsic::aarch64_sve_ld2_sret: {
4028*d415bd75Srobert StringRef Name = F->getName();
4029*d415bd75Srobert Name = Name.substr(5);
4030*d415bd75Srobert unsigned N = StringSwitch<unsigned>(Name)
4031*d415bd75Srobert .StartsWith("aarch64.sve.ld2", 2)
4032*d415bd75Srobert .StartsWith("aarch64.sve.ld3", 3)
4033*d415bd75Srobert .StartsWith("aarch64.sve.ld4", 4)
4034*d415bd75Srobert .Default(0);
4035*d415bd75Srobert ScalableVectorType *RetTy =
4036*d415bd75Srobert dyn_cast<ScalableVectorType>(F->getReturnType());
4037*d415bd75Srobert unsigned MinElts = RetTy->getMinNumElements() / N;
4038*d415bd75Srobert SmallVector<Value *, 2> Args(CI->args());
4039*d415bd75Srobert Value *NewLdCall = Builder.CreateCall(NewFn, Args);
4040*d415bd75Srobert Value *Ret = llvm::PoisonValue::get(RetTy);
4041*d415bd75Srobert for (unsigned I = 0; I < N; I++) {
4042*d415bd75Srobert Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4043*d415bd75Srobert Value *SRet = Builder.CreateExtractValue(NewLdCall, I);
4044*d415bd75Srobert Ret = Builder.CreateInsertVector(RetTy, Ret, SRet, Idx);
4045*d415bd75Srobert }
4046*d415bd75Srobert NewCall = dyn_cast<CallInst>(Ret);
4047*d415bd75Srobert break;
4048*d415bd75Srobert }
4049*d415bd75Srobert
4050*d415bd75Srobert case Intrinsic::vector_extract: {
4051*d415bd75Srobert StringRef Name = F->getName();
4052*d415bd75Srobert Name = Name.substr(5); // Strip llvm
4053*d415bd75Srobert if (!Name.startswith("aarch64.sve.tuple.get")) {
4054*d415bd75Srobert DefaultCase();
4055*d415bd75Srobert return;
4056*d415bd75Srobert }
4057*d415bd75Srobert ScalableVectorType *RetTy =
4058*d415bd75Srobert dyn_cast<ScalableVectorType>(F->getReturnType());
4059*d415bd75Srobert unsigned MinElts = RetTy->getMinNumElements();
4060*d415bd75Srobert unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4061*d415bd75Srobert Value *NewIdx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4062*d415bd75Srobert NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0), NewIdx});
4063*d415bd75Srobert break;
4064*d415bd75Srobert }
4065*d415bd75Srobert
4066*d415bd75Srobert case Intrinsic::vector_insert: {
4067*d415bd75Srobert StringRef Name = F->getName();
4068*d415bd75Srobert Name = Name.substr(5);
4069*d415bd75Srobert if (!Name.startswith("aarch64.sve.tuple")) {
4070*d415bd75Srobert DefaultCase();
4071*d415bd75Srobert return;
4072*d415bd75Srobert }
4073*d415bd75Srobert if (Name.startswith("aarch64.sve.tuple.set")) {
4074*d415bd75Srobert unsigned I = dyn_cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4075*d415bd75Srobert ScalableVectorType *Ty =
4076*d415bd75Srobert dyn_cast<ScalableVectorType>(CI->getArgOperand(2)->getType());
4077*d415bd75Srobert Value *NewIdx =
4078*d415bd75Srobert ConstantInt::get(Type::getInt64Ty(C), I * Ty->getMinNumElements());
4079*d415bd75Srobert NewCall = Builder.CreateCall(
4080*d415bd75Srobert NewFn, {CI->getArgOperand(0), CI->getArgOperand(2), NewIdx});
4081*d415bd75Srobert break;
4082*d415bd75Srobert }
4083*d415bd75Srobert if (Name.startswith("aarch64.sve.tuple.create")) {
4084*d415bd75Srobert unsigned N = StringSwitch<unsigned>(Name)
4085*d415bd75Srobert .StartsWith("aarch64.sve.tuple.create2", 2)
4086*d415bd75Srobert .StartsWith("aarch64.sve.tuple.create3", 3)
4087*d415bd75Srobert .StartsWith("aarch64.sve.tuple.create4", 4)
4088*d415bd75Srobert .Default(0);
4089*d415bd75Srobert assert(N > 1 && "Create is expected to be between 2-4");
4090*d415bd75Srobert ScalableVectorType *RetTy =
4091*d415bd75Srobert dyn_cast<ScalableVectorType>(F->getReturnType());
4092*d415bd75Srobert Value *Ret = llvm::PoisonValue::get(RetTy);
4093*d415bd75Srobert unsigned MinElts = RetTy->getMinNumElements() / N;
4094*d415bd75Srobert for (unsigned I = 0; I < N; I++) {
4095*d415bd75Srobert Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4096*d415bd75Srobert Value *V = CI->getArgOperand(I);
4097*d415bd75Srobert Ret = Builder.CreateInsertVector(RetTy, Ret, V, Idx);
4098*d415bd75Srobert }
4099*d415bd75Srobert NewCall = dyn_cast<CallInst>(Ret);
4100*d415bd75Srobert }
4101*d415bd75Srobert break;
4102*d415bd75Srobert }
410309467b48Spatrick
410473471bf0Spatrick case Intrinsic::arm_neon_bfdot:
410573471bf0Spatrick case Intrinsic::arm_neon_bfmmla:
410673471bf0Spatrick case Intrinsic::arm_neon_bfmlalb:
410773471bf0Spatrick case Intrinsic::arm_neon_bfmlalt:
410873471bf0Spatrick case Intrinsic::aarch64_neon_bfdot:
410973471bf0Spatrick case Intrinsic::aarch64_neon_bfmmla:
411073471bf0Spatrick case Intrinsic::aarch64_neon_bfmlalb:
411173471bf0Spatrick case Intrinsic::aarch64_neon_bfmlalt: {
411273471bf0Spatrick SmallVector<Value *, 3> Args;
4113*d415bd75Srobert assert(CI->arg_size() == 3 &&
411473471bf0Spatrick "Mismatch between function args and call args");
411573471bf0Spatrick size_t OperandWidth =
411673471bf0Spatrick CI->getArgOperand(1)->getType()->getPrimitiveSizeInBits();
411773471bf0Spatrick assert((OperandWidth == 64 || OperandWidth == 128) &&
411873471bf0Spatrick "Unexpected operand width");
411973471bf0Spatrick Type *NewTy = FixedVectorType::get(Type::getBFloatTy(C), OperandWidth / 16);
4120*d415bd75Srobert auto Iter = CI->args().begin();
412173471bf0Spatrick Args.push_back(*Iter++);
412273471bf0Spatrick Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
412373471bf0Spatrick Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
412473471bf0Spatrick NewCall = Builder.CreateCall(NewFn, Args);
412573471bf0Spatrick break;
412673471bf0Spatrick }
412773471bf0Spatrick
412809467b48Spatrick case Intrinsic::bitreverse:
412909467b48Spatrick NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
413009467b48Spatrick break;
413109467b48Spatrick
413209467b48Spatrick case Intrinsic::ctlz:
413309467b48Spatrick case Intrinsic::cttz:
4134*d415bd75Srobert assert(CI->arg_size() == 1 &&
413509467b48Spatrick "Mismatch between function args and call args");
413609467b48Spatrick NewCall =
413709467b48Spatrick Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()});
413809467b48Spatrick break;
413909467b48Spatrick
414009467b48Spatrick case Intrinsic::objectsize: {
4141*d415bd75Srobert Value *NullIsUnknownSize =
4142*d415bd75Srobert CI->arg_size() == 2 ? Builder.getFalse() : CI->getArgOperand(2);
414309467b48Spatrick Value *Dynamic =
4144*d415bd75Srobert CI->arg_size() < 4 ? Builder.getFalse() : CI->getArgOperand(3);
414509467b48Spatrick NewCall = Builder.CreateCall(
414609467b48Spatrick NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic});
414709467b48Spatrick break;
414809467b48Spatrick }
414909467b48Spatrick
415009467b48Spatrick case Intrinsic::ctpop:
415109467b48Spatrick NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
415209467b48Spatrick break;
415309467b48Spatrick
415409467b48Spatrick case Intrinsic::convert_from_fp16:
415509467b48Spatrick NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
415609467b48Spatrick break;
415709467b48Spatrick
415809467b48Spatrick case Intrinsic::dbg_value:
415909467b48Spatrick // Upgrade from the old version that had an extra offset argument.
4160*d415bd75Srobert assert(CI->arg_size() == 4);
416109467b48Spatrick // Drop nonzero offsets instead of attempting to upgrade them.
416209467b48Spatrick if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
416309467b48Spatrick if (Offset->isZeroValue()) {
416409467b48Spatrick NewCall = Builder.CreateCall(
416509467b48Spatrick NewFn,
416609467b48Spatrick {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
416709467b48Spatrick break;
416809467b48Spatrick }
416909467b48Spatrick CI->eraseFromParent();
417009467b48Spatrick return;
417109467b48Spatrick
417273471bf0Spatrick case Intrinsic::ptr_annotation:
417373471bf0Spatrick // Upgrade from versions that lacked the annotation attribute argument.
4174*d415bd75Srobert if (CI->arg_size() != 4) {
4175*d415bd75Srobert DefaultCase();
4176*d415bd75Srobert return;
4177*d415bd75Srobert }
4178*d415bd75Srobert
417973471bf0Spatrick // Create a new call with an added null annotation attribute argument.
418073471bf0Spatrick NewCall = Builder.CreateCall(
418173471bf0Spatrick NewFn,
418273471bf0Spatrick {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
418373471bf0Spatrick CI->getArgOperand(3), Constant::getNullValue(Builder.getInt8PtrTy())});
418473471bf0Spatrick NewCall->takeName(CI);
418573471bf0Spatrick CI->replaceAllUsesWith(NewCall);
418673471bf0Spatrick CI->eraseFromParent();
418773471bf0Spatrick return;
418873471bf0Spatrick
418973471bf0Spatrick case Intrinsic::var_annotation:
419073471bf0Spatrick // Upgrade from versions that lacked the annotation attribute argument.
4191*d415bd75Srobert if (CI->arg_size() != 4) {
4192*d415bd75Srobert DefaultCase();
4193*d415bd75Srobert return;
4194*d415bd75Srobert }
419573471bf0Spatrick // Create a new call with an added null annotation attribute argument.
419673471bf0Spatrick NewCall = Builder.CreateCall(
419773471bf0Spatrick NewFn,
419873471bf0Spatrick {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
419973471bf0Spatrick CI->getArgOperand(3), Constant::getNullValue(Builder.getInt8PtrTy())});
4200*d415bd75Srobert NewCall->takeName(CI);
4201*d415bd75Srobert CI->replaceAllUsesWith(NewCall);
420273471bf0Spatrick CI->eraseFromParent();
420373471bf0Spatrick return;
420473471bf0Spatrick
420509467b48Spatrick case Intrinsic::x86_xop_vfrcz_ss:
420609467b48Spatrick case Intrinsic::x86_xop_vfrcz_sd:
420709467b48Spatrick NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)});
420809467b48Spatrick break;
420909467b48Spatrick
421009467b48Spatrick case Intrinsic::x86_xop_vpermil2pd:
421109467b48Spatrick case Intrinsic::x86_xop_vpermil2ps:
421209467b48Spatrick case Intrinsic::x86_xop_vpermil2pd_256:
421309467b48Spatrick case Intrinsic::x86_xop_vpermil2ps_256: {
4214*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
421509467b48Spatrick VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType());
421609467b48Spatrick VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy);
421709467b48Spatrick Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy);
421809467b48Spatrick NewCall = Builder.CreateCall(NewFn, Args);
421909467b48Spatrick break;
422009467b48Spatrick }
422109467b48Spatrick
422209467b48Spatrick case Intrinsic::x86_sse41_ptestc:
422309467b48Spatrick case Intrinsic::x86_sse41_ptestz:
422409467b48Spatrick case Intrinsic::x86_sse41_ptestnzc: {
422509467b48Spatrick // The arguments for these intrinsics used to be v4f32, and changed
422609467b48Spatrick // to v2i64. This is purely a nop, since those are bitwise intrinsics.
422709467b48Spatrick // So, the only thing required is a bitcast for both arguments.
422809467b48Spatrick // First, check the arguments have the old type.
422909467b48Spatrick Value *Arg0 = CI->getArgOperand(0);
4230097a140dSpatrick if (Arg0->getType() != FixedVectorType::get(Type::getFloatTy(C), 4))
423109467b48Spatrick return;
423209467b48Spatrick
423309467b48Spatrick // Old intrinsic, add bitcasts
423409467b48Spatrick Value *Arg1 = CI->getArgOperand(1);
423509467b48Spatrick
4236097a140dSpatrick auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
423709467b48Spatrick
423809467b48Spatrick Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast");
423909467b48Spatrick Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
424009467b48Spatrick
424109467b48Spatrick NewCall = Builder.CreateCall(NewFn, {BC0, BC1});
424209467b48Spatrick break;
424309467b48Spatrick }
424409467b48Spatrick
424509467b48Spatrick case Intrinsic::x86_rdtscp: {
424609467b48Spatrick // This used to take 1 arguments. If we have no arguments, it is already
424709467b48Spatrick // upgraded.
424809467b48Spatrick if (CI->getNumOperands() == 0)
424909467b48Spatrick return;
425009467b48Spatrick
425109467b48Spatrick NewCall = Builder.CreateCall(NewFn);
425209467b48Spatrick // Extract the second result and store it.
425309467b48Spatrick Value *Data = Builder.CreateExtractValue(NewCall, 1);
425409467b48Spatrick // Cast the pointer to the right type.
425509467b48Spatrick Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(0),
425609467b48Spatrick llvm::PointerType::getUnqual(Data->getType()));
4257097a140dSpatrick Builder.CreateAlignedStore(Data, Ptr, Align(1));
425809467b48Spatrick // Replace the original call result with the first result of the new call.
425909467b48Spatrick Value *TSC = Builder.CreateExtractValue(NewCall, 0);
426009467b48Spatrick
426173471bf0Spatrick NewCall->takeName(CI);
426209467b48Spatrick CI->replaceAllUsesWith(TSC);
426309467b48Spatrick CI->eraseFromParent();
426409467b48Spatrick return;
426509467b48Spatrick }
426609467b48Spatrick
426709467b48Spatrick case Intrinsic::x86_sse41_insertps:
426809467b48Spatrick case Intrinsic::x86_sse41_dppd:
426909467b48Spatrick case Intrinsic::x86_sse41_dpps:
427009467b48Spatrick case Intrinsic::x86_sse41_mpsadbw:
427109467b48Spatrick case Intrinsic::x86_avx_dp_ps_256:
427209467b48Spatrick case Intrinsic::x86_avx2_mpsadbw: {
427309467b48Spatrick // Need to truncate the last argument from i32 to i8 -- this argument models
427409467b48Spatrick // an inherently 8-bit immediate operand to these x86 instructions.
4275*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
427609467b48Spatrick
427709467b48Spatrick // Replace the last argument with a trunc.
427809467b48Spatrick Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
427909467b48Spatrick NewCall = Builder.CreateCall(NewFn, Args);
428009467b48Spatrick break;
428109467b48Spatrick }
428209467b48Spatrick
428373471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_pd_128:
428473471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_pd_256:
428573471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_pd_512:
428673471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_ps_128:
428773471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_ps_256:
428873471bf0Spatrick case Intrinsic::x86_avx512_mask_cmp_ps_512: {
4289*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
429073471bf0Spatrick unsigned NumElts =
429173471bf0Spatrick cast<FixedVectorType>(Args[0]->getType())->getNumElements();
429273471bf0Spatrick Args[3] = getX86MaskVec(Builder, Args[3], NumElts);
429373471bf0Spatrick
429473471bf0Spatrick NewCall = Builder.CreateCall(NewFn, Args);
429573471bf0Spatrick Value *Res = ApplyX86MaskOn1BitsVec(Builder, NewCall, nullptr);
429673471bf0Spatrick
429773471bf0Spatrick NewCall->takeName(CI);
429873471bf0Spatrick CI->replaceAllUsesWith(Res);
429973471bf0Spatrick CI->eraseFromParent();
430073471bf0Spatrick return;
430173471bf0Spatrick }
430273471bf0Spatrick
4303*d415bd75Srobert case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128:
4304*d415bd75Srobert case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256:
4305*d415bd75Srobert case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512:
4306*d415bd75Srobert case Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128:
4307*d415bd75Srobert case Intrinsic::x86_avx512bf16_cvtneps2bf16_256:
4308*d415bd75Srobert case Intrinsic::x86_avx512bf16_cvtneps2bf16_512: {
4309*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
4310*d415bd75Srobert unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
4311*d415bd75Srobert if (NewFn->getIntrinsicID() ==
4312*d415bd75Srobert Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
4313*d415bd75Srobert Args[1] = Builder.CreateBitCast(
4314*d415bd75Srobert Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4315*d415bd75Srobert
4316*d415bd75Srobert NewCall = Builder.CreateCall(NewFn, Args);
4317*d415bd75Srobert Value *Res = Builder.CreateBitCast(
4318*d415bd75Srobert NewCall, FixedVectorType::get(Builder.getInt16Ty(), NumElts));
4319*d415bd75Srobert
4320*d415bd75Srobert NewCall->takeName(CI);
4321*d415bd75Srobert CI->replaceAllUsesWith(Res);
4322*d415bd75Srobert CI->eraseFromParent();
4323*d415bd75Srobert return;
4324*d415bd75Srobert }
4325*d415bd75Srobert case Intrinsic::x86_avx512bf16_dpbf16ps_128:
4326*d415bd75Srobert case Intrinsic::x86_avx512bf16_dpbf16ps_256:
4327*d415bd75Srobert case Intrinsic::x86_avx512bf16_dpbf16ps_512:{
4328*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
4329*d415bd75Srobert unsigned NumElts =
4330*d415bd75Srobert cast<FixedVectorType>(CI->getType())->getNumElements() * 2;
4331*d415bd75Srobert Args[1] = Builder.CreateBitCast(
4332*d415bd75Srobert Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4333*d415bd75Srobert Args[2] = Builder.CreateBitCast(
4334*d415bd75Srobert Args[2], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4335*d415bd75Srobert
4336*d415bd75Srobert NewCall = Builder.CreateCall(NewFn, Args);
4337*d415bd75Srobert break;
4338*d415bd75Srobert }
4339*d415bd75Srobert
434009467b48Spatrick case Intrinsic::thread_pointer: {
434109467b48Spatrick NewCall = Builder.CreateCall(NewFn, {});
434209467b48Spatrick break;
434309467b48Spatrick }
434409467b48Spatrick
434509467b48Spatrick case Intrinsic::invariant_start:
434673471bf0Spatrick case Intrinsic::invariant_end: {
4347*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
434873471bf0Spatrick NewCall = Builder.CreateCall(NewFn, Args);
434973471bf0Spatrick break;
435073471bf0Spatrick }
435109467b48Spatrick case Intrinsic::masked_load:
435209467b48Spatrick case Intrinsic::masked_store:
435309467b48Spatrick case Intrinsic::masked_gather:
435409467b48Spatrick case Intrinsic::masked_scatter: {
4355*d415bd75Srobert SmallVector<Value *, 4> Args(CI->args());
435609467b48Spatrick NewCall = Builder.CreateCall(NewFn, Args);
435773471bf0Spatrick NewCall->copyMetadata(*CI);
435809467b48Spatrick break;
435909467b48Spatrick }
436009467b48Spatrick
436109467b48Spatrick case Intrinsic::memcpy:
436209467b48Spatrick case Intrinsic::memmove:
436309467b48Spatrick case Intrinsic::memset: {
436409467b48Spatrick // We have to make sure that the call signature is what we're expecting.
436509467b48Spatrick // We only want to change the old signatures by removing the alignment arg:
436609467b48Spatrick // @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i32, i1)
436709467b48Spatrick // -> @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i1)
436809467b48Spatrick // @llvm.memset...(i8*, i8, i[32|64], i32, i1)
436909467b48Spatrick // -> @llvm.memset...(i8*, i8, i[32|64], i1)
437009467b48Spatrick // Note: i8*'s in the above can be any pointer type
4371*d415bd75Srobert if (CI->arg_size() != 5) {
437209467b48Spatrick DefaultCase();
437309467b48Spatrick return;
437409467b48Spatrick }
437509467b48Spatrick // Remove alignment argument (3), and add alignment attributes to the
437609467b48Spatrick // dest/src pointers.
437709467b48Spatrick Value *Args[4] = {CI->getArgOperand(0), CI->getArgOperand(1),
437809467b48Spatrick CI->getArgOperand(2), CI->getArgOperand(4)};
437909467b48Spatrick NewCall = Builder.CreateCall(NewFn, Args);
4380*d415bd75Srobert AttributeList OldAttrs = CI->getAttributes();
4381*d415bd75Srobert AttributeList NewAttrs = AttributeList::get(
4382*d415bd75Srobert C, OldAttrs.getFnAttrs(), OldAttrs.getRetAttrs(),
4383*d415bd75Srobert {OldAttrs.getParamAttrs(0), OldAttrs.getParamAttrs(1),
4384*d415bd75Srobert OldAttrs.getParamAttrs(2), OldAttrs.getParamAttrs(4)});
4385*d415bd75Srobert NewCall->setAttributes(NewAttrs);
438609467b48Spatrick auto *MemCI = cast<MemIntrinsic>(NewCall);
438709467b48Spatrick // All mem intrinsics support dest alignment.
438809467b48Spatrick const ConstantInt *Align = cast<ConstantInt>(CI->getArgOperand(3));
4389097a140dSpatrick MemCI->setDestAlignment(Align->getMaybeAlignValue());
439009467b48Spatrick // Memcpy/Memmove also support source alignment.
439109467b48Spatrick if (auto *MTI = dyn_cast<MemTransferInst>(MemCI))
4392097a140dSpatrick MTI->setSourceAlignment(Align->getMaybeAlignValue());
439309467b48Spatrick break;
439409467b48Spatrick }
439509467b48Spatrick }
439609467b48Spatrick assert(NewCall && "Should have either set this variable or returned through "
439709467b48Spatrick "the default case");
439873471bf0Spatrick NewCall->takeName(CI);
439909467b48Spatrick CI->replaceAllUsesWith(NewCall);
440009467b48Spatrick CI->eraseFromParent();
440109467b48Spatrick }
440209467b48Spatrick
UpgradeCallsToIntrinsic(Function * F)440309467b48Spatrick void llvm::UpgradeCallsToIntrinsic(Function *F) {
440409467b48Spatrick assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
440509467b48Spatrick
440609467b48Spatrick // Check if this function should be upgraded and get the replacement function
440709467b48Spatrick // if there is one.
440809467b48Spatrick Function *NewFn;
440909467b48Spatrick if (UpgradeIntrinsicFunction(F, NewFn)) {
441009467b48Spatrick // Replace all users of the old function with the new function or new
441109467b48Spatrick // instructions. This is not a range loop because the call is deleted.
441273471bf0Spatrick for (User *U : make_early_inc_range(F->users()))
4413*d415bd75Srobert if (CallBase *CB = dyn_cast<CallBase>(U))
4414*d415bd75Srobert UpgradeIntrinsicCall(CB, NewFn);
441509467b48Spatrick
441609467b48Spatrick // Remove old function, no longer used, from the module.
441709467b48Spatrick F->eraseFromParent();
441809467b48Spatrick }
441909467b48Spatrick }
442009467b48Spatrick
UpgradeTBAANode(MDNode & MD)442109467b48Spatrick MDNode *llvm::UpgradeTBAANode(MDNode &MD) {
442209467b48Spatrick // Check if the tag uses struct-path aware TBAA format.
442309467b48Spatrick if (isa<MDNode>(MD.getOperand(0)) && MD.getNumOperands() >= 3)
442409467b48Spatrick return &MD;
442509467b48Spatrick
442609467b48Spatrick auto &Context = MD.getContext();
442709467b48Spatrick if (MD.getNumOperands() == 3) {
442809467b48Spatrick Metadata *Elts[] = {MD.getOperand(0), MD.getOperand(1)};
442909467b48Spatrick MDNode *ScalarType = MDNode::get(Context, Elts);
443009467b48Spatrick // Create a MDNode <ScalarType, ScalarType, offset 0, const>
443109467b48Spatrick Metadata *Elts2[] = {ScalarType, ScalarType,
443209467b48Spatrick ConstantAsMetadata::get(
443309467b48Spatrick Constant::getNullValue(Type::getInt64Ty(Context))),
443409467b48Spatrick MD.getOperand(2)};
443509467b48Spatrick return MDNode::get(Context, Elts2);
443609467b48Spatrick }
443709467b48Spatrick // Create a MDNode <MD, MD, offset 0>
443809467b48Spatrick Metadata *Elts[] = {&MD, &MD, ConstantAsMetadata::get(Constant::getNullValue(
443909467b48Spatrick Type::getInt64Ty(Context)))};
444009467b48Spatrick return MDNode::get(Context, Elts);
444109467b48Spatrick }
444209467b48Spatrick
UpgradeBitCastInst(unsigned Opc,Value * V,Type * DestTy,Instruction * & Temp)444309467b48Spatrick Instruction *llvm::UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,
444409467b48Spatrick Instruction *&Temp) {
444509467b48Spatrick if (Opc != Instruction::BitCast)
444609467b48Spatrick return nullptr;
444709467b48Spatrick
444809467b48Spatrick Temp = nullptr;
444909467b48Spatrick Type *SrcTy = V->getType();
445009467b48Spatrick if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
445109467b48Spatrick SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
445209467b48Spatrick LLVMContext &Context = V->getContext();
445309467b48Spatrick
445409467b48Spatrick // We have no information about target data layout, so we assume that
445509467b48Spatrick // the maximum pointer size is 64bit.
445609467b48Spatrick Type *MidTy = Type::getInt64Ty(Context);
445709467b48Spatrick Temp = CastInst::Create(Instruction::PtrToInt, V, MidTy);
445809467b48Spatrick
445909467b48Spatrick return CastInst::Create(Instruction::IntToPtr, Temp, DestTy);
446009467b48Spatrick }
446109467b48Spatrick
446209467b48Spatrick return nullptr;
446309467b48Spatrick }
446409467b48Spatrick
UpgradeBitCastExpr(unsigned Opc,Constant * C,Type * DestTy)4465*d415bd75Srobert Constant *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {
446609467b48Spatrick if (Opc != Instruction::BitCast)
446709467b48Spatrick return nullptr;
446809467b48Spatrick
446909467b48Spatrick Type *SrcTy = C->getType();
447009467b48Spatrick if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
447109467b48Spatrick SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
447209467b48Spatrick LLVMContext &Context = C->getContext();
447309467b48Spatrick
447409467b48Spatrick // We have no information about target data layout, so we assume that
447509467b48Spatrick // the maximum pointer size is 64bit.
447609467b48Spatrick Type *MidTy = Type::getInt64Ty(Context);
447709467b48Spatrick
447809467b48Spatrick return ConstantExpr::getIntToPtr(ConstantExpr::getPtrToInt(C, MidTy),
447909467b48Spatrick DestTy);
448009467b48Spatrick }
448109467b48Spatrick
448209467b48Spatrick return nullptr;
448309467b48Spatrick }
448409467b48Spatrick
448509467b48Spatrick /// Check the debug info version number, if it is out-dated, drop the debug
448609467b48Spatrick /// info. Return true if module is modified.
UpgradeDebugInfo(Module & M)448709467b48Spatrick bool llvm::UpgradeDebugInfo(Module &M) {
448809467b48Spatrick unsigned Version = getDebugMetadataVersionFromModule(M);
448909467b48Spatrick if (Version == DEBUG_METADATA_VERSION) {
449009467b48Spatrick bool BrokenDebugInfo = false;
449109467b48Spatrick if (verifyModule(M, &llvm::errs(), &BrokenDebugInfo))
449209467b48Spatrick report_fatal_error("Broken module found, compilation aborted!");
449309467b48Spatrick if (!BrokenDebugInfo)
449409467b48Spatrick // Everything is ok.
449509467b48Spatrick return false;
449609467b48Spatrick else {
449709467b48Spatrick // Diagnose malformed debug info.
449809467b48Spatrick DiagnosticInfoIgnoringInvalidDebugMetadata Diag(M);
449909467b48Spatrick M.getContext().diagnose(Diag);
450009467b48Spatrick }
450109467b48Spatrick }
450209467b48Spatrick bool Modified = StripDebugInfo(M);
450309467b48Spatrick if (Modified && Version != DEBUG_METADATA_VERSION) {
450409467b48Spatrick // Diagnose a version mismatch.
450509467b48Spatrick DiagnosticInfoDebugMetadataVersion DiagVersion(M, Version);
450609467b48Spatrick M.getContext().diagnose(DiagVersion);
450709467b48Spatrick }
450809467b48Spatrick return Modified;
450909467b48Spatrick }
451009467b48Spatrick
451109467b48Spatrick /// This checks for objc retain release marker which should be upgraded. It
451209467b48Spatrick /// returns true if module is modified.
UpgradeRetainReleaseMarker(Module & M)451309467b48Spatrick static bool UpgradeRetainReleaseMarker(Module &M) {
451409467b48Spatrick bool Changed = false;
451509467b48Spatrick const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
451609467b48Spatrick NamedMDNode *ModRetainReleaseMarker = M.getNamedMetadata(MarkerKey);
451709467b48Spatrick if (ModRetainReleaseMarker) {
451809467b48Spatrick MDNode *Op = ModRetainReleaseMarker->getOperand(0);
451909467b48Spatrick if (Op) {
452009467b48Spatrick MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(0));
452109467b48Spatrick if (ID) {
452209467b48Spatrick SmallVector<StringRef, 4> ValueComp;
452309467b48Spatrick ID->getString().split(ValueComp, "#");
452409467b48Spatrick if (ValueComp.size() == 2) {
452509467b48Spatrick std::string NewValue = ValueComp[0].str() + ";" + ValueComp[1].str();
452609467b48Spatrick ID = MDString::get(M.getContext(), NewValue);
452709467b48Spatrick }
452809467b48Spatrick M.addModuleFlag(Module::Error, MarkerKey, ID);
452909467b48Spatrick M.eraseNamedMetadata(ModRetainReleaseMarker);
453009467b48Spatrick Changed = true;
453109467b48Spatrick }
453209467b48Spatrick }
453309467b48Spatrick }
453409467b48Spatrick return Changed;
453509467b48Spatrick }
453609467b48Spatrick
UpgradeARCRuntime(Module & M)453709467b48Spatrick void llvm::UpgradeARCRuntime(Module &M) {
453809467b48Spatrick // This lambda converts normal function calls to ARC runtime functions to
453909467b48Spatrick // intrinsic calls.
454009467b48Spatrick auto UpgradeToIntrinsic = [&](const char *OldFunc,
454109467b48Spatrick llvm::Intrinsic::ID IntrinsicFunc) {
454209467b48Spatrick Function *Fn = M.getFunction(OldFunc);
454309467b48Spatrick
454409467b48Spatrick if (!Fn)
454509467b48Spatrick return;
454609467b48Spatrick
454709467b48Spatrick Function *NewFn = llvm::Intrinsic::getDeclaration(&M, IntrinsicFunc);
454809467b48Spatrick
454973471bf0Spatrick for (User *U : make_early_inc_range(Fn->users())) {
455073471bf0Spatrick CallInst *CI = dyn_cast<CallInst>(U);
455109467b48Spatrick if (!CI || CI->getCalledFunction() != Fn)
455209467b48Spatrick continue;
455309467b48Spatrick
455409467b48Spatrick IRBuilder<> Builder(CI->getParent(), CI->getIterator());
455509467b48Spatrick FunctionType *NewFuncTy = NewFn->getFunctionType();
455609467b48Spatrick SmallVector<Value *, 2> Args;
455709467b48Spatrick
455809467b48Spatrick // Don't upgrade the intrinsic if it's not valid to bitcast the return
455909467b48Spatrick // value to the return type of the old function.
456009467b48Spatrick if (NewFuncTy->getReturnType() != CI->getType() &&
456109467b48Spatrick !CastInst::castIsValid(Instruction::BitCast, CI,
456209467b48Spatrick NewFuncTy->getReturnType()))
456309467b48Spatrick continue;
456409467b48Spatrick
456509467b48Spatrick bool InvalidCast = false;
456609467b48Spatrick
4567*d415bd75Srobert for (unsigned I = 0, E = CI->arg_size(); I != E; ++I) {
456809467b48Spatrick Value *Arg = CI->getArgOperand(I);
456909467b48Spatrick
457009467b48Spatrick // Bitcast argument to the parameter type of the new function if it's
457109467b48Spatrick // not a variadic argument.
457209467b48Spatrick if (I < NewFuncTy->getNumParams()) {
457309467b48Spatrick // Don't upgrade the intrinsic if it's not valid to bitcast the argument
457409467b48Spatrick // to the parameter type of the new function.
457509467b48Spatrick if (!CastInst::castIsValid(Instruction::BitCast, Arg,
457609467b48Spatrick NewFuncTy->getParamType(I))) {
457709467b48Spatrick InvalidCast = true;
457809467b48Spatrick break;
457909467b48Spatrick }
458009467b48Spatrick Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
458109467b48Spatrick }
458209467b48Spatrick Args.push_back(Arg);
458309467b48Spatrick }
458409467b48Spatrick
458509467b48Spatrick if (InvalidCast)
458609467b48Spatrick continue;
458709467b48Spatrick
458809467b48Spatrick // Create a call instruction that calls the new function.
458909467b48Spatrick CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
459009467b48Spatrick NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
459173471bf0Spatrick NewCall->takeName(CI);
459209467b48Spatrick
459309467b48Spatrick // Bitcast the return value back to the type of the old call.
459409467b48Spatrick Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType());
459509467b48Spatrick
459609467b48Spatrick if (!CI->use_empty())
459709467b48Spatrick CI->replaceAllUsesWith(NewRetVal);
459809467b48Spatrick CI->eraseFromParent();
459909467b48Spatrick }
460009467b48Spatrick
460109467b48Spatrick if (Fn->use_empty())
460209467b48Spatrick Fn->eraseFromParent();
460309467b48Spatrick };
460409467b48Spatrick
460509467b48Spatrick // Unconditionally convert a call to "clang.arc.use" to a call to
460609467b48Spatrick // "llvm.objc.clang.arc.use".
460709467b48Spatrick UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use);
460809467b48Spatrick
460909467b48Spatrick // Upgrade the retain release marker. If there is no need to upgrade
461009467b48Spatrick // the marker, that means either the module is already new enough to contain
461109467b48Spatrick // new intrinsics or it is not ARC. There is no need to upgrade runtime call.
461209467b48Spatrick if (!UpgradeRetainReleaseMarker(M))
461309467b48Spatrick return;
461409467b48Spatrick
461509467b48Spatrick std::pair<const char *, llvm::Intrinsic::ID> RuntimeFuncs[] = {
461609467b48Spatrick {"objc_autorelease", llvm::Intrinsic::objc_autorelease},
461709467b48Spatrick {"objc_autoreleasePoolPop", llvm::Intrinsic::objc_autoreleasePoolPop},
461809467b48Spatrick {"objc_autoreleasePoolPush", llvm::Intrinsic::objc_autoreleasePoolPush},
461909467b48Spatrick {"objc_autoreleaseReturnValue",
462009467b48Spatrick llvm::Intrinsic::objc_autoreleaseReturnValue},
462109467b48Spatrick {"objc_copyWeak", llvm::Intrinsic::objc_copyWeak},
462209467b48Spatrick {"objc_destroyWeak", llvm::Intrinsic::objc_destroyWeak},
462309467b48Spatrick {"objc_initWeak", llvm::Intrinsic::objc_initWeak},
462409467b48Spatrick {"objc_loadWeak", llvm::Intrinsic::objc_loadWeak},
462509467b48Spatrick {"objc_loadWeakRetained", llvm::Intrinsic::objc_loadWeakRetained},
462609467b48Spatrick {"objc_moveWeak", llvm::Intrinsic::objc_moveWeak},
462709467b48Spatrick {"objc_release", llvm::Intrinsic::objc_release},
462809467b48Spatrick {"objc_retain", llvm::Intrinsic::objc_retain},
462909467b48Spatrick {"objc_retainAutorelease", llvm::Intrinsic::objc_retainAutorelease},
463009467b48Spatrick {"objc_retainAutoreleaseReturnValue",
463109467b48Spatrick llvm::Intrinsic::objc_retainAutoreleaseReturnValue},
463209467b48Spatrick {"objc_retainAutoreleasedReturnValue",
463309467b48Spatrick llvm::Intrinsic::objc_retainAutoreleasedReturnValue},
463409467b48Spatrick {"objc_retainBlock", llvm::Intrinsic::objc_retainBlock},
463509467b48Spatrick {"objc_storeStrong", llvm::Intrinsic::objc_storeStrong},
463609467b48Spatrick {"objc_storeWeak", llvm::Intrinsic::objc_storeWeak},
463709467b48Spatrick {"objc_unsafeClaimAutoreleasedReturnValue",
463809467b48Spatrick llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue},
463909467b48Spatrick {"objc_retainedObject", llvm::Intrinsic::objc_retainedObject},
464009467b48Spatrick {"objc_unretainedObject", llvm::Intrinsic::objc_unretainedObject},
464109467b48Spatrick {"objc_unretainedPointer", llvm::Intrinsic::objc_unretainedPointer},
464209467b48Spatrick {"objc_retain_autorelease", llvm::Intrinsic::objc_retain_autorelease},
464309467b48Spatrick {"objc_sync_enter", llvm::Intrinsic::objc_sync_enter},
464409467b48Spatrick {"objc_sync_exit", llvm::Intrinsic::objc_sync_exit},
464509467b48Spatrick {"objc_arc_annotation_topdown_bbstart",
464609467b48Spatrick llvm::Intrinsic::objc_arc_annotation_topdown_bbstart},
464709467b48Spatrick {"objc_arc_annotation_topdown_bbend",
464809467b48Spatrick llvm::Intrinsic::objc_arc_annotation_topdown_bbend},
464909467b48Spatrick {"objc_arc_annotation_bottomup_bbstart",
465009467b48Spatrick llvm::Intrinsic::objc_arc_annotation_bottomup_bbstart},
465109467b48Spatrick {"objc_arc_annotation_bottomup_bbend",
465209467b48Spatrick llvm::Intrinsic::objc_arc_annotation_bottomup_bbend}};
465309467b48Spatrick
465409467b48Spatrick for (auto &I : RuntimeFuncs)
465509467b48Spatrick UpgradeToIntrinsic(I.first, I.second);
465609467b48Spatrick }
465709467b48Spatrick
UpgradeModuleFlags(Module & M)465809467b48Spatrick bool llvm::UpgradeModuleFlags(Module &M) {
465909467b48Spatrick NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
466009467b48Spatrick if (!ModFlags)
466109467b48Spatrick return false;
466209467b48Spatrick
466309467b48Spatrick bool HasObjCFlag = false, HasClassProperties = false, Changed = false;
4664097a140dSpatrick bool HasSwiftVersionFlag = false;
4665097a140dSpatrick uint8_t SwiftMajorVersion, SwiftMinorVersion;
4666097a140dSpatrick uint32_t SwiftABIVersion;
4667097a140dSpatrick auto Int8Ty = Type::getInt8Ty(M.getContext());
4668097a140dSpatrick auto Int32Ty = Type::getInt32Ty(M.getContext());
4669097a140dSpatrick
467009467b48Spatrick for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
467109467b48Spatrick MDNode *Op = ModFlags->getOperand(I);
467209467b48Spatrick if (Op->getNumOperands() != 3)
467309467b48Spatrick continue;
467409467b48Spatrick MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
467509467b48Spatrick if (!ID)
467609467b48Spatrick continue;
4677*d415bd75Srobert auto SetBehavior = [&](Module::ModFlagBehavior B) {
4678*d415bd75Srobert Metadata *Ops[3] = {ConstantAsMetadata::get(ConstantInt::get(
4679*d415bd75Srobert Type::getInt32Ty(M.getContext()), B)),
4680*d415bd75Srobert MDString::get(M.getContext(), ID->getString()),
4681*d415bd75Srobert Op->getOperand(2)};
4682*d415bd75Srobert ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
4683*d415bd75Srobert Changed = true;
4684*d415bd75Srobert };
4685*d415bd75Srobert
468609467b48Spatrick if (ID->getString() == "Objective-C Image Info Version")
468709467b48Spatrick HasObjCFlag = true;
468809467b48Spatrick if (ID->getString() == "Objective-C Class Properties")
468909467b48Spatrick HasClassProperties = true;
4690*d415bd75Srobert // Upgrade PIC from Error/Max to Min.
4691*d415bd75Srobert if (ID->getString() == "PIC Level") {
4692*d415bd75Srobert if (auto *Behavior =
4693*d415bd75Srobert mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
4694*d415bd75Srobert uint64_t V = Behavior->getLimitedValue();
4695*d415bd75Srobert if (V == Module::Error || V == Module::Max)
4696*d415bd75Srobert SetBehavior(Module::Min);
4697*d415bd75Srobert }
4698*d415bd75Srobert }
4699*d415bd75Srobert // Upgrade "PIE Level" from Error to Max.
4700*d415bd75Srobert if (ID->getString() == "PIE Level")
4701*d415bd75Srobert if (auto *Behavior =
4702*d415bd75Srobert mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)))
4703*d415bd75Srobert if (Behavior->getLimitedValue() == Module::Error)
4704*d415bd75Srobert SetBehavior(Module::Max);
4705*d415bd75Srobert
4706*d415bd75Srobert // Upgrade branch protection and return address signing module flags. The
4707*d415bd75Srobert // module flag behavior for these fields were Error and now they are Min.
4708*d415bd75Srobert if (ID->getString() == "branch-target-enforcement" ||
4709*d415bd75Srobert ID->getString().startswith("sign-return-address")) {
471009467b48Spatrick if (auto *Behavior =
471109467b48Spatrick mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
471209467b48Spatrick if (Behavior->getLimitedValue() == Module::Error) {
471309467b48Spatrick Type *Int32Ty = Type::getInt32Ty(M.getContext());
471409467b48Spatrick Metadata *Ops[3] = {
4715*d415bd75Srobert ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Min)),
4716*d415bd75Srobert Op->getOperand(1), Op->getOperand(2)};
471709467b48Spatrick ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
471809467b48Spatrick Changed = true;
471909467b48Spatrick }
472009467b48Spatrick }
472109467b48Spatrick }
4722*d415bd75Srobert
472309467b48Spatrick // Upgrade Objective-C Image Info Section. Removed the whitespce in the
472409467b48Spatrick // section name so that llvm-lto will not complain about mismatching
472509467b48Spatrick // module flags that is functionally the same.
472609467b48Spatrick if (ID->getString() == "Objective-C Image Info Section") {
472709467b48Spatrick if (auto *Value = dyn_cast_or_null<MDString>(Op->getOperand(2))) {
472809467b48Spatrick SmallVector<StringRef, 4> ValueComp;
472909467b48Spatrick Value->getString().split(ValueComp, " ");
473009467b48Spatrick if (ValueComp.size() != 1) {
473109467b48Spatrick std::string NewValue;
473209467b48Spatrick for (auto &S : ValueComp)
473309467b48Spatrick NewValue += S.str();
473409467b48Spatrick Metadata *Ops[3] = {Op->getOperand(0), Op->getOperand(1),
473509467b48Spatrick MDString::get(M.getContext(), NewValue)};
473609467b48Spatrick ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
473709467b48Spatrick Changed = true;
473809467b48Spatrick }
473909467b48Spatrick }
474009467b48Spatrick }
4741097a140dSpatrick
4742097a140dSpatrick // IRUpgrader turns a i32 type "Objective-C Garbage Collection" into i8 value.
4743097a140dSpatrick // If the higher bits are set, it adds new module flag for swift info.
4744097a140dSpatrick if (ID->getString() == "Objective-C Garbage Collection") {
4745097a140dSpatrick auto Md = dyn_cast<ConstantAsMetadata>(Op->getOperand(2));
4746097a140dSpatrick if (Md) {
4747097a140dSpatrick assert(Md->getValue() && "Expected non-empty metadata");
4748097a140dSpatrick auto Type = Md->getValue()->getType();
4749097a140dSpatrick if (Type == Int8Ty)
4750097a140dSpatrick continue;
4751097a140dSpatrick unsigned Val = Md->getValue()->getUniqueInteger().getZExtValue();
4752097a140dSpatrick if ((Val & 0xff) != Val) {
4753097a140dSpatrick HasSwiftVersionFlag = true;
4754097a140dSpatrick SwiftABIVersion = (Val & 0xff00) >> 8;
4755097a140dSpatrick SwiftMajorVersion = (Val & 0xff000000) >> 24;
4756097a140dSpatrick SwiftMinorVersion = (Val & 0xff0000) >> 16;
4757097a140dSpatrick }
4758097a140dSpatrick Metadata *Ops[3] = {
4759097a140dSpatrick ConstantAsMetadata::get(ConstantInt::get(Int32Ty,Module::Error)),
4760097a140dSpatrick Op->getOperand(1),
4761097a140dSpatrick ConstantAsMetadata::get(ConstantInt::get(Int8Ty,Val & 0xff))};
4762097a140dSpatrick ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
4763097a140dSpatrick Changed = true;
4764097a140dSpatrick }
4765097a140dSpatrick }
476609467b48Spatrick }
476709467b48Spatrick
476809467b48Spatrick // "Objective-C Class Properties" is recently added for Objective-C. We
476909467b48Spatrick // upgrade ObjC bitcodes to contain a "Objective-C Class Properties" module
477009467b48Spatrick // flag of value 0, so we can correclty downgrade this flag when trying to
477109467b48Spatrick // link an ObjC bitcode without this module flag with an ObjC bitcode with
477209467b48Spatrick // this module flag.
477309467b48Spatrick if (HasObjCFlag && !HasClassProperties) {
477409467b48Spatrick M.addModuleFlag(llvm::Module::Override, "Objective-C Class Properties",
477509467b48Spatrick (uint32_t)0);
477609467b48Spatrick Changed = true;
477709467b48Spatrick }
477809467b48Spatrick
4779097a140dSpatrick if (HasSwiftVersionFlag) {
4780097a140dSpatrick M.addModuleFlag(Module::Error, "Swift ABI Version",
4781097a140dSpatrick SwiftABIVersion);
4782097a140dSpatrick M.addModuleFlag(Module::Error, "Swift Major Version",
4783097a140dSpatrick ConstantInt::get(Int8Ty, SwiftMajorVersion));
4784097a140dSpatrick M.addModuleFlag(Module::Error, "Swift Minor Version",
4785097a140dSpatrick ConstantInt::get(Int8Ty, SwiftMinorVersion));
4786097a140dSpatrick Changed = true;
4787097a140dSpatrick }
4788097a140dSpatrick
478909467b48Spatrick return Changed;
479009467b48Spatrick }
479109467b48Spatrick
UpgradeSectionAttributes(Module & M)479209467b48Spatrick void llvm::UpgradeSectionAttributes(Module &M) {
479309467b48Spatrick auto TrimSpaces = [](StringRef Section) -> std::string {
479409467b48Spatrick SmallVector<StringRef, 5> Components;
479509467b48Spatrick Section.split(Components, ',');
479609467b48Spatrick
479709467b48Spatrick SmallString<32> Buffer;
479809467b48Spatrick raw_svector_ostream OS(Buffer);
479909467b48Spatrick
480009467b48Spatrick for (auto Component : Components)
480109467b48Spatrick OS << ',' << Component.trim();
480209467b48Spatrick
4803097a140dSpatrick return std::string(OS.str().substr(1));
480409467b48Spatrick };
480509467b48Spatrick
480609467b48Spatrick for (auto &GV : M.globals()) {
480709467b48Spatrick if (!GV.hasSection())
480809467b48Spatrick continue;
480909467b48Spatrick
481009467b48Spatrick StringRef Section = GV.getSection();
481109467b48Spatrick
481209467b48Spatrick if (!Section.startswith("__DATA, __objc_catlist"))
481309467b48Spatrick continue;
481409467b48Spatrick
481509467b48Spatrick // __DATA, __objc_catlist, regular, no_dead_strip
481609467b48Spatrick // __DATA,__objc_catlist,regular,no_dead_strip
481709467b48Spatrick GV.setSection(TrimSpaces(Section));
481809467b48Spatrick }
481909467b48Spatrick }
482009467b48Spatrick
4821097a140dSpatrick namespace {
4822097a140dSpatrick // Prior to LLVM 10.0, the strictfp attribute could be used on individual
4823097a140dSpatrick // callsites within a function that did not also have the strictfp attribute.
4824097a140dSpatrick // Since 10.0, if strict FP semantics are needed within a function, the
4825097a140dSpatrick // function must have the strictfp attribute and all calls within the function
4826097a140dSpatrick // must also have the strictfp attribute. This latter restriction is
4827097a140dSpatrick // necessary to prevent unwanted libcall simplification when a function is
4828097a140dSpatrick // being cloned (such as for inlining).
4829097a140dSpatrick //
4830097a140dSpatrick // The "dangling" strictfp attribute usage was only used to prevent constant
4831097a140dSpatrick // folding and other libcall simplification. The nobuiltin attribute on the
4832097a140dSpatrick // callsite has the same effect.
4833097a140dSpatrick struct StrictFPUpgradeVisitor : public InstVisitor<StrictFPUpgradeVisitor> {
4834*d415bd75Srobert StrictFPUpgradeVisitor() = default;
4835097a140dSpatrick
visitCallBase__anon29628f320511::StrictFPUpgradeVisitor4836097a140dSpatrick void visitCallBase(CallBase &Call) {
4837097a140dSpatrick if (!Call.isStrictFP())
4838097a140dSpatrick return;
4839097a140dSpatrick if (isa<ConstrainedFPIntrinsic>(&Call))
4840097a140dSpatrick return;
4841097a140dSpatrick // If we get here, the caller doesn't have the strictfp attribute
4842097a140dSpatrick // but this callsite does. Replace the strictfp attribute with nobuiltin.
4843*d415bd75Srobert Call.removeFnAttr(Attribute::StrictFP);
4844*d415bd75Srobert Call.addFnAttr(Attribute::NoBuiltin);
4845097a140dSpatrick }
4846097a140dSpatrick };
4847097a140dSpatrick } // namespace
4848097a140dSpatrick
UpgradeFunctionAttributes(Function & F)4849097a140dSpatrick void llvm::UpgradeFunctionAttributes(Function &F) {
4850097a140dSpatrick // If a function definition doesn't have the strictfp attribute,
4851097a140dSpatrick // convert any callsite strictfp attributes to nobuiltin.
4852097a140dSpatrick if (!F.isDeclaration() && !F.hasFnAttribute(Attribute::StrictFP)) {
4853097a140dSpatrick StrictFPUpgradeVisitor SFPV;
4854097a140dSpatrick SFPV.visit(F);
4855097a140dSpatrick }
485673471bf0Spatrick
485773471bf0Spatrick // Remove all incompatibile attributes from function.
4858*d415bd75Srobert F.removeRetAttrs(AttributeFuncs::typeIncompatible(F.getReturnType()));
485973471bf0Spatrick for (auto &Arg : F.args())
486073471bf0Spatrick Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
4861097a140dSpatrick }
4862097a140dSpatrick
isOldLoopArgument(Metadata * MD)486309467b48Spatrick static bool isOldLoopArgument(Metadata *MD) {
486409467b48Spatrick auto *T = dyn_cast_or_null<MDTuple>(MD);
486509467b48Spatrick if (!T)
486609467b48Spatrick return false;
486709467b48Spatrick if (T->getNumOperands() < 1)
486809467b48Spatrick return false;
486909467b48Spatrick auto *S = dyn_cast_or_null<MDString>(T->getOperand(0));
487009467b48Spatrick if (!S)
487109467b48Spatrick return false;
487209467b48Spatrick return S->getString().startswith("llvm.vectorizer.");
487309467b48Spatrick }
487409467b48Spatrick
upgradeLoopTag(LLVMContext & C,StringRef OldTag)487509467b48Spatrick static MDString *upgradeLoopTag(LLVMContext &C, StringRef OldTag) {
487609467b48Spatrick StringRef OldPrefix = "llvm.vectorizer.";
487709467b48Spatrick assert(OldTag.startswith(OldPrefix) && "Expected old prefix");
487809467b48Spatrick
487909467b48Spatrick if (OldTag == "llvm.vectorizer.unroll")
488009467b48Spatrick return MDString::get(C, "llvm.loop.interleave.count");
488109467b48Spatrick
488209467b48Spatrick return MDString::get(
488309467b48Spatrick C, (Twine("llvm.loop.vectorize.") + OldTag.drop_front(OldPrefix.size()))
488409467b48Spatrick .str());
488509467b48Spatrick }
488609467b48Spatrick
upgradeLoopArgument(Metadata * MD)488709467b48Spatrick static Metadata *upgradeLoopArgument(Metadata *MD) {
488809467b48Spatrick auto *T = dyn_cast_or_null<MDTuple>(MD);
488909467b48Spatrick if (!T)
489009467b48Spatrick return MD;
489109467b48Spatrick if (T->getNumOperands() < 1)
489209467b48Spatrick return MD;
489309467b48Spatrick auto *OldTag = dyn_cast_or_null<MDString>(T->getOperand(0));
489409467b48Spatrick if (!OldTag)
489509467b48Spatrick return MD;
489609467b48Spatrick if (!OldTag->getString().startswith("llvm.vectorizer."))
489709467b48Spatrick return MD;
489809467b48Spatrick
489909467b48Spatrick // This has an old tag. Upgrade it.
490009467b48Spatrick SmallVector<Metadata *, 8> Ops;
490109467b48Spatrick Ops.reserve(T->getNumOperands());
490209467b48Spatrick Ops.push_back(upgradeLoopTag(T->getContext(), OldTag->getString()));
490309467b48Spatrick for (unsigned I = 1, E = T->getNumOperands(); I != E; ++I)
490409467b48Spatrick Ops.push_back(T->getOperand(I));
490509467b48Spatrick
490609467b48Spatrick return MDTuple::get(T->getContext(), Ops);
490709467b48Spatrick }
490809467b48Spatrick
upgradeInstructionLoopAttachment(MDNode & N)490909467b48Spatrick MDNode *llvm::upgradeInstructionLoopAttachment(MDNode &N) {
491009467b48Spatrick auto *T = dyn_cast<MDTuple>(&N);
491109467b48Spatrick if (!T)
491209467b48Spatrick return &N;
491309467b48Spatrick
491409467b48Spatrick if (none_of(T->operands(), isOldLoopArgument))
491509467b48Spatrick return &N;
491609467b48Spatrick
491709467b48Spatrick SmallVector<Metadata *, 8> Ops;
491809467b48Spatrick Ops.reserve(T->getNumOperands());
491909467b48Spatrick for (Metadata *MD : T->operands())
492009467b48Spatrick Ops.push_back(upgradeLoopArgument(MD));
492109467b48Spatrick
492209467b48Spatrick return MDTuple::get(T->getContext(), Ops);
492309467b48Spatrick }
492409467b48Spatrick
UpgradeDataLayoutString(StringRef DL,StringRef TT)492509467b48Spatrick std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) {
492673471bf0Spatrick Triple T(TT);
492773471bf0Spatrick // For AMDGPU we uprgrade older DataLayouts to include the default globals
492873471bf0Spatrick // address space of 1.
492973471bf0Spatrick if (T.isAMDGPU() && !DL.contains("-G") && !DL.startswith("G")) {
493073471bf0Spatrick return DL.empty() ? std::string("G1") : (DL + "-G1").str();
493173471bf0Spatrick }
493209467b48Spatrick
4933*d415bd75Srobert if (T.isRISCV64()) {
4934*d415bd75Srobert // Make i32 a native type for 64-bit RISC-V.
4935*d415bd75Srobert auto I = DL.find("-n64-");
4936*d415bd75Srobert if (I != StringRef::npos)
4937*d415bd75Srobert return (DL.take_front(I) + "-n32:64-" + DL.drop_front(I + 5)).str();
4938*d415bd75Srobert return DL.str();
4939*d415bd75Srobert }
494009467b48Spatrick
4941*d415bd75Srobert std::string Res = DL.str();
4942*d415bd75Srobert if (!T.isX86())
4943*d415bd75Srobert return Res;
4944*d415bd75Srobert
4945*d415bd75Srobert // If the datalayout matches the expected format, add pointer size address
4946*d415bd75Srobert // spaces to the datalayout.
4947*d415bd75Srobert std::string AddrSpaces = "-p270:32:32-p271:32:32-p272:64:64";
4948*d415bd75Srobert if (!DL.contains(AddrSpaces)) {
494909467b48Spatrick SmallVector<StringRef, 4> Groups;
495009467b48Spatrick Regex R("(e-m:[a-z](-p:32:32)?)(-[if]64:.*$)");
4951*d415bd75Srobert if (R.match(DL, &Groups))
4952*d415bd75Srobert Res = (Groups[1] + AddrSpaces + Groups[3]).str();
4953*d415bd75Srobert }
495409467b48Spatrick
4955*d415bd75Srobert // For 32-bit MSVC targets, raise the alignment of f80 values to 16 bytes.
4956*d415bd75Srobert // Raising the alignment is safe because Clang did not produce f80 values in
4957*d415bd75Srobert // the MSVC environment before this upgrade was added.
4958*d415bd75Srobert if (T.isWindowsMSVCEnvironment() && !T.isArch64Bit()) {
4959*d415bd75Srobert StringRef Ref = Res;
4960*d415bd75Srobert auto I = Ref.find("-f80:32-");
4961*d415bd75Srobert if (I != StringRef::npos)
4962*d415bd75Srobert Res = (Ref.take_front(I) + "-f80:128-" + Ref.drop_front(I + 8)).str();
4963*d415bd75Srobert }
4964*d415bd75Srobert
4965*d415bd75Srobert return Res;
496609467b48Spatrick }
496709467b48Spatrick
UpgradeAttributes(AttrBuilder & B)4968097a140dSpatrick void llvm::UpgradeAttributes(AttrBuilder &B) {
496909467b48Spatrick StringRef FramePointer;
4970*d415bd75Srobert Attribute A = B.getAttribute("no-frame-pointer-elim");
4971*d415bd75Srobert if (A.isValid()) {
497209467b48Spatrick // The value can be "true" or "false".
4973*d415bd75Srobert FramePointer = A.getValueAsString() == "true" ? "all" : "none";
497409467b48Spatrick B.removeAttribute("no-frame-pointer-elim");
497509467b48Spatrick }
497609467b48Spatrick if (B.contains("no-frame-pointer-elim-non-leaf")) {
497709467b48Spatrick // The value is ignored. "no-frame-pointer-elim"="true" takes priority.
497809467b48Spatrick if (FramePointer != "all")
497909467b48Spatrick FramePointer = "non-leaf";
498009467b48Spatrick B.removeAttribute("no-frame-pointer-elim-non-leaf");
498109467b48Spatrick }
498209467b48Spatrick if (!FramePointer.empty())
498309467b48Spatrick B.addAttribute("frame-pointer", FramePointer);
4984097a140dSpatrick
4985*d415bd75Srobert A = B.getAttribute("null-pointer-is-valid");
4986*d415bd75Srobert if (A.isValid()) {
4987097a140dSpatrick // The value can be "true" or "false".
4988*d415bd75Srobert bool NullPointerIsValid = A.getValueAsString() == "true";
4989097a140dSpatrick B.removeAttribute("null-pointer-is-valid");
4990097a140dSpatrick if (NullPointerIsValid)
4991097a140dSpatrick B.addAttribute(Attribute::NullPointerIsValid);
4992097a140dSpatrick }
499309467b48Spatrick }
4994*d415bd75Srobert
UpgradeOperandBundles(std::vector<OperandBundleDef> & Bundles)4995*d415bd75Srobert void llvm::UpgradeOperandBundles(std::vector<OperandBundleDef> &Bundles) {
4996*d415bd75Srobert
4997*d415bd75Srobert // clang.arc.attachedcall bundles are now required to have an operand.
4998*d415bd75Srobert // If they don't, it's okay to drop them entirely: when there is an operand,
4999*d415bd75Srobert // the "attachedcall" is meaningful and required, but without an operand,
5000*d415bd75Srobert // it's just a marker NOP. Dropping it merely prevents an optimization.
5001*d415bd75Srobert erase_if(Bundles, [&](OperandBundleDef &OBD) {
5002*d415bd75Srobert return OBD.getTag() == "clang.arc.attachedcall" &&
5003*d415bd75Srobert OBD.inputs().empty();
5004*d415bd75Srobert });
5005*d415bd75Srobert }
5006