10b57cec5SDimitry Andric //===-- AutoUpgrade.cpp - Implement auto-upgrade helper functions ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the auto-upgrade helper functions.
100b57cec5SDimitry Andric // This is where deprecated IR intrinsics and other IR features are updated to
110b57cec5SDimitry Andric // current specifications.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/IR/AutoUpgrade.h"
1606c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1806c3fb27SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
1906c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h"
200b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
210b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
2206c3fb27SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
230b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
240b57cec5SDimitry Andric #include "llvm/IR/Function.h"
250b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
265ffd83dbSDimitry Andric #include "llvm/IR/InstVisitor.h"
27fe6060f1SDimitry Andric #include "llvm/IR/Instruction.h"
280b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
29e8d8bef9SDimitry Andric #include "llvm/IR/Intrinsics.h"
30480093f4SDimitry Andric #include "llvm/IR/IntrinsicsAArch64.h"
31480093f4SDimitry Andric #include "llvm/IR/IntrinsicsARM.h"
3206c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsNVPTX.h"
3306c3fb27SDimitry Andric #include "llvm/IR/IntrinsicsRISCV.h"
341ac55f4cSDimitry Andric #include "llvm/IR/IntrinsicsWebAssembly.h"
35480093f4SDimitry Andric #include "llvm/IR/IntrinsicsX86.h"
360b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
3706c3fb27SDimitry Andric #include "llvm/IR/Metadata.h"
380b57cec5SDimitry Andric #include "llvm/IR/Module.h"
390b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
4006c3fb27SDimitry Andric #include "llvm/Support/CommandLine.h"
410b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
420b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
4306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
440b57cec5SDimitry Andric #include <cstring>
4506c3fb27SDimitry Andric 
460b57cec5SDimitry Andric using namespace llvm;
470b57cec5SDimitry Andric 
4806c3fb27SDimitry Andric static cl::opt<bool>
4906c3fb27SDimitry Andric     DisableAutoUpgradeDebugInfo("disable-auto-upgrade-debug-info",
5006c3fb27SDimitry Andric                                 cl::desc("Disable autoupgrade of debug info"));
5106c3fb27SDimitry Andric 
rename(GlobalValue * GV)520b57cec5SDimitry Andric static void rename(GlobalValue *GV) { GV->setName(GV->getName() + ".old"); }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric // Upgrade the declarations of the SSE4.1 ptest intrinsics whose arguments have
550b57cec5SDimitry Andric // changed their type from v4f32 to v2i64.
upgradePTESTIntrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)567a6dacacSDimitry Andric static bool upgradePTESTIntrinsic(Function *F, Intrinsic::ID IID,
570b57cec5SDimitry Andric                                   Function *&NewFn) {
580b57cec5SDimitry Andric   // Check whether this is an old version of the function, which received
590b57cec5SDimitry Andric   // v4f32 arguments.
600b57cec5SDimitry Andric   Type *Arg0Type = F->getFunctionType()->getParamType(0);
615ffd83dbSDimitry Andric   if (Arg0Type != FixedVectorType::get(Type::getFloatTy(F->getContext()), 4))
620b57cec5SDimitry Andric     return false;
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // Yes, it's old, replace it with new version.
650b57cec5SDimitry Andric   rename(F);
660b57cec5SDimitry Andric   NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
670b57cec5SDimitry Andric   return true;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric // Upgrade the declarations of intrinsic functions whose 8-bit immediate mask
710b57cec5SDimitry Andric // arguments have changed their type from i32 to i8.
upgradeX86IntrinsicsWith8BitMask(Function * F,Intrinsic::ID IID,Function * & NewFn)727a6dacacSDimitry Andric static bool upgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID,
730b57cec5SDimitry Andric                                              Function *&NewFn) {
740b57cec5SDimitry Andric   // Check that the last argument is an i32.
750b57cec5SDimitry Andric   Type *LastArgType = F->getFunctionType()->getParamType(
760b57cec5SDimitry Andric      F->getFunctionType()->getNumParams() - 1);
770b57cec5SDimitry Andric   if (!LastArgType->isIntegerTy(32))
780b57cec5SDimitry Andric     return false;
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // Move this function aside and map down.
810b57cec5SDimitry Andric   rename(F);
820b57cec5SDimitry Andric   NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
830b57cec5SDimitry Andric   return true;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
86e8d8bef9SDimitry Andric // Upgrade the declaration of fp compare intrinsics that change return type
87e8d8bef9SDimitry Andric // from scalar to vXi1 mask.
upgradeX86MaskedFPCompare(Function * F,Intrinsic::ID IID,Function * & NewFn)887a6dacacSDimitry Andric static bool upgradeX86MaskedFPCompare(Function *F, Intrinsic::ID IID,
89e8d8bef9SDimitry Andric                                       Function *&NewFn) {
90e8d8bef9SDimitry Andric   // Check if the return type is a vector.
91e8d8bef9SDimitry Andric   if (F->getReturnType()->isVectorTy())
92e8d8bef9SDimitry Andric     return false;
93e8d8bef9SDimitry Andric 
94e8d8bef9SDimitry Andric   rename(F);
95e8d8bef9SDimitry Andric   NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
96e8d8bef9SDimitry Andric   return true;
97e8d8bef9SDimitry Andric }
98e8d8bef9SDimitry Andric 
upgradeX86BF16Intrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)997a6dacacSDimitry Andric static bool upgradeX86BF16Intrinsic(Function *F, Intrinsic::ID IID,
100bdd1243dSDimitry Andric                                     Function *&NewFn) {
101bdd1243dSDimitry Andric   if (F->getReturnType()->getScalarType()->isBFloatTy())
102bdd1243dSDimitry Andric     return false;
103bdd1243dSDimitry Andric 
104bdd1243dSDimitry Andric   rename(F);
105bdd1243dSDimitry Andric   NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
106bdd1243dSDimitry Andric   return true;
107bdd1243dSDimitry Andric }
108bdd1243dSDimitry Andric 
upgradeX86BF16DPIntrinsic(Function * F,Intrinsic::ID IID,Function * & NewFn)1097a6dacacSDimitry Andric static bool upgradeX86BF16DPIntrinsic(Function *F, Intrinsic::ID IID,
110bdd1243dSDimitry Andric                                       Function *&NewFn) {
111bdd1243dSDimitry Andric   if (F->getFunctionType()->getParamType(1)->getScalarType()->isBFloatTy())
112bdd1243dSDimitry Andric     return false;
113bdd1243dSDimitry Andric 
114bdd1243dSDimitry Andric   rename(F);
115bdd1243dSDimitry Andric   NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
116bdd1243dSDimitry Andric   return true;
117bdd1243dSDimitry Andric }
118bdd1243dSDimitry Andric 
shouldUpgradeX86Intrinsic(Function * F,StringRef Name)1197a6dacacSDimitry Andric static bool shouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
1200b57cec5SDimitry Andric   // All of the intrinsics matches below should be marked with which llvm
1210b57cec5SDimitry Andric   // version started autoupgrading them. At some point in the future we would
1220b57cec5SDimitry Andric   // like to use this information to remove upgrade code for some older
1230b57cec5SDimitry Andric   // intrinsics. It is currently undecided how we will determine that future
1240b57cec5SDimitry Andric   // point.
1255f757f3fSDimitry Andric   if (Name.consume_front("avx."))
1265f757f3fSDimitry Andric     return (Name.starts_with("blend.p") ||        // Added in 3.7
1275f757f3fSDimitry Andric             Name == "cvt.ps2.pd.256" ||           // Added in 3.9
1285f757f3fSDimitry Andric             Name == "cvtdq2.pd.256" ||            // Added in 3.9
1295f757f3fSDimitry Andric             Name == "cvtdq2.ps.256" ||            // Added in 7.0
1305f757f3fSDimitry Andric             Name.starts_with("movnt.") ||         // Added in 3.2
1315f757f3fSDimitry Andric             Name.starts_with("sqrt.p") ||         // Added in 7.0
1325f757f3fSDimitry Andric             Name.starts_with("storeu.") ||        // Added in 3.9
1335f757f3fSDimitry Andric             Name.starts_with("vbroadcast.s") ||   // Added in 3.5
1345f757f3fSDimitry Andric             Name.starts_with("vbroadcastf128") || // Added in 4.0
1355f757f3fSDimitry Andric             Name.starts_with("vextractf128.") ||  // Added in 3.7
1365f757f3fSDimitry Andric             Name.starts_with("vinsertf128.") ||   // Added in 3.7
1375f757f3fSDimitry Andric             Name.starts_with("vperm2f128.") ||    // Added in 6.0
1385f757f3fSDimitry Andric             Name.starts_with("vpermil."));        // Added in 3.1
1395f757f3fSDimitry Andric 
1405f757f3fSDimitry Andric   if (Name.consume_front("avx2."))
1415f757f3fSDimitry Andric     return (Name == "movntdqa" ||             // Added in 5.0
1425f757f3fSDimitry Andric             Name.starts_with("pabs.") ||      // Added in 6.0
1435f757f3fSDimitry Andric             Name.starts_with("padds.") ||     // Added in 8.0
1445f757f3fSDimitry Andric             Name.starts_with("paddus.") ||    // Added in 8.0
1455f757f3fSDimitry Andric             Name.starts_with("pblendd.") ||   // Added in 3.7
1465f757f3fSDimitry Andric             Name == "pblendw" ||              // Added in 3.7
1475f757f3fSDimitry Andric             Name.starts_with("pbroadcast") || // Added in 3.8
1485f757f3fSDimitry Andric             Name.starts_with("pcmpeq.") ||    // Added in 3.1
1495f757f3fSDimitry Andric             Name.starts_with("pcmpgt.") ||    // Added in 3.1
1505f757f3fSDimitry Andric             Name.starts_with("pmax") ||       // Added in 3.9
1515f757f3fSDimitry Andric             Name.starts_with("pmin") ||       // Added in 3.9
1525f757f3fSDimitry Andric             Name.starts_with("pmovsx") ||     // Added in 3.9
1535f757f3fSDimitry Andric             Name.starts_with("pmovzx") ||     // Added in 3.9
1545f757f3fSDimitry Andric             Name == "pmul.dq" ||              // Added in 7.0
1555f757f3fSDimitry Andric             Name == "pmulu.dq" ||             // Added in 7.0
1565f757f3fSDimitry Andric             Name.starts_with("psll.dq") ||    // Added in 3.7
1575f757f3fSDimitry Andric             Name.starts_with("psrl.dq") ||    // Added in 3.7
1585f757f3fSDimitry Andric             Name.starts_with("psubs.") ||     // Added in 8.0
1595f757f3fSDimitry Andric             Name.starts_with("psubus.") ||    // Added in 8.0
1605f757f3fSDimitry Andric             Name.starts_with("vbroadcast") || // Added in 3.8
1615f757f3fSDimitry Andric             Name == "vbroadcasti128" ||       // Added in 3.7
1625f757f3fSDimitry Andric             Name == "vextracti128" ||         // Added in 3.7
1635f757f3fSDimitry Andric             Name == "vinserti128" ||          // Added in 3.7
1645f757f3fSDimitry Andric             Name == "vperm2i128");            // Added in 6.0
1655f757f3fSDimitry Andric 
1665f757f3fSDimitry Andric   if (Name.consume_front("avx512.")) {
1675f757f3fSDimitry Andric     if (Name.consume_front("mask."))
1685f757f3fSDimitry Andric       // 'avx512.mask.*'
1695f757f3fSDimitry Andric       return (Name.starts_with("add.p") ||       // Added in 7.0. 128/256 in 4.0
1705f757f3fSDimitry Andric               Name.starts_with("and.") ||        // Added in 3.9
1715f757f3fSDimitry Andric               Name.starts_with("andn.") ||       // Added in 3.9
1725f757f3fSDimitry Andric               Name.starts_with("broadcast.s") || // Added in 3.9
1735f757f3fSDimitry Andric               Name.starts_with("broadcastf32x4.") || // Added in 6.0
1745f757f3fSDimitry Andric               Name.starts_with("broadcastf32x8.") || // Added in 6.0
1755f757f3fSDimitry Andric               Name.starts_with("broadcastf64x2.") || // Added in 6.0
1765f757f3fSDimitry Andric               Name.starts_with("broadcastf64x4.") || // Added in 6.0
1775f757f3fSDimitry Andric               Name.starts_with("broadcasti32x4.") || // Added in 6.0
1785f757f3fSDimitry Andric               Name.starts_with("broadcasti32x8.") || // Added in 6.0
1795f757f3fSDimitry Andric               Name.starts_with("broadcasti64x2.") || // Added in 6.0
1805f757f3fSDimitry Andric               Name.starts_with("broadcasti64x4.") || // Added in 6.0
1815f757f3fSDimitry Andric               Name.starts_with("cmp.b") ||           // Added in 5.0
1825f757f3fSDimitry Andric               Name.starts_with("cmp.d") ||           // Added in 5.0
1835f757f3fSDimitry Andric               Name.starts_with("cmp.q") ||           // Added in 5.0
1845f757f3fSDimitry Andric               Name.starts_with("cmp.w") ||           // Added in 5.0
1855f757f3fSDimitry Andric               Name.starts_with("compress.b") ||      // Added in 9.0
1865f757f3fSDimitry Andric               Name.starts_with("compress.d") ||      // Added in 9.0
1875f757f3fSDimitry Andric               Name.starts_with("compress.p") ||      // Added in 9.0
1885f757f3fSDimitry Andric               Name.starts_with("compress.q") ||      // Added in 9.0
1895f757f3fSDimitry Andric               Name.starts_with("compress.store.") || // Added in 7.0
1905f757f3fSDimitry Andric               Name.starts_with("compress.w") ||      // Added in 9.0
1915f757f3fSDimitry Andric               Name.starts_with("conflict.") ||       // Added in 9.0
1925f757f3fSDimitry Andric               Name.starts_with("cvtdq2pd.") ||       // Added in 4.0
1935f757f3fSDimitry Andric               Name.starts_with("cvtdq2ps.") ||       // Added in 7.0 updated 9.0
1945f757f3fSDimitry Andric               Name == "cvtpd2dq.256" ||              // Added in 7.0
1955f757f3fSDimitry Andric               Name == "cvtpd2ps.256" ||              // Added in 7.0
1965f757f3fSDimitry Andric               Name == "cvtps2pd.128" ||              // Added in 7.0
1975f757f3fSDimitry Andric               Name == "cvtps2pd.256" ||              // Added in 7.0
1985f757f3fSDimitry Andric               Name.starts_with("cvtqq2pd.") ||       // Added in 7.0 updated 9.0
1995f757f3fSDimitry Andric               Name == "cvtqq2ps.256" ||              // Added in 9.0
2005f757f3fSDimitry Andric               Name == "cvtqq2ps.512" ||              // Added in 9.0
2015f757f3fSDimitry Andric               Name == "cvttpd2dq.256" ||             // Added in 7.0
2025f757f3fSDimitry Andric               Name == "cvttps2dq.128" ||             // Added in 7.0
2035f757f3fSDimitry Andric               Name == "cvttps2dq.256" ||             // Added in 7.0
2045f757f3fSDimitry Andric               Name.starts_with("cvtudq2pd.") ||      // Added in 4.0
2055f757f3fSDimitry Andric               Name.starts_with("cvtudq2ps.") ||      // Added in 7.0 updated 9.0
2065f757f3fSDimitry Andric               Name.starts_with("cvtuqq2pd.") ||      // Added in 7.0 updated 9.0
2075f757f3fSDimitry Andric               Name == "cvtuqq2ps.256" ||             // Added in 9.0
2085f757f3fSDimitry Andric               Name == "cvtuqq2ps.512" ||             // Added in 9.0
2095f757f3fSDimitry Andric               Name.starts_with("dbpsadbw.") ||       // Added in 7.0
2105f757f3fSDimitry Andric               Name.starts_with("div.p") ||    // Added in 7.0. 128/256 in 4.0
2115f757f3fSDimitry Andric               Name.starts_with("expand.b") || // Added in 9.0
2125f757f3fSDimitry Andric               Name.starts_with("expand.d") || // Added in 9.0
2135f757f3fSDimitry Andric               Name.starts_with("expand.load.") || // Added in 7.0
2145f757f3fSDimitry Andric               Name.starts_with("expand.p") ||     // Added in 9.0
2155f757f3fSDimitry Andric               Name.starts_with("expand.q") ||     // Added in 9.0
2165f757f3fSDimitry Andric               Name.starts_with("expand.w") ||     // Added in 9.0
2175f757f3fSDimitry Andric               Name.starts_with("fpclass.p") ||    // Added in 7.0
2185f757f3fSDimitry Andric               Name.starts_with("insert") ||       // Added in 4.0
2195f757f3fSDimitry Andric               Name.starts_with("load.") ||        // Added in 3.9
2205f757f3fSDimitry Andric               Name.starts_with("loadu.") ||       // Added in 3.9
2215f757f3fSDimitry Andric               Name.starts_with("lzcnt.") ||       // Added in 5.0
2225f757f3fSDimitry Andric               Name.starts_with("max.p") ||       // Added in 7.0. 128/256 in 5.0
2235f757f3fSDimitry Andric               Name.starts_with("min.p") ||       // Added in 7.0. 128/256 in 5.0
2245f757f3fSDimitry Andric               Name.starts_with("movddup") ||     // Added in 3.9
2255f757f3fSDimitry Andric               Name.starts_with("move.s") ||      // Added in 4.0
2265f757f3fSDimitry Andric               Name.starts_with("movshdup") ||    // Added in 3.9
2275f757f3fSDimitry Andric               Name.starts_with("movsldup") ||    // Added in 3.9
2285f757f3fSDimitry Andric               Name.starts_with("mul.p") ||       // Added in 7.0. 128/256 in 4.0
2295f757f3fSDimitry Andric               Name.starts_with("or.") ||         // Added in 3.9
2305f757f3fSDimitry Andric               Name.starts_with("pabs.") ||       // Added in 6.0
2315f757f3fSDimitry Andric               Name.starts_with("packssdw.") ||   // Added in 5.0
2325f757f3fSDimitry Andric               Name.starts_with("packsswb.") ||   // Added in 5.0
2335f757f3fSDimitry Andric               Name.starts_with("packusdw.") ||   // Added in 5.0
2345f757f3fSDimitry Andric               Name.starts_with("packuswb.") ||   // Added in 5.0
2355f757f3fSDimitry Andric               Name.starts_with("padd.") ||       // Added in 4.0
2365f757f3fSDimitry Andric               Name.starts_with("padds.") ||      // Added in 8.0
2375f757f3fSDimitry Andric               Name.starts_with("paddus.") ||     // Added in 8.0
2385f757f3fSDimitry Andric               Name.starts_with("palignr.") ||    // Added in 3.9
2395f757f3fSDimitry Andric               Name.starts_with("pand.") ||       // Added in 3.9
2405f757f3fSDimitry Andric               Name.starts_with("pandn.") ||      // Added in 3.9
2415f757f3fSDimitry Andric               Name.starts_with("pavg") ||        // Added in 6.0
2425f757f3fSDimitry Andric               Name.starts_with("pbroadcast") ||  // Added in 6.0
2435f757f3fSDimitry Andric               Name.starts_with("pcmpeq.") ||     // Added in 3.9
2445f757f3fSDimitry Andric               Name.starts_with("pcmpgt.") ||     // Added in 3.9
2455f757f3fSDimitry Andric               Name.starts_with("perm.df.") ||    // Added in 3.9
2465f757f3fSDimitry Andric               Name.starts_with("perm.di.") ||    // Added in 3.9
2475f757f3fSDimitry Andric               Name.starts_with("permvar.") ||    // Added in 7.0
2485f757f3fSDimitry Andric               Name.starts_with("pmaddubs.w.") || // Added in 7.0
2495f757f3fSDimitry Andric               Name.starts_with("pmaddw.d.") ||   // Added in 7.0
2505f757f3fSDimitry Andric               Name.starts_with("pmax") ||        // Added in 4.0
2515f757f3fSDimitry Andric               Name.starts_with("pmin") ||        // Added in 4.0
2525f757f3fSDimitry Andric               Name == "pmov.qd.256" ||           // Added in 9.0
2535f757f3fSDimitry Andric               Name == "pmov.qd.512" ||           // Added in 9.0
2545f757f3fSDimitry Andric               Name == "pmov.wb.256" ||           // Added in 9.0
2555f757f3fSDimitry Andric               Name == "pmov.wb.512" ||           // Added in 9.0
2565f757f3fSDimitry Andric               Name.starts_with("pmovsx") ||      // Added in 4.0
2575f757f3fSDimitry Andric               Name.starts_with("pmovzx") ||      // Added in 4.0
2585f757f3fSDimitry Andric               Name.starts_with("pmul.dq.") ||    // Added in 4.0
2595f757f3fSDimitry Andric               Name.starts_with("pmul.hr.sw.") || // Added in 7.0
2605f757f3fSDimitry Andric               Name.starts_with("pmulh.w.") ||    // Added in 7.0
2615f757f3fSDimitry Andric               Name.starts_with("pmulhu.w.") ||   // Added in 7.0
2625f757f3fSDimitry Andric               Name.starts_with("pmull.") ||      // Added in 4.0
2635f757f3fSDimitry Andric               Name.starts_with("pmultishift.qb.") || // Added in 8.0
2645f757f3fSDimitry Andric               Name.starts_with("pmulu.dq.") ||       // Added in 4.0
2655f757f3fSDimitry Andric               Name.starts_with("por.") ||            // Added in 3.9
2665f757f3fSDimitry Andric               Name.starts_with("prol.") ||           // Added in 8.0
2675f757f3fSDimitry Andric               Name.starts_with("prolv.") ||          // Added in 8.0
2685f757f3fSDimitry Andric               Name.starts_with("pror.") ||           // Added in 8.0
2695f757f3fSDimitry Andric               Name.starts_with("prorv.") ||          // Added in 8.0
2705f757f3fSDimitry Andric               Name.starts_with("pshuf.b.") ||        // Added in 4.0
2715f757f3fSDimitry Andric               Name.starts_with("pshuf.d.") ||        // Added in 3.9
2725f757f3fSDimitry Andric               Name.starts_with("pshufh.w.") ||       // Added in 3.9
2735f757f3fSDimitry Andric               Name.starts_with("pshufl.w.") ||       // Added in 3.9
2745f757f3fSDimitry Andric               Name.starts_with("psll.d") ||          // Added in 4.0
2755f757f3fSDimitry Andric               Name.starts_with("psll.q") ||          // Added in 4.0
2765f757f3fSDimitry Andric               Name.starts_with("psll.w") ||          // Added in 4.0
2775f757f3fSDimitry Andric               Name.starts_with("pslli") ||           // Added in 4.0
2785f757f3fSDimitry Andric               Name.starts_with("psllv") ||           // Added in 4.0
2795f757f3fSDimitry Andric               Name.starts_with("psra.d") ||          // Added in 4.0
2805f757f3fSDimitry Andric               Name.starts_with("psra.q") ||          // Added in 4.0
2815f757f3fSDimitry Andric               Name.starts_with("psra.w") ||          // Added in 4.0
2825f757f3fSDimitry Andric               Name.starts_with("psrai") ||           // Added in 4.0
2835f757f3fSDimitry Andric               Name.starts_with("psrav") ||           // Added in 4.0
2845f757f3fSDimitry Andric               Name.starts_with("psrl.d") ||          // Added in 4.0
2855f757f3fSDimitry Andric               Name.starts_with("psrl.q") ||          // Added in 4.0
2865f757f3fSDimitry Andric               Name.starts_with("psrl.w") ||          // Added in 4.0
2875f757f3fSDimitry Andric               Name.starts_with("psrli") ||           // Added in 4.0
2885f757f3fSDimitry Andric               Name.starts_with("psrlv") ||           // Added in 4.0
2895f757f3fSDimitry Andric               Name.starts_with("psub.") ||           // Added in 4.0
2905f757f3fSDimitry Andric               Name.starts_with("psubs.") ||          // Added in 8.0
2915f757f3fSDimitry Andric               Name.starts_with("psubus.") ||         // Added in 8.0
2925f757f3fSDimitry Andric               Name.starts_with("pternlog.") ||       // Added in 7.0
2935f757f3fSDimitry Andric               Name.starts_with("punpckh") ||         // Added in 3.9
2945f757f3fSDimitry Andric               Name.starts_with("punpckl") ||         // Added in 3.9
2955f757f3fSDimitry Andric               Name.starts_with("pxor.") ||           // Added in 3.9
2965f757f3fSDimitry Andric               Name.starts_with("shuf.f") ||          // Added in 6.0
2975f757f3fSDimitry Andric               Name.starts_with("shuf.i") ||          // Added in 6.0
2985f757f3fSDimitry Andric               Name.starts_with("shuf.p") ||          // Added in 4.0
2995f757f3fSDimitry Andric               Name.starts_with("sqrt.p") ||          // Added in 7.0
3005f757f3fSDimitry Andric               Name.starts_with("store.b.") ||        // Added in 3.9
3015f757f3fSDimitry Andric               Name.starts_with("store.d.") ||        // Added in 3.9
3025f757f3fSDimitry Andric               Name.starts_with("store.p") ||         // Added in 3.9
3035f757f3fSDimitry Andric               Name.starts_with("store.q.") ||        // Added in 3.9
3045f757f3fSDimitry Andric               Name.starts_with("store.w.") ||        // Added in 3.9
3055f757f3fSDimitry Andric               Name == "store.ss" ||                  // Added in 7.0
3065f757f3fSDimitry Andric               Name.starts_with("storeu.") ||         // Added in 3.9
3075f757f3fSDimitry Andric               Name.starts_with("sub.p") ||       // Added in 7.0. 128/256 in 4.0
3085f757f3fSDimitry Andric               Name.starts_with("ucmp.") ||       // Added in 5.0
3095f757f3fSDimitry Andric               Name.starts_with("unpckh.") ||     // Added in 3.9
3105f757f3fSDimitry Andric               Name.starts_with("unpckl.") ||     // Added in 3.9
3115f757f3fSDimitry Andric               Name.starts_with("valign.") ||     // Added in 4.0
3125f757f3fSDimitry Andric               Name == "vcvtph2ps.128" ||         // Added in 11.0
3135f757f3fSDimitry Andric               Name == "vcvtph2ps.256" ||         // Added in 11.0
3145f757f3fSDimitry Andric               Name.starts_with("vextract") ||    // Added in 4.0
3155f757f3fSDimitry Andric               Name.starts_with("vfmadd.") ||     // Added in 7.0
3165f757f3fSDimitry Andric               Name.starts_with("vfmaddsub.") ||  // Added in 7.0
3175f757f3fSDimitry Andric               Name.starts_with("vfnmadd.") ||    // Added in 7.0
3185f757f3fSDimitry Andric               Name.starts_with("vfnmsub.") ||    // Added in 7.0
3195f757f3fSDimitry Andric               Name.starts_with("vpdpbusd.") ||   // Added in 7.0
3205f757f3fSDimitry Andric               Name.starts_with("vpdpbusds.") ||  // Added in 7.0
3215f757f3fSDimitry Andric               Name.starts_with("vpdpwssd.") ||   // Added in 7.0
3225f757f3fSDimitry Andric               Name.starts_with("vpdpwssds.") ||  // Added in 7.0
3235f757f3fSDimitry Andric               Name.starts_with("vpermi2var.") || // Added in 7.0
3245f757f3fSDimitry Andric               Name.starts_with("vpermil.p") ||   // Added in 3.9
3255f757f3fSDimitry Andric               Name.starts_with("vpermilvar.") || // Added in 4.0
3265f757f3fSDimitry Andric               Name.starts_with("vpermt2var.") || // Added in 7.0
3275f757f3fSDimitry Andric               Name.starts_with("vpmadd52") ||    // Added in 7.0
3285f757f3fSDimitry Andric               Name.starts_with("vpshld.") ||     // Added in 7.0
3295f757f3fSDimitry Andric               Name.starts_with("vpshldv.") ||    // Added in 8.0
3305f757f3fSDimitry Andric               Name.starts_with("vpshrd.") ||     // Added in 7.0
3315f757f3fSDimitry Andric               Name.starts_with("vpshrdv.") ||    // Added in 8.0
3325f757f3fSDimitry Andric               Name.starts_with("vpshufbitqmb.") || // Added in 8.0
3335f757f3fSDimitry Andric               Name.starts_with("xor."));           // Added in 3.9
3345f757f3fSDimitry Andric 
3355f757f3fSDimitry Andric     if (Name.consume_front("mask3."))
3365f757f3fSDimitry Andric       // 'avx512.mask3.*'
3375f757f3fSDimitry Andric       return (Name.starts_with("vfmadd.") ||    // Added in 7.0
3385f757f3fSDimitry Andric               Name.starts_with("vfmaddsub.") || // Added in 7.0
3395f757f3fSDimitry Andric               Name.starts_with("vfmsub.") ||    // Added in 7.0
3405f757f3fSDimitry Andric               Name.starts_with("vfmsubadd.") || // Added in 7.0
3415f757f3fSDimitry Andric               Name.starts_with("vfnmsub."));    // Added in 7.0
3425f757f3fSDimitry Andric 
3435f757f3fSDimitry Andric     if (Name.consume_front("maskz."))
3445f757f3fSDimitry Andric       // 'avx512.maskz.*'
3455f757f3fSDimitry Andric       return (Name.starts_with("pternlog.") ||   // Added in 7.0
3465f757f3fSDimitry Andric               Name.starts_with("vfmadd.") ||     // Added in 7.0
3475f757f3fSDimitry Andric               Name.starts_with("vfmaddsub.") ||  // Added in 7.0
3485f757f3fSDimitry Andric               Name.starts_with("vpdpbusd.") ||   // Added in 7.0
3495f757f3fSDimitry Andric               Name.starts_with("vpdpbusds.") ||  // Added in 7.0
3505f757f3fSDimitry Andric               Name.starts_with("vpdpwssd.") ||   // Added in 7.0
3515f757f3fSDimitry Andric               Name.starts_with("vpdpwssds.") ||  // Added in 7.0
3525f757f3fSDimitry Andric               Name.starts_with("vpermt2var.") || // Added in 7.0
3535f757f3fSDimitry Andric               Name.starts_with("vpmadd52") ||    // Added in 7.0
3545f757f3fSDimitry Andric               Name.starts_with("vpshldv.") ||    // Added in 8.0
3555f757f3fSDimitry Andric               Name.starts_with("vpshrdv."));     // Added in 8.0
3565f757f3fSDimitry Andric 
3575f757f3fSDimitry Andric     // 'avx512.*'
3585f757f3fSDimitry Andric     return (Name == "movntdqa" ||               // Added in 5.0
3595f757f3fSDimitry Andric             Name == "pmul.dq.512" ||            // Added in 7.0
3605f757f3fSDimitry Andric             Name == "pmulu.dq.512" ||           // Added in 7.0
3615f757f3fSDimitry Andric             Name.starts_with("broadcastm") ||   // Added in 6.0
3625f757f3fSDimitry Andric             Name.starts_with("cmp.p") ||        // Added in 12.0
3635f757f3fSDimitry Andric             Name.starts_with("cvtb2mask.") ||   // Added in 7.0
3645f757f3fSDimitry Andric             Name.starts_with("cvtd2mask.") ||   // Added in 7.0
3655f757f3fSDimitry Andric             Name.starts_with("cvtmask2") ||     // Added in 5.0
3665f757f3fSDimitry Andric             Name.starts_with("cvtq2mask.") ||   // Added in 7.0
3675f757f3fSDimitry Andric             Name == "cvtusi2sd" ||              // Added in 7.0
3685f757f3fSDimitry Andric             Name.starts_with("cvtw2mask.") ||   // Added in 7.0
3695f757f3fSDimitry Andric             Name == "kand.w" ||                 // Added in 7.0
3705f757f3fSDimitry Andric             Name == "kandn.w" ||                // Added in 7.0
3715f757f3fSDimitry Andric             Name == "knot.w" ||                 // Added in 7.0
3725f757f3fSDimitry Andric             Name == "kor.w" ||                  // Added in 7.0
3735f757f3fSDimitry Andric             Name == "kortestc.w" ||             // Added in 7.0
3745f757f3fSDimitry Andric             Name == "kortestz.w" ||             // Added in 7.0
3755f757f3fSDimitry Andric             Name.starts_with("kunpck") ||       // added in 6.0
3765f757f3fSDimitry Andric             Name == "kxnor.w" ||                // Added in 7.0
3775f757f3fSDimitry Andric             Name == "kxor.w" ||                 // Added in 7.0
3785f757f3fSDimitry Andric             Name.starts_with("padds.") ||       // Added in 8.0
3795f757f3fSDimitry Andric             Name.starts_with("pbroadcast") ||   // Added in 3.9
3805f757f3fSDimitry Andric             Name.starts_with("prol") ||         // Added in 8.0
3815f757f3fSDimitry Andric             Name.starts_with("pror") ||         // Added in 8.0
3825f757f3fSDimitry Andric             Name.starts_with("psll.dq") ||      // Added in 3.9
3835f757f3fSDimitry Andric             Name.starts_with("psrl.dq") ||      // Added in 3.9
3845f757f3fSDimitry Andric             Name.starts_with("psubs.") ||       // Added in 8.0
3855f757f3fSDimitry Andric             Name.starts_with("ptestm") ||       // Added in 6.0
3865f757f3fSDimitry Andric             Name.starts_with("ptestnm") ||      // Added in 6.0
3875f757f3fSDimitry Andric             Name.starts_with("storent.") ||     // Added in 3.9
3885f757f3fSDimitry Andric             Name.starts_with("vbroadcast.s") || // Added in 7.0
3895f757f3fSDimitry Andric             Name.starts_with("vpshld.") ||      // Added in 8.0
3905f757f3fSDimitry Andric             Name.starts_with("vpshrd."));       // Added in 8.0
3915f757f3fSDimitry Andric   }
3925f757f3fSDimitry Andric 
3935f757f3fSDimitry Andric   if (Name.consume_front("fma."))
3945f757f3fSDimitry Andric     return (Name.starts_with("vfmadd.") ||    // Added in 7.0
3955f757f3fSDimitry Andric             Name.starts_with("vfmsub.") ||    // Added in 7.0
3965f757f3fSDimitry Andric             Name.starts_with("vfmsubadd.") || // Added in 7.0
3975f757f3fSDimitry Andric             Name.starts_with("vfnmadd.") ||   // Added in 7.0
3985f757f3fSDimitry Andric             Name.starts_with("vfnmsub."));    // Added in 7.0
3995f757f3fSDimitry Andric 
4005f757f3fSDimitry Andric   if (Name.consume_front("fma4."))
4015f757f3fSDimitry Andric     return Name.starts_with("vfmadd.s"); // Added in 7.0
4025f757f3fSDimitry Andric 
4035f757f3fSDimitry Andric   if (Name.consume_front("sse."))
4045f757f3fSDimitry Andric     return (Name == "add.ss" ||            // Added in 4.0
4055f757f3fSDimitry Andric             Name == "cvtsi2ss" ||          // Added in 7.0
4065f757f3fSDimitry Andric             Name == "cvtsi642ss" ||        // Added in 7.0
4075f757f3fSDimitry Andric             Name == "div.ss" ||            // Added in 4.0
4085f757f3fSDimitry Andric             Name == "mul.ss" ||            // Added in 4.0
4095f757f3fSDimitry Andric             Name.starts_with("sqrt.p") ||  // Added in 7.0
4105f757f3fSDimitry Andric             Name == "sqrt.ss" ||           // Added in 7.0
4115f757f3fSDimitry Andric             Name.starts_with("storeu.") || // Added in 3.9
4125f757f3fSDimitry Andric             Name == "sub.ss");             // Added in 4.0
4135f757f3fSDimitry Andric 
4145f757f3fSDimitry Andric   if (Name.consume_front("sse2."))
4155f757f3fSDimitry Andric     return (Name == "add.sd" ||            // Added in 4.0
4165f757f3fSDimitry Andric             Name == "cvtdq2pd" ||          // Added in 3.9
4175f757f3fSDimitry Andric             Name == "cvtdq2ps" ||          // Added in 7.0
4185f757f3fSDimitry Andric             Name == "cvtps2pd" ||          // Added in 3.9
4195f757f3fSDimitry Andric             Name == "cvtsi2sd" ||          // Added in 7.0
4205f757f3fSDimitry Andric             Name == "cvtsi642sd" ||        // Added in 7.0
4215f757f3fSDimitry Andric             Name == "cvtss2sd" ||          // Added in 7.0
4225f757f3fSDimitry Andric             Name == "div.sd" ||            // Added in 4.0
4235f757f3fSDimitry Andric             Name == "mul.sd" ||            // Added in 4.0
4245f757f3fSDimitry Andric             Name.starts_with("padds.") ||  // Added in 8.0
4255f757f3fSDimitry Andric             Name.starts_with("paddus.") || // Added in 8.0
4265f757f3fSDimitry Andric             Name.starts_with("pcmpeq.") || // Added in 3.1
4275f757f3fSDimitry Andric             Name.starts_with("pcmpgt.") || // Added in 3.1
4285f757f3fSDimitry Andric             Name == "pmaxs.w" ||           // Added in 3.9
4295f757f3fSDimitry Andric             Name == "pmaxu.b" ||           // Added in 3.9
4305f757f3fSDimitry Andric             Name == "pmins.w" ||           // Added in 3.9
4315f757f3fSDimitry Andric             Name == "pminu.b" ||           // Added in 3.9
4325f757f3fSDimitry Andric             Name == "pmulu.dq" ||          // Added in 7.0
4335f757f3fSDimitry Andric             Name.starts_with("pshuf") ||   // Added in 3.9
4345f757f3fSDimitry Andric             Name.starts_with("psll.dq") || // Added in 3.7
4355f757f3fSDimitry Andric             Name.starts_with("psrl.dq") || // Added in 3.7
4365f757f3fSDimitry Andric             Name.starts_with("psubs.") ||  // Added in 8.0
4375f757f3fSDimitry Andric             Name.starts_with("psubus.") || // Added in 8.0
4385f757f3fSDimitry Andric             Name.starts_with("sqrt.p") ||  // Added in 7.0
4395f757f3fSDimitry Andric             Name == "sqrt.sd" ||           // Added in 7.0
4405f757f3fSDimitry Andric             Name == "storel.dq" ||         // Added in 3.9
4415f757f3fSDimitry Andric             Name.starts_with("storeu.") || // Added in 3.9
4425f757f3fSDimitry Andric             Name == "sub.sd");             // Added in 4.0
4435f757f3fSDimitry Andric 
4445f757f3fSDimitry Andric   if (Name.consume_front("sse41."))
4455f757f3fSDimitry Andric     return (Name.starts_with("blendp") || // Added in 3.7
4465f757f3fSDimitry Andric             Name == "movntdqa" ||         // Added in 5.0
4475f757f3fSDimitry Andric             Name == "pblendw" ||          // Added in 3.7
4485f757f3fSDimitry Andric             Name == "pmaxsb" ||           // Added in 3.9
4495f757f3fSDimitry Andric             Name == "pmaxsd" ||           // Added in 3.9
4505f757f3fSDimitry Andric             Name == "pmaxud" ||           // Added in 3.9
4515f757f3fSDimitry Andric             Name == "pmaxuw" ||           // Added in 3.9
4525f757f3fSDimitry Andric             Name == "pminsb" ||           // Added in 3.9
4535f757f3fSDimitry Andric             Name == "pminsd" ||           // Added in 3.9
4545f757f3fSDimitry Andric             Name == "pminud" ||           // Added in 3.9
4555f757f3fSDimitry Andric             Name == "pminuw" ||           // Added in 3.9
4565f757f3fSDimitry Andric             Name.starts_with("pmovsx") || // Added in 3.8
4575f757f3fSDimitry Andric             Name.starts_with("pmovzx") || // Added in 3.9
4585f757f3fSDimitry Andric             Name == "pmuldq");            // Added in 7.0
4595f757f3fSDimitry Andric 
4605f757f3fSDimitry Andric   if (Name.consume_front("sse42."))
4615f757f3fSDimitry Andric     return Name == "crc32.64.8"; // Added in 3.4
4625f757f3fSDimitry Andric 
4635f757f3fSDimitry Andric   if (Name.consume_front("sse4a."))
4645f757f3fSDimitry Andric     return Name.starts_with("movnt."); // Added in 3.9
4655f757f3fSDimitry Andric 
4665f757f3fSDimitry Andric   if (Name.consume_front("ssse3."))
4675f757f3fSDimitry Andric     return (Name == "pabs.b.128" || // Added in 6.0
4685f757f3fSDimitry Andric             Name == "pabs.d.128" || // Added in 6.0
4695f757f3fSDimitry Andric             Name == "pabs.w.128");  // Added in 6.0
4705f757f3fSDimitry Andric 
4715f757f3fSDimitry Andric   if (Name.consume_front("xop."))
4725f757f3fSDimitry Andric     return (Name == "vpcmov" ||          // Added in 3.8
4735f757f3fSDimitry Andric             Name == "vpcmov.256" ||      // Added in 5.0
4745f757f3fSDimitry Andric             Name.starts_with("vpcom") || // Added in 3.2, Updated in 9.0
4755f757f3fSDimitry Andric             Name.starts_with("vprot"));  // Added in 8.0
4765f757f3fSDimitry Andric 
4775f757f3fSDimitry Andric   return (Name == "addcarry.u32" ||        // Added in 8.0
4780b57cec5SDimitry Andric           Name == "addcarry.u64" ||        // Added in 8.0
4795f757f3fSDimitry Andric           Name == "addcarryx.u32" ||       // Added in 8.0
4805f757f3fSDimitry Andric           Name == "addcarryx.u64" ||       // Added in 8.0
4810b57cec5SDimitry Andric           Name == "subborrow.u32" ||       // Added in 8.0
4820b57cec5SDimitry Andric           Name == "subborrow.u64" ||       // Added in 8.0
4835f757f3fSDimitry Andric           Name.starts_with("vcvtph2ps.")); // Added in 11.0
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
upgradeX86IntrinsicFunction(Function * F,StringRef Name,Function * & NewFn)4867a6dacacSDimitry Andric static bool upgradeX86IntrinsicFunction(Function *F, StringRef Name,
4870b57cec5SDimitry Andric                                         Function *&NewFn) {
4880b57cec5SDimitry Andric   // Only handle intrinsics that start with "x86.".
4895f757f3fSDimitry Andric   if (!Name.consume_front("x86."))
4900b57cec5SDimitry Andric     return false;
4910b57cec5SDimitry Andric 
4927a6dacacSDimitry Andric   if (shouldUpgradeX86Intrinsic(F, Name)) {
4930b57cec5SDimitry Andric     NewFn = nullptr;
4940b57cec5SDimitry Andric     return true;
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   if (Name == "rdtscp") { // Added in 8.0
4980b57cec5SDimitry Andric     // If this intrinsic has 0 operands, it's the new version.
4990b57cec5SDimitry Andric     if (F->getFunctionType()->getNumParams() == 0)
5000b57cec5SDimitry Andric       return false;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric     rename(F);
5030b57cec5SDimitry Andric     NewFn = Intrinsic::getDeclaration(F->getParent(),
5040b57cec5SDimitry Andric                                       Intrinsic::x86_rdtscp);
5050b57cec5SDimitry Andric     return true;
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5085f757f3fSDimitry Andric   Intrinsic::ID ID;
5095f757f3fSDimitry Andric 
5100b57cec5SDimitry Andric   // SSE4.1 ptest functions may have an old signature.
5115f757f3fSDimitry Andric   if (Name.consume_front("sse41.ptest")) { // Added in 3.2
5125f757f3fSDimitry Andric     ID = StringSwitch<Intrinsic::ID>(Name)
5135f757f3fSDimitry Andric              .Case("c", Intrinsic::x86_sse41_ptestc)
5145f757f3fSDimitry Andric              .Case("z", Intrinsic::x86_sse41_ptestz)
5155f757f3fSDimitry Andric              .Case("nzc", Intrinsic::x86_sse41_ptestnzc)
5165f757f3fSDimitry Andric              .Default(Intrinsic::not_intrinsic);
5175f757f3fSDimitry Andric     if (ID != Intrinsic::not_intrinsic)
5187a6dacacSDimitry Andric       return upgradePTESTIntrinsic(F, ID, NewFn);
5195f757f3fSDimitry Andric 
5205f757f3fSDimitry Andric     return false;
5210b57cec5SDimitry Andric   }
5225f757f3fSDimitry Andric 
5230b57cec5SDimitry Andric   // Several blend and other instructions with masks used the wrong number of
5240b57cec5SDimitry Andric   // bits.
5250b57cec5SDimitry Andric 
5265f757f3fSDimitry Andric   // Added in 3.6
5275f757f3fSDimitry Andric   ID = StringSwitch<Intrinsic::ID>(Name)
5285f757f3fSDimitry Andric            .Case("sse41.insertps", Intrinsic::x86_sse41_insertps)
5295f757f3fSDimitry Andric            .Case("sse41.dppd", Intrinsic::x86_sse41_dppd)
5305f757f3fSDimitry Andric            .Case("sse41.dpps", Intrinsic::x86_sse41_dpps)
5315f757f3fSDimitry Andric            .Case("sse41.mpsadbw", Intrinsic::x86_sse41_mpsadbw)
5325f757f3fSDimitry Andric            .Case("avx.dp.ps.256", Intrinsic::x86_avx_dp_ps_256)
5335f757f3fSDimitry Andric            .Case("avx2.mpsadbw", Intrinsic::x86_avx2_mpsadbw)
5345f757f3fSDimitry Andric            .Default(Intrinsic::not_intrinsic);
5355f757f3fSDimitry Andric   if (ID != Intrinsic::not_intrinsic)
5367a6dacacSDimitry Andric     return upgradeX86IntrinsicsWith8BitMask(F, ID, NewFn);
5375f757f3fSDimitry Andric 
5385f757f3fSDimitry Andric   if (Name.consume_front("avx512.mask.cmp.")) {
5395f757f3fSDimitry Andric     // Added in 7.0
5405f757f3fSDimitry Andric     ID = StringSwitch<Intrinsic::ID>(Name)
5415f757f3fSDimitry Andric              .Case("pd.128", Intrinsic::x86_avx512_mask_cmp_pd_128)
5425f757f3fSDimitry Andric              .Case("pd.256", Intrinsic::x86_avx512_mask_cmp_pd_256)
5435f757f3fSDimitry Andric              .Case("pd.512", Intrinsic::x86_avx512_mask_cmp_pd_512)
5445f757f3fSDimitry Andric              .Case("ps.128", Intrinsic::x86_avx512_mask_cmp_ps_128)
5455f757f3fSDimitry Andric              .Case("ps.256", Intrinsic::x86_avx512_mask_cmp_ps_256)
5465f757f3fSDimitry Andric              .Case("ps.512", Intrinsic::x86_avx512_mask_cmp_ps_512)
5475f757f3fSDimitry Andric              .Default(Intrinsic::not_intrinsic);
5485f757f3fSDimitry Andric     if (ID != Intrinsic::not_intrinsic)
5497a6dacacSDimitry Andric       return upgradeX86MaskedFPCompare(F, ID, NewFn);
5505f757f3fSDimitry Andric     return false; // No other 'x86.avx523.mask.cmp.*'.
5510b57cec5SDimitry Andric   }
5525f757f3fSDimitry Andric 
5535f757f3fSDimitry Andric   if (Name.consume_front("avx512bf16.")) {
5545f757f3fSDimitry Andric     // Added in 9.0
5555f757f3fSDimitry Andric     ID = StringSwitch<Intrinsic::ID>(Name)
5565f757f3fSDimitry Andric              .Case("cvtne2ps2bf16.128",
5575f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128)
5585f757f3fSDimitry Andric              .Case("cvtne2ps2bf16.256",
5595f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256)
5605f757f3fSDimitry Andric              .Case("cvtne2ps2bf16.512",
5615f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512)
5625f757f3fSDimitry Andric              .Case("mask.cvtneps2bf16.128",
5635f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
5645f757f3fSDimitry Andric              .Case("cvtneps2bf16.256",
5655f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_cvtneps2bf16_256)
5665f757f3fSDimitry Andric              .Case("cvtneps2bf16.512",
5675f757f3fSDimitry Andric                    Intrinsic::x86_avx512bf16_cvtneps2bf16_512)
5685f757f3fSDimitry Andric              .Default(Intrinsic::not_intrinsic);
5695f757f3fSDimitry Andric     if (ID != Intrinsic::not_intrinsic)
5707a6dacacSDimitry Andric       return upgradeX86BF16Intrinsic(F, ID, NewFn);
5715f757f3fSDimitry Andric 
5725f757f3fSDimitry Andric     // Added in 9.0
5735f757f3fSDimitry Andric     ID = StringSwitch<Intrinsic::ID>(Name)
5745f757f3fSDimitry Andric              .Case("dpbf16ps.128", Intrinsic::x86_avx512bf16_dpbf16ps_128)
5755f757f3fSDimitry Andric              .Case("dpbf16ps.256", Intrinsic::x86_avx512bf16_dpbf16ps_256)
5765f757f3fSDimitry Andric              .Case("dpbf16ps.512", Intrinsic::x86_avx512bf16_dpbf16ps_512)
5775f757f3fSDimitry Andric              .Default(Intrinsic::not_intrinsic);
5785f757f3fSDimitry Andric     if (ID != Intrinsic::not_intrinsic)
5797a6dacacSDimitry Andric       return upgradeX86BF16DPIntrinsic(F, ID, NewFn);
5805f757f3fSDimitry Andric     return false; // No other 'x86.avx512bf16.*'.
5810b57cec5SDimitry Andric   }
5825f757f3fSDimitry Andric 
5835f757f3fSDimitry Andric   if (Name.consume_front("xop.")) {
5845f757f3fSDimitry Andric     Intrinsic::ID ID = Intrinsic::not_intrinsic;
5855f757f3fSDimitry Andric     if (Name.starts_with("vpermil2")) { // Added in 3.9
5865f757f3fSDimitry Andric       // Upgrade any XOP PERMIL2 index operand still using a float/double
5875f757f3fSDimitry Andric       // vector.
5880b57cec5SDimitry Andric       auto Idx = F->getFunctionType()->getParamType(2);
5890b57cec5SDimitry Andric       if (Idx->isFPOrFPVectorTy()) {
5900b57cec5SDimitry Andric         unsigned IdxSize = Idx->getPrimitiveSizeInBits();
5910b57cec5SDimitry Andric         unsigned EltSize = Idx->getScalarSizeInBits();
5920b57cec5SDimitry Andric         if (EltSize == 64 && IdxSize == 128)
5935f757f3fSDimitry Andric           ID = Intrinsic::x86_xop_vpermil2pd;
5940b57cec5SDimitry Andric         else if (EltSize == 32 && IdxSize == 128)
5955f757f3fSDimitry Andric           ID = Intrinsic::x86_xop_vpermil2ps;
5960b57cec5SDimitry Andric         else if (EltSize == 64 && IdxSize == 256)
5975f757f3fSDimitry Andric           ID = Intrinsic::x86_xop_vpermil2pd_256;
5980b57cec5SDimitry Andric         else
5995f757f3fSDimitry Andric           ID = Intrinsic::x86_xop_vpermil2ps_256;
6005f757f3fSDimitry Andric       }
6015f757f3fSDimitry Andric     } else if (F->arg_size() == 2)
6025f757f3fSDimitry Andric       // frcz.ss/sd may need to have an argument dropped. Added in 3.2
6035f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
6045f757f3fSDimitry Andric                .Case("vfrcz.ss", Intrinsic::x86_xop_vfrcz_ss)
6055f757f3fSDimitry Andric                .Case("vfrcz.sd", Intrinsic::x86_xop_vfrcz_sd)
6065f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
6075f757f3fSDimitry Andric 
6085f757f3fSDimitry Andric     if (ID != Intrinsic::not_intrinsic) {
6095f757f3fSDimitry Andric       rename(F);
6105f757f3fSDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
6110b57cec5SDimitry Andric       return true;
6120b57cec5SDimitry Andric     }
6135f757f3fSDimitry Andric     return false; // No other 'x86.xop.*'
6140b57cec5SDimitry Andric   }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   if (Name == "seh.recoverfp") {
6170b57cec5SDimitry Andric     NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_recoverfp);
6180b57cec5SDimitry Andric     return true;
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   return false;
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
6241db9f3b2SDimitry Andric // Upgrade ARM (IsArm) or Aarch64 (!IsArm) intrinsic fns. Return true iff so.
6251db9f3b2SDimitry Andric // IsArm: 'arm.*', !IsArm: 'aarch64.*'.
upgradeArmOrAarch64IntrinsicFunction(bool IsArm,Function * F,StringRef Name,Function * & NewFn)6267a6dacacSDimitry Andric static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F,
6271db9f3b2SDimitry Andric                                                  StringRef Name,
6281db9f3b2SDimitry Andric                                                  Function *&NewFn) {
6291db9f3b2SDimitry Andric   if (Name.starts_with("rbit")) {
6301db9f3b2SDimitry Andric     // '(arm|aarch64).rbit'.
6311db9f3b2SDimitry Andric     NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::bitreverse,
6321db9f3b2SDimitry Andric                                       F->arg_begin()->getType());
6331db9f3b2SDimitry Andric     return true;
6341db9f3b2SDimitry Andric   }
6351db9f3b2SDimitry Andric 
6361db9f3b2SDimitry Andric   if (Name == "thread.pointer") {
6371db9f3b2SDimitry Andric     // '(arm|aarch64).thread.pointer'.
6381db9f3b2SDimitry Andric     NewFn =
6391db9f3b2SDimitry Andric         Intrinsic::getDeclaration(F->getParent(), Intrinsic::thread_pointer);
6401db9f3b2SDimitry Andric     return true;
6411db9f3b2SDimitry Andric   }
6421db9f3b2SDimitry Andric 
6431db9f3b2SDimitry Andric   bool Neon = Name.consume_front("neon.");
6441db9f3b2SDimitry Andric   if (Neon) {
6451db9f3b2SDimitry Andric     // '(arm|aarch64).neon.*'.
6461db9f3b2SDimitry Andric     // Changed in 12.0: bfdot accept v4bf16 and v8bf16 instead of v8i8 and
6471db9f3b2SDimitry Andric     // v16i8 respectively.
6481db9f3b2SDimitry Andric     if (Name.consume_front("bfdot.")) {
6491db9f3b2SDimitry Andric       // (arm|aarch64).neon.bfdot.*'.
6501db9f3b2SDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
6511db9f3b2SDimitry Andric                              .Cases("v2f32.v8i8", "v4f32.v16i8",
6521db9f3b2SDimitry Andric                                     IsArm ? Intrinsic::arm_neon_bfdot
6531db9f3b2SDimitry Andric                                           : Intrinsic::aarch64_neon_bfdot)
6541db9f3b2SDimitry Andric                              .Default(Intrinsic::not_intrinsic);
6551db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
6561db9f3b2SDimitry Andric         size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits();
6571db9f3b2SDimitry Andric         assert((OperandWidth == 64 || OperandWidth == 128) &&
6581db9f3b2SDimitry Andric                "Unexpected operand width");
6591db9f3b2SDimitry Andric         LLVMContext &Ctx = F->getParent()->getContext();
6601db9f3b2SDimitry Andric         std::array<Type *, 2> Tys{
6611db9f3b2SDimitry Andric             {F->getReturnType(),
6621db9f3b2SDimitry Andric              FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16)}};
6631db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
6641db9f3b2SDimitry Andric         return true;
6651db9f3b2SDimitry Andric       }
6661db9f3b2SDimitry Andric       return false; // No other '(arm|aarch64).neon.bfdot.*'.
6671db9f3b2SDimitry Andric     }
6681db9f3b2SDimitry Andric 
6691db9f3b2SDimitry Andric     // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic
6701db9f3b2SDimitry Andric     // anymore and accept v8bf16 instead of v16i8.
6711db9f3b2SDimitry Andric     if (Name.consume_front("bfm")) {
6721db9f3b2SDimitry Andric       // (arm|aarch64).neon.bfm*'.
6731db9f3b2SDimitry Andric       if (Name.consume_back(".v4f32.v16i8")) {
6741db9f3b2SDimitry Andric         // (arm|aarch64).neon.bfm*.v4f32.v16i8'.
6751db9f3b2SDimitry Andric         Intrinsic::ID ID =
6761db9f3b2SDimitry Andric             StringSwitch<Intrinsic::ID>(Name)
6771db9f3b2SDimitry Andric                 .Case("mla", IsArm ? Intrinsic::arm_neon_bfmmla
6781db9f3b2SDimitry Andric                                    : Intrinsic::aarch64_neon_bfmmla)
6791db9f3b2SDimitry Andric                 .Case("lalb", IsArm ? Intrinsic::arm_neon_bfmlalb
6801db9f3b2SDimitry Andric                                     : Intrinsic::aarch64_neon_bfmlalb)
6811db9f3b2SDimitry Andric                 .Case("lalt", IsArm ? Intrinsic::arm_neon_bfmlalt
6821db9f3b2SDimitry Andric                                     : Intrinsic::aarch64_neon_bfmlalt)
6831db9f3b2SDimitry Andric                 .Default(Intrinsic::not_intrinsic);
6841db9f3b2SDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
6851db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
6861db9f3b2SDimitry Andric           return true;
6871db9f3b2SDimitry Andric         }
6881db9f3b2SDimitry Andric         return false; // No other '(arm|aarch64).neon.bfm*.v16i8'.
6891db9f3b2SDimitry Andric       }
6901db9f3b2SDimitry Andric       return false; // No other '(arm|aarch64).neon.bfm*.
6911db9f3b2SDimitry Andric     }
6921db9f3b2SDimitry Andric     // Continue on to Aarch64 Neon or Arm Neon.
6931db9f3b2SDimitry Andric   }
6941db9f3b2SDimitry Andric   // Continue on to Arm or Aarch64.
6951db9f3b2SDimitry Andric 
6961db9f3b2SDimitry Andric   if (IsArm) {
6971db9f3b2SDimitry Andric     // 'arm.*'.
6981db9f3b2SDimitry Andric     if (Neon) {
6991db9f3b2SDimitry Andric       // 'arm.neon.*'.
7001db9f3b2SDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
7011db9f3b2SDimitry Andric                              .StartsWith("vclz.", Intrinsic::ctlz)
7021db9f3b2SDimitry Andric                              .StartsWith("vcnt.", Intrinsic::ctpop)
7031db9f3b2SDimitry Andric                              .StartsWith("vqadds.", Intrinsic::sadd_sat)
7041db9f3b2SDimitry Andric                              .StartsWith("vqaddu.", Intrinsic::uadd_sat)
7051db9f3b2SDimitry Andric                              .StartsWith("vqsubs.", Intrinsic::ssub_sat)
7061db9f3b2SDimitry Andric                              .StartsWith("vqsubu.", Intrinsic::usub_sat)
7071db9f3b2SDimitry Andric                              .Default(Intrinsic::not_intrinsic);
7081db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
7091db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
7101db9f3b2SDimitry Andric                                           F->arg_begin()->getType());
7111db9f3b2SDimitry Andric         return true;
7121db9f3b2SDimitry Andric       }
7131db9f3b2SDimitry Andric 
7141db9f3b2SDimitry Andric       if (Name.consume_front("vst")) {
7151db9f3b2SDimitry Andric         // 'arm.neon.vst*'.
7161db9f3b2SDimitry Andric         static const Regex vstRegex("^([1234]|[234]lane)\\.v[a-z0-9]*$");
7171db9f3b2SDimitry Andric         SmallVector<StringRef, 2> Groups;
7181db9f3b2SDimitry Andric         if (vstRegex.match(Name, &Groups)) {
7191db9f3b2SDimitry Andric           static const Intrinsic::ID StoreInts[] = {
7201db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst1, Intrinsic::arm_neon_vst2,
7211db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst3, Intrinsic::arm_neon_vst4};
7221db9f3b2SDimitry Andric 
7231db9f3b2SDimitry Andric           static const Intrinsic::ID StoreLaneInts[] = {
7241db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane,
7251db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst4lane};
7261db9f3b2SDimitry Andric 
7271db9f3b2SDimitry Andric           auto fArgs = F->getFunctionType()->params();
7281db9f3b2SDimitry Andric           Type *Tys[] = {fArgs[0], fArgs[1]};
7291db9f3b2SDimitry Andric           if (Groups[1].size() == 1)
7301db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(F->getParent(),
7311db9f3b2SDimitry Andric                                               StoreInts[fArgs.size() - 3], Tys);
7321db9f3b2SDimitry Andric           else
7331db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(
7341db9f3b2SDimitry Andric                 F->getParent(), StoreLaneInts[fArgs.size() - 5], Tys);
7351db9f3b2SDimitry Andric           return true;
7361db9f3b2SDimitry Andric         }
7371db9f3b2SDimitry Andric         return false; // No other 'arm.neon.vst*'.
7381db9f3b2SDimitry Andric       }
7391db9f3b2SDimitry Andric 
7401db9f3b2SDimitry Andric       return false; // No other 'arm.neon.*'.
7411db9f3b2SDimitry Andric     }
7421db9f3b2SDimitry Andric 
7431db9f3b2SDimitry Andric     if (Name.consume_front("mve.")) {
7441db9f3b2SDimitry Andric       // 'arm.mve.*'.
7451db9f3b2SDimitry Andric       if (Name == "vctp64") {
7461db9f3b2SDimitry Andric         if (cast<FixedVectorType>(F->getReturnType())->getNumElements() == 4) {
7471db9f3b2SDimitry Andric           // A vctp64 returning a v4i1 is converted to return a v2i1. Rename
7481db9f3b2SDimitry Andric           // the function and deal with it below in UpgradeIntrinsicCall.
7491db9f3b2SDimitry Andric           rename(F);
7501db9f3b2SDimitry Andric           return true;
7511db9f3b2SDimitry Andric         }
7521db9f3b2SDimitry Andric         return false; // Not 'arm.mve.vctp64'.
7531db9f3b2SDimitry Andric       }
7541db9f3b2SDimitry Andric 
7551db9f3b2SDimitry Andric       // These too are changed to accept a v2i1 instead of the old v4i1.
7561db9f3b2SDimitry Andric       if (Name.consume_back(".v4i1")) {
7571db9f3b2SDimitry Andric         // 'arm.mve.*.v4i1'.
7581db9f3b2SDimitry Andric         if (Name.consume_back(".predicated.v2i64.v4i32"))
7591db9f3b2SDimitry Andric           // 'arm.mve.*.predicated.v2i64.v4i32.v4i1'
7601db9f3b2SDimitry Andric           return Name == "mull.int" || Name == "vqdmull";
7611db9f3b2SDimitry Andric 
7621db9f3b2SDimitry Andric         if (Name.consume_back(".v2i64")) {
7631db9f3b2SDimitry Andric           // 'arm.mve.*.v2i64.v4i1'
7641db9f3b2SDimitry Andric           bool IsGather = Name.consume_front("vldr.gather.");
7651db9f3b2SDimitry Andric           if (IsGather || Name.consume_front("vstr.scatter.")) {
7661db9f3b2SDimitry Andric             if (Name.consume_front("base.")) {
7671db9f3b2SDimitry Andric               // Optional 'wb.' prefix.
7681db9f3b2SDimitry Andric               Name.consume_front("wb.");
7691db9f3b2SDimitry Andric               // 'arm.mve.(vldr.gather|vstr.scatter).base.(wb.)?
7701db9f3b2SDimitry Andric               // predicated.v2i64.v2i64.v4i1'.
7711db9f3b2SDimitry Andric               return Name == "predicated.v2i64";
7721db9f3b2SDimitry Andric             }
7731db9f3b2SDimitry Andric 
7741db9f3b2SDimitry Andric             if (Name.consume_front("offset.predicated."))
7751db9f3b2SDimitry Andric               return Name == (IsGather ? "v2i64.p0i64" : "p0i64.v2i64") ||
7761db9f3b2SDimitry Andric                      Name == (IsGather ? "v2i64.p0" : "p0.v2i64");
7771db9f3b2SDimitry Andric 
7781db9f3b2SDimitry Andric             // No other 'arm.mve.(vldr.gather|vstr.scatter).*.v2i64.v4i1'.
7791db9f3b2SDimitry Andric             return false;
7801db9f3b2SDimitry Andric           }
7811db9f3b2SDimitry Andric 
7821db9f3b2SDimitry Andric           return false; // No other 'arm.mve.*.v2i64.v4i1'.
7831db9f3b2SDimitry Andric         }
7841db9f3b2SDimitry Andric         return false; // No other 'arm.mve.*.v4i1'.
7851db9f3b2SDimitry Andric       }
7861db9f3b2SDimitry Andric       return false; // No other 'arm.mve.*'.
7871db9f3b2SDimitry Andric     }
7881db9f3b2SDimitry Andric 
7891db9f3b2SDimitry Andric     if (Name.consume_front("cde.vcx")) {
7901db9f3b2SDimitry Andric       // 'arm.cde.vcx*'.
7911db9f3b2SDimitry Andric       if (Name.consume_back(".predicated.v2i64.v4i1"))
7921db9f3b2SDimitry Andric         // 'arm.cde.vcx*.predicated.v2i64.v4i1'.
7931db9f3b2SDimitry Andric         return Name == "1q" || Name == "1qa" || Name == "2q" || Name == "2qa" ||
7941db9f3b2SDimitry Andric                Name == "3q" || Name == "3qa";
7951db9f3b2SDimitry Andric 
7961db9f3b2SDimitry Andric       return false; // No other 'arm.cde.vcx*'.
7971db9f3b2SDimitry Andric     }
7981db9f3b2SDimitry Andric   } else {
7991db9f3b2SDimitry Andric     // 'aarch64.*'.
8001db9f3b2SDimitry Andric     if (Neon) {
8011db9f3b2SDimitry Andric       // 'aarch64.neon.*'.
8021db9f3b2SDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
8031db9f3b2SDimitry Andric                              .StartsWith("frintn", Intrinsic::roundeven)
8041db9f3b2SDimitry Andric                              .StartsWith("rbit", Intrinsic::bitreverse)
8051db9f3b2SDimitry Andric                              .Default(Intrinsic::not_intrinsic);
8061db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
8071db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
8081db9f3b2SDimitry Andric                                           F->arg_begin()->getType());
8091db9f3b2SDimitry Andric         return true;
8101db9f3b2SDimitry Andric       }
8111db9f3b2SDimitry Andric 
8121db9f3b2SDimitry Andric       if (Name.starts_with("addp")) {
8131db9f3b2SDimitry Andric         // 'aarch64.neon.addp*'.
8141db9f3b2SDimitry Andric         if (F->arg_size() != 2)
8151db9f3b2SDimitry Andric           return false; // Invalid IR.
8161db9f3b2SDimitry Andric         VectorType *Ty = dyn_cast<VectorType>(F->getReturnType());
8171db9f3b2SDimitry Andric         if (Ty && Ty->getElementType()->isFloatingPointTy()) {
8181db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8191db9f3b2SDimitry Andric                                             Intrinsic::aarch64_neon_faddp, Ty);
8201db9f3b2SDimitry Andric           return true;
8211db9f3b2SDimitry Andric         }
8221db9f3b2SDimitry Andric       }
8231db9f3b2SDimitry Andric       return false; // No other 'aarch64.neon.*'.
8241db9f3b2SDimitry Andric     }
8251db9f3b2SDimitry Andric     if (Name.consume_front("sve.")) {
8261db9f3b2SDimitry Andric       // 'aarch64.sve.*'.
8271db9f3b2SDimitry Andric       if (Name.consume_front("bf")) {
8281db9f3b2SDimitry Andric         if (Name.consume_back(".lane")) {
8291db9f3b2SDimitry Andric           // 'aarch64.sve.bf*.lane'.
8301db9f3b2SDimitry Andric           Intrinsic::ID ID =
8311db9f3b2SDimitry Andric               StringSwitch<Intrinsic::ID>(Name)
8321db9f3b2SDimitry Andric                   .Case("dot", Intrinsic::aarch64_sve_bfdot_lane_v2)
8331db9f3b2SDimitry Andric                   .Case("mlalb", Intrinsic::aarch64_sve_bfmlalb_lane_v2)
8341db9f3b2SDimitry Andric                   .Case("mlalt", Intrinsic::aarch64_sve_bfmlalt_lane_v2)
8351db9f3b2SDimitry Andric                   .Default(Intrinsic::not_intrinsic);
8361db9f3b2SDimitry Andric           if (ID != Intrinsic::not_intrinsic) {
8371db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
8381db9f3b2SDimitry Andric             return true;
8391db9f3b2SDimitry Andric           }
8401db9f3b2SDimitry Andric           return false; // No other 'aarch64.sve.bf*.lane'.
8411db9f3b2SDimitry Andric         }
8421db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.bf*'.
8431db9f3b2SDimitry Andric       }
8441db9f3b2SDimitry Andric 
8451db9f3b2SDimitry Andric       if (Name.consume_front("ld")) {
8461db9f3b2SDimitry Andric         // 'aarch64.sve.ld*'.
8471db9f3b2SDimitry Andric         static const Regex LdRegex("^[234](.nxv[a-z0-9]+|$)");
8481db9f3b2SDimitry Andric         if (LdRegex.match(Name)) {
8491db9f3b2SDimitry Andric           Type *ScalarTy =
8501db9f3b2SDimitry Andric               dyn_cast<VectorType>(F->getReturnType())->getElementType();
8511db9f3b2SDimitry Andric           ElementCount EC = dyn_cast<VectorType>(F->arg_begin()->getType())
8521db9f3b2SDimitry Andric                                 ->getElementCount();
8531db9f3b2SDimitry Andric           Type *Ty = VectorType::get(ScalarTy, EC);
8541db9f3b2SDimitry Andric           static const Intrinsic::ID LoadIDs[] = {
8551db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld2_sret,
8561db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld3_sret,
8571db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld4_sret,
8581db9f3b2SDimitry Andric           };
8591db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8601db9f3b2SDimitry Andric                                             LoadIDs[Name[0] - '2'], Ty);
8611db9f3b2SDimitry Andric           return true;
8621db9f3b2SDimitry Andric         }
8631db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.ld*'.
8641db9f3b2SDimitry Andric       }
8651db9f3b2SDimitry Andric 
8661db9f3b2SDimitry Andric       if (Name.consume_front("tuple.")) {
8671db9f3b2SDimitry Andric         // 'aarch64.sve.tuple.*'.
8681db9f3b2SDimitry Andric         if (Name.starts_with("get")) {
8691db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.get*'.
8701db9f3b2SDimitry Andric           Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
8711db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8721db9f3b2SDimitry Andric                                             Intrinsic::vector_extract, Tys);
8731db9f3b2SDimitry Andric           return true;
8741db9f3b2SDimitry Andric         }
8751db9f3b2SDimitry Andric 
8761db9f3b2SDimitry Andric         if (Name.starts_with("set")) {
8771db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.set*'.
8781db9f3b2SDimitry Andric           auto Args = F->getFunctionType()->params();
8791db9f3b2SDimitry Andric           Type *Tys[] = {Args[0], Args[2], Args[1]};
8801db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8811db9f3b2SDimitry Andric                                             Intrinsic::vector_insert, Tys);
8821db9f3b2SDimitry Andric           return true;
8831db9f3b2SDimitry Andric         }
8841db9f3b2SDimitry Andric 
8851db9f3b2SDimitry Andric         static const Regex CreateTupleRegex("^create[234](.nxv[a-z0-9]+|$)");
8861db9f3b2SDimitry Andric         if (CreateTupleRegex.match(Name)) {
8871db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.create*'.
8881db9f3b2SDimitry Andric           auto Args = F->getFunctionType()->params();
8891db9f3b2SDimitry Andric           Type *Tys[] = {F->getReturnType(), Args[1]};
8901db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8911db9f3b2SDimitry Andric                                             Intrinsic::vector_insert, Tys);
8921db9f3b2SDimitry Andric           return true;
8931db9f3b2SDimitry Andric         }
8941db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.tuple.*'.
8951db9f3b2SDimitry Andric       }
8961db9f3b2SDimitry Andric       return false; // No other 'aarch64.sve.*'.
8971db9f3b2SDimitry Andric     }
8981db9f3b2SDimitry Andric   }
8991db9f3b2SDimitry Andric   return false; // No other 'arm.*', 'aarch64.*'.
9001db9f3b2SDimitry Andric }
9011db9f3b2SDimitry Andric 
shouldUpgradeNVPTXBF16Intrinsic(StringRef Name)9027a6dacacSDimitry Andric static Intrinsic::ID shouldUpgradeNVPTXBF16Intrinsic(StringRef Name) {
9035f757f3fSDimitry Andric   if (Name.consume_front("abs."))
90406c3fb27SDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9055f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_abs_bf16)
9065f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_abs_bf16x2)
90706c3fb27SDimitry Andric         .Default(Intrinsic::not_intrinsic);
9085f757f3fSDimitry Andric 
9095f757f3fSDimitry Andric   if (Name.consume_front("fma.rn."))
9105f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9115f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fma_rn_bf16)
9125f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fma_rn_bf16x2)
9135f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fma_rn_ftz_bf16)
9145f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fma_rn_ftz_bf16x2)
9155f757f3fSDimitry Andric         .Case("ftz.relu.bf16", Intrinsic::nvvm_fma_rn_ftz_relu_bf16)
9165f757f3fSDimitry Andric         .Case("ftz.relu.bf16x2", Intrinsic::nvvm_fma_rn_ftz_relu_bf16x2)
9175f757f3fSDimitry Andric         .Case("ftz.sat.bf16", Intrinsic::nvvm_fma_rn_ftz_sat_bf16)
9185f757f3fSDimitry Andric         .Case("ftz.sat.bf16x2", Intrinsic::nvvm_fma_rn_ftz_sat_bf16x2)
9195f757f3fSDimitry Andric         .Case("relu.bf16", Intrinsic::nvvm_fma_rn_relu_bf16)
9205f757f3fSDimitry Andric         .Case("relu.bf16x2", Intrinsic::nvvm_fma_rn_relu_bf16x2)
9215f757f3fSDimitry Andric         .Case("sat.bf16", Intrinsic::nvvm_fma_rn_sat_bf16)
9225f757f3fSDimitry Andric         .Case("sat.bf16x2", Intrinsic::nvvm_fma_rn_sat_bf16x2)
9235f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9245f757f3fSDimitry Andric 
9255f757f3fSDimitry Andric   if (Name.consume_front("fmax."))
9265f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9275f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fmax_bf16)
9285f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fmax_bf16x2)
9295f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fmax_ftz_bf16)
9305f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fmax_ftz_bf16x2)
9315f757f3fSDimitry Andric         .Case("ftz.nan.bf16", Intrinsic::nvvm_fmax_ftz_nan_bf16)
9325f757f3fSDimitry Andric         .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmax_ftz_nan_bf16x2)
9335f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16",
9345f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16)
9355f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16x2",
9365f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16x2)
9375f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16)
9385f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16x2",
9395f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16x2)
9405f757f3fSDimitry Andric         .Case("nan.bf16", Intrinsic::nvvm_fmax_nan_bf16)
9415f757f3fSDimitry Andric         .Case("nan.bf16x2", Intrinsic::nvvm_fmax_nan_bf16x2)
9425f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16)
9435f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16x2",
9445f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16x2)
9455f757f3fSDimitry Andric         .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmax_xorsign_abs_bf16)
9465f757f3fSDimitry Andric         .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmax_xorsign_abs_bf16x2)
9475f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9485f757f3fSDimitry Andric 
9495f757f3fSDimitry Andric   if (Name.consume_front("fmin."))
9505f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9515f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fmin_bf16)
9525f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fmin_bf16x2)
9535f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fmin_ftz_bf16)
9545f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fmin_ftz_bf16x2)
9555f757f3fSDimitry Andric         .Case("ftz.nan.bf16", Intrinsic::nvvm_fmin_ftz_nan_bf16)
9565f757f3fSDimitry Andric         .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmin_ftz_nan_bf16x2)
9575f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16",
9585f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16)
9595f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16x2",
9605f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16x2)
9615f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16)
9625f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16x2",
9635f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16x2)
9645f757f3fSDimitry Andric         .Case("nan.bf16", Intrinsic::nvvm_fmin_nan_bf16)
9655f757f3fSDimitry Andric         .Case("nan.bf16x2", Intrinsic::nvvm_fmin_nan_bf16x2)
9665f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16)
9675f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16x2",
9685f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16x2)
9695f757f3fSDimitry Andric         .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmin_xorsign_abs_bf16)
9705f757f3fSDimitry Andric         .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmin_xorsign_abs_bf16x2)
9715f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9725f757f3fSDimitry Andric 
9735f757f3fSDimitry Andric   if (Name.consume_front("neg."))
9745f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9755f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_neg_bf16)
9765f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_neg_bf16x2)
9775f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9785f757f3fSDimitry Andric 
9795f757f3fSDimitry Andric   return Intrinsic::not_intrinsic;
98006c3fb27SDimitry Andric }
98106c3fb27SDimitry Andric 
upgradeIntrinsicFunction1(Function * F,Function * & NewFn)9827a6dacacSDimitry Andric static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
9830b57cec5SDimitry Andric   assert(F && "Illegal to upgrade a non-existent Function.");
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   StringRef Name = F->getName();
9865f757f3fSDimitry Andric 
9875f757f3fSDimitry Andric   // Quickly eliminate it, if it's not a candidate.
9885f757f3fSDimitry Andric   if (!Name.consume_front("llvm.") || Name.empty())
9890b57cec5SDimitry Andric     return false;
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric   switch (Name[0]) {
9920b57cec5SDimitry Andric   default: break;
9930b57cec5SDimitry Andric   case 'a': {
9941db9f3b2SDimitry Andric     bool IsArm = Name.consume_front("arm.");
9951db9f3b2SDimitry Andric     if (IsArm || Name.consume_front("aarch64.")) {
9967a6dacacSDimitry Andric       if (upgradeArmOrAarch64IntrinsicFunction(IsArm, F, Name, NewFn))
9970b57cec5SDimitry Andric         return true;
998e8d8bef9SDimitry Andric       break;
999e8d8bef9SDimitry Andric     }
1000e8d8bef9SDimitry Andric 
10015f757f3fSDimitry Andric     if (Name.consume_front("amdgcn.")) {
100206c3fb27SDimitry Andric       if (Name == "alignbit") {
100304eeddc0SDimitry Andric         // Target specific intrinsic became redundant
100404eeddc0SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::fshr,
100504eeddc0SDimitry Andric                                           {F->getReturnType()});
100604eeddc0SDimitry Andric         return true;
100704eeddc0SDimitry Andric       }
100804eeddc0SDimitry Andric 
10095f757f3fSDimitry Andric       if (Name.consume_front("atomic.")) {
10105f757f3fSDimitry Andric         if (Name.starts_with("inc") || Name.starts_with("dec")) {
10115f757f3fSDimitry Andric           // These were replaced with atomicrmw uinc_wrap and udec_wrap, so
10125f757f3fSDimitry Andric           // there's no new declaration.
101306c3fb27SDimitry Andric           NewFn = nullptr;
101406c3fb27SDimitry Andric           return true;
10150b57cec5SDimitry Andric         }
10165f757f3fSDimitry Andric         break; // No other 'amdgcn.atomic.*'
10175f757f3fSDimitry Andric       }
10185f757f3fSDimitry Andric 
10195f757f3fSDimitry Andric       if (Name.starts_with("ldexp.")) {
10205f757f3fSDimitry Andric         // Target specific intrinsic became redundant
10215f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(
10225f757f3fSDimitry Andric           F->getParent(), Intrinsic::ldexp,
10235f757f3fSDimitry Andric           {F->getReturnType(), F->getArg(1)->getType()});
10245f757f3fSDimitry Andric         return true;
10255f757f3fSDimitry Andric       }
10265f757f3fSDimitry Andric       break; // No other 'amdgcn.*'
10275f757f3fSDimitry Andric     }
10280b57cec5SDimitry Andric 
102906c3fb27SDimitry Andric     break;
103006c3fb27SDimitry Andric   }
10310b57cec5SDimitry Andric   case 'c': {
10325f757f3fSDimitry Andric     if (F->arg_size() == 1) {
10335f757f3fSDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
10345f757f3fSDimitry Andric                              .StartsWith("ctlz.", Intrinsic::ctlz)
10355f757f3fSDimitry Andric                              .StartsWith("cttz.", Intrinsic::cttz)
10365f757f3fSDimitry Andric                              .Default(Intrinsic::not_intrinsic);
10375f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
10380b57cec5SDimitry Andric         rename(F);
10395f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
10400b57cec5SDimitry Andric                                           F->arg_begin()->getType());
10410b57cec5SDimitry Andric         return true;
10420b57cec5SDimitry Andric       }
10435f757f3fSDimitry Andric     }
10445f757f3fSDimitry Andric 
10455f757f3fSDimitry Andric     if (F->arg_size() == 2 && Name.equals("coro.end")) {
10460b57cec5SDimitry Andric       rename(F);
10475f757f3fSDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::coro_end);
10480b57cec5SDimitry Andric       return true;
10490b57cec5SDimitry Andric     }
10505f757f3fSDimitry Andric 
10510b57cec5SDimitry Andric     break;
10520b57cec5SDimitry Andric   }
10535f757f3fSDimitry Andric   case 'd':
10545f757f3fSDimitry Andric     if (Name.consume_front("dbg.")) {
10555f757f3fSDimitry Andric       if (Name == "addr" || (Name == "value" && F->arg_size() == 4)) {
105606c3fb27SDimitry Andric         rename(F);
105706c3fb27SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value);
105806c3fb27SDimitry Andric         return true;
105906c3fb27SDimitry Andric       }
10605f757f3fSDimitry Andric       break; // No other 'dbg.*'.
10610b57cec5SDimitry Andric     }
10620b57cec5SDimitry Andric     break;
10635f757f3fSDimitry Andric   case 'e':
10645f757f3fSDimitry Andric     if (Name.consume_front("experimental.vector.")) {
10655f757f3fSDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
10665f757f3fSDimitry Andric                              .StartsWith("extract.", Intrinsic::vector_extract)
10675f757f3fSDimitry Andric                              .StartsWith("insert.", Intrinsic::vector_insert)
10685f757f3fSDimitry Andric                              .Default(Intrinsic::not_intrinsic);
10695f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
10705f757f3fSDimitry Andric         const auto *FT = F->getFunctionType();
10715f757f3fSDimitry Andric         SmallVector<Type *, 2> Tys;
10725f757f3fSDimitry Andric         if (ID == Intrinsic::vector_extract)
10735f757f3fSDimitry Andric           // Extracting overloads the return type.
10745f757f3fSDimitry Andric           Tys.push_back(FT->getReturnType());
10755f757f3fSDimitry Andric         Tys.push_back(FT->getParamType(0));
10765f757f3fSDimitry Andric         if (ID == Intrinsic::vector_insert)
10775f757f3fSDimitry Andric           // Inserting overloads the inserted type.
10785f757f3fSDimitry Andric           Tys.push_back(FT->getParamType(1));
107981ad6265SDimitry Andric         rename(F);
10805f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
108181ad6265SDimitry Andric         return true;
108281ad6265SDimitry Andric       }
108381ad6265SDimitry Andric 
10845f757f3fSDimitry Andric       if (Name.consume_front("reduce.")) {
10850b57cec5SDimitry Andric         SmallVector<StringRef, 2> Groups;
10865f757f3fSDimitry Andric         static const Regex R("^([a-z]+)\\.[a-z][0-9]+");
10875f757f3fSDimitry Andric         if (R.match(Name, &Groups))
1088e8d8bef9SDimitry Andric           ID = StringSwitch<Intrinsic::ID>(Groups[1])
1089e8d8bef9SDimitry Andric                    .Case("add", Intrinsic::vector_reduce_add)
1090e8d8bef9SDimitry Andric                    .Case("mul", Intrinsic::vector_reduce_mul)
1091e8d8bef9SDimitry Andric                    .Case("and", Intrinsic::vector_reduce_and)
1092e8d8bef9SDimitry Andric                    .Case("or", Intrinsic::vector_reduce_or)
1093e8d8bef9SDimitry Andric                    .Case("xor", Intrinsic::vector_reduce_xor)
1094e8d8bef9SDimitry Andric                    .Case("smax", Intrinsic::vector_reduce_smax)
1095e8d8bef9SDimitry Andric                    .Case("smin", Intrinsic::vector_reduce_smin)
1096e8d8bef9SDimitry Andric                    .Case("umax", Intrinsic::vector_reduce_umax)
1097e8d8bef9SDimitry Andric                    .Case("umin", Intrinsic::vector_reduce_umin)
1098e8d8bef9SDimitry Andric                    .Case("fmax", Intrinsic::vector_reduce_fmax)
1099e8d8bef9SDimitry Andric                    .Case("fmin", Intrinsic::vector_reduce_fmin)
1100e8d8bef9SDimitry Andric                    .Default(Intrinsic::not_intrinsic);
11015f757f3fSDimitry Andric 
11025f757f3fSDimitry Andric         bool V2 = false;
11035f757f3fSDimitry Andric         if (ID == Intrinsic::not_intrinsic) {
11045f757f3fSDimitry Andric           static const Regex R2("^v2\\.([a-z]+)\\.[fi][0-9]+");
1105e8d8bef9SDimitry Andric           Groups.clear();
11065f757f3fSDimitry Andric           V2 = true;
11075f757f3fSDimitry Andric           if (R2.match(Name, &Groups))
11085f757f3fSDimitry Andric             ID = StringSwitch<Intrinsic::ID>(Groups[1])
11095f757f3fSDimitry Andric                      .Case("fadd", Intrinsic::vector_reduce_fadd)
11105f757f3fSDimitry Andric                      .Case("fmul", Intrinsic::vector_reduce_fmul)
11115f757f3fSDimitry Andric                      .Default(Intrinsic::not_intrinsic);
11125f757f3fSDimitry Andric         }
1113e8d8bef9SDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
1114e8d8bef9SDimitry Andric           rename(F);
1115e8d8bef9SDimitry Andric           auto Args = F->getFunctionType()->params();
11165f757f3fSDimitry Andric           NewFn =
11175f757f3fSDimitry Andric               Intrinsic::getDeclaration(F->getParent(), ID, {Args[V2 ? 1 : 0]});
11180b57cec5SDimitry Andric           return true;
11190b57cec5SDimitry Andric         }
11205f757f3fSDimitry Andric         break; // No other 'expermental.vector.reduce.*'.
11210b57cec5SDimitry Andric       }
11225f757f3fSDimitry Andric       break; // No other 'experimental.vector.*'.
11230b57cec5SDimitry Andric     }
11245f757f3fSDimitry Andric     break; // No other 'e*'.
1125bdd1243dSDimitry Andric   case 'f':
11265f757f3fSDimitry Andric     if (Name.starts_with("flt.rounds")) {
1127bdd1243dSDimitry Andric       rename(F);
1128bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::get_rounding);
1129bdd1243dSDimitry Andric       return true;
1130bdd1243dSDimitry Andric     }
1131bdd1243dSDimitry Andric     break;
11320b57cec5SDimitry Andric   case 'i':
11335f757f3fSDimitry Andric     if (Name.starts_with("invariant.group.barrier")) {
11340b57cec5SDimitry Andric       // Rename invariant.group.barrier to launder.invariant.group
11350b57cec5SDimitry Andric       auto Args = F->getFunctionType()->params();
11360b57cec5SDimitry Andric       Type* ObjectPtr[1] = {Args[0]};
11370b57cec5SDimitry Andric       rename(F);
11380b57cec5SDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(),
11390b57cec5SDimitry Andric           Intrinsic::launder_invariant_group, ObjectPtr);
11400b57cec5SDimitry Andric       return true;
11410b57cec5SDimitry Andric     }
11420b57cec5SDimitry Andric     break;
11430b57cec5SDimitry Andric   case 'm': {
11440b57cec5SDimitry Andric     // Updating the memory intrinsics (memcpy/memmove/memset) that have an
11450b57cec5SDimitry Andric     // alignment parameter to embedding the alignment as an attribute of
11460b57cec5SDimitry Andric     // the pointer args.
11475f757f3fSDimitry Andric     if (unsigned ID = StringSwitch<unsigned>(Name)
11485f757f3fSDimitry Andric                           .StartsWith("memcpy.", Intrinsic::memcpy)
11495f757f3fSDimitry Andric                           .StartsWith("memmove.", Intrinsic::memmove)
11505f757f3fSDimitry Andric                           .Default(0)) {
11515f757f3fSDimitry Andric       if (F->arg_size() == 5) {
11520b57cec5SDimitry Andric         rename(F);
11530b57cec5SDimitry Andric         // Get the types of dest, src, and len
11545f757f3fSDimitry Andric         ArrayRef<Type *> ParamTypes =
11555f757f3fSDimitry Andric             F->getFunctionType()->params().slice(0, 3);
11565f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, ParamTypes);
11570b57cec5SDimitry Andric         return true;
11580b57cec5SDimitry Andric       }
11590b57cec5SDimitry Andric     }
11605f757f3fSDimitry Andric     if (Name.starts_with("memset.") && F->arg_size() == 5) {
11610b57cec5SDimitry Andric       rename(F);
11620b57cec5SDimitry Andric       // Get the types of dest, and len
11630b57cec5SDimitry Andric       const auto *FT = F->getFunctionType();
11640b57cec5SDimitry Andric       Type *ParamTypes[2] = {
11650b57cec5SDimitry Andric           FT->getParamType(0), // Dest
11660b57cec5SDimitry Andric           FT->getParamType(2)  // len
11670b57cec5SDimitry Andric       };
11680b57cec5SDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memset,
11690b57cec5SDimitry Andric                                         ParamTypes);
11700b57cec5SDimitry Andric       return true;
11710b57cec5SDimitry Andric     }
11720b57cec5SDimitry Andric     break;
11730b57cec5SDimitry Andric   }
11740b57cec5SDimitry Andric   case 'n': {
11755f757f3fSDimitry Andric     if (Name.consume_front("nvvm.")) {
11765f757f3fSDimitry Andric       // Check for nvvm intrinsics corresponding exactly to an LLVM intrinsic.
11775f757f3fSDimitry Andric       if (F->arg_size() == 1) {
11785f757f3fSDimitry Andric         Intrinsic::ID IID =
11795f757f3fSDimitry Andric             StringSwitch<Intrinsic::ID>(Name)
11800b57cec5SDimitry Andric                 .Cases("brev32", "brev64", Intrinsic::bitreverse)
11810b57cec5SDimitry Andric                 .Case("clz.i", Intrinsic::ctlz)
11820b57cec5SDimitry Andric                 .Case("popc.i", Intrinsic::ctpop)
11830b57cec5SDimitry Andric                 .Default(Intrinsic::not_intrinsic);
11845f757f3fSDimitry Andric         if (IID != Intrinsic::not_intrinsic) {
11850b57cec5SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), IID,
11860b57cec5SDimitry Andric                                             {F->getReturnType()});
11870b57cec5SDimitry Andric           return true;
11880b57cec5SDimitry Andric         }
11895f757f3fSDimitry Andric       }
11905f757f3fSDimitry Andric 
11915f757f3fSDimitry Andric       // Check for nvvm intrinsics that need a return type adjustment.
11925f757f3fSDimitry Andric       if (!F->getReturnType()->getScalarType()->isBFloatTy()) {
11937a6dacacSDimitry Andric         Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic(Name);
11945f757f3fSDimitry Andric         if (IID != Intrinsic::not_intrinsic) {
119506c3fb27SDimitry Andric           NewFn = nullptr;
119606c3fb27SDimitry Andric           return true;
119706c3fb27SDimitry Andric         }
11985f757f3fSDimitry Andric       }
11995f757f3fSDimitry Andric 
12000b57cec5SDimitry Andric       // The following nvvm intrinsics correspond exactly to an LLVM idiom, but
12010b57cec5SDimitry Andric       // not to an intrinsic alone.  We expand them in UpgradeIntrinsicCall.
12020b57cec5SDimitry Andric       //
12030b57cec5SDimitry Andric       // TODO: We could add lohi.i2d.
12045f757f3fSDimitry Andric       bool Expand = false;
12055f757f3fSDimitry Andric       if (Name.consume_front("abs."))
12065f757f3fSDimitry Andric         // nvvm.abs.{i,ii}
12075f757f3fSDimitry Andric         Expand = Name == "i" || Name == "ll";
12085f757f3fSDimitry Andric       else if (Name == "clz.ll" || Name == "popc.ll" || Name == "h2f")
12095f757f3fSDimitry Andric         Expand = true;
12105f757f3fSDimitry Andric       else if (Name.consume_front("max.") || Name.consume_front("min."))
12115f757f3fSDimitry Andric         // nvvm.{min,max}.{i,ii,ui,ull}
12127a6dacacSDimitry Andric         Expand = Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
12137a6dacacSDimitry Andric                  Name == "ui" || Name == "ull";
12145f757f3fSDimitry Andric       else if (Name.consume_front("atomic.load.add."))
12155f757f3fSDimitry Andric         // nvvm.atomic.load.add.{f32.p,f64.p}
12165f757f3fSDimitry Andric         Expand = Name.starts_with("f32.p") || Name.starts_with("f64.p");
12175f757f3fSDimitry Andric       else
12185f757f3fSDimitry Andric         Expand = false;
12195f757f3fSDimitry Andric 
12200b57cec5SDimitry Andric       if (Expand) {
12210b57cec5SDimitry Andric         NewFn = nullptr;
12220b57cec5SDimitry Andric         return true;
12230b57cec5SDimitry Andric       }
12245f757f3fSDimitry Andric       break; // No other 'nvvm.*'.
12250b57cec5SDimitry Andric     }
12260b57cec5SDimitry Andric     break;
12270b57cec5SDimitry Andric   }
12280b57cec5SDimitry Andric   case 'o':
12290b57cec5SDimitry Andric     // We only need to change the name to match the mangling including the
12300b57cec5SDimitry Andric     // address space.
12315f757f3fSDimitry Andric     if (Name.starts_with("objectsize.")) {
12320b57cec5SDimitry Andric       Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
12330b57cec5SDimitry Andric       if (F->arg_size() == 2 || F->arg_size() == 3 ||
1234fe6060f1SDimitry Andric           F->getName() !=
1235fe6060f1SDimitry Andric               Intrinsic::getName(Intrinsic::objectsize, Tys, F->getParent())) {
12360b57cec5SDimitry Andric         rename(F);
12370b57cec5SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::objectsize,
12380b57cec5SDimitry Andric                                           Tys);
12390b57cec5SDimitry Andric         return true;
12400b57cec5SDimitry Andric       }
12410b57cec5SDimitry Andric     }
12420b57cec5SDimitry Andric     break;
12430b57cec5SDimitry Andric 
12448bcb0991SDimitry Andric   case 'p':
12455f757f3fSDimitry Andric     if (Name.starts_with("ptr.annotation.") && F->arg_size() == 4) {
1246d409305fSDimitry Andric       rename(F);
1247bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(
1248bdd1243dSDimitry Andric           F->getParent(), Intrinsic::ptr_annotation,
1249bdd1243dSDimitry Andric           {F->arg_begin()->getType(), F->getArg(1)->getType()});
1250d409305fSDimitry Andric       return true;
12518bcb0991SDimitry Andric     }
12528bcb0991SDimitry Andric     break;
12538bcb0991SDimitry Andric 
12545f757f3fSDimitry Andric   case 'r': {
12555f757f3fSDimitry Andric     if (Name.consume_front("riscv.")) {
12565f757f3fSDimitry Andric       Intrinsic::ID ID;
12575f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
12585f757f3fSDimitry Andric                .Case("aes32dsi", Intrinsic::riscv_aes32dsi)
12595f757f3fSDimitry Andric                .Case("aes32dsmi", Intrinsic::riscv_aes32dsmi)
12605f757f3fSDimitry Andric                .Case("aes32esi", Intrinsic::riscv_aes32esi)
12615f757f3fSDimitry Andric                .Case("aes32esmi", Intrinsic::riscv_aes32esmi)
12625f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
12635f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
12645f757f3fSDimitry Andric         if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32)) {
126506c3fb27SDimitry Andric           rename(F);
12665f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
126706c3fb27SDimitry Andric           return true;
126806c3fb27SDimitry Andric         }
12695f757f3fSDimitry Andric         break; // No other applicable upgrades.
127006c3fb27SDimitry Andric       }
12715f757f3fSDimitry Andric 
12725f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
12735f757f3fSDimitry Andric                .StartsWith("sm4ks", Intrinsic::riscv_sm4ks)
12745f757f3fSDimitry Andric                .StartsWith("sm4ed", Intrinsic::riscv_sm4ed)
12755f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
12765f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
12775f757f3fSDimitry Andric         if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32) ||
127806c3fb27SDimitry Andric             F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
127906c3fb27SDimitry Andric           rename(F);
12805f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
128106c3fb27SDimitry Andric           return true;
128206c3fb27SDimitry Andric         }
12835f757f3fSDimitry Andric         break; // No other applicable upgrades.
12845f757f3fSDimitry Andric       }
12855f757f3fSDimitry Andric 
12865f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
12875f757f3fSDimitry Andric                .StartsWith("sha256sig0", Intrinsic::riscv_sha256sig0)
12885f757f3fSDimitry Andric                .StartsWith("sha256sig1", Intrinsic::riscv_sha256sig1)
12895f757f3fSDimitry Andric                .StartsWith("sha256sum0", Intrinsic::riscv_sha256sum0)
12905f757f3fSDimitry Andric                .StartsWith("sha256sum1", Intrinsic::riscv_sha256sum1)
12915f757f3fSDimitry Andric                .StartsWith("sm3p0", Intrinsic::riscv_sm3p0)
12925f757f3fSDimitry Andric                .StartsWith("sm3p1", Intrinsic::riscv_sm3p1)
12935f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
12945f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
12955f757f3fSDimitry Andric         if (F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
129606c3fb27SDimitry Andric           rename(F);
12975f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
129806c3fb27SDimitry Andric           return true;
129906c3fb27SDimitry Andric         }
13005f757f3fSDimitry Andric         break; // No other applicable upgrades.
130106c3fb27SDimitry Andric       }
13025f757f3fSDimitry Andric       break; // No other 'riscv.*' intrinsics
130306c3fb27SDimitry Andric     }
13045f757f3fSDimitry Andric   } break;
130506c3fb27SDimitry Andric 
13060b57cec5SDimitry Andric   case 's':
13070b57cec5SDimitry Andric     if (Name == "stackprotectorcheck") {
13080b57cec5SDimitry Andric       NewFn = nullptr;
13090b57cec5SDimitry Andric       return true;
13100b57cec5SDimitry Andric     }
13110b57cec5SDimitry Andric     break;
13120b57cec5SDimitry Andric 
1313d409305fSDimitry Andric   case 'v': {
1314d409305fSDimitry Andric     if (Name == "var.annotation" && F->arg_size() == 4) {
1315d409305fSDimitry Andric       rename(F);
1316bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(
1317bdd1243dSDimitry Andric           F->getParent(), Intrinsic::var_annotation,
1318bdd1243dSDimitry Andric           {{F->arg_begin()->getType(), F->getArg(1)->getType()}});
1319d409305fSDimitry Andric       return true;
1320d409305fSDimitry Andric     }
1321d409305fSDimitry Andric     break;
1322d409305fSDimitry Andric   }
1323d409305fSDimitry Andric 
13241ac55f4cSDimitry Andric   case 'w':
13255f757f3fSDimitry Andric     if (Name.consume_front("wasm.")) {
13265f757f3fSDimitry Andric       Intrinsic::ID ID =
13275f757f3fSDimitry Andric           StringSwitch<Intrinsic::ID>(Name)
13285f757f3fSDimitry Andric               .StartsWith("fma.", Intrinsic::wasm_relaxed_madd)
13295f757f3fSDimitry Andric               .StartsWith("fms.", Intrinsic::wasm_relaxed_nmadd)
13305f757f3fSDimitry Andric               .StartsWith("laneselect.", Intrinsic::wasm_relaxed_laneselect)
13315f757f3fSDimitry Andric               .Default(Intrinsic::not_intrinsic);
13325f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
13331ac55f4cSDimitry Andric         rename(F);
13345f757f3fSDimitry Andric         NewFn =
13355f757f3fSDimitry Andric             Intrinsic::getDeclaration(F->getParent(), ID, F->getReturnType());
13361ac55f4cSDimitry Andric         return true;
13371ac55f4cSDimitry Andric       }
13385f757f3fSDimitry Andric 
13395f757f3fSDimitry Andric       if (Name.consume_front("dot.i8x16.i7x16.")) {
13405f757f3fSDimitry Andric         ID = StringSwitch<Intrinsic::ID>(Name)
13415f757f3fSDimitry Andric                  .Case("signed", Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed)
13425f757f3fSDimitry Andric                  .Case("add.signed",
13435f757f3fSDimitry Andric                        Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed)
13445f757f3fSDimitry Andric                  .Default(Intrinsic::not_intrinsic);
13455f757f3fSDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
13461ac55f4cSDimitry Andric           rename(F);
13475f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
13481ac55f4cSDimitry Andric           return true;
13491ac55f4cSDimitry Andric         }
13505f757f3fSDimitry Andric         break; // No other 'wasm.dot.i8x16.i7x16.*'.
13511ac55f4cSDimitry Andric       }
13525f757f3fSDimitry Andric       break; // No other 'wasm.*'.
13531ac55f4cSDimitry Andric     }
13541ac55f4cSDimitry Andric     break;
13551ac55f4cSDimitry Andric 
13560b57cec5SDimitry Andric   case 'x':
13577a6dacacSDimitry Andric     if (upgradeX86IntrinsicFunction(F, Name, NewFn))
13580b57cec5SDimitry Andric       return true;
13590b57cec5SDimitry Andric   }
136081ad6265SDimitry Andric 
136181ad6265SDimitry Andric   auto *ST = dyn_cast<StructType>(F->getReturnType());
13625f757f3fSDimitry Andric   if (ST && (!ST->isLiteral() || ST->isPacked()) &&
13635f757f3fSDimitry Andric       F->getIntrinsicID() != Intrinsic::not_intrinsic) {
136481ad6265SDimitry Andric     // Replace return type with literal non-packed struct. Only do this for
136581ad6265SDimitry Andric     // intrinsics declared to return a struct, not for intrinsics with
136681ad6265SDimitry Andric     // overloaded return type, in which case the exact struct type will be
136781ad6265SDimitry Andric     // mangled into the name.
136881ad6265SDimitry Andric     SmallVector<Intrinsic::IITDescriptor> Desc;
136981ad6265SDimitry Andric     Intrinsic::getIntrinsicInfoTableEntries(F->getIntrinsicID(), Desc);
137081ad6265SDimitry Andric     if (Desc.front().Kind == Intrinsic::IITDescriptor::Struct) {
137181ad6265SDimitry Andric       auto *FT = F->getFunctionType();
137281ad6265SDimitry Andric       auto *NewST = StructType::get(ST->getContext(), ST->elements());
137381ad6265SDimitry Andric       auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());
137481ad6265SDimitry Andric       std::string Name = F->getName().str();
137581ad6265SDimitry Andric       rename(F);
137681ad6265SDimitry Andric       NewFn = Function::Create(NewFT, F->getLinkage(), F->getAddressSpace(),
137781ad6265SDimitry Andric                                Name, F->getParent());
137881ad6265SDimitry Andric 
137981ad6265SDimitry Andric       // The new function may also need remangling.
1380f3fd488fSDimitry Andric       if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn))
138181ad6265SDimitry Andric         NewFn = *Result;
138281ad6265SDimitry Andric       return true;
138381ad6265SDimitry Andric     }
138481ad6265SDimitry Andric   }
138581ad6265SDimitry Andric 
13860b57cec5SDimitry Andric   // Remangle our intrinsic since we upgrade the mangling
13870b57cec5SDimitry Andric   auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F);
1388bdd1243dSDimitry Andric   if (Result != std::nullopt) {
138981ad6265SDimitry Andric     NewFn = *Result;
13900b57cec5SDimitry Andric     return true;
13910b57cec5SDimitry Andric   }
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric   //  This may not belong here. This function is effectively being overloaded
13940b57cec5SDimitry Andric   //  to both detect an intrinsic which needs upgrading, and to provide the
13950b57cec5SDimitry Andric   //  upgraded form of the intrinsic. We should perhaps have two separate
13960b57cec5SDimitry Andric   //  functions for this.
13970b57cec5SDimitry Andric   return false;
13980b57cec5SDimitry Andric }
13990b57cec5SDimitry Andric 
UpgradeIntrinsicFunction(Function * F,Function * & NewFn)14000b57cec5SDimitry Andric bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
14010b57cec5SDimitry Andric   NewFn = nullptr;
14027a6dacacSDimitry Andric   bool Upgraded = upgradeIntrinsicFunction1(F, NewFn);
14030b57cec5SDimitry Andric   assert(F != NewFn && "Intrinsic function upgraded to the same function");
14040b57cec5SDimitry Andric 
14050b57cec5SDimitry Andric   // Upgrade intrinsic attributes.  This does not change the function.
14060b57cec5SDimitry Andric   if (NewFn)
14070b57cec5SDimitry Andric     F = NewFn;
14080b57cec5SDimitry Andric   if (Intrinsic::ID id = F->getIntrinsicID())
14090b57cec5SDimitry Andric     F->setAttributes(Intrinsic::getAttributes(F->getContext(), id));
14100b57cec5SDimitry Andric   return Upgraded;
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric 
UpgradeGlobalVariable(GlobalVariable * GV)14130b57cec5SDimitry Andric GlobalVariable *llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
14140b57cec5SDimitry Andric   if (!(GV->hasName() && (GV->getName() == "llvm.global_ctors" ||
14150b57cec5SDimitry Andric                           GV->getName() == "llvm.global_dtors")) ||
14160b57cec5SDimitry Andric       !GV->hasInitializer())
14170b57cec5SDimitry Andric     return nullptr;
14180b57cec5SDimitry Andric   ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType());
14190b57cec5SDimitry Andric   if (!ATy)
14200b57cec5SDimitry Andric     return nullptr;
14210b57cec5SDimitry Andric   StructType *STy = dyn_cast<StructType>(ATy->getElementType());
14220b57cec5SDimitry Andric   if (!STy || STy->getNumElements() != 2)
14230b57cec5SDimitry Andric     return nullptr;
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric   LLVMContext &C = GV->getContext();
14260b57cec5SDimitry Andric   IRBuilder<> IRB(C);
14270b57cec5SDimitry Andric   auto EltTy = StructType::get(STy->getElementType(0), STy->getElementType(1),
14285f757f3fSDimitry Andric                                IRB.getPtrTy());
14290b57cec5SDimitry Andric   Constant *Init = GV->getInitializer();
14300b57cec5SDimitry Andric   unsigned N = Init->getNumOperands();
14310b57cec5SDimitry Andric   std::vector<Constant *> NewCtors(N);
14320b57cec5SDimitry Andric   for (unsigned i = 0; i != N; ++i) {
14330b57cec5SDimitry Andric     auto Ctor = cast<Constant>(Init->getOperand(i));
14345f757f3fSDimitry Andric     NewCtors[i] = ConstantStruct::get(EltTy, Ctor->getAggregateElement(0u),
14355f757f3fSDimitry Andric                                       Ctor->getAggregateElement(1),
14365f757f3fSDimitry Andric                                       Constant::getNullValue(IRB.getPtrTy()));
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric   Constant *NewInit = ConstantArray::get(ArrayType::get(EltTy, N), NewCtors);
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric   return new GlobalVariable(NewInit->getType(), false, GV->getLinkage(),
14410b57cec5SDimitry Andric                             NewInit, GV->getName());
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric // Handles upgrading SSE2/AVX2/AVX512BW PSLLDQ intrinsics by converting them
14450b57cec5SDimitry Andric // to byte shuffles.
upgradeX86PSLLDQIntrinsics(IRBuilder<> & Builder,Value * Op,unsigned Shift)14467a6dacacSDimitry Andric static Value *upgradeX86PSLLDQIntrinsics(IRBuilder<> &Builder, Value *Op,
14477a6dacacSDimitry Andric                                          unsigned Shift) {
1448e8d8bef9SDimitry Andric   auto *ResultTy = cast<FixedVectorType>(Op->getType());
14495ffd83dbSDimitry Andric   unsigned NumElts = ResultTy->getNumElements() * 8;
14500b57cec5SDimitry Andric 
14510b57cec5SDimitry Andric   // Bitcast from a 64-bit element type to a byte element type.
14525ffd83dbSDimitry Andric   Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
14530b57cec5SDimitry Andric   Op = Builder.CreateBitCast(Op, VecTy, "cast");
14540b57cec5SDimitry Andric 
14550b57cec5SDimitry Andric   // We'll be shuffling in zeroes.
14560b57cec5SDimitry Andric   Value *Res = Constant::getNullValue(VecTy);
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
14590b57cec5SDimitry Andric   // we'll just return the zero vector.
14600b57cec5SDimitry Andric   if (Shift < 16) {
14615ffd83dbSDimitry Andric     int Idxs[64];
14620b57cec5SDimitry Andric     // 256/512-bit version is split into 2/4 16-byte lanes.
14630b57cec5SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 16)
14640b57cec5SDimitry Andric       for (unsigned i = 0; i != 16; ++i) {
14650b57cec5SDimitry Andric         unsigned Idx = NumElts + i - Shift;
14660b57cec5SDimitry Andric         if (Idx < NumElts)
14670b57cec5SDimitry Andric           Idx -= NumElts - 16; // end of lane, switch operand.
14680b57cec5SDimitry Andric         Idxs[l + i] = Idx + l;
14690b57cec5SDimitry Andric       }
14700b57cec5SDimitry Andric 
1471bdd1243dSDimitry Andric     Res = Builder.CreateShuffleVector(Res, Op, ArrayRef(Idxs, NumElts));
14720b57cec5SDimitry Andric   }
14730b57cec5SDimitry Andric 
14740b57cec5SDimitry Andric   // Bitcast back to a 64-bit element type.
14750b57cec5SDimitry Andric   return Builder.CreateBitCast(Res, ResultTy, "cast");
14760b57cec5SDimitry Andric }
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric // Handles upgrading SSE2/AVX2/AVX512BW PSRLDQ intrinsics by converting them
14790b57cec5SDimitry Andric // to byte shuffles.
upgradeX86PSRLDQIntrinsics(IRBuilder<> & Builder,Value * Op,unsigned Shift)14807a6dacacSDimitry Andric static Value *upgradeX86PSRLDQIntrinsics(IRBuilder<> &Builder, Value *Op,
14810b57cec5SDimitry Andric                                          unsigned Shift) {
1482e8d8bef9SDimitry Andric   auto *ResultTy = cast<FixedVectorType>(Op->getType());
14835ffd83dbSDimitry Andric   unsigned NumElts = ResultTy->getNumElements() * 8;
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   // Bitcast from a 64-bit element type to a byte element type.
14865ffd83dbSDimitry Andric   Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
14870b57cec5SDimitry Andric   Op = Builder.CreateBitCast(Op, VecTy, "cast");
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric   // We'll be shuffling in zeroes.
14900b57cec5SDimitry Andric   Value *Res = Constant::getNullValue(VecTy);
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric   // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
14930b57cec5SDimitry Andric   // we'll just return the zero vector.
14940b57cec5SDimitry Andric   if (Shift < 16) {
14955ffd83dbSDimitry Andric     int Idxs[64];
14960b57cec5SDimitry Andric     // 256/512-bit version is split into 2/4 16-byte lanes.
14970b57cec5SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 16)
14980b57cec5SDimitry Andric       for (unsigned i = 0; i != 16; ++i) {
14990b57cec5SDimitry Andric         unsigned Idx = i + Shift;
15000b57cec5SDimitry Andric         if (Idx >= 16)
15010b57cec5SDimitry Andric           Idx += NumElts - 16; // end of lane, switch operand.
15020b57cec5SDimitry Andric         Idxs[l + i] = Idx + l;
15030b57cec5SDimitry Andric       }
15040b57cec5SDimitry Andric 
1505bdd1243dSDimitry Andric     Res = Builder.CreateShuffleVector(Op, Res, ArrayRef(Idxs, NumElts));
15060b57cec5SDimitry Andric   }
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric   // Bitcast back to a 64-bit element type.
15090b57cec5SDimitry Andric   return Builder.CreateBitCast(Res, ResultTy, "cast");
15100b57cec5SDimitry Andric }
15110b57cec5SDimitry Andric 
getX86MaskVec(IRBuilder<> & Builder,Value * Mask,unsigned NumElts)15120b57cec5SDimitry Andric static Value *getX86MaskVec(IRBuilder<> &Builder, Value *Mask,
15130b57cec5SDimitry Andric                             unsigned NumElts) {
1514e8d8bef9SDimitry Andric   assert(isPowerOf2_32(NumElts) && "Expected power-of-2 mask elements");
15155ffd83dbSDimitry Andric   llvm::VectorType *MaskTy = FixedVectorType::get(
15165ffd83dbSDimitry Andric       Builder.getInt1Ty(), cast<IntegerType>(Mask->getType())->getBitWidth());
15170b57cec5SDimitry Andric   Mask = Builder.CreateBitCast(Mask, MaskTy);
15180b57cec5SDimitry Andric 
1519e8d8bef9SDimitry Andric   // If we have less than 8 elements (1, 2 or 4), then the starting mask was an
1520e8d8bef9SDimitry Andric   // i8 and we need to extract down to the right number of elements.
1521e8d8bef9SDimitry Andric   if (NumElts <= 4) {
15225ffd83dbSDimitry Andric     int Indices[4];
15230b57cec5SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
15240b57cec5SDimitry Andric       Indices[i] = i;
1525bdd1243dSDimitry Andric     Mask = Builder.CreateShuffleVector(Mask, Mask, ArrayRef(Indices, NumElts),
1526bdd1243dSDimitry Andric                                        "extract");
15270b57cec5SDimitry Andric   }
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric   return Mask;
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric 
emitX86Select(IRBuilder<> & Builder,Value * Mask,Value * Op0,Value * Op1)15327a6dacacSDimitry Andric static Value *emitX86Select(IRBuilder<> &Builder, Value *Mask, Value *Op0,
15337a6dacacSDimitry Andric                             Value *Op1) {
15340b57cec5SDimitry Andric   // If the mask is all ones just emit the first operation.
15350b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
15360b57cec5SDimitry Andric     if (C->isAllOnesValue())
15370b57cec5SDimitry Andric       return Op0;
15380b57cec5SDimitry Andric 
15395ffd83dbSDimitry Andric   Mask = getX86MaskVec(Builder, Mask,
1540e8d8bef9SDimitry Andric                        cast<FixedVectorType>(Op0->getType())->getNumElements());
15410b57cec5SDimitry Andric   return Builder.CreateSelect(Mask, Op0, Op1);
15420b57cec5SDimitry Andric }
15430b57cec5SDimitry Andric 
emitX86ScalarSelect(IRBuilder<> & Builder,Value * Mask,Value * Op0,Value * Op1)15447a6dacacSDimitry Andric static Value *emitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask, Value *Op0,
15457a6dacacSDimitry Andric                                   Value *Op1) {
15460b57cec5SDimitry Andric   // If the mask is all ones just emit the first operation.
15470b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
15480b57cec5SDimitry Andric     if (C->isAllOnesValue())
15490b57cec5SDimitry Andric       return Op0;
15500b57cec5SDimitry Andric 
15515ffd83dbSDimitry Andric   auto *MaskTy = FixedVectorType::get(Builder.getInt1Ty(),
15520b57cec5SDimitry Andric                                       Mask->getType()->getIntegerBitWidth());
15530b57cec5SDimitry Andric   Mask = Builder.CreateBitCast(Mask, MaskTy);
15540b57cec5SDimitry Andric   Mask = Builder.CreateExtractElement(Mask, (uint64_t)0);
15550b57cec5SDimitry Andric   return Builder.CreateSelect(Mask, Op0, Op1);
15560b57cec5SDimitry Andric }
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric // Handle autoupgrade for masked PALIGNR and VALIGND/Q intrinsics.
15590b57cec5SDimitry Andric // PALIGNR handles large immediates by shifting while VALIGN masks the immediate
15600b57cec5SDimitry Andric // 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)15617a6dacacSDimitry Andric static Value *upgradeX86ALIGNIntrinsics(IRBuilder<> &Builder, Value *Op0,
15620b57cec5SDimitry Andric                                         Value *Op1, Value *Shift,
15630b57cec5SDimitry Andric                                         Value *Passthru, Value *Mask,
15640b57cec5SDimitry Andric                                         bool IsVALIGN) {
15650b57cec5SDimitry Andric   unsigned ShiftVal = cast<llvm::ConstantInt>(Shift)->getZExtValue();
15660b57cec5SDimitry Andric 
1567e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
15680b57cec5SDimitry Andric   assert((IsVALIGN || NumElts % 16 == 0) && "Illegal NumElts for PALIGNR!");
15690b57cec5SDimitry Andric   assert((!IsVALIGN || NumElts <= 16) && "NumElts too large for VALIGN!");
15700b57cec5SDimitry Andric   assert(isPowerOf2_32(NumElts) && "NumElts not a power of 2!");
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   // Mask the immediate for VALIGN.
15730b57cec5SDimitry Andric   if (IsVALIGN)
15740b57cec5SDimitry Andric     ShiftVal &= (NumElts - 1);
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   // If palignr is shifting the pair of vectors more than the size of two
15770b57cec5SDimitry Andric   // lanes, emit zero.
15780b57cec5SDimitry Andric   if (ShiftVal >= 32)
15790b57cec5SDimitry Andric     return llvm::Constant::getNullValue(Op0->getType());
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric   // If palignr is shifting the pair of input vectors more than one lane,
15820b57cec5SDimitry Andric   // but less than two lanes, convert to shifting in zeroes.
15830b57cec5SDimitry Andric   if (ShiftVal > 16) {
15840b57cec5SDimitry Andric     ShiftVal -= 16;
15850b57cec5SDimitry Andric     Op1 = Op0;
15860b57cec5SDimitry Andric     Op0 = llvm::Constant::getNullValue(Op0->getType());
15870b57cec5SDimitry Andric   }
15880b57cec5SDimitry Andric 
15895ffd83dbSDimitry Andric   int Indices[64];
15900b57cec5SDimitry Andric   // 256-bit palignr operates on 128-bit lanes so we need to handle that
15910b57cec5SDimitry Andric   for (unsigned l = 0; l < NumElts; l += 16) {
15920b57cec5SDimitry Andric     for (unsigned i = 0; i != 16; ++i) {
15930b57cec5SDimitry Andric       unsigned Idx = ShiftVal + i;
15940b57cec5SDimitry Andric       if (!IsVALIGN && Idx >= 16) // Disable wrap for VALIGN.
15950b57cec5SDimitry Andric         Idx += NumElts - 16; // End of lane, switch operand.
15960b57cec5SDimitry Andric       Indices[l + i] = Idx + l;
15970b57cec5SDimitry Andric     }
15980b57cec5SDimitry Andric   }
15990b57cec5SDimitry Andric 
1600bdd1243dSDimitry Andric   Value *Align = Builder.CreateShuffleVector(
1601bdd1243dSDimitry Andric       Op1, Op0, ArrayRef(Indices, NumElts), "palignr");
16020b57cec5SDimitry Andric 
16037a6dacacSDimitry Andric   return emitX86Select(Builder, Mask, Align, Passthru);
16040b57cec5SDimitry Andric }
16050b57cec5SDimitry Andric 
upgradeX86VPERMT2Intrinsics(IRBuilder<> & Builder,CallBase & CI,bool ZeroMask,bool IndexForm)16067a6dacacSDimitry Andric static Value *upgradeX86VPERMT2Intrinsics(IRBuilder<> &Builder, CallBase &CI,
16070b57cec5SDimitry Andric                                           bool ZeroMask, bool IndexForm) {
16080b57cec5SDimitry Andric   Type *Ty = CI.getType();
16090b57cec5SDimitry Andric   unsigned VecWidth = Ty->getPrimitiveSizeInBits();
16100b57cec5SDimitry Andric   unsigned EltWidth = Ty->getScalarSizeInBits();
16110b57cec5SDimitry Andric   bool IsFloat = Ty->isFPOrFPVectorTy();
16120b57cec5SDimitry Andric   Intrinsic::ID IID;
16130b57cec5SDimitry Andric   if (VecWidth == 128 && EltWidth == 32 && IsFloat)
16140b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_128;
16150b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 32 && !IsFloat)
16160b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_128;
16170b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 64 && IsFloat)
16180b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_128;
16190b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 64 && !IsFloat)
16200b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_128;
16210b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 32 && IsFloat)
16220b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_256;
16230b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
16240b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_256;
16250b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
16260b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_256;
16270b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
16280b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_256;
16290b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
16300b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_512;
16310b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
16320b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_512;
16330b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
16340b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_512;
16350b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
16360b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_512;
16370b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 16)
16380b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_128;
16390b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 16)
16400b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_256;
16410b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 16)
16420b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_512;
16430b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 8)
16440b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_128;
16450b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 8)
16460b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_256;
16470b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 8)
16480b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_512;
16490b57cec5SDimitry Andric   else
16500b57cec5SDimitry Andric     llvm_unreachable("Unexpected intrinsic");
16510b57cec5SDimitry Andric 
16520b57cec5SDimitry Andric   Value *Args[] = { CI.getArgOperand(0) , CI.getArgOperand(1),
16530b57cec5SDimitry Andric                     CI.getArgOperand(2) };
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   // If this isn't index form we need to swap operand 0 and 1.
16560b57cec5SDimitry Andric   if (!IndexForm)
16570b57cec5SDimitry Andric     std::swap(Args[0], Args[1]);
16580b57cec5SDimitry Andric 
16590b57cec5SDimitry Andric   Value *V = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
16600b57cec5SDimitry Andric                                 Args);
16610b57cec5SDimitry Andric   Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty)
16620b57cec5SDimitry Andric                              : Builder.CreateBitCast(CI.getArgOperand(1),
16630b57cec5SDimitry Andric                                                      Ty);
16647a6dacacSDimitry Andric   return emitX86Select(Builder, CI.getArgOperand(3), V, PassThru);
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric 
upgradeX86BinaryIntrinsics(IRBuilder<> & Builder,CallBase & CI,Intrinsic::ID IID)16677a6dacacSDimitry Andric static Value *upgradeX86BinaryIntrinsics(IRBuilder<> &Builder, CallBase &CI,
1668e8d8bef9SDimitry Andric                                          Intrinsic::ID IID) {
16690b57cec5SDimitry Andric   Type *Ty = CI.getType();
16700b57cec5SDimitry Andric   Value *Op0 = CI.getOperand(0);
16710b57cec5SDimitry Andric   Value *Op1 = CI.getOperand(1);
16720b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
16730b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Op0, Op1});
16740b57cec5SDimitry Andric 
1675349cc55cSDimitry Andric   if (CI.arg_size() == 4) { // For masked intrinsics.
16760b57cec5SDimitry Andric     Value *VecSrc = CI.getOperand(2);
16770b57cec5SDimitry Andric     Value *Mask = CI.getOperand(3);
16787a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
16790b57cec5SDimitry Andric   }
16800b57cec5SDimitry Andric   return Res;
16810b57cec5SDimitry Andric }
16820b57cec5SDimitry Andric 
upgradeX86Rotate(IRBuilder<> & Builder,CallBase & CI,bool IsRotateRight)168381ad6265SDimitry Andric static Value *upgradeX86Rotate(IRBuilder<> &Builder, CallBase &CI,
16840b57cec5SDimitry Andric                                bool IsRotateRight) {
16850b57cec5SDimitry Andric   Type *Ty = CI.getType();
16860b57cec5SDimitry Andric   Value *Src = CI.getArgOperand(0);
16870b57cec5SDimitry Andric   Value *Amt = CI.getArgOperand(1);
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric   // Amount may be scalar immediate, in which case create a splat vector.
16900b57cec5SDimitry Andric   // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
16910b57cec5SDimitry Andric   // we only care about the lowest log2 bits anyway.
16920b57cec5SDimitry Andric   if (Amt->getType() != Ty) {
1693e8d8bef9SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
16940b57cec5SDimitry Andric     Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
16950b57cec5SDimitry Andric     Amt = Builder.CreateVectorSplat(NumElts, Amt);
16960b57cec5SDimitry Andric   }
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric   Intrinsic::ID IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl;
16990b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
17000b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Src, Src, Amt});
17010b57cec5SDimitry Andric 
1702349cc55cSDimitry Andric   if (CI.arg_size() == 4) { // For masked intrinsics.
17030b57cec5SDimitry Andric     Value *VecSrc = CI.getOperand(2);
17040b57cec5SDimitry Andric     Value *Mask = CI.getOperand(3);
17057a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
17060b57cec5SDimitry Andric   }
17070b57cec5SDimitry Andric   return Res;
17080b57cec5SDimitry Andric }
17090b57cec5SDimitry Andric 
upgradeX86vpcom(IRBuilder<> & Builder,CallBase & CI,unsigned Imm,bool IsSigned)171081ad6265SDimitry Andric static Value *upgradeX86vpcom(IRBuilder<> &Builder, CallBase &CI, unsigned Imm,
17110b57cec5SDimitry Andric                               bool IsSigned) {
17120b57cec5SDimitry Andric   Type *Ty = CI.getType();
17130b57cec5SDimitry Andric   Value *LHS = CI.getArgOperand(0);
17140b57cec5SDimitry Andric   Value *RHS = CI.getArgOperand(1);
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric   CmpInst::Predicate Pred;
17170b57cec5SDimitry Andric   switch (Imm) {
17180b57cec5SDimitry Andric   case 0x0:
17190b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
17200b57cec5SDimitry Andric     break;
17210b57cec5SDimitry Andric   case 0x1:
17220b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
17230b57cec5SDimitry Andric     break;
17240b57cec5SDimitry Andric   case 0x2:
17250b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
17260b57cec5SDimitry Andric     break;
17270b57cec5SDimitry Andric   case 0x3:
17280b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
17290b57cec5SDimitry Andric     break;
17300b57cec5SDimitry Andric   case 0x4:
17310b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
17320b57cec5SDimitry Andric     break;
17330b57cec5SDimitry Andric   case 0x5:
17340b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
17350b57cec5SDimitry Andric     break;
17360b57cec5SDimitry Andric   case 0x6:
17370b57cec5SDimitry Andric     return Constant::getNullValue(Ty); // FALSE
17380b57cec5SDimitry Andric   case 0x7:
17390b57cec5SDimitry Andric     return Constant::getAllOnesValue(Ty); // TRUE
17400b57cec5SDimitry Andric   default:
17410b57cec5SDimitry Andric     llvm_unreachable("Unknown XOP vpcom/vpcomu predicate");
17420b57cec5SDimitry Andric   }
17430b57cec5SDimitry Andric 
17440b57cec5SDimitry Andric   Value *Cmp = Builder.CreateICmp(Pred, LHS, RHS);
17450b57cec5SDimitry Andric   Value *Ext = Builder.CreateSExt(Cmp, Ty);
17460b57cec5SDimitry Andric   return Ext;
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric 
upgradeX86ConcatShift(IRBuilder<> & Builder,CallBase & CI,bool IsShiftRight,bool ZeroMask)174981ad6265SDimitry Andric static Value *upgradeX86ConcatShift(IRBuilder<> &Builder, CallBase &CI,
17500b57cec5SDimitry Andric                                     bool IsShiftRight, bool ZeroMask) {
17510b57cec5SDimitry Andric   Type *Ty = CI.getType();
17520b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
17530b57cec5SDimitry Andric   Value *Op1 = CI.getArgOperand(1);
17540b57cec5SDimitry Andric   Value *Amt = CI.getArgOperand(2);
17550b57cec5SDimitry Andric 
17560b57cec5SDimitry Andric   if (IsShiftRight)
17570b57cec5SDimitry Andric     std::swap(Op0, Op1);
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric   // Amount may be scalar immediate, in which case create a splat vector.
17600b57cec5SDimitry Andric   // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
17610b57cec5SDimitry Andric   // we only care about the lowest log2 bits anyway.
17620b57cec5SDimitry Andric   if (Amt->getType() != Ty) {
1763e8d8bef9SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
17640b57cec5SDimitry Andric     Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
17650b57cec5SDimitry Andric     Amt = Builder.CreateVectorSplat(NumElts, Amt);
17660b57cec5SDimitry Andric   }
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric   Intrinsic::ID IID = IsShiftRight ? Intrinsic::fshr : Intrinsic::fshl;
17690b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
17700b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Op0, Op1, Amt});
17710b57cec5SDimitry Andric 
1772349cc55cSDimitry Andric   unsigned NumArgs = CI.arg_size();
17730b57cec5SDimitry Andric   if (NumArgs >= 4) { // For masked intrinsics.
17740b57cec5SDimitry Andric     Value *VecSrc = NumArgs == 5 ? CI.getArgOperand(3) :
17750b57cec5SDimitry Andric                     ZeroMask     ? ConstantAggregateZero::get(CI.getType()) :
17760b57cec5SDimitry Andric                                    CI.getArgOperand(0);
17770b57cec5SDimitry Andric     Value *Mask = CI.getOperand(NumArgs - 1);
17787a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
17790b57cec5SDimitry Andric   }
17800b57cec5SDimitry Andric   return Res;
17810b57cec5SDimitry Andric }
17820b57cec5SDimitry Andric 
upgradeMaskedStore(IRBuilder<> & Builder,Value * Ptr,Value * Data,Value * Mask,bool Aligned)17837a6dacacSDimitry Andric static Value *upgradeMaskedStore(IRBuilder<> &Builder, Value *Ptr, Value *Data,
17847a6dacacSDimitry Andric                                  Value *Mask, bool Aligned) {
17850b57cec5SDimitry Andric   // Cast the pointer to the right type.
17860b57cec5SDimitry Andric   Ptr = Builder.CreateBitCast(Ptr,
17870b57cec5SDimitry Andric                               llvm::PointerType::getUnqual(Data->getType()));
17885ffd83dbSDimitry Andric   const Align Alignment =
17895ffd83dbSDimitry Andric       Aligned
1790bdd1243dSDimitry Andric           ? Align(Data->getType()->getPrimitiveSizeInBits().getFixedValue() / 8)
17915ffd83dbSDimitry Andric           : Align(1);
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric   // If the mask is all ones just emit a regular store.
17940b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
17950b57cec5SDimitry Andric     if (C->isAllOnesValue())
17965ffd83dbSDimitry Andric       return Builder.CreateAlignedStore(Data, Ptr, Alignment);
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric   // Convert the mask from an integer type to a vector of i1.
1799e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Data->getType())->getNumElements();
18000b57cec5SDimitry Andric   Mask = getX86MaskVec(Builder, Mask, NumElts);
18015ffd83dbSDimitry Andric   return Builder.CreateMaskedStore(Data, Ptr, Alignment, Mask);
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
upgradeMaskedLoad(IRBuilder<> & Builder,Value * Ptr,Value * Passthru,Value * Mask,bool Aligned)18047a6dacacSDimitry Andric static Value *upgradeMaskedLoad(IRBuilder<> &Builder, Value *Ptr,
18057a6dacacSDimitry Andric                                 Value *Passthru, Value *Mask, bool Aligned) {
18060b57cec5SDimitry Andric   Type *ValTy = Passthru->getType();
18070b57cec5SDimitry Andric   // Cast the pointer to the right type.
18080b57cec5SDimitry Andric   Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(ValTy));
18095ffd83dbSDimitry Andric   const Align Alignment =
18105ffd83dbSDimitry Andric       Aligned
1811bdd1243dSDimitry Andric           ? Align(
1812bdd1243dSDimitry Andric                 Passthru->getType()->getPrimitiveSizeInBits().getFixedValue() /
18135ffd83dbSDimitry Andric                 8)
18145ffd83dbSDimitry Andric           : Align(1);
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric   // If the mask is all ones just emit a regular store.
18170b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
18180b57cec5SDimitry Andric     if (C->isAllOnesValue())
18195ffd83dbSDimitry Andric       return Builder.CreateAlignedLoad(ValTy, Ptr, Alignment);
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   // Convert the mask from an integer type to a vector of i1.
1822fe6060f1SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(ValTy)->getNumElements();
18230b57cec5SDimitry Andric   Mask = getX86MaskVec(Builder, Mask, NumElts);
1824fe6060f1SDimitry Andric   return Builder.CreateMaskedLoad(ValTy, Ptr, Alignment, Mask, Passthru);
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric 
upgradeAbs(IRBuilder<> & Builder,CallBase & CI)182781ad6265SDimitry Andric static Value *upgradeAbs(IRBuilder<> &Builder, CallBase &CI) {
1828e8d8bef9SDimitry Andric   Type *Ty = CI.getType();
18290b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
1830e8d8bef9SDimitry Andric   Function *F = Intrinsic::getDeclaration(CI.getModule(), Intrinsic::abs, Ty);
1831e8d8bef9SDimitry Andric   Value *Res = Builder.CreateCall(F, {Op0, Builder.getInt1(false)});
1832349cc55cSDimitry Andric   if (CI.arg_size() == 3)
18337a6dacacSDimitry Andric     Res = emitX86Select(Builder, CI.getArgOperand(2), Res, CI.getArgOperand(1));
18340b57cec5SDimitry Andric   return Res;
18350b57cec5SDimitry Andric }
18360b57cec5SDimitry Andric 
upgradePMULDQ(IRBuilder<> & Builder,CallBase & CI,bool IsSigned)183781ad6265SDimitry Andric static Value *upgradePMULDQ(IRBuilder<> &Builder, CallBase &CI, bool IsSigned) {
18380b57cec5SDimitry Andric   Type *Ty = CI.getType();
18390b57cec5SDimitry Andric 
18400b57cec5SDimitry Andric   // Arguments have a vXi32 type so cast to vXi64.
18410b57cec5SDimitry Andric   Value *LHS = Builder.CreateBitCast(CI.getArgOperand(0), Ty);
18420b57cec5SDimitry Andric   Value *RHS = Builder.CreateBitCast(CI.getArgOperand(1), Ty);
18430b57cec5SDimitry Andric 
18440b57cec5SDimitry Andric   if (IsSigned) {
18450b57cec5SDimitry Andric     // Shift left then arithmetic shift right.
18460b57cec5SDimitry Andric     Constant *ShiftAmt = ConstantInt::get(Ty, 32);
18470b57cec5SDimitry Andric     LHS = Builder.CreateShl(LHS, ShiftAmt);
18480b57cec5SDimitry Andric     LHS = Builder.CreateAShr(LHS, ShiftAmt);
18490b57cec5SDimitry Andric     RHS = Builder.CreateShl(RHS, ShiftAmt);
18500b57cec5SDimitry Andric     RHS = Builder.CreateAShr(RHS, ShiftAmt);
18510b57cec5SDimitry Andric   } else {
18520b57cec5SDimitry Andric     // Clear the upper bits.
18530b57cec5SDimitry Andric     Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
18540b57cec5SDimitry Andric     LHS = Builder.CreateAnd(LHS, Mask);
18550b57cec5SDimitry Andric     RHS = Builder.CreateAnd(RHS, Mask);
18560b57cec5SDimitry Andric   }
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric   Value *Res = Builder.CreateMul(LHS, RHS);
18590b57cec5SDimitry Andric 
1860349cc55cSDimitry Andric   if (CI.arg_size() == 4)
18617a6dacacSDimitry Andric     Res = emitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2));
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   return Res;
18640b57cec5SDimitry Andric }
18650b57cec5SDimitry Andric 
18660b57cec5SDimitry Andric // Applying mask on vector of i1's and make sure result is at least 8 bits wide.
applyX86MaskOn1BitsVec(IRBuilder<> & Builder,Value * Vec,Value * Mask)18677a6dacacSDimitry Andric static Value *applyX86MaskOn1BitsVec(IRBuilder<> &Builder, Value *Vec,
18680b57cec5SDimitry Andric                                      Value *Mask) {
1869e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
18700b57cec5SDimitry Andric   if (Mask) {
18710b57cec5SDimitry Andric     const auto *C = dyn_cast<Constant>(Mask);
18720b57cec5SDimitry Andric     if (!C || !C->isAllOnesValue())
18730b57cec5SDimitry Andric       Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
18740b57cec5SDimitry Andric   }
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric   if (NumElts < 8) {
18775ffd83dbSDimitry Andric     int Indices[8];
18780b57cec5SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
18790b57cec5SDimitry Andric       Indices[i] = i;
18800b57cec5SDimitry Andric     for (unsigned i = NumElts; i != 8; ++i)
18810b57cec5SDimitry Andric       Indices[i] = NumElts + i % NumElts;
18820b57cec5SDimitry Andric     Vec = Builder.CreateShuffleVector(Vec,
18830b57cec5SDimitry Andric                                       Constant::getNullValue(Vec->getType()),
18840b57cec5SDimitry Andric                                       Indices);
18850b57cec5SDimitry Andric   }
18860b57cec5SDimitry Andric   return Builder.CreateBitCast(Vec, Builder.getIntNTy(std::max(NumElts, 8U)));
18870b57cec5SDimitry Andric }
18880b57cec5SDimitry Andric 
upgradeMaskedCompare(IRBuilder<> & Builder,CallBase & CI,unsigned CC,bool Signed)188981ad6265SDimitry Andric static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallBase &CI,
18900b57cec5SDimitry Andric                                    unsigned CC, bool Signed) {
18910b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
1892e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   Value *Cmp;
18950b57cec5SDimitry Andric   if (CC == 3) {
18965ffd83dbSDimitry Andric     Cmp = Constant::getNullValue(
18975ffd83dbSDimitry Andric         FixedVectorType::get(Builder.getInt1Ty(), NumElts));
18980b57cec5SDimitry Andric   } else if (CC == 7) {
18995ffd83dbSDimitry Andric     Cmp = Constant::getAllOnesValue(
19005ffd83dbSDimitry Andric         FixedVectorType::get(Builder.getInt1Ty(), NumElts));
19010b57cec5SDimitry Andric   } else {
19020b57cec5SDimitry Andric     ICmpInst::Predicate Pred;
19030b57cec5SDimitry Andric     switch (CC) {
19040b57cec5SDimitry Andric     default: llvm_unreachable("Unknown condition code");
19050b57cec5SDimitry Andric     case 0: Pred = ICmpInst::ICMP_EQ;  break;
19060b57cec5SDimitry Andric     case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
19070b57cec5SDimitry Andric     case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
19080b57cec5SDimitry Andric     case 4: Pred = ICmpInst::ICMP_NE;  break;
19090b57cec5SDimitry Andric     case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
19100b57cec5SDimitry Andric     case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
19110b57cec5SDimitry Andric     }
19120b57cec5SDimitry Andric     Cmp = Builder.CreateICmp(Pred, Op0, CI.getArgOperand(1));
19130b57cec5SDimitry Andric   }
19140b57cec5SDimitry Andric 
1915349cc55cSDimitry Andric   Value *Mask = CI.getArgOperand(CI.arg_size() - 1);
19160b57cec5SDimitry Andric 
19177a6dacacSDimitry Andric   return applyX86MaskOn1BitsVec(Builder, Cmp, Mask);
19180b57cec5SDimitry Andric }
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric // Replace a masked intrinsic with an older unmasked intrinsic.
upgradeX86MaskedShift(IRBuilder<> & Builder,CallBase & CI,Intrinsic::ID IID)19217a6dacacSDimitry Andric static Value *upgradeX86MaskedShift(IRBuilder<> &Builder, CallBase &CI,
19220b57cec5SDimitry Andric                                     Intrinsic::ID IID) {
19230b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID);
19240b57cec5SDimitry Andric   Value *Rep = Builder.CreateCall(Intrin,
19250b57cec5SDimitry Andric                                  { CI.getArgOperand(0), CI.getArgOperand(1) });
19267a6dacacSDimitry Andric   return emitX86Select(Builder, CI.getArgOperand(3), Rep, CI.getArgOperand(2));
19270b57cec5SDimitry Andric }
19280b57cec5SDimitry Andric 
upgradeMaskedMove(IRBuilder<> & Builder,CallBase & CI)192981ad6265SDimitry Andric static Value *upgradeMaskedMove(IRBuilder<> &Builder, CallBase &CI) {
19300b57cec5SDimitry Andric   Value* A = CI.getArgOperand(0);
19310b57cec5SDimitry Andric   Value* B = CI.getArgOperand(1);
19320b57cec5SDimitry Andric   Value* Src = CI.getArgOperand(2);
19330b57cec5SDimitry Andric   Value* Mask = CI.getArgOperand(3);
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric   Value* AndNode = Builder.CreateAnd(Mask, APInt(8, 1));
19360b57cec5SDimitry Andric   Value* Cmp = Builder.CreateIsNotNull(AndNode);
19370b57cec5SDimitry Andric   Value* Extract1 = Builder.CreateExtractElement(B, (uint64_t)0);
19380b57cec5SDimitry Andric   Value* Extract2 = Builder.CreateExtractElement(Src, (uint64_t)0);
19390b57cec5SDimitry Andric   Value* Select = Builder.CreateSelect(Cmp, Extract1, Extract2);
19400b57cec5SDimitry Andric   return Builder.CreateInsertElement(A, Select, (uint64_t)0);
19410b57cec5SDimitry Andric }
19420b57cec5SDimitry Andric 
upgradeMaskToInt(IRBuilder<> & Builder,CallBase & CI)19437a6dacacSDimitry Andric static Value *upgradeMaskToInt(IRBuilder<> &Builder, CallBase &CI) {
19440b57cec5SDimitry Andric   Value* Op = CI.getArgOperand(0);
19450b57cec5SDimitry Andric   Type* ReturnOp = CI.getType();
1946e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(CI.getType())->getNumElements();
19470b57cec5SDimitry Andric   Value *Mask = getX86MaskVec(Builder, Op, NumElts);
19480b57cec5SDimitry Andric   return Builder.CreateSExt(Mask, ReturnOp, "vpmovm2");
19490b57cec5SDimitry Andric }
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric // Replace intrinsic with unmasked version and a select.
upgradeAVX512MaskToSelect(StringRef Name,IRBuilder<> & Builder,CallBase & CI,Value * & Rep)19520b57cec5SDimitry Andric static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder,
195381ad6265SDimitry Andric                                       CallBase &CI, Value *&Rep) {
19540b57cec5SDimitry Andric   Name = Name.substr(12); // Remove avx512.mask.
19550b57cec5SDimitry Andric 
19560b57cec5SDimitry Andric   unsigned VecWidth = CI.getType()->getPrimitiveSizeInBits();
19570b57cec5SDimitry Andric   unsigned EltWidth = CI.getType()->getScalarSizeInBits();
19580b57cec5SDimitry Andric   Intrinsic::ID IID;
19595f757f3fSDimitry Andric   if (Name.starts_with("max.p")) {
19600b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
19610b57cec5SDimitry Andric       IID = Intrinsic::x86_sse_max_ps;
19620b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
19630b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_max_pd;
19640b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
19650b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_max_ps_256;
19660b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
19670b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_max_pd_256;
19680b57cec5SDimitry Andric     else
19690b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
19705f757f3fSDimitry Andric   } else if (Name.starts_with("min.p")) {
19710b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
19720b57cec5SDimitry Andric       IID = Intrinsic::x86_sse_min_ps;
19730b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
19740b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_min_pd;
19750b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
19760b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_min_ps_256;
19770b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
19780b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_min_pd_256;
19790b57cec5SDimitry Andric     else
19800b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
19815f757f3fSDimitry Andric   } else if (Name.starts_with("pshuf.b.")) {
19820b57cec5SDimitry Andric     if (VecWidth == 128)
19830b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pshuf_b_128;
19840b57cec5SDimitry Andric     else if (VecWidth == 256)
19850b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pshuf_b;
19860b57cec5SDimitry Andric     else if (VecWidth == 512)
19870b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pshuf_b_512;
19880b57cec5SDimitry Andric     else
19890b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
19905f757f3fSDimitry Andric   } else if (Name.starts_with("pmul.hr.sw.")) {
19910b57cec5SDimitry Andric     if (VecWidth == 128)
19920b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pmul_hr_sw_128;
19930b57cec5SDimitry Andric     else if (VecWidth == 256)
19940b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmul_hr_sw;
19950b57cec5SDimitry Andric     else if (VecWidth == 512)
19960b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmul_hr_sw_512;
19970b57cec5SDimitry Andric     else
19980b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
19995f757f3fSDimitry Andric   } else if (Name.starts_with("pmulh.w.")) {
20000b57cec5SDimitry Andric     if (VecWidth == 128)
20010b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmulh_w;
20020b57cec5SDimitry Andric     else if (VecWidth == 256)
20030b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmulh_w;
20040b57cec5SDimitry Andric     else if (VecWidth == 512)
20050b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmulh_w_512;
20060b57cec5SDimitry Andric     else
20070b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20085f757f3fSDimitry Andric   } else if (Name.starts_with("pmulhu.w.")) {
20090b57cec5SDimitry Andric     if (VecWidth == 128)
20100b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmulhu_w;
20110b57cec5SDimitry Andric     else if (VecWidth == 256)
20120b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmulhu_w;
20130b57cec5SDimitry Andric     else if (VecWidth == 512)
20140b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmulhu_w_512;
20150b57cec5SDimitry Andric     else
20160b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20175f757f3fSDimitry Andric   } else if (Name.starts_with("pmaddw.d.")) {
20180b57cec5SDimitry Andric     if (VecWidth == 128)
20190b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmadd_wd;
20200b57cec5SDimitry Andric     else if (VecWidth == 256)
20210b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmadd_wd;
20220b57cec5SDimitry Andric     else if (VecWidth == 512)
20230b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmaddw_d_512;
20240b57cec5SDimitry Andric     else
20250b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20265f757f3fSDimitry Andric   } else if (Name.starts_with("pmaddubs.w.")) {
20270b57cec5SDimitry Andric     if (VecWidth == 128)
20280b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pmadd_ub_sw_128;
20290b57cec5SDimitry Andric     else if (VecWidth == 256)
20300b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmadd_ub_sw;
20310b57cec5SDimitry Andric     else if (VecWidth == 512)
20320b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmaddubs_w_512;
20330b57cec5SDimitry Andric     else
20340b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20355f757f3fSDimitry Andric   } else if (Name.starts_with("packsswb.")) {
20360b57cec5SDimitry Andric     if (VecWidth == 128)
20370b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packsswb_128;
20380b57cec5SDimitry Andric     else if (VecWidth == 256)
20390b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packsswb;
20400b57cec5SDimitry Andric     else if (VecWidth == 512)
20410b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packsswb_512;
20420b57cec5SDimitry Andric     else
20430b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20445f757f3fSDimitry Andric   } else if (Name.starts_with("packssdw.")) {
20450b57cec5SDimitry Andric     if (VecWidth == 128)
20460b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packssdw_128;
20470b57cec5SDimitry Andric     else if (VecWidth == 256)
20480b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packssdw;
20490b57cec5SDimitry Andric     else if (VecWidth == 512)
20500b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packssdw_512;
20510b57cec5SDimitry Andric     else
20520b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20535f757f3fSDimitry Andric   } else if (Name.starts_with("packuswb.")) {
20540b57cec5SDimitry Andric     if (VecWidth == 128)
20550b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packuswb_128;
20560b57cec5SDimitry Andric     else if (VecWidth == 256)
20570b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packuswb;
20580b57cec5SDimitry Andric     else if (VecWidth == 512)
20590b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packuswb_512;
20600b57cec5SDimitry Andric     else
20610b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20625f757f3fSDimitry Andric   } else if (Name.starts_with("packusdw.")) {
20630b57cec5SDimitry Andric     if (VecWidth == 128)
20640b57cec5SDimitry Andric       IID = Intrinsic::x86_sse41_packusdw;
20650b57cec5SDimitry Andric     else if (VecWidth == 256)
20660b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packusdw;
20670b57cec5SDimitry Andric     else if (VecWidth == 512)
20680b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packusdw_512;
20690b57cec5SDimitry Andric     else
20700b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20715f757f3fSDimitry Andric   } else if (Name.starts_with("vpermilvar.")) {
20720b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
20730b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_ps;
20740b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
20750b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_pd;
20760b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
20770b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_ps_256;
20780b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
20790b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_pd_256;
20800b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32)
20810b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
20820b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64)
20830b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
20840b57cec5SDimitry Andric     else
20850b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20860b57cec5SDimitry Andric   } else if (Name == "cvtpd2dq.256") {
20870b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvt_pd2dq_256;
20880b57cec5SDimitry Andric   } else if (Name == "cvtpd2ps.256") {
20890b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvt_pd2_ps_256;
20900b57cec5SDimitry Andric   } else if (Name == "cvttpd2dq.256") {
20910b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvtt_pd2dq_256;
20920b57cec5SDimitry Andric   } else if (Name == "cvttps2dq.128") {
20930b57cec5SDimitry Andric     IID = Intrinsic::x86_sse2_cvttps2dq;
20940b57cec5SDimitry Andric   } else if (Name == "cvttps2dq.256") {
20950b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvtt_ps2dq_256;
20965f757f3fSDimitry Andric   } else if (Name.starts_with("permvar.")) {
20970b57cec5SDimitry Andric     bool IsFloat = CI.getType()->isFPOrFPVectorTy();
20980b57cec5SDimitry Andric     if (VecWidth == 256 && EltWidth == 32 && IsFloat)
20990b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_permps;
21000b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
21010b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_permd;
21020b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
21030b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_df_256;
21040b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
21050b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_di_256;
21060b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
21070b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_sf_512;
21080b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
21090b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_si_512;
21100b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
21110b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_df_512;
21120b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
21130b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_di_512;
21140b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 16)
21150b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_128;
21160b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 16)
21170b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_256;
21180b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 16)
21190b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_512;
21200b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 8)
21210b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_128;
21220b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 8)
21230b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_256;
21240b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 8)
21250b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_512;
21260b57cec5SDimitry Andric     else
21270b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21285f757f3fSDimitry Andric   } else if (Name.starts_with("dbpsadbw.")) {
21290b57cec5SDimitry Andric     if (VecWidth == 128)
21300b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_128;
21310b57cec5SDimitry Andric     else if (VecWidth == 256)
21320b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_256;
21330b57cec5SDimitry Andric     else if (VecWidth == 512)
21340b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_512;
21350b57cec5SDimitry Andric     else
21360b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21375f757f3fSDimitry Andric   } else if (Name.starts_with("pmultishift.qb.")) {
21380b57cec5SDimitry Andric     if (VecWidth == 128)
21390b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_128;
21400b57cec5SDimitry Andric     else if (VecWidth == 256)
21410b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_256;
21420b57cec5SDimitry Andric     else if (VecWidth == 512)
21430b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_512;
21440b57cec5SDimitry Andric     else
21450b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21465f757f3fSDimitry Andric   } else if (Name.starts_with("conflict.")) {
21470b57cec5SDimitry Andric     if (Name[9] == 'd' && VecWidth == 128)
21480b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_128;
21490b57cec5SDimitry Andric     else if (Name[9] == 'd' && VecWidth == 256)
21500b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_256;
21510b57cec5SDimitry Andric     else if (Name[9] == 'd' && VecWidth == 512)
21520b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_512;
21530b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 128)
21540b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_128;
21550b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 256)
21560b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_256;
21570b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 512)
21580b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_512;
21590b57cec5SDimitry Andric     else
21600b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21615f757f3fSDimitry Andric   } else if (Name.starts_with("pavg.")) {
21620b57cec5SDimitry Andric     if (Name[5] == 'b' && VecWidth == 128)
21630b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pavg_b;
21640b57cec5SDimitry Andric     else if (Name[5] == 'b' && VecWidth == 256)
21650b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pavg_b;
21660b57cec5SDimitry Andric     else if (Name[5] == 'b' && VecWidth == 512)
21670b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pavg_b_512;
21680b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 128)
21690b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pavg_w;
21700b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 256)
21710b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pavg_w;
21720b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 512)
21730b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pavg_w_512;
21740b57cec5SDimitry Andric     else
21750b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21760b57cec5SDimitry Andric   } else
21770b57cec5SDimitry Andric     return false;
21780b57cec5SDimitry Andric 
2179349cc55cSDimitry Andric   SmallVector<Value *, 4> Args(CI.args());
21800b57cec5SDimitry Andric   Args.pop_back();
21810b57cec5SDimitry Andric   Args.pop_back();
21820b57cec5SDimitry Andric   Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
21830b57cec5SDimitry Andric                            Args);
2184349cc55cSDimitry Andric   unsigned NumArgs = CI.arg_size();
21857a6dacacSDimitry Andric   Rep = emitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep,
21860b57cec5SDimitry Andric                       CI.getArgOperand(NumArgs - 2));
21870b57cec5SDimitry Andric   return true;
21880b57cec5SDimitry Andric }
21890b57cec5SDimitry Andric 
21900b57cec5SDimitry Andric /// Upgrade comment in call to inline asm that represents an objc retain release
21910b57cec5SDimitry Andric /// marker.
UpgradeInlineAsmString(std::string * AsmStr)21920b57cec5SDimitry Andric void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
21930b57cec5SDimitry Andric   size_t Pos;
21940b57cec5SDimitry Andric   if (AsmStr->find("mov\tfp") == 0 &&
21950b57cec5SDimitry Andric       AsmStr->find("objc_retainAutoreleaseReturnValue") != std::string::npos &&
21960b57cec5SDimitry Andric       (Pos = AsmStr->find("# marker")) != std::string::npos) {
21970b57cec5SDimitry Andric     AsmStr->replace(Pos, 1, ";");
21980b57cec5SDimitry Andric   }
21990b57cec5SDimitry Andric }
22000b57cec5SDimitry Andric 
upgradeARMIntrinsicCall(StringRef Name,CallBase * CI,Function * F,IRBuilder<> & Builder)22017a6dacacSDimitry Andric static Value *upgradeARMIntrinsicCall(StringRef Name, CallBase *CI, Function *F,
22020eae32dcSDimitry Andric                                       IRBuilder<> &Builder) {
22030eae32dcSDimitry Andric   if (Name == "mve.vctp64.old") {
22040eae32dcSDimitry Andric     // Replace the old v4i1 vctp64 with a v2i1 vctp and predicate-casts to the
22050eae32dcSDimitry Andric     // correct type.
22060eae32dcSDimitry Andric     Value *VCTP = Builder.CreateCall(
22070eae32dcSDimitry Andric         Intrinsic::getDeclaration(F->getParent(), Intrinsic::arm_mve_vctp64),
22080eae32dcSDimitry Andric         CI->getArgOperand(0), CI->getName());
22090eae32dcSDimitry Andric     Value *C1 = Builder.CreateCall(
22100eae32dcSDimitry Andric         Intrinsic::getDeclaration(
22110eae32dcSDimitry Andric             F->getParent(), Intrinsic::arm_mve_pred_v2i,
22120eae32dcSDimitry Andric             {VectorType::get(Builder.getInt1Ty(), 2, false)}),
22130eae32dcSDimitry Andric         VCTP);
22140eae32dcSDimitry Andric     return Builder.CreateCall(
22150eae32dcSDimitry Andric         Intrinsic::getDeclaration(
22160eae32dcSDimitry Andric             F->getParent(), Intrinsic::arm_mve_pred_i2v,
22170eae32dcSDimitry Andric             {VectorType::get(Builder.getInt1Ty(), 4, false)}),
22180eae32dcSDimitry Andric         C1);
22190eae32dcSDimitry Andric   } else if (Name == "mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
22200eae32dcSDimitry Andric              Name == "mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
22210eae32dcSDimitry Andric              Name == "mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
22220eae32dcSDimitry Andric              Name == "mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
222306c3fb27SDimitry Andric              Name ==
222406c3fb27SDimitry Andric                  "mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
222506c3fb27SDimitry Andric              Name == "mve.vldr.gather.offset.predicated.v2i64.p0.v2i64.v4i1" ||
22260eae32dcSDimitry Andric              Name == "mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
22270eae32dcSDimitry Andric              Name == "mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
222806c3fb27SDimitry Andric              Name ==
222906c3fb27SDimitry Andric                  "mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
223006c3fb27SDimitry Andric              Name == "mve.vstr.scatter.offset.predicated.p0.v2i64.v2i64.v4i1" ||
22310eae32dcSDimitry Andric              Name == "cde.vcx1q.predicated.v2i64.v4i1" ||
22320eae32dcSDimitry Andric              Name == "cde.vcx1qa.predicated.v2i64.v4i1" ||
22330eae32dcSDimitry Andric              Name == "cde.vcx2q.predicated.v2i64.v4i1" ||
22340eae32dcSDimitry Andric              Name == "cde.vcx2qa.predicated.v2i64.v4i1" ||
22350eae32dcSDimitry Andric              Name == "cde.vcx3q.predicated.v2i64.v4i1" ||
22360eae32dcSDimitry Andric              Name == "cde.vcx3qa.predicated.v2i64.v4i1") {
22370eae32dcSDimitry Andric     std::vector<Type *> Tys;
22380eae32dcSDimitry Andric     unsigned ID = CI->getIntrinsicID();
22390eae32dcSDimitry Andric     Type *V2I1Ty = FixedVectorType::get(Builder.getInt1Ty(), 2);
22400eae32dcSDimitry Andric     switch (ID) {
22410eae32dcSDimitry Andric     case Intrinsic::arm_mve_mull_int_predicated:
22420eae32dcSDimitry Andric     case Intrinsic::arm_mve_vqdmull_predicated:
22430eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_base_predicated:
22440eae32dcSDimitry Andric       Tys = {CI->getType(), CI->getOperand(0)->getType(), V2I1Ty};
22450eae32dcSDimitry Andric       break;
22460eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_base_wb_predicated:
22470eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_base_predicated:
22480eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated:
22490eae32dcSDimitry Andric       Tys = {CI->getOperand(0)->getType(), CI->getOperand(0)->getType(),
22500eae32dcSDimitry Andric              V2I1Ty};
22510eae32dcSDimitry Andric       break;
22520eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_offset_predicated:
22530eae32dcSDimitry Andric       Tys = {CI->getType(), CI->getOperand(0)->getType(),
22540eae32dcSDimitry Andric              CI->getOperand(1)->getType(), V2I1Ty};
22550eae32dcSDimitry Andric       break;
22560eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_offset_predicated:
22570eae32dcSDimitry Andric       Tys = {CI->getOperand(0)->getType(), CI->getOperand(1)->getType(),
22580eae32dcSDimitry Andric              CI->getOperand(2)->getType(), V2I1Ty};
22590eae32dcSDimitry Andric       break;
22600eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx1q_predicated:
22610eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx1qa_predicated:
22620eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx2q_predicated:
22630eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx2qa_predicated:
22640eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx3q_predicated:
22650eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx3qa_predicated:
22660eae32dcSDimitry Andric       Tys = {CI->getOperand(1)->getType(), V2I1Ty};
22670eae32dcSDimitry Andric       break;
22680eae32dcSDimitry Andric     default:
22690eae32dcSDimitry Andric       llvm_unreachable("Unhandled Intrinsic!");
22700eae32dcSDimitry Andric     }
22710eae32dcSDimitry Andric 
22720eae32dcSDimitry Andric     std::vector<Value *> Ops;
22730eae32dcSDimitry Andric     for (Value *Op : CI->args()) {
22740eae32dcSDimitry Andric       Type *Ty = Op->getType();
22750eae32dcSDimitry Andric       if (Ty->getScalarSizeInBits() == 1) {
22760eae32dcSDimitry Andric         Value *C1 = Builder.CreateCall(
22770eae32dcSDimitry Andric             Intrinsic::getDeclaration(
22780eae32dcSDimitry Andric                 F->getParent(), Intrinsic::arm_mve_pred_v2i,
22790eae32dcSDimitry Andric                 {VectorType::get(Builder.getInt1Ty(), 4, false)}),
22800eae32dcSDimitry Andric             Op);
22810eae32dcSDimitry Andric         Op = Builder.CreateCall(
22820eae32dcSDimitry Andric             Intrinsic::getDeclaration(F->getParent(),
22830eae32dcSDimitry Andric                                       Intrinsic::arm_mve_pred_i2v, {V2I1Ty}),
22840eae32dcSDimitry Andric             C1);
22850eae32dcSDimitry Andric       }
22860eae32dcSDimitry Andric       Ops.push_back(Op);
22870eae32dcSDimitry Andric     }
22880eae32dcSDimitry Andric 
22890eae32dcSDimitry Andric     Function *Fn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
22900eae32dcSDimitry Andric     return Builder.CreateCall(Fn, Ops, CI->getName());
22910eae32dcSDimitry Andric   }
229281ad6265SDimitry Andric   llvm_unreachable("Unknown function for ARM CallBase upgrade.");
22930eae32dcSDimitry Andric }
22940eae32dcSDimitry Andric 
upgradeAMDGCNIntrinsicCall(StringRef Name,CallBase * CI,Function * F,IRBuilder<> & Builder)22957a6dacacSDimitry Andric static Value *upgradeAMDGCNIntrinsicCall(StringRef Name, CallBase *CI,
229606c3fb27SDimitry Andric                                          Function *F, IRBuilder<> &Builder) {
22975f757f3fSDimitry Andric   const bool IsInc = Name.starts_with("atomic.inc.");
22985f757f3fSDimitry Andric   if (IsInc || Name.starts_with("atomic.dec.")) {
229906c3fb27SDimitry Andric     if (CI->getNumOperands() != 6) // Malformed bitcode.
230006c3fb27SDimitry Andric       return nullptr;
230106c3fb27SDimitry Andric 
230206c3fb27SDimitry Andric     AtomicRMWInst::BinOp RMWOp =
230306c3fb27SDimitry Andric         IsInc ? AtomicRMWInst::UIncWrap : AtomicRMWInst::UDecWrap;
230406c3fb27SDimitry Andric 
230506c3fb27SDimitry Andric     Value *Ptr = CI->getArgOperand(0);
230606c3fb27SDimitry Andric     Value *Val = CI->getArgOperand(1);
230706c3fb27SDimitry Andric     ConstantInt *OrderArg = dyn_cast<ConstantInt>(CI->getArgOperand(2));
230806c3fb27SDimitry Andric     ConstantInt *VolatileArg = dyn_cast<ConstantInt>(CI->getArgOperand(4));
230906c3fb27SDimitry Andric 
231006c3fb27SDimitry Andric     AtomicOrdering Order = AtomicOrdering::SequentiallyConsistent;
231106c3fb27SDimitry Andric     if (OrderArg && isValidAtomicOrdering(OrderArg->getZExtValue()))
231206c3fb27SDimitry Andric       Order = static_cast<AtomicOrdering>(OrderArg->getZExtValue());
231306c3fb27SDimitry Andric     if (Order == AtomicOrdering::NotAtomic ||
231406c3fb27SDimitry Andric         Order == AtomicOrdering::Unordered)
231506c3fb27SDimitry Andric       Order = AtomicOrdering::SequentiallyConsistent;
231606c3fb27SDimitry Andric 
23175f757f3fSDimitry Andric     // The scope argument never really worked correctly. Use agent as the most
23185f757f3fSDimitry Andric     // conservative option which should still always produce the instruction.
23195f757f3fSDimitry Andric     SyncScope::ID SSID = F->getContext().getOrInsertSyncScopeID("agent");
23205f757f3fSDimitry Andric     AtomicRMWInst *RMW =
23215f757f3fSDimitry Andric         Builder.CreateAtomicRMW(RMWOp, Ptr, Val, std::nullopt, Order, SSID);
232206c3fb27SDimitry Andric 
232306c3fb27SDimitry Andric     if (!VolatileArg || !VolatileArg->isZero())
232406c3fb27SDimitry Andric       RMW->setVolatile(true);
232506c3fb27SDimitry Andric     return RMW;
232606c3fb27SDimitry Andric   }
232706c3fb27SDimitry Andric 
232806c3fb27SDimitry Andric   llvm_unreachable("Unknown function for AMDGPU intrinsic upgrade.");
232906c3fb27SDimitry Andric }
233006c3fb27SDimitry Andric 
23310b57cec5SDimitry Andric /// Upgrade a call to an old intrinsic. All argument and return casting must be
23320b57cec5SDimitry Andric /// provided to seamlessly integrate with existing context.
UpgradeIntrinsicCall(CallBase * CI,Function * NewFn)233381ad6265SDimitry Andric void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
2334bdd1243dSDimitry Andric   // Note dyn_cast to Function is not quite the same as getCalledFunction, which
2335bdd1243dSDimitry Andric   // checks the callee's function type matches. It's likely we need to handle
2336bdd1243dSDimitry Andric   // type changes here.
2337bdd1243dSDimitry Andric   Function *F = dyn_cast<Function>(CI->getCalledOperand());
2338bdd1243dSDimitry Andric   if (!F)
2339bdd1243dSDimitry Andric     return;
2340bdd1243dSDimitry Andric 
23410b57cec5SDimitry Andric   LLVMContext &C = CI->getContext();
23420b57cec5SDimitry Andric   IRBuilder<> Builder(C);
23430b57cec5SDimitry Andric   Builder.SetInsertPoint(CI->getParent(), CI->getIterator());
23440b57cec5SDimitry Andric 
23450b57cec5SDimitry Andric   if (!NewFn) {
23460b57cec5SDimitry Andric     // Get the Function's name.
23470b57cec5SDimitry Andric     StringRef Name = F->getName();
23480b57cec5SDimitry Andric 
23495f757f3fSDimitry Andric     assert(Name.starts_with("llvm.") && "Intrinsic doesn't start with 'llvm.'");
23500b57cec5SDimitry Andric     Name = Name.substr(5);
23510b57cec5SDimitry Andric 
23527a6dacacSDimitry Andric     bool IsX86 = Name.consume_front("x86.");
23537a6dacacSDimitry Andric     bool IsNVVM = Name.consume_front("nvvm.");
23547a6dacacSDimitry Andric     bool IsARM = Name.consume_front("arm.");
23557a6dacacSDimitry Andric     bool IsAMDGCN = Name.consume_front("amdgcn.");
23560b57cec5SDimitry Andric 
23575f757f3fSDimitry Andric     if (IsX86 && Name.starts_with("sse4a.movnt.")) {
23580b57cec5SDimitry Andric       SmallVector<Metadata *, 1> Elts;
23590b57cec5SDimitry Andric       Elts.push_back(
23600b57cec5SDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
23610b57cec5SDimitry Andric       MDNode *Node = MDNode::get(C, Elts);
23620b57cec5SDimitry Andric 
23630b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
23640b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
23650b57cec5SDimitry Andric 
23660b57cec5SDimitry Andric       // Nontemporal (unaligned) store of the 0'th element of the float/double
23670b57cec5SDimitry Andric       // vector.
23680b57cec5SDimitry Andric       Type *SrcEltTy = cast<VectorType>(Arg1->getType())->getElementType();
23690b57cec5SDimitry Andric       PointerType *EltPtrTy = PointerType::getUnqual(SrcEltTy);
23700b57cec5SDimitry Andric       Value *Addr = Builder.CreateBitCast(Arg0, EltPtrTy, "cast");
23710b57cec5SDimitry Andric       Value *Extract =
23720b57cec5SDimitry Andric           Builder.CreateExtractElement(Arg1, (uint64_t)0, "extractelement");
23730b57cec5SDimitry Andric 
23745ffd83dbSDimitry Andric       StoreInst *SI = Builder.CreateAlignedStore(Extract, Addr, Align(1));
237506c3fb27SDimitry Andric       SI->setMetadata(LLVMContext::MD_nontemporal, Node);
23760b57cec5SDimitry Andric 
23770b57cec5SDimitry Andric       // Remove intrinsic.
23780b57cec5SDimitry Andric       CI->eraseFromParent();
23790b57cec5SDimitry Andric       return;
23800b57cec5SDimitry Andric     }
23810b57cec5SDimitry Andric 
23825f757f3fSDimitry Andric     if (IsX86 && (Name.starts_with("avx.movnt.") ||
23835f757f3fSDimitry Andric                   Name.starts_with("avx512.storent."))) {
23840b57cec5SDimitry Andric       SmallVector<Metadata *, 1> Elts;
23850b57cec5SDimitry Andric       Elts.push_back(
23860b57cec5SDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
23870b57cec5SDimitry Andric       MDNode *Node = MDNode::get(C, Elts);
23880b57cec5SDimitry Andric 
23890b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
23900b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric       // Convert the type of the pointer to a pointer to the stored type.
23930b57cec5SDimitry Andric       Value *BC = Builder.CreateBitCast(Arg0,
23940b57cec5SDimitry Andric                                         PointerType::getUnqual(Arg1->getType()),
23950b57cec5SDimitry Andric                                         "cast");
23965ffd83dbSDimitry Andric       StoreInst *SI = Builder.CreateAlignedStore(
23975ffd83dbSDimitry Andric           Arg1, BC,
2398bdd1243dSDimitry Andric           Align(Arg1->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
239906c3fb27SDimitry Andric       SI->setMetadata(LLVMContext::MD_nontemporal, Node);
24000b57cec5SDimitry Andric 
24010b57cec5SDimitry Andric       // Remove intrinsic.
24020b57cec5SDimitry Andric       CI->eraseFromParent();
24030b57cec5SDimitry Andric       return;
24040b57cec5SDimitry Andric     }
24050b57cec5SDimitry Andric 
24060b57cec5SDimitry Andric     if (IsX86 && Name == "sse2.storel.dq") {
24070b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
24080b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
24090b57cec5SDimitry Andric 
24105ffd83dbSDimitry Andric       auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
24110b57cec5SDimitry Andric       Value *BC0 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
24120b57cec5SDimitry Andric       Value *Elt = Builder.CreateExtractElement(BC0, (uint64_t)0);
24130b57cec5SDimitry Andric       Value *BC = Builder.CreateBitCast(Arg0,
24140b57cec5SDimitry Andric                                         PointerType::getUnqual(Elt->getType()),
24150b57cec5SDimitry Andric                                         "cast");
24165ffd83dbSDimitry Andric       Builder.CreateAlignedStore(Elt, BC, Align(1));
24170b57cec5SDimitry Andric 
24180b57cec5SDimitry Andric       // Remove intrinsic.
24190b57cec5SDimitry Andric       CI->eraseFromParent();
24200b57cec5SDimitry Andric       return;
24210b57cec5SDimitry Andric     }
24220b57cec5SDimitry Andric 
24235f757f3fSDimitry Andric     if (IsX86 && (Name.starts_with("sse.storeu.") ||
24245f757f3fSDimitry Andric                   Name.starts_with("sse2.storeu.") ||
24255f757f3fSDimitry Andric                   Name.starts_with("avx.storeu."))) {
24260b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
24270b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
24280b57cec5SDimitry Andric 
24290b57cec5SDimitry Andric       Arg0 = Builder.CreateBitCast(Arg0,
24300b57cec5SDimitry Andric                                    PointerType::getUnqual(Arg1->getType()),
24310b57cec5SDimitry Andric                                    "cast");
24325ffd83dbSDimitry Andric       Builder.CreateAlignedStore(Arg1, Arg0, Align(1));
24330b57cec5SDimitry Andric 
24340b57cec5SDimitry Andric       // Remove intrinsic.
24350b57cec5SDimitry Andric       CI->eraseFromParent();
24360b57cec5SDimitry Andric       return;
24370b57cec5SDimitry Andric     }
24380b57cec5SDimitry Andric 
24390b57cec5SDimitry Andric     if (IsX86 && Name == "avx512.mask.store.ss") {
24400b57cec5SDimitry Andric       Value *Mask = Builder.CreateAnd(CI->getArgOperand(2), Builder.getInt8(1));
24417a6dacacSDimitry Andric       upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
24420b57cec5SDimitry Andric                          Mask, false);
24430b57cec5SDimitry Andric 
24440b57cec5SDimitry Andric       // Remove intrinsic.
24450b57cec5SDimitry Andric       CI->eraseFromParent();
24460b57cec5SDimitry Andric       return;
24470b57cec5SDimitry Andric     }
24480b57cec5SDimitry Andric 
24497a6dacacSDimitry Andric     if (IsX86 && Name.starts_with("avx512.mask.store")) {
24500b57cec5SDimitry Andric       // "avx512.mask.storeu." or "avx512.mask.store."
24510b57cec5SDimitry Andric       bool Aligned = Name[17] != 'u'; // "avx512.mask.storeu".
24527a6dacacSDimitry Andric       upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
24530b57cec5SDimitry Andric                          CI->getArgOperand(2), Aligned);
24540b57cec5SDimitry Andric 
24550b57cec5SDimitry Andric       // Remove intrinsic.
24560b57cec5SDimitry Andric       CI->eraseFromParent();
24570b57cec5SDimitry Andric       return;
24580b57cec5SDimitry Andric     }
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric     Value *Rep;
24610b57cec5SDimitry Andric     // Upgrade packed integer vector compare intrinsics to compare instructions.
24625f757f3fSDimitry Andric     if (IsX86 && (Name.starts_with("sse2.pcmp") ||
24635f757f3fSDimitry Andric                   Name.starts_with("avx2.pcmp"))) {
24640b57cec5SDimitry Andric       // "sse2.pcpmpeq." "sse2.pcmpgt." "avx2.pcmpeq." or "avx2.pcmpgt."
24650b57cec5SDimitry Andric       bool CmpEq = Name[9] == 'e';
24660b57cec5SDimitry Andric       Rep = Builder.CreateICmp(CmpEq ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_SGT,
24670b57cec5SDimitry Andric                                CI->getArgOperand(0), CI->getArgOperand(1));
24680b57cec5SDimitry Andric       Rep = Builder.CreateSExt(Rep, CI->getType(), "");
24695f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.broadcastm"))) {
24700b57cec5SDimitry Andric       Type *ExtTy = Type::getInt32Ty(C);
24710b57cec5SDimitry Andric       if (CI->getOperand(0)->getType()->isIntegerTy(8))
24720b57cec5SDimitry Andric         ExtTy = Type::getInt64Ty(C);
24730b57cec5SDimitry Andric       unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() /
24740b57cec5SDimitry Andric                          ExtTy->getPrimitiveSizeInBits();
24750b57cec5SDimitry Andric       Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy);
24760b57cec5SDimitry Andric       Rep = Builder.CreateVectorSplat(NumElts, Rep);
24770b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse.sqrt.ss" ||
24780b57cec5SDimitry Andric                          Name == "sse2.sqrt.sd")) {
24790b57cec5SDimitry Andric       Value *Vec = CI->getArgOperand(0);
24800b57cec5SDimitry Andric       Value *Elt0 = Builder.CreateExtractElement(Vec, (uint64_t)0);
24810b57cec5SDimitry Andric       Function *Intr = Intrinsic::getDeclaration(F->getParent(),
24820b57cec5SDimitry Andric                                                  Intrinsic::sqrt, Elt0->getType());
24830b57cec5SDimitry Andric       Elt0 = Builder.CreateCall(Intr, Elt0);
24840b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(Vec, Elt0, (uint64_t)0);
24855f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.sqrt.p") ||
24865f757f3fSDimitry Andric                          Name.starts_with("sse2.sqrt.p") ||
24875f757f3fSDimitry Andric                          Name.starts_with("sse.sqrt.p"))) {
24880b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
24890b57cec5SDimitry Andric                                                          Intrinsic::sqrt,
24900b57cec5SDimitry Andric                                                          CI->getType()),
24910b57cec5SDimitry Andric                                {CI->getArgOperand(0)});
24925f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.sqrt.p"))) {
2493349cc55cSDimitry Andric       if (CI->arg_size() == 4 &&
24940b57cec5SDimitry Andric           (!isa<ConstantInt>(CI->getArgOperand(3)) ||
24950b57cec5SDimitry Andric            cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
24960b57cec5SDimitry Andric         Intrinsic::ID IID = Name[18] == 's' ? Intrinsic::x86_avx512_sqrt_ps_512
24970b57cec5SDimitry Andric                                             : Intrinsic::x86_avx512_sqrt_pd_512;
24980b57cec5SDimitry Andric 
24990b57cec5SDimitry Andric         Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(3) };
25000b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
25010b57cec5SDimitry Andric                                                            IID), Args);
25020b57cec5SDimitry Andric       } else {
25030b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
25040b57cec5SDimitry Andric                                                            Intrinsic::sqrt,
25050b57cec5SDimitry Andric                                                            CI->getType()),
25060b57cec5SDimitry Andric                                  {CI->getArgOperand(0)});
25070b57cec5SDimitry Andric       }
25087a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
25090b57cec5SDimitry Andric                           CI->getArgOperand(1));
25105f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.ptestm") ||
25115f757f3fSDimitry Andric                          Name.starts_with("avx512.ptestnm"))) {
25120b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
25130b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
25140b57cec5SDimitry Andric       Value *Mask = CI->getArgOperand(2);
25150b57cec5SDimitry Andric       Rep = Builder.CreateAnd(Op0, Op1);
25160b57cec5SDimitry Andric       llvm::Type *Ty = Op0->getType();
25170b57cec5SDimitry Andric       Value *Zero = llvm::Constant::getNullValue(Ty);
25180b57cec5SDimitry Andric       ICmpInst::Predicate Pred =
25195f757f3fSDimitry Andric         Name.starts_with("avx512.ptestm") ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
25200b57cec5SDimitry Andric       Rep = Builder.CreateICmp(Pred, Rep, Zero);
25217a6dacacSDimitry Andric       Rep = applyX86MaskOn1BitsVec(Builder, Rep, Mask);
25225f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.pbroadcast"))){
2523e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getArgOperand(1)->getType())
2524e8d8bef9SDimitry Andric                              ->getNumElements();
25250b57cec5SDimitry Andric       Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0));
25267a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
25270b57cec5SDimitry Andric                           CI->getArgOperand(1));
25285f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.kunpck"))) {
25290b57cec5SDimitry Andric       unsigned NumElts = CI->getType()->getScalarSizeInBits();
25300b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), NumElts);
25310b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), NumElts);
25325ffd83dbSDimitry Andric       int Indices[64];
25330b57cec5SDimitry Andric       for (unsigned i = 0; i != NumElts; ++i)
25340b57cec5SDimitry Andric         Indices[i] = i;
25350b57cec5SDimitry Andric 
25360b57cec5SDimitry Andric       // First extract half of each vector. This gives better codegen than
25370b57cec5SDimitry Andric       // doing it in a single shuffle.
2538bdd1243dSDimitry Andric       LHS =
2539bdd1243dSDimitry Andric           Builder.CreateShuffleVector(LHS, LHS, ArrayRef(Indices, NumElts / 2));
2540bdd1243dSDimitry Andric       RHS =
2541bdd1243dSDimitry Andric           Builder.CreateShuffleVector(RHS, RHS, ArrayRef(Indices, NumElts / 2));
25420b57cec5SDimitry Andric       // Concat the vectors.
25430b57cec5SDimitry Andric       // NOTE: Operands have to be swapped to match intrinsic definition.
2544bdd1243dSDimitry Andric       Rep = Builder.CreateShuffleVector(RHS, LHS, ArrayRef(Indices, NumElts));
25450b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25460b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.kand.w") {
25470b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25480b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25490b57cec5SDimitry Andric       Rep = Builder.CreateAnd(LHS, RHS);
25500b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25510b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.kandn.w") {
25520b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25530b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25540b57cec5SDimitry Andric       LHS = Builder.CreateNot(LHS);
25550b57cec5SDimitry Andric       Rep = Builder.CreateAnd(LHS, RHS);
25560b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25570b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.kor.w") {
25580b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25590b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25600b57cec5SDimitry Andric       Rep = Builder.CreateOr(LHS, RHS);
25610b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25620b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.kxor.w") {
25630b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25640b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25650b57cec5SDimitry Andric       Rep = Builder.CreateXor(LHS, RHS);
25660b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25670b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.kxnor.w") {
25680b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25690b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25700b57cec5SDimitry Andric       LHS = Builder.CreateNot(LHS);
25710b57cec5SDimitry Andric       Rep = Builder.CreateXor(LHS, RHS);
25720b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25730b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.knot.w") {
25740b57cec5SDimitry Andric       Rep = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25750b57cec5SDimitry Andric       Rep = Builder.CreateNot(Rep);
25760b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, CI->getType());
25770b57cec5SDimitry Andric     } else if (IsX86 &&
25780b57cec5SDimitry Andric                (Name == "avx512.kortestz.w" || Name == "avx512.kortestc.w")) {
25790b57cec5SDimitry Andric       Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
25800b57cec5SDimitry Andric       Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
25810b57cec5SDimitry Andric       Rep = Builder.CreateOr(LHS, RHS);
25820b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, Builder.getInt16Ty());
25830b57cec5SDimitry Andric       Value *C;
25840b57cec5SDimitry Andric       if (Name[14] == 'c')
25850b57cec5SDimitry Andric         C = ConstantInt::getAllOnesValue(Builder.getInt16Ty());
25860b57cec5SDimitry Andric       else
25870b57cec5SDimitry Andric         C = ConstantInt::getNullValue(Builder.getInt16Ty());
25880b57cec5SDimitry Andric       Rep = Builder.CreateICmpEQ(Rep, C);
25890b57cec5SDimitry Andric       Rep = Builder.CreateZExt(Rep, Builder.getInt32Ty());
25900b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse.add.ss" || Name == "sse2.add.sd" ||
25910b57cec5SDimitry Andric                          Name == "sse.sub.ss" || Name == "sse2.sub.sd" ||
25920b57cec5SDimitry Andric                          Name == "sse.mul.ss" || Name == "sse2.mul.sd" ||
25930b57cec5SDimitry Andric                          Name == "sse.div.ss" || Name == "sse2.div.sd")) {
25940b57cec5SDimitry Andric       Type *I32Ty = Type::getInt32Ty(C);
25950b57cec5SDimitry Andric       Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0),
25960b57cec5SDimitry Andric                                                  ConstantInt::get(I32Ty, 0));
25970b57cec5SDimitry Andric       Value *Elt1 = Builder.CreateExtractElement(CI->getArgOperand(1),
25980b57cec5SDimitry Andric                                                  ConstantInt::get(I32Ty, 0));
25990b57cec5SDimitry Andric       Value *EltOp;
26000b57cec5SDimitry Andric       if (Name.contains(".add."))
26010b57cec5SDimitry Andric         EltOp = Builder.CreateFAdd(Elt0, Elt1);
26020b57cec5SDimitry Andric       else if (Name.contains(".sub."))
26030b57cec5SDimitry Andric         EltOp = Builder.CreateFSub(Elt0, Elt1);
26040b57cec5SDimitry Andric       else if (Name.contains(".mul."))
26050b57cec5SDimitry Andric         EltOp = Builder.CreateFMul(Elt0, Elt1);
26060b57cec5SDimitry Andric       else
26070b57cec5SDimitry Andric         EltOp = Builder.CreateFDiv(Elt0, Elt1);
26080b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(0), EltOp,
26090b57cec5SDimitry Andric                                         ConstantInt::get(I32Ty, 0));
26105f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.pcmp")) {
26110b57cec5SDimitry Andric       // "avx512.mask.pcmpeq." or "avx512.mask.pcmpgt."
26120b57cec5SDimitry Andric       bool CmpEq = Name[16] == 'e';
26130b57cec5SDimitry Andric       Rep = upgradeMaskedCompare(Builder, *CI, CmpEq ? 0 : 6, true);
26145f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.vpshufbitqmb.")) {
26150b57cec5SDimitry Andric       Type *OpTy = CI->getArgOperand(0)->getType();
26160b57cec5SDimitry Andric       unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
26170b57cec5SDimitry Andric       Intrinsic::ID IID;
26180b57cec5SDimitry Andric       switch (VecWidth) {
26190b57cec5SDimitry Andric       default: llvm_unreachable("Unexpected intrinsic");
26200b57cec5SDimitry Andric       case 128: IID = Intrinsic::x86_avx512_vpshufbitqmb_128; break;
26210b57cec5SDimitry Andric       case 256: IID = Intrinsic::x86_avx512_vpshufbitqmb_256; break;
26220b57cec5SDimitry Andric       case 512: IID = Intrinsic::x86_avx512_vpshufbitqmb_512; break;
26230b57cec5SDimitry Andric       }
26240b57cec5SDimitry Andric 
26250b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
26260b57cec5SDimitry Andric                                { CI->getOperand(0), CI->getArgOperand(1) });
26277a6dacacSDimitry Andric       Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
26285f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.fpclass.p")) {
26290b57cec5SDimitry Andric       Type *OpTy = CI->getArgOperand(0)->getType();
26300b57cec5SDimitry Andric       unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
26310b57cec5SDimitry Andric       unsigned EltWidth = OpTy->getScalarSizeInBits();
26320b57cec5SDimitry Andric       Intrinsic::ID IID;
26330b57cec5SDimitry Andric       if (VecWidth == 128 && EltWidth == 32)
26340b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_ps_128;
26350b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 32)
26360b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_ps_256;
26370b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 32)
26380b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_ps_512;
26390b57cec5SDimitry Andric       else if (VecWidth == 128 && EltWidth == 64)
26400b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_pd_128;
26410b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 64)
26420b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_pd_256;
26430b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 64)
26440b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_fpclass_pd_512;
26450b57cec5SDimitry Andric       else
26460b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
26470b57cec5SDimitry Andric 
26480b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
26490b57cec5SDimitry Andric                                { CI->getOperand(0), CI->getArgOperand(1) });
26507a6dacacSDimitry Andric       Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
26515f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.cmp.p")) {
2652349cc55cSDimitry Andric       SmallVector<Value *, 4> Args(CI->args());
2653e8d8bef9SDimitry Andric       Type *OpTy = Args[0]->getType();
26540b57cec5SDimitry Andric       unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
26550b57cec5SDimitry Andric       unsigned EltWidth = OpTy->getScalarSizeInBits();
26560b57cec5SDimitry Andric       Intrinsic::ID IID;
26570b57cec5SDimitry Andric       if (VecWidth == 128 && EltWidth == 32)
2658e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_ps_128;
26590b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 32)
2660e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_ps_256;
26610b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 32)
2662e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_ps_512;
26630b57cec5SDimitry Andric       else if (VecWidth == 128 && EltWidth == 64)
2664e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_pd_128;
26650b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 64)
2666e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_pd_256;
26670b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 64)
2668e8d8bef9SDimitry Andric         IID = Intrinsic::x86_avx512_mask_cmp_pd_512;
26690b57cec5SDimitry Andric       else
26700b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
26710b57cec5SDimitry Andric 
2672e8d8bef9SDimitry Andric       Value *Mask = Constant::getAllOnesValue(CI->getType());
2673e8d8bef9SDimitry Andric       if (VecWidth == 512)
2674e8d8bef9SDimitry Andric         std::swap(Mask, Args.back());
2675e8d8bef9SDimitry Andric       Args.push_back(Mask);
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
26780b57cec5SDimitry Andric                                Args);
26795f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.cmp.")) {
26800b57cec5SDimitry Andric       // Integer compare intrinsics.
26810b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
26820b57cec5SDimitry Andric       Rep = upgradeMaskedCompare(Builder, *CI, Imm, true);
26835f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.ucmp.")) {
26840b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
26850b57cec5SDimitry Andric       Rep = upgradeMaskedCompare(Builder, *CI, Imm, false);
26865f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.cvtb2mask.") ||
26875f757f3fSDimitry Andric                          Name.starts_with("avx512.cvtw2mask.") ||
26885f757f3fSDimitry Andric                          Name.starts_with("avx512.cvtd2mask.") ||
26895f757f3fSDimitry Andric                          Name.starts_with("avx512.cvtq2mask."))) {
26900b57cec5SDimitry Andric       Value *Op = CI->getArgOperand(0);
26910b57cec5SDimitry Andric       Value *Zero = llvm::Constant::getNullValue(Op->getType());
26920b57cec5SDimitry Andric       Rep = Builder.CreateICmp(ICmpInst::ICMP_SLT, Op, Zero);
26937a6dacacSDimitry Andric       Rep = applyX86MaskOn1BitsVec(Builder, Rep, nullptr);
26940b57cec5SDimitry Andric     } else if(IsX86 && (Name == "ssse3.pabs.b.128" ||
26950b57cec5SDimitry Andric                         Name == "ssse3.pabs.w.128" ||
26960b57cec5SDimitry Andric                         Name == "ssse3.pabs.d.128" ||
26975f757f3fSDimitry Andric                         Name.starts_with("avx2.pabs") ||
26985f757f3fSDimitry Andric                         Name.starts_with("avx512.mask.pabs"))) {
26990b57cec5SDimitry Andric       Rep = upgradeAbs(Builder, *CI);
27000b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse41.pmaxsb" ||
27010b57cec5SDimitry Andric                          Name == "sse2.pmaxs.w" ||
27020b57cec5SDimitry Andric                          Name == "sse41.pmaxsd" ||
27035f757f3fSDimitry Andric                          Name.starts_with("avx2.pmaxs") ||
27045f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmaxs"))) {
27057a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smax);
27060b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.pmaxu.b" ||
27070b57cec5SDimitry Andric                          Name == "sse41.pmaxuw" ||
27080b57cec5SDimitry Andric                          Name == "sse41.pmaxud" ||
27095f757f3fSDimitry Andric                          Name.starts_with("avx2.pmaxu") ||
27105f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmaxu"))) {
27117a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umax);
27120b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse41.pminsb" ||
27130b57cec5SDimitry Andric                          Name == "sse2.pmins.w" ||
27140b57cec5SDimitry Andric                          Name == "sse41.pminsd" ||
27155f757f3fSDimitry Andric                          Name.starts_with("avx2.pmins") ||
27165f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmins"))) {
27177a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smin);
27180b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.pminu.b" ||
27190b57cec5SDimitry Andric                          Name == "sse41.pminuw" ||
27200b57cec5SDimitry Andric                          Name == "sse41.pminud" ||
27215f757f3fSDimitry Andric                          Name.starts_with("avx2.pminu") ||
27225f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pminu"))) {
27237a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umin);
27240b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.pmulu.dq" ||
27250b57cec5SDimitry Andric                          Name == "avx2.pmulu.dq" ||
27260b57cec5SDimitry Andric                          Name == "avx512.pmulu.dq.512" ||
27275f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmulu.dq."))) {
27280b57cec5SDimitry Andric       Rep = upgradePMULDQ(Builder, *CI, /*Signed*/false);
27290b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse41.pmuldq" ||
27300b57cec5SDimitry Andric                          Name == "avx2.pmul.dq" ||
27310b57cec5SDimitry Andric                          Name == "avx512.pmul.dq.512" ||
27325f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmul.dq."))) {
27330b57cec5SDimitry Andric       Rep = upgradePMULDQ(Builder, *CI, /*Signed*/true);
27340b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse.cvtsi2ss" ||
27350b57cec5SDimitry Andric                          Name == "sse2.cvtsi2sd" ||
27360b57cec5SDimitry Andric                          Name == "sse.cvtsi642ss" ||
27370b57cec5SDimitry Andric                          Name == "sse2.cvtsi642sd")) {
27385ffd83dbSDimitry Andric       Rep = Builder.CreateSIToFP(
27395ffd83dbSDimitry Andric           CI->getArgOperand(1),
27405ffd83dbSDimitry Andric           cast<VectorType>(CI->getType())->getElementType());
27410b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
27420b57cec5SDimitry Andric     } else if (IsX86 && Name == "avx512.cvtusi2sd") {
27435ffd83dbSDimitry Andric       Rep = Builder.CreateUIToFP(
27445ffd83dbSDimitry Andric           CI->getArgOperand(1),
27455ffd83dbSDimitry Andric           cast<VectorType>(CI->getType())->getElementType());
27460b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
27470b57cec5SDimitry Andric     } else if (IsX86 && Name == "sse2.cvtss2sd") {
27480b57cec5SDimitry Andric       Rep = Builder.CreateExtractElement(CI->getArgOperand(1), (uint64_t)0);
27495ffd83dbSDimitry Andric       Rep = Builder.CreateFPExt(
27505ffd83dbSDimitry Andric           Rep, cast<VectorType>(CI->getType())->getElementType());
27510b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
27520b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.cvtdq2pd" ||
27530b57cec5SDimitry Andric                          Name == "sse2.cvtdq2ps" ||
27540b57cec5SDimitry Andric                          Name == "avx.cvtdq2.pd.256" ||
27550b57cec5SDimitry Andric                          Name == "avx.cvtdq2.ps.256" ||
27565f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtdq2pd.") ||
27575f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtudq2pd.") ||
27585f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtdq2ps.") ||
27595f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtudq2ps.") ||
27605f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtqq2pd.") ||
27615f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.cvtuqq2pd.") ||
27620b57cec5SDimitry Andric                          Name == "avx512.mask.cvtqq2ps.256" ||
27630b57cec5SDimitry Andric                          Name == "avx512.mask.cvtqq2ps.512" ||
27640b57cec5SDimitry Andric                          Name == "avx512.mask.cvtuqq2ps.256" ||
27650b57cec5SDimitry Andric                          Name == "avx512.mask.cvtuqq2ps.512" ||
27660b57cec5SDimitry Andric                          Name == "sse2.cvtps2pd" ||
27670b57cec5SDimitry Andric                          Name == "avx.cvt.ps2.pd.256" ||
27680b57cec5SDimitry Andric                          Name == "avx512.mask.cvtps2pd.128" ||
27690b57cec5SDimitry Andric                          Name == "avx512.mask.cvtps2pd.256")) {
2770e8d8bef9SDimitry Andric       auto *DstTy = cast<FixedVectorType>(CI->getType());
27710b57cec5SDimitry Andric       Rep = CI->getArgOperand(0);
2772e8d8bef9SDimitry Andric       auto *SrcTy = cast<FixedVectorType>(Rep->getType());
27730b57cec5SDimitry Andric 
27745ffd83dbSDimitry Andric       unsigned NumDstElts = DstTy->getNumElements();
27755ffd83dbSDimitry Andric       if (NumDstElts < SrcTy->getNumElements()) {
27760b57cec5SDimitry Andric         assert(NumDstElts == 2 && "Unexpected vector size");
27775ffd83dbSDimitry Andric         Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1});
27780b57cec5SDimitry Andric       }
27790b57cec5SDimitry Andric 
27805ffd83dbSDimitry Andric       bool IsPS2PD = SrcTy->getElementType()->isFloatTy();
27817a6dacacSDimitry Andric       bool IsUnsigned = Name.contains("cvtu");
27820b57cec5SDimitry Andric       if (IsPS2PD)
27830b57cec5SDimitry Andric         Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd");
2784349cc55cSDimitry Andric       else if (CI->arg_size() == 4 &&
27850b57cec5SDimitry Andric                (!isa<ConstantInt>(CI->getArgOperand(3)) ||
27860b57cec5SDimitry Andric                 cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
27870b57cec5SDimitry Andric         Intrinsic::ID IID = IsUnsigned ? Intrinsic::x86_avx512_uitofp_round
27880b57cec5SDimitry Andric                                        : Intrinsic::x86_avx512_sitofp_round;
27890b57cec5SDimitry Andric         Function *F = Intrinsic::getDeclaration(CI->getModule(), IID,
27900b57cec5SDimitry Andric                                                 { DstTy, SrcTy });
27910b57cec5SDimitry Andric         Rep = Builder.CreateCall(F, { Rep, CI->getArgOperand(3) });
27920b57cec5SDimitry Andric       } else {
27930b57cec5SDimitry Andric         Rep = IsUnsigned ? Builder.CreateUIToFP(Rep, DstTy, "cvt")
27940b57cec5SDimitry Andric                          : Builder.CreateSIToFP(Rep, DstTy, "cvt");
27950b57cec5SDimitry Andric       }
27960b57cec5SDimitry Andric 
2797349cc55cSDimitry Andric       if (CI->arg_size() >= 3)
27987a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
27990b57cec5SDimitry Andric                             CI->getArgOperand(1));
28005f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vcvtph2ps.") ||
28015f757f3fSDimitry Andric                          Name.starts_with("vcvtph2ps."))) {
2802e8d8bef9SDimitry Andric       auto *DstTy = cast<FixedVectorType>(CI->getType());
28035ffd83dbSDimitry Andric       Rep = CI->getArgOperand(0);
2804e8d8bef9SDimitry Andric       auto *SrcTy = cast<FixedVectorType>(Rep->getType());
28055ffd83dbSDimitry Andric       unsigned NumDstElts = DstTy->getNumElements();
28065ffd83dbSDimitry Andric       if (NumDstElts != SrcTy->getNumElements()) {
28075ffd83dbSDimitry Andric         assert(NumDstElts == 4 && "Unexpected vector size");
28085ffd83dbSDimitry Andric         Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1, 2, 3});
28095ffd83dbSDimitry Andric       }
28105ffd83dbSDimitry Andric       Rep = Builder.CreateBitCast(
28115ffd83dbSDimitry Andric           Rep, FixedVectorType::get(Type::getHalfTy(C), NumDstElts));
28125ffd83dbSDimitry Andric       Rep = Builder.CreateFPExt(Rep, DstTy, "cvtph2ps");
2813349cc55cSDimitry Andric       if (CI->arg_size() >= 3)
28147a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
28155ffd83dbSDimitry Andric                             CI->getArgOperand(1));
28165f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.load")) {
28170eae32dcSDimitry Andric       // "avx512.mask.loadu." or "avx512.mask.load."
28180eae32dcSDimitry Andric       bool Aligned = Name[16] != 'u'; // "avx512.mask.loadu".
28190eae32dcSDimitry Andric       Rep =
28207a6dacacSDimitry Andric           upgradeMaskedLoad(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
28210eae32dcSDimitry Andric                             CI->getArgOperand(2), Aligned);
28225f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.expand.load.")) {
2823e8d8bef9SDimitry Andric       auto *ResultTy = cast<FixedVectorType>(CI->getType());
28245ffd83dbSDimitry Andric       Type *PtrTy = ResultTy->getElementType();
28250b57cec5SDimitry Andric 
28260b57cec5SDimitry Andric       // Cast the pointer to element type.
28270b57cec5SDimitry Andric       Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
28280b57cec5SDimitry Andric                                          llvm::PointerType::getUnqual(PtrTy));
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric       Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
28315ffd83dbSDimitry Andric                                      ResultTy->getNumElements());
28320b57cec5SDimitry Andric 
28330b57cec5SDimitry Andric       Function *ELd = Intrinsic::getDeclaration(F->getParent(),
28340b57cec5SDimitry Andric                                                 Intrinsic::masked_expandload,
28350b57cec5SDimitry Andric                                                 ResultTy);
28360b57cec5SDimitry Andric       Rep = Builder.CreateCall(ELd, { Ptr, MaskVec, CI->getOperand(1) });
28375f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.compress.store.")) {
28385ffd83dbSDimitry Andric       auto *ResultTy = cast<VectorType>(CI->getArgOperand(1)->getType());
28395ffd83dbSDimitry Andric       Type *PtrTy = ResultTy->getElementType();
28400b57cec5SDimitry Andric 
28410b57cec5SDimitry Andric       // Cast the pointer to element type.
28420b57cec5SDimitry Andric       Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
28430b57cec5SDimitry Andric                                          llvm::PointerType::getUnqual(PtrTy));
28440b57cec5SDimitry Andric 
2845e8d8bef9SDimitry Andric       Value *MaskVec =
2846e8d8bef9SDimitry Andric           getX86MaskVec(Builder, CI->getArgOperand(2),
2847e8d8bef9SDimitry Andric                         cast<FixedVectorType>(ResultTy)->getNumElements());
28480b57cec5SDimitry Andric 
28490b57cec5SDimitry Andric       Function *CSt = Intrinsic::getDeclaration(F->getParent(),
28500b57cec5SDimitry Andric                                                 Intrinsic::masked_compressstore,
28510b57cec5SDimitry Andric                                                 ResultTy);
28520b57cec5SDimitry Andric       Rep = Builder.CreateCall(CSt, { CI->getArgOperand(1), Ptr, MaskVec });
28535f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.compress.") ||
28545f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.expand."))) {
2855e8d8bef9SDimitry Andric       auto *ResultTy = cast<FixedVectorType>(CI->getType());
28560b57cec5SDimitry Andric 
28570b57cec5SDimitry Andric       Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
28585ffd83dbSDimitry Andric                                      ResultTy->getNumElements());
28590b57cec5SDimitry Andric 
28600b57cec5SDimitry Andric       bool IsCompress = Name[12] == 'c';
28610b57cec5SDimitry Andric       Intrinsic::ID IID = IsCompress ? Intrinsic::x86_avx512_mask_compress
28620b57cec5SDimitry Andric                                      : Intrinsic::x86_avx512_mask_expand;
28630b57cec5SDimitry Andric       Function *Intr = Intrinsic::getDeclaration(F->getParent(), IID, ResultTy);
28640b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intr, { CI->getOperand(0), CI->getOperand(1),
28650b57cec5SDimitry Andric                                        MaskVec });
28665f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("xop.vpcom")) {
28670b57cec5SDimitry Andric       bool IsSigned;
28685f757f3fSDimitry Andric       if (Name.ends_with("ub") || Name.ends_with("uw") || Name.ends_with("ud") ||
28695f757f3fSDimitry Andric           Name.ends_with("uq"))
28700b57cec5SDimitry Andric         IsSigned = false;
28715f757f3fSDimitry Andric       else if (Name.ends_with("b") || Name.ends_with("w") || Name.ends_with("d") ||
28725f757f3fSDimitry Andric                Name.ends_with("q"))
28730b57cec5SDimitry Andric         IsSigned = true;
28740b57cec5SDimitry Andric       else
28750b57cec5SDimitry Andric         llvm_unreachable("Unknown suffix");
28760b57cec5SDimitry Andric 
28770b57cec5SDimitry Andric       unsigned Imm;
2878349cc55cSDimitry Andric       if (CI->arg_size() == 3) {
28790b57cec5SDimitry Andric         Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
28800b57cec5SDimitry Andric       } else {
28810b57cec5SDimitry Andric         Name = Name.substr(9); // strip off "xop.vpcom"
28825f757f3fSDimitry Andric         if (Name.starts_with("lt"))
28830b57cec5SDimitry Andric           Imm = 0;
28845f757f3fSDimitry Andric         else if (Name.starts_with("le"))
28850b57cec5SDimitry Andric           Imm = 1;
28865f757f3fSDimitry Andric         else if (Name.starts_with("gt"))
28870b57cec5SDimitry Andric           Imm = 2;
28885f757f3fSDimitry Andric         else if (Name.starts_with("ge"))
28890b57cec5SDimitry Andric           Imm = 3;
28905f757f3fSDimitry Andric         else if (Name.starts_with("eq"))
28910b57cec5SDimitry Andric           Imm = 4;
28925f757f3fSDimitry Andric         else if (Name.starts_with("ne"))
28930b57cec5SDimitry Andric           Imm = 5;
28945f757f3fSDimitry Andric         else if (Name.starts_with("false"))
28950b57cec5SDimitry Andric           Imm = 6;
28965f757f3fSDimitry Andric         else if (Name.starts_with("true"))
28970b57cec5SDimitry Andric           Imm = 7;
28980b57cec5SDimitry Andric         else
28990b57cec5SDimitry Andric           llvm_unreachable("Unknown condition");
29000b57cec5SDimitry Andric       }
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric       Rep = upgradeX86vpcom(Builder, *CI, Imm, IsSigned);
29035f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("xop.vpcmov")) {
29040b57cec5SDimitry Andric       Value *Sel = CI->getArgOperand(2);
29050b57cec5SDimitry Andric       Value *NotSel = Builder.CreateNot(Sel);
29060b57cec5SDimitry Andric       Value *Sel0 = Builder.CreateAnd(CI->getArgOperand(0), Sel);
29070b57cec5SDimitry Andric       Value *Sel1 = Builder.CreateAnd(CI->getArgOperand(1), NotSel);
29080b57cec5SDimitry Andric       Rep = Builder.CreateOr(Sel0, Sel1);
29095f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("xop.vprot") ||
29105f757f3fSDimitry Andric                          Name.starts_with("avx512.prol") ||
29115f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.prol"))) {
29120b57cec5SDimitry Andric       Rep = upgradeX86Rotate(Builder, *CI, false);
29135f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.pror") ||
29145f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pror"))) {
29150b57cec5SDimitry Andric       Rep = upgradeX86Rotate(Builder, *CI, true);
29165f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.vpshld.") ||
29175f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpshld") ||
29185f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpshld"))) {
29190b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
29200b57cec5SDimitry Andric       Rep = upgradeX86ConcatShift(Builder, *CI, false, ZeroMask);
29215f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.vpshrd.") ||
29225f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpshrd") ||
29235f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpshrd"))) {
29240b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
29250b57cec5SDimitry Andric       Rep = upgradeX86ConcatShift(Builder, *CI, true, ZeroMask);
29260b57cec5SDimitry Andric     } else if (IsX86 && Name == "sse42.crc32.64.8") {
29270b57cec5SDimitry Andric       Function *CRC32 = Intrinsic::getDeclaration(F->getParent(),
29280b57cec5SDimitry Andric                                                Intrinsic::x86_sse42_crc32_32_8);
29290b57cec5SDimitry Andric       Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
29300b57cec5SDimitry Andric       Rep = Builder.CreateCall(CRC32, {Trunc0, CI->getArgOperand(1)});
29310b57cec5SDimitry Andric       Rep = Builder.CreateZExt(Rep, CI->getType(), "");
29325f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vbroadcast.s") ||
29335f757f3fSDimitry Andric                          Name.starts_with("avx512.vbroadcast.s"))) {
29340b57cec5SDimitry Andric       // Replace broadcasts with a series of insertelements.
2935e8d8bef9SDimitry Andric       auto *VecTy = cast<FixedVectorType>(CI->getType());
29365ffd83dbSDimitry Andric       Type *EltTy = VecTy->getElementType();
29375ffd83dbSDimitry Andric       unsigned EltNum = VecTy->getNumElements();
29385f757f3fSDimitry Andric       Value *Load = Builder.CreateLoad(EltTy, CI->getArgOperand(0));
29390b57cec5SDimitry Andric       Type *I32Ty = Type::getInt32Ty(C);
2940349cc55cSDimitry Andric       Rep = PoisonValue::get(VecTy);
29410b57cec5SDimitry Andric       for (unsigned I = 0; I < EltNum; ++I)
29420b57cec5SDimitry Andric         Rep = Builder.CreateInsertElement(Rep, Load,
29430b57cec5SDimitry Andric                                           ConstantInt::get(I32Ty, I));
29445f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("sse41.pmovsx") ||
29455f757f3fSDimitry Andric                          Name.starts_with("sse41.pmovzx") ||
29465f757f3fSDimitry Andric                          Name.starts_with("avx2.pmovsx") ||
29475f757f3fSDimitry Andric                          Name.starts_with("avx2.pmovzx") ||
29485f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmovsx") ||
29495f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pmovzx"))) {
2950e8d8bef9SDimitry Andric       auto *DstTy = cast<FixedVectorType>(CI->getType());
29510b57cec5SDimitry Andric       unsigned NumDstElts = DstTy->getNumElements();
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric       // Extract a subvector of the first NumDstElts lanes and sign/zero extend.
29545ffd83dbSDimitry Andric       SmallVector<int, 8> ShuffleMask(NumDstElts);
29550b57cec5SDimitry Andric       for (unsigned i = 0; i != NumDstElts; ++i)
29560b57cec5SDimitry Andric         ShuffleMask[i] = i;
29570b57cec5SDimitry Andric 
2958e8d8bef9SDimitry Andric       Value *SV =
2959e8d8bef9SDimitry Andric           Builder.CreateShuffleVector(CI->getArgOperand(0), ShuffleMask);
29600b57cec5SDimitry Andric 
29617a6dacacSDimitry Andric       bool DoSext = Name.contains("pmovsx");
29620b57cec5SDimitry Andric       Rep = DoSext ? Builder.CreateSExt(SV, DstTy)
29630b57cec5SDimitry Andric                    : Builder.CreateZExt(SV, DstTy);
29640b57cec5SDimitry Andric       // If there are 3 arguments, it's a masked intrinsic so we need a select.
2965349cc55cSDimitry Andric       if (CI->arg_size() == 3)
29667a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
29670b57cec5SDimitry Andric                             CI->getArgOperand(1));
29680b57cec5SDimitry Andric     } else if (Name == "avx512.mask.pmov.qd.256" ||
29690b57cec5SDimitry Andric                Name == "avx512.mask.pmov.qd.512" ||
29700b57cec5SDimitry Andric                Name == "avx512.mask.pmov.wb.256" ||
29710b57cec5SDimitry Andric                Name == "avx512.mask.pmov.wb.512") {
29720b57cec5SDimitry Andric       Type *Ty = CI->getArgOperand(1)->getType();
29730b57cec5SDimitry Andric       Rep = Builder.CreateTrunc(CI->getArgOperand(0), Ty);
29747a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
29750b57cec5SDimitry Andric                           CI->getArgOperand(1));
29765f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vbroadcastf128") ||
29770b57cec5SDimitry Andric                          Name == "avx2.vbroadcasti128")) {
29780b57cec5SDimitry Andric       // Replace vbroadcastf128/vbroadcasti128 with a vector load+shuffle.
29795ffd83dbSDimitry Andric       Type *EltTy = cast<VectorType>(CI->getType())->getElementType();
29800b57cec5SDimitry Andric       unsigned NumSrcElts = 128 / EltTy->getPrimitiveSizeInBits();
29815ffd83dbSDimitry Andric       auto *VT = FixedVectorType::get(EltTy, NumSrcElts);
29820b57cec5SDimitry Andric       Value *Op = Builder.CreatePointerCast(CI->getArgOperand(0),
29830b57cec5SDimitry Andric                                             PointerType::getUnqual(VT));
29845ffd83dbSDimitry Andric       Value *Load = Builder.CreateAlignedLoad(VT, Op, Align(1));
29850b57cec5SDimitry Andric       if (NumSrcElts == 2)
2986e8d8bef9SDimitry Andric         Rep = Builder.CreateShuffleVector(Load, ArrayRef<int>{0, 1, 0, 1});
29870b57cec5SDimitry Andric       else
2988e8d8bef9SDimitry Andric         Rep = Builder.CreateShuffleVector(
2989e8d8bef9SDimitry Andric             Load, ArrayRef<int>{0, 1, 2, 3, 0, 1, 2, 3});
29905f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.shuf.i") ||
29915f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.shuf.f"))) {
29920b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
29930b57cec5SDimitry Andric       Type *VT = CI->getType();
29940b57cec5SDimitry Andric       unsigned NumLanes = VT->getPrimitiveSizeInBits() / 128;
29950b57cec5SDimitry Andric       unsigned NumElementsInLane = 128 / VT->getScalarSizeInBits();
29960b57cec5SDimitry Andric       unsigned ControlBitsMask = NumLanes - 1;
29970b57cec5SDimitry Andric       unsigned NumControlBits = NumLanes / 2;
29985ffd83dbSDimitry Andric       SmallVector<int, 8> ShuffleMask(0);
29990b57cec5SDimitry Andric 
30000b57cec5SDimitry Andric       for (unsigned l = 0; l != NumLanes; ++l) {
30010b57cec5SDimitry Andric         unsigned LaneMask = (Imm >> (l * NumControlBits)) & ControlBitsMask;
30020b57cec5SDimitry Andric         // We actually need the other source.
30030b57cec5SDimitry Andric         if (l >= NumLanes / 2)
30040b57cec5SDimitry Andric           LaneMask += NumLanes;
30050b57cec5SDimitry Andric         for (unsigned i = 0; i != NumElementsInLane; ++i)
30060b57cec5SDimitry Andric           ShuffleMask.push_back(LaneMask * NumElementsInLane + i);
30070b57cec5SDimitry Andric       }
30080b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
30090b57cec5SDimitry Andric                                         CI->getArgOperand(1), ShuffleMask);
30107a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep,
30110b57cec5SDimitry Andric                           CI->getArgOperand(3));
30125f757f3fSDimitry Andric     }else if (IsX86 && (Name.starts_with("avx512.mask.broadcastf") ||
30135f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.broadcasti"))) {
30140b57cec5SDimitry Andric       unsigned NumSrcElts =
3015e8d8bef9SDimitry Andric           cast<FixedVectorType>(CI->getArgOperand(0)->getType())
3016e8d8bef9SDimitry Andric               ->getNumElements();
3017e8d8bef9SDimitry Andric       unsigned NumDstElts =
3018e8d8bef9SDimitry Andric           cast<FixedVectorType>(CI->getType())->getNumElements();
30190b57cec5SDimitry Andric 
30205ffd83dbSDimitry Andric       SmallVector<int, 8> ShuffleMask(NumDstElts);
30210b57cec5SDimitry Andric       for (unsigned i = 0; i != NumDstElts; ++i)
30220b57cec5SDimitry Andric         ShuffleMask[i] = i % NumSrcElts;
30230b57cec5SDimitry Andric 
30240b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
30250b57cec5SDimitry Andric                                         CI->getArgOperand(0),
30260b57cec5SDimitry Andric                                         ShuffleMask);
30277a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
30280b57cec5SDimitry Andric                           CI->getArgOperand(1));
30295f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx2.pbroadcast") ||
30305f757f3fSDimitry Andric                          Name.starts_with("avx2.vbroadcast") ||
30315f757f3fSDimitry Andric                          Name.starts_with("avx512.pbroadcast") ||
30325f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.broadcast.s"))) {
30330b57cec5SDimitry Andric       // Replace vp?broadcasts with a vector shuffle.
30340b57cec5SDimitry Andric       Value *Op = CI->getArgOperand(0);
30355ffd83dbSDimitry Andric       ElementCount EC = cast<VectorType>(CI->getType())->getElementCount();
30365ffd83dbSDimitry Andric       Type *MaskTy = VectorType::get(Type::getInt32Ty(C), EC);
3037e8d8bef9SDimitry Andric       SmallVector<int, 8> M;
3038e8d8bef9SDimitry Andric       ShuffleVectorInst::getShuffleMask(Constant::getNullValue(MaskTy), M);
3039e8d8bef9SDimitry Andric       Rep = Builder.CreateShuffleVector(Op, M);
30400b57cec5SDimitry Andric 
3041349cc55cSDimitry Andric       if (CI->arg_size() == 3)
30427a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
30430b57cec5SDimitry Andric                             CI->getArgOperand(1));
30445f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("sse2.padds.") ||
30455f757f3fSDimitry Andric                          Name.starts_with("avx2.padds.") ||
30465f757f3fSDimitry Andric                          Name.starts_with("avx512.padds.") ||
30475f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.padds."))) {
30487a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::sadd_sat);
30495f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("sse2.psubs.") ||
30505f757f3fSDimitry Andric                          Name.starts_with("avx2.psubs.") ||
30515f757f3fSDimitry Andric                          Name.starts_with("avx512.psubs.") ||
30525f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.psubs."))) {
30537a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::ssub_sat);
30545f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("sse2.paddus.") ||
30555f757f3fSDimitry Andric                          Name.starts_with("avx2.paddus.") ||
30565f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.paddus."))) {
30577a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::uadd_sat);
30585f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("sse2.psubus.") ||
30595f757f3fSDimitry Andric                          Name.starts_with("avx2.psubus.") ||
30605f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.psubus."))) {
30617a6dacacSDimitry Andric       Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::usub_sat);
30625f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.palignr.")) {
30637a6dacacSDimitry Andric       Rep = upgradeX86ALIGNIntrinsics(
30647a6dacacSDimitry Andric           Builder, CI->getArgOperand(0), CI->getArgOperand(1),
30657a6dacacSDimitry Andric           CI->getArgOperand(2), CI->getArgOperand(3), CI->getArgOperand(4),
30660b57cec5SDimitry Andric           false);
30675f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.valign.")) {
30687a6dacacSDimitry Andric       Rep = upgradeX86ALIGNIntrinsics(
30697a6dacacSDimitry Andric           Builder, CI->getArgOperand(0), CI->getArgOperand(1),
30707a6dacacSDimitry Andric           CI->getArgOperand(2), CI->getArgOperand(3), CI->getArgOperand(4),
30710b57cec5SDimitry Andric           true);
30720b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.psll.dq" ||
30730b57cec5SDimitry Andric                          Name == "avx2.psll.dq")) {
30740b57cec5SDimitry Andric       // 128/256-bit shift left specified in bits.
30750b57cec5SDimitry Andric       unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
30767a6dacacSDimitry Andric       Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0),
30770b57cec5SDimitry Andric                                        Shift / 8); // Shift is in bits.
30780b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.psrl.dq" ||
30790b57cec5SDimitry Andric                          Name == "avx2.psrl.dq")) {
30800b57cec5SDimitry Andric       // 128/256-bit shift right specified in bits.
30810b57cec5SDimitry Andric       unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
30827a6dacacSDimitry Andric       Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0),
30830b57cec5SDimitry Andric                                        Shift / 8); // Shift is in bits.
30840b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.psll.dq.bs" ||
30850b57cec5SDimitry Andric                          Name == "avx2.psll.dq.bs" ||
30860b57cec5SDimitry Andric                          Name == "avx512.psll.dq.512")) {
30870b57cec5SDimitry Andric       // 128/256/512-bit shift left specified in bytes.
30880b57cec5SDimitry Andric       unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
30897a6dacacSDimitry Andric       Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
30900b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.psrl.dq.bs" ||
30910b57cec5SDimitry Andric                          Name == "avx2.psrl.dq.bs" ||
30920b57cec5SDimitry Andric                          Name == "avx512.psrl.dq.512")) {
30930b57cec5SDimitry Andric       // 128/256/512-bit shift right specified in bytes.
30940b57cec5SDimitry Andric       unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
30957a6dacacSDimitry Andric       Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
30960b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse41.pblendw" ||
30975f757f3fSDimitry Andric                          Name.starts_with("sse41.blendp") ||
30985f757f3fSDimitry Andric                          Name.starts_with("avx.blend.p") ||
30990b57cec5SDimitry Andric                          Name == "avx2.pblendw" ||
31005f757f3fSDimitry Andric                          Name.starts_with("avx2.pblendd."))) {
31010b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
31020b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
31030b57cec5SDimitry Andric       unsigned Imm = cast <ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3104e8d8bef9SDimitry Andric       auto *VecTy = cast<FixedVectorType>(CI->getType());
31050b57cec5SDimitry Andric       unsigned NumElts = VecTy->getNumElements();
31060b57cec5SDimitry Andric 
31075ffd83dbSDimitry Andric       SmallVector<int, 16> Idxs(NumElts);
31080b57cec5SDimitry Andric       for (unsigned i = 0; i != NumElts; ++i)
31090b57cec5SDimitry Andric         Idxs[i] = ((Imm >> (i%8)) & 1) ? i + NumElts : i;
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
31125f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vinsertf128.") ||
31130b57cec5SDimitry Andric                          Name == "avx2.vinserti128" ||
31145f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.insert"))) {
31150b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
31160b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
31170b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3118e8d8bef9SDimitry Andric       unsigned DstNumElts =
3119e8d8bef9SDimitry Andric           cast<FixedVectorType>(CI->getType())->getNumElements();
3120e8d8bef9SDimitry Andric       unsigned SrcNumElts =
3121e8d8bef9SDimitry Andric           cast<FixedVectorType>(Op1->getType())->getNumElements();
31220b57cec5SDimitry Andric       unsigned Scale = DstNumElts / SrcNumElts;
31230b57cec5SDimitry Andric 
31240b57cec5SDimitry Andric       // Mask off the high bits of the immediate value; hardware ignores those.
31250b57cec5SDimitry Andric       Imm = Imm % Scale;
31260b57cec5SDimitry Andric 
31270b57cec5SDimitry Andric       // Extend the second operand into a vector the size of the destination.
31285ffd83dbSDimitry Andric       SmallVector<int, 8> Idxs(DstNumElts);
31290b57cec5SDimitry Andric       for (unsigned i = 0; i != SrcNumElts; ++i)
31300b57cec5SDimitry Andric         Idxs[i] = i;
31310b57cec5SDimitry Andric       for (unsigned i = SrcNumElts; i != DstNumElts; ++i)
31320b57cec5SDimitry Andric         Idxs[i] = SrcNumElts;
3133e8d8bef9SDimitry Andric       Rep = Builder.CreateShuffleVector(Op1, Idxs);
31340b57cec5SDimitry Andric 
31350b57cec5SDimitry Andric       // Insert the second operand into the first operand.
31360b57cec5SDimitry Andric 
31370b57cec5SDimitry Andric       // Note that there is no guarantee that instruction lowering will actually
31380b57cec5SDimitry Andric       // produce a vinsertf128 instruction for the created shuffles. In
31390b57cec5SDimitry Andric       // particular, the 0 immediate case involves no lane changes, so it can
31400b57cec5SDimitry Andric       // be handled as a blend.
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric       // Example of shuffle mask for 32-bit elements:
31430b57cec5SDimitry Andric       // Imm = 1  <i32 0, i32 1, i32 2,  i32 3,  i32 8, i32 9, i32 10, i32 11>
31440b57cec5SDimitry Andric       // Imm = 0  <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6,  i32 7 >
31450b57cec5SDimitry Andric 
31460b57cec5SDimitry Andric       // First fill with identify mask.
31470b57cec5SDimitry Andric       for (unsigned i = 0; i != DstNumElts; ++i)
31480b57cec5SDimitry Andric         Idxs[i] = i;
31490b57cec5SDimitry Andric       // Then replace the elements where we need to insert.
31500b57cec5SDimitry Andric       for (unsigned i = 0; i != SrcNumElts; ++i)
31510b57cec5SDimitry Andric         Idxs[i + Imm * SrcNumElts] = i + DstNumElts;
31520b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Rep, Idxs);
31530b57cec5SDimitry Andric 
31540b57cec5SDimitry Andric       // If the intrinsic has a mask operand, handle that.
3155349cc55cSDimitry Andric       if (CI->arg_size() == 5)
31567a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep,
31570b57cec5SDimitry Andric                             CI->getArgOperand(3));
31585f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vextractf128.") ||
31590b57cec5SDimitry Andric                          Name == "avx2.vextracti128" ||
31605f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vextract"))) {
31610b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
31620b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3163e8d8bef9SDimitry Andric       unsigned DstNumElts =
3164e8d8bef9SDimitry Andric           cast<FixedVectorType>(CI->getType())->getNumElements();
3165e8d8bef9SDimitry Andric       unsigned SrcNumElts =
3166e8d8bef9SDimitry Andric           cast<FixedVectorType>(Op0->getType())->getNumElements();
31670b57cec5SDimitry Andric       unsigned Scale = SrcNumElts / DstNumElts;
31680b57cec5SDimitry Andric 
31690b57cec5SDimitry Andric       // Mask off the high bits of the immediate value; hardware ignores those.
31700b57cec5SDimitry Andric       Imm = Imm % Scale;
31710b57cec5SDimitry Andric 
31720b57cec5SDimitry Andric       // Get indexes for the subvector of the input vector.
31735ffd83dbSDimitry Andric       SmallVector<int, 8> Idxs(DstNumElts);
31740b57cec5SDimitry Andric       for (unsigned i = 0; i != DstNumElts; ++i) {
31750b57cec5SDimitry Andric         Idxs[i] = i + (Imm * DstNumElts);
31760b57cec5SDimitry Andric       }
31770b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
31780b57cec5SDimitry Andric 
31790b57cec5SDimitry Andric       // If the intrinsic has a mask operand, handle that.
3180349cc55cSDimitry Andric       if (CI->arg_size() == 4)
31817a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
31820b57cec5SDimitry Andric                             CI->getArgOperand(2));
31830b57cec5SDimitry Andric     } else if (!IsX86 && Name == "stackprotectorcheck") {
31840b57cec5SDimitry Andric       Rep = nullptr;
31855f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.perm.df.") ||
31865f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.perm.di."))) {
31870b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
31880b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3189e8d8bef9SDimitry Andric       auto *VecTy = cast<FixedVectorType>(CI->getType());
31900b57cec5SDimitry Andric       unsigned NumElts = VecTy->getNumElements();
31910b57cec5SDimitry Andric 
31925ffd83dbSDimitry Andric       SmallVector<int, 8> Idxs(NumElts);
31930b57cec5SDimitry Andric       for (unsigned i = 0; i != NumElts; ++i)
31940b57cec5SDimitry Andric         Idxs[i] = (i & ~0x3) + ((Imm >> (2 * (i & 0x3))) & 3);
31950b57cec5SDimitry Andric 
31960b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
31970b57cec5SDimitry Andric 
3198349cc55cSDimitry Andric       if (CI->arg_size() == 4)
31997a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
32000b57cec5SDimitry Andric                             CI->getArgOperand(2));
32015f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vperm2f128.") ||
32020b57cec5SDimitry Andric                          Name == "avx2.vperm2i128")) {
32030b57cec5SDimitry Andric       // The immediate permute control byte looks like this:
32040b57cec5SDimitry Andric       //    [1:0] - select 128 bits from sources for low half of destination
32050b57cec5SDimitry Andric       //    [2]   - ignore
32060b57cec5SDimitry Andric       //    [3]   - zero low half of destination
32070b57cec5SDimitry Andric       //    [5:4] - select 128 bits from sources for high half of destination
32080b57cec5SDimitry Andric       //    [6]   - ignore
32090b57cec5SDimitry Andric       //    [7]   - zero high half of destination
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric       uint8_t Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
32120b57cec5SDimitry Andric 
3213e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
32140b57cec5SDimitry Andric       unsigned HalfSize = NumElts / 2;
32155ffd83dbSDimitry Andric       SmallVector<int, 8> ShuffleMask(NumElts);
32160b57cec5SDimitry Andric 
32170b57cec5SDimitry Andric       // Determine which operand(s) are actually in use for this instruction.
32180b57cec5SDimitry Andric       Value *V0 = (Imm & 0x02) ? CI->getArgOperand(1) : CI->getArgOperand(0);
32190b57cec5SDimitry Andric       Value *V1 = (Imm & 0x20) ? CI->getArgOperand(1) : CI->getArgOperand(0);
32200b57cec5SDimitry Andric 
32210b57cec5SDimitry Andric       // If needed, replace operands based on zero mask.
32220b57cec5SDimitry Andric       V0 = (Imm & 0x08) ? ConstantAggregateZero::get(CI->getType()) : V0;
32230b57cec5SDimitry Andric       V1 = (Imm & 0x80) ? ConstantAggregateZero::get(CI->getType()) : V1;
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric       // Permute low half of result.
32260b57cec5SDimitry Andric       unsigned StartIndex = (Imm & 0x01) ? HalfSize : 0;
32270b57cec5SDimitry Andric       for (unsigned i = 0; i < HalfSize; ++i)
32280b57cec5SDimitry Andric         ShuffleMask[i] = StartIndex + i;
32290b57cec5SDimitry Andric 
32300b57cec5SDimitry Andric       // Permute high half of result.
32310b57cec5SDimitry Andric       StartIndex = (Imm & 0x10) ? HalfSize : 0;
32320b57cec5SDimitry Andric       for (unsigned i = 0; i < HalfSize; ++i)
32330b57cec5SDimitry Andric         ShuffleMask[i + HalfSize] = NumElts + StartIndex + i;
32340b57cec5SDimitry Andric 
32350b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(V0, V1, ShuffleMask);
32360b57cec5SDimitry Andric 
32375f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx.vpermil.") ||
32380b57cec5SDimitry Andric                          Name == "sse2.pshuf.d" ||
32395f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpermil.p") ||
32405f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pshuf.d."))) {
32410b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
32420b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3243e8d8bef9SDimitry Andric       auto *VecTy = cast<FixedVectorType>(CI->getType());
32440b57cec5SDimitry Andric       unsigned NumElts = VecTy->getNumElements();
32450b57cec5SDimitry Andric       // Calculate the size of each index in the immediate.
32460b57cec5SDimitry Andric       unsigned IdxSize = 64 / VecTy->getScalarSizeInBits();
32470b57cec5SDimitry Andric       unsigned IdxMask = ((1 << IdxSize) - 1);
32480b57cec5SDimitry Andric 
32495ffd83dbSDimitry Andric       SmallVector<int, 8> Idxs(NumElts);
32500b57cec5SDimitry Andric       // Lookup the bits for this element, wrapping around the immediate every
32510b57cec5SDimitry Andric       // 8-bits. Elements are grouped into sets of 2 or 4 elements so we need
32520b57cec5SDimitry Andric       // to offset by the first index of each group.
32530b57cec5SDimitry Andric       for (unsigned i = 0; i != NumElts; ++i)
32540b57cec5SDimitry Andric         Idxs[i] = ((Imm >> ((i * IdxSize) % 8)) & IdxMask) | (i & ~IdxMask);
32550b57cec5SDimitry Andric 
32560b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
32570b57cec5SDimitry Andric 
3258349cc55cSDimitry Andric       if (CI->arg_size() == 4)
32597a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
32600b57cec5SDimitry Andric                             CI->getArgOperand(2));
32610b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.pshufl.w" ||
32625f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pshufl.w."))) {
32630b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
32640b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3265e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
32660b57cec5SDimitry Andric 
32675ffd83dbSDimitry Andric       SmallVector<int, 16> Idxs(NumElts);
32680b57cec5SDimitry Andric       for (unsigned l = 0; l != NumElts; l += 8) {
32690b57cec5SDimitry Andric         for (unsigned i = 0; i != 4; ++i)
32700b57cec5SDimitry Andric           Idxs[i + l] = ((Imm >> (2 * i)) & 0x3) + l;
32710b57cec5SDimitry Andric         for (unsigned i = 4; i != 8; ++i)
32720b57cec5SDimitry Andric           Idxs[i + l] = i + l;
32730b57cec5SDimitry Andric       }
32740b57cec5SDimitry Andric 
32750b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
32760b57cec5SDimitry Andric 
3277349cc55cSDimitry Andric       if (CI->arg_size() == 4)
32787a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
32790b57cec5SDimitry Andric                             CI->getArgOperand(2));
32800b57cec5SDimitry Andric     } else if (IsX86 && (Name == "sse2.pshufh.w" ||
32815f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pshufh.w."))) {
32820b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
32830b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3284e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
32850b57cec5SDimitry Andric 
32865ffd83dbSDimitry Andric       SmallVector<int, 16> Idxs(NumElts);
32870b57cec5SDimitry Andric       for (unsigned l = 0; l != NumElts; l += 8) {
32880b57cec5SDimitry Andric         for (unsigned i = 0; i != 4; ++i)
32890b57cec5SDimitry Andric           Idxs[i + l] = i + l;
32900b57cec5SDimitry Andric         for (unsigned i = 0; i != 4; ++i)
32910b57cec5SDimitry Andric           Idxs[i + l + 4] = ((Imm >> (2 * i)) & 0x3) + 4 + l;
32920b57cec5SDimitry Andric       }
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
32950b57cec5SDimitry Andric 
3296349cc55cSDimitry Andric       if (CI->arg_size() == 4)
32977a6dacacSDimitry Andric         Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
32980b57cec5SDimitry Andric                             CI->getArgOperand(2));
32995f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.shuf.p")) {
33000b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
33010b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
33020b57cec5SDimitry Andric       unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3303e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
33040b57cec5SDimitry Andric 
33050b57cec5SDimitry Andric       unsigned NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
33060b57cec5SDimitry Andric       unsigned HalfLaneElts = NumLaneElts / 2;
33070b57cec5SDimitry Andric 
33085ffd83dbSDimitry Andric       SmallVector<int, 16> Idxs(NumElts);
33090b57cec5SDimitry Andric       for (unsigned i = 0; i != NumElts; ++i) {
33100b57cec5SDimitry Andric         // Base index is the starting element of the lane.
33110b57cec5SDimitry Andric         Idxs[i] = i - (i % NumLaneElts);
33120b57cec5SDimitry Andric         // If we are half way through the lane switch to the other source.
33130b57cec5SDimitry Andric         if ((i % NumLaneElts) >= HalfLaneElts)
33140b57cec5SDimitry Andric           Idxs[i] += NumElts;
33150b57cec5SDimitry Andric         // Now select the specific element. By adding HalfLaneElts bits from
33160b57cec5SDimitry Andric         // the immediate. Wrapping around the immediate every 8-bits.
33170b57cec5SDimitry Andric         Idxs[i] += (Imm >> ((i * HalfLaneElts) % 8)) & ((1 << HalfLaneElts) - 1);
33180b57cec5SDimitry Andric       }
33190b57cec5SDimitry Andric 
33200b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
33210b57cec5SDimitry Andric 
33227a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep,
33230b57cec5SDimitry Andric                           CI->getArgOperand(3));
33245f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.movddup") ||
33255f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.movshdup") ||
33265f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.movsldup"))) {
33270b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
3328e8d8bef9SDimitry Andric       unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
33290b57cec5SDimitry Andric       unsigned NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
33300b57cec5SDimitry Andric 
33310b57cec5SDimitry Andric       unsigned Offset = 0;
33325f757f3fSDimitry Andric       if (Name.starts_with("avx512.mask.movshdup."))
33330b57cec5SDimitry Andric         Offset = 1;
33340b57cec5SDimitry Andric 
33355ffd83dbSDimitry Andric       SmallVector<int, 16> Idxs(NumElts);
33360b57cec5SDimitry Andric       for (unsigned l = 0; l != NumElts; l += NumLaneElts)
33370b57cec5SDimitry Andric         for (unsigned i = 0; i != NumLaneElts; i += 2) {
33380b57cec5SDimitry Andric           Idxs[i + l + 0] = i + l + Offset;
33390b57cec5SDimitry Andric           Idxs[i + l + 1] = i + l + Offset;
33400b57cec5SDimitry Andric         }
33410b57cec5SDimitry Andric 
33420b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
33430b57cec5SDimitry Andric 
33447a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
33450b57cec5SDimitry Andric                           CI->getArgOperand(1));
33465f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.punpckl") ||
33475f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.unpckl."))) {
33480b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
33490b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
3350e8d8bef9SDimitry Andric       int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
33510b57cec5SDimitry Andric       int NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
33520b57cec5SDimitry Andric 
33535ffd83dbSDimitry Andric       SmallVector<int, 64> Idxs(NumElts);
33540b57cec5SDimitry Andric       for (int l = 0; l != NumElts; l += NumLaneElts)
33550b57cec5SDimitry Andric         for (int i = 0; i != NumLaneElts; ++i)
33560b57cec5SDimitry Andric           Idxs[i + l] = l + (i / 2) + NumElts * (i % 2);
33570b57cec5SDimitry Andric 
33580b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
33590b57cec5SDimitry Andric 
33607a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
33610b57cec5SDimitry Andric                           CI->getArgOperand(2));
33625f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.punpckh") ||
33635f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.unpckh."))) {
33640b57cec5SDimitry Andric       Value *Op0 = CI->getArgOperand(0);
33650b57cec5SDimitry Andric       Value *Op1 = CI->getArgOperand(1);
3366e8d8bef9SDimitry Andric       int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
33670b57cec5SDimitry Andric       int NumLaneElts = 128/CI->getType()->getScalarSizeInBits();
33680b57cec5SDimitry Andric 
33695ffd83dbSDimitry Andric       SmallVector<int, 64> Idxs(NumElts);
33700b57cec5SDimitry Andric       for (int l = 0; l != NumElts; l += NumLaneElts)
33710b57cec5SDimitry Andric         for (int i = 0; i != NumLaneElts; ++i)
33720b57cec5SDimitry Andric           Idxs[i + l] = (NumLaneElts / 2) + l + (i / 2) + NumElts * (i % 2);
33730b57cec5SDimitry Andric 
33740b57cec5SDimitry Andric       Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
33750b57cec5SDimitry Andric 
33767a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
33770b57cec5SDimitry Andric                           CI->getArgOperand(2));
33785f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.and.") ||
33795f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pand."))) {
33800b57cec5SDimitry Andric       VectorType *FTy = cast<VectorType>(CI->getType());
33810b57cec5SDimitry Andric       VectorType *ITy = VectorType::getInteger(FTy);
33820b57cec5SDimitry Andric       Rep = Builder.CreateAnd(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
33830b57cec5SDimitry Andric                               Builder.CreateBitCast(CI->getArgOperand(1), ITy));
33840b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, FTy);
33857a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
33860b57cec5SDimitry Andric                           CI->getArgOperand(2));
33875f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.andn.") ||
33885f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pandn."))) {
33890b57cec5SDimitry Andric       VectorType *FTy = cast<VectorType>(CI->getType());
33900b57cec5SDimitry Andric       VectorType *ITy = VectorType::getInteger(FTy);
33910b57cec5SDimitry Andric       Rep = Builder.CreateNot(Builder.CreateBitCast(CI->getArgOperand(0), ITy));
33920b57cec5SDimitry Andric       Rep = Builder.CreateAnd(Rep,
33930b57cec5SDimitry Andric                               Builder.CreateBitCast(CI->getArgOperand(1), ITy));
33940b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, FTy);
33957a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
33960b57cec5SDimitry Andric                           CI->getArgOperand(2));
33975f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.or.") ||
33985f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.por."))) {
33990b57cec5SDimitry Andric       VectorType *FTy = cast<VectorType>(CI->getType());
34000b57cec5SDimitry Andric       VectorType *ITy = VectorType::getInteger(FTy);
34010b57cec5SDimitry Andric       Rep = Builder.CreateOr(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
34020b57cec5SDimitry Andric                              Builder.CreateBitCast(CI->getArgOperand(1), ITy));
34030b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, FTy);
34047a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34050b57cec5SDimitry Andric                           CI->getArgOperand(2));
34065f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.xor.") ||
34075f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.pxor."))) {
34080b57cec5SDimitry Andric       VectorType *FTy = cast<VectorType>(CI->getType());
34090b57cec5SDimitry Andric       VectorType *ITy = VectorType::getInteger(FTy);
34100b57cec5SDimitry Andric       Rep = Builder.CreateXor(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
34110b57cec5SDimitry Andric                               Builder.CreateBitCast(CI->getArgOperand(1), ITy));
34120b57cec5SDimitry Andric       Rep = Builder.CreateBitCast(Rep, FTy);
34137a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34140b57cec5SDimitry Andric                           CI->getArgOperand(2));
34155f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.padd.")) {
34160b57cec5SDimitry Andric       Rep = Builder.CreateAdd(CI->getArgOperand(0), CI->getArgOperand(1));
34177a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34180b57cec5SDimitry Andric                           CI->getArgOperand(2));
34195f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.psub.")) {
34200b57cec5SDimitry Andric       Rep = Builder.CreateSub(CI->getArgOperand(0), CI->getArgOperand(1));
34217a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34220b57cec5SDimitry Andric                           CI->getArgOperand(2));
34235f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.pmull.")) {
34240b57cec5SDimitry Andric       Rep = Builder.CreateMul(CI->getArgOperand(0), CI->getArgOperand(1));
34257a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34260b57cec5SDimitry Andric                           CI->getArgOperand(2));
34275f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.add.p")) {
34285f757f3fSDimitry Andric       if (Name.ends_with(".512")) {
34290b57cec5SDimitry Andric         Intrinsic::ID IID;
34300b57cec5SDimitry Andric         if (Name[17] == 's')
34310b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_add_ps_512;
34320b57cec5SDimitry Andric         else
34330b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_add_pd_512;
34340b57cec5SDimitry Andric 
34350b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
34360b57cec5SDimitry Andric                                  { CI->getArgOperand(0), CI->getArgOperand(1),
34370b57cec5SDimitry Andric                                    CI->getArgOperand(4) });
34380b57cec5SDimitry Andric       } else {
34390b57cec5SDimitry Andric         Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
34400b57cec5SDimitry Andric       }
34417a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34420b57cec5SDimitry Andric                           CI->getArgOperand(2));
34435f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.div.p")) {
34445f757f3fSDimitry Andric       if (Name.ends_with(".512")) {
34450b57cec5SDimitry Andric         Intrinsic::ID IID;
34460b57cec5SDimitry Andric         if (Name[17] == 's')
34470b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_div_ps_512;
34480b57cec5SDimitry Andric         else
34490b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_div_pd_512;
34500b57cec5SDimitry Andric 
34510b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
34520b57cec5SDimitry Andric                                  { CI->getArgOperand(0), CI->getArgOperand(1),
34530b57cec5SDimitry Andric                                    CI->getArgOperand(4) });
34540b57cec5SDimitry Andric       } else {
34550b57cec5SDimitry Andric         Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
34560b57cec5SDimitry Andric       }
34577a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34580b57cec5SDimitry Andric                           CI->getArgOperand(2));
34595f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.mul.p")) {
34605f757f3fSDimitry Andric       if (Name.ends_with(".512")) {
34610b57cec5SDimitry Andric         Intrinsic::ID IID;
34620b57cec5SDimitry Andric         if (Name[17] == 's')
34630b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_mul_ps_512;
34640b57cec5SDimitry Andric         else
34650b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_mul_pd_512;
34660b57cec5SDimitry Andric 
34670b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
34680b57cec5SDimitry Andric                                  { CI->getArgOperand(0), CI->getArgOperand(1),
34690b57cec5SDimitry Andric                                    CI->getArgOperand(4) });
34700b57cec5SDimitry Andric       } else {
34710b57cec5SDimitry Andric         Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
34720b57cec5SDimitry Andric       }
34737a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34740b57cec5SDimitry Andric                           CI->getArgOperand(2));
34755f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.sub.p")) {
34765f757f3fSDimitry Andric       if (Name.ends_with(".512")) {
34770b57cec5SDimitry Andric         Intrinsic::ID IID;
34780b57cec5SDimitry Andric         if (Name[17] == 's')
34790b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_sub_ps_512;
34800b57cec5SDimitry Andric         else
34810b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_sub_pd_512;
34820b57cec5SDimitry Andric 
34830b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
34840b57cec5SDimitry Andric                                  { CI->getArgOperand(0), CI->getArgOperand(1),
34850b57cec5SDimitry Andric                                    CI->getArgOperand(4) });
34860b57cec5SDimitry Andric       } else {
34870b57cec5SDimitry Andric         Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
34880b57cec5SDimitry Andric       }
34897a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
34900b57cec5SDimitry Andric                           CI->getArgOperand(2));
34915f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.max.p") ||
34925f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.min.p")) &&
34930b57cec5SDimitry Andric                Name.drop_front(18) == ".512") {
34940b57cec5SDimitry Andric       bool IsDouble = Name[17] == 'd';
34950b57cec5SDimitry Andric       bool IsMin = Name[13] == 'i';
34960b57cec5SDimitry Andric       static const Intrinsic::ID MinMaxTbl[2][2] = {
34970b57cec5SDimitry Andric         { Intrinsic::x86_avx512_max_ps_512, Intrinsic::x86_avx512_max_pd_512 },
34980b57cec5SDimitry Andric         { Intrinsic::x86_avx512_min_ps_512, Intrinsic::x86_avx512_min_pd_512 }
34990b57cec5SDimitry Andric       };
35000b57cec5SDimitry Andric       Intrinsic::ID IID = MinMaxTbl[IsMin][IsDouble];
35010b57cec5SDimitry Andric 
35020b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
35030b57cec5SDimitry Andric                                { CI->getArgOperand(0), CI->getArgOperand(1),
35040b57cec5SDimitry Andric                                  CI->getArgOperand(4) });
35057a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
35060b57cec5SDimitry Andric                           CI->getArgOperand(2));
35075f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.lzcnt.")) {
35080b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
35090b57cec5SDimitry Andric                                                          Intrinsic::ctlz,
35100b57cec5SDimitry Andric                                                          CI->getType()),
35110b57cec5SDimitry Andric                                { CI->getArgOperand(0), Builder.getInt1(false) });
35127a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
35130b57cec5SDimitry Andric                           CI->getArgOperand(1));
35145f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.psll")) {
35150b57cec5SDimitry Andric       bool IsImmediate = Name[16] == 'i' ||
35160b57cec5SDimitry Andric                          (Name.size() > 18 && Name[18] == 'i');
35170b57cec5SDimitry Andric       bool IsVariable = Name[16] == 'v';
35180b57cec5SDimitry Andric       char Size = Name[16] == '.' ? Name[17] :
35190b57cec5SDimitry Andric                   Name[17] == '.' ? Name[18] :
35200b57cec5SDimitry Andric                   Name[18] == '.' ? Name[19] :
35210b57cec5SDimitry Andric                                     Name[20];
35220b57cec5SDimitry Andric 
35230b57cec5SDimitry Andric       Intrinsic::ID IID;
35240b57cec5SDimitry Andric       if (IsVariable && Name[17] != '.') {
35250b57cec5SDimitry Andric         if (Size == 'd' && Name[17] == '2') // avx512.mask.psllv2.di
35260b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psllv_q;
35270b57cec5SDimitry Andric         else if (Size == 'd' && Name[17] == '4') // avx512.mask.psllv4.di
35280b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psllv_q_256;
35290b57cec5SDimitry Andric         else if (Size == 's' && Name[17] == '4') // avx512.mask.psllv4.si
35300b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psllv_d;
35310b57cec5SDimitry Andric         else if (Size == 's' && Name[17] == '8') // avx512.mask.psllv8.si
35320b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psllv_d_256;
35330b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '8') // avx512.mask.psllv8.hi
35340b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psllv_w_128;
35350b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '1') // avx512.mask.psllv16.hi
35360b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psllv_w_256;
35370b57cec5SDimitry Andric         else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psllv32hi
35380b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psllv_w_512;
35390b57cec5SDimitry Andric         else
35400b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
35415f757f3fSDimitry Andric       } else if (Name.ends_with(".128")) {
35420b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psll.d.128, avx512.mask.psll.di.128
35430b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_pslli_d
35440b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psll_d;
35450b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psll.q.128, avx512.mask.psll.qi.128
35460b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_pslli_q
35470b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psll_q;
35480b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psll.w.128, avx512.mask.psll.wi.128
35490b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_pslli_w
35500b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psll_w;
35510b57cec5SDimitry Andric         else
35520b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
35535f757f3fSDimitry Andric       } else if (Name.ends_with(".256")) {
35540b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psll.d.256, avx512.mask.psll.di.256
35550b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_pslli_d
35560b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psll_d;
35570b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psll.q.256, avx512.mask.psll.qi.256
35580b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_pslli_q
35590b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psll_q;
35600b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psll.w.256, avx512.mask.psll.wi.256
35610b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_pslli_w
35620b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psll_w;
35630b57cec5SDimitry Andric         else
35640b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
35650b57cec5SDimitry Andric       } else {
35660b57cec5SDimitry Andric         if (Size == 'd') // psll.di.512, pslli.d, psll.d, psllv.d.512
35670b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_pslli_d_512 :
35680b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psllv_d_512 :
35690b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psll_d_512;
35700b57cec5SDimitry Andric         else if (Size == 'q') // psll.qi.512, pslli.q, psll.q, psllv.q.512
35710b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_pslli_q_512 :
35720b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psllv_q_512 :
35730b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psll_q_512;
35740b57cec5SDimitry Andric         else if (Size == 'w') // psll.wi.512, pslli.w, psll.w
35750b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_pslli_w_512
35760b57cec5SDimitry Andric                             : Intrinsic::x86_avx512_psll_w_512;
35770b57cec5SDimitry Andric         else
35780b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
35790b57cec5SDimitry Andric       }
35800b57cec5SDimitry Andric 
35817a6dacacSDimitry Andric       Rep = upgradeX86MaskedShift(Builder, *CI, IID);
35825f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.psrl")) {
35830b57cec5SDimitry Andric       bool IsImmediate = Name[16] == 'i' ||
35840b57cec5SDimitry Andric                          (Name.size() > 18 && Name[18] == 'i');
35850b57cec5SDimitry Andric       bool IsVariable = Name[16] == 'v';
35860b57cec5SDimitry Andric       char Size = Name[16] == '.' ? Name[17] :
35870b57cec5SDimitry Andric                   Name[17] == '.' ? Name[18] :
35880b57cec5SDimitry Andric                   Name[18] == '.' ? Name[19] :
35890b57cec5SDimitry Andric                                     Name[20];
35900b57cec5SDimitry Andric 
35910b57cec5SDimitry Andric       Intrinsic::ID IID;
35920b57cec5SDimitry Andric       if (IsVariable && Name[17] != '.') {
35930b57cec5SDimitry Andric         if (Size == 'd' && Name[17] == '2') // avx512.mask.psrlv2.di
35940b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrlv_q;
35950b57cec5SDimitry Andric         else if (Size == 'd' && Name[17] == '4') // avx512.mask.psrlv4.di
35960b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrlv_q_256;
35970b57cec5SDimitry Andric         else if (Size == 's' && Name[17] == '4') // avx512.mask.psrlv4.si
35980b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrlv_d;
35990b57cec5SDimitry Andric         else if (Size == 's' && Name[17] == '8') // avx512.mask.psrlv8.si
36000b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrlv_d_256;
36010b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrlv8.hi
36020b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrlv_w_128;
36030b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrlv16.hi
36040b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrlv_w_256;
36050b57cec5SDimitry Andric         else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrlv32hi
36060b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrlv_w_512;
36070b57cec5SDimitry Andric         else
36080b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36095f757f3fSDimitry Andric       } else if (Name.ends_with(".128")) {
36100b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psrl.d.128, avx512.mask.psrl.di.128
36110b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_psrli_d
36120b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psrl_d;
36130b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psrl.q.128, avx512.mask.psrl.qi.128
36140b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_psrli_q
36150b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psrl_q;
36160b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psrl.w.128, avx512.mask.psrl.wi.128
36170b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_psrli_w
36180b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psrl_w;
36190b57cec5SDimitry Andric         else
36200b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36215f757f3fSDimitry Andric       } else if (Name.ends_with(".256")) {
36220b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psrl.d.256, avx512.mask.psrl.di.256
36230b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_psrli_d
36240b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psrl_d;
36250b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psrl.q.256, avx512.mask.psrl.qi.256
36260b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_psrli_q
36270b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psrl_q;
36280b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psrl.w.256, avx512.mask.psrl.wi.256
36290b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_psrli_w
36300b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psrl_w;
36310b57cec5SDimitry Andric         else
36320b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36330b57cec5SDimitry Andric       } else {
36340b57cec5SDimitry Andric         if (Size == 'd') // psrl.di.512, psrli.d, psrl.d, psrl.d.512
36350b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrli_d_512 :
36360b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrlv_d_512 :
36370b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psrl_d_512;
36380b57cec5SDimitry Andric         else if (Size == 'q') // psrl.qi.512, psrli.q, psrl.q, psrl.q.512
36390b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrli_q_512 :
36400b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrlv_q_512 :
36410b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psrl_q_512;
36420b57cec5SDimitry Andric         else if (Size == 'w') // psrl.wi.512, psrli.w, psrl.w)
36430b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrli_w_512
36440b57cec5SDimitry Andric                             : Intrinsic::x86_avx512_psrl_w_512;
36450b57cec5SDimitry Andric         else
36460b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36470b57cec5SDimitry Andric       }
36480b57cec5SDimitry Andric 
36497a6dacacSDimitry Andric       Rep = upgradeX86MaskedShift(Builder, *CI, IID);
36505f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.psra")) {
36510b57cec5SDimitry Andric       bool IsImmediate = Name[16] == 'i' ||
36520b57cec5SDimitry Andric                          (Name.size() > 18 && Name[18] == 'i');
36530b57cec5SDimitry Andric       bool IsVariable = Name[16] == 'v';
36540b57cec5SDimitry Andric       char Size = Name[16] == '.' ? Name[17] :
36550b57cec5SDimitry Andric                   Name[17] == '.' ? Name[18] :
36560b57cec5SDimitry Andric                   Name[18] == '.' ? Name[19] :
36570b57cec5SDimitry Andric                                     Name[20];
36580b57cec5SDimitry Andric 
36590b57cec5SDimitry Andric       Intrinsic::ID IID;
36600b57cec5SDimitry Andric       if (IsVariable && Name[17] != '.') {
36610b57cec5SDimitry Andric         if (Size == 's' && Name[17] == '4') // avx512.mask.psrav4.si
36620b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrav_d;
36630b57cec5SDimitry Andric         else if (Size == 's' && Name[17] == '8') // avx512.mask.psrav8.si
36640b57cec5SDimitry Andric           IID = Intrinsic::x86_avx2_psrav_d_256;
36650b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrav8.hi
36660b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrav_w_128;
36670b57cec5SDimitry Andric         else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrav16.hi
36680b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrav_w_256;
36690b57cec5SDimitry Andric         else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrav32hi
36700b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_psrav_w_512;
36710b57cec5SDimitry Andric         else
36720b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36735f757f3fSDimitry Andric       } else if (Name.ends_with(".128")) {
36740b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psra.d.128, avx512.mask.psra.di.128
36750b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_psrai_d
36760b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psra_d;
36770b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psra.q.128, avx512.mask.psra.qi.128
36780b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_128 :
36790b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrav_q_128 :
36800b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psra_q_128;
36810b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psra.w.128, avx512.mask.psra.wi.128
36820b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_sse2_psrai_w
36830b57cec5SDimitry Andric                             : Intrinsic::x86_sse2_psra_w;
36840b57cec5SDimitry Andric         else
36850b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36865f757f3fSDimitry Andric       } else if (Name.ends_with(".256")) {
36870b57cec5SDimitry Andric         if (Size == 'd') // avx512.mask.psra.d.256, avx512.mask.psra.di.256
36880b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_psrai_d
36890b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psra_d;
36900b57cec5SDimitry Andric         else if (Size == 'q') // avx512.mask.psra.q.256, avx512.mask.psra.qi.256
36910b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_256 :
36920b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrav_q_256 :
36930b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psra_q_256;
36940b57cec5SDimitry Andric         else if (Size == 'w') // avx512.mask.psra.w.256, avx512.mask.psra.wi.256
36950b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx2_psrai_w
36960b57cec5SDimitry Andric                             : Intrinsic::x86_avx2_psra_w;
36970b57cec5SDimitry Andric         else
36980b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
36990b57cec5SDimitry Andric       } else {
37000b57cec5SDimitry Andric         if (Size == 'd') // psra.di.512, psrai.d, psra.d, psrav.d.512
37010b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrai_d_512 :
37020b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrav_d_512 :
37030b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psra_d_512;
37040b57cec5SDimitry Andric         else if (Size == 'q') // psra.qi.512, psrai.q, psra.q
37050b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrai_q_512 :
37060b57cec5SDimitry Andric                 IsVariable  ? Intrinsic::x86_avx512_psrav_q_512 :
37070b57cec5SDimitry Andric                               Intrinsic::x86_avx512_psra_q_512;
37080b57cec5SDimitry Andric         else if (Size == 'w') // psra.wi.512, psrai.w, psra.w
37090b57cec5SDimitry Andric           IID = IsImmediate ? Intrinsic::x86_avx512_psrai_w_512
37100b57cec5SDimitry Andric                             : Intrinsic::x86_avx512_psra_w_512;
37110b57cec5SDimitry Andric         else
37120b57cec5SDimitry Andric           llvm_unreachable("Unexpected size");
37130b57cec5SDimitry Andric       }
37140b57cec5SDimitry Andric 
37157a6dacacSDimitry Andric       Rep = upgradeX86MaskedShift(Builder, *CI, IID);
37165f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.move.s")) {
37170b57cec5SDimitry Andric       Rep = upgradeMaskedMove(Builder, *CI);
37185f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.cvtmask2")) {
37197a6dacacSDimitry Andric       Rep = upgradeMaskToInt(Builder, *CI);
37205f757f3fSDimitry Andric     } else if (IsX86 && Name.ends_with(".movntdqa")) {
37210b57cec5SDimitry Andric       MDNode *Node = MDNode::get(
37220b57cec5SDimitry Andric           C, ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
37230b57cec5SDimitry Andric 
37240b57cec5SDimitry Andric       Value *Ptr = CI->getArgOperand(0);
37250b57cec5SDimitry Andric 
37260b57cec5SDimitry Andric       // Convert the type of the pointer to a pointer to the stored type.
37275ffd83dbSDimitry Andric       Value *BC = Builder.CreateBitCast(
37285ffd83dbSDimitry Andric           Ptr, PointerType::getUnqual(CI->getType()), "cast");
37295ffd83dbSDimitry Andric       LoadInst *LI = Builder.CreateAlignedLoad(
37305ffd83dbSDimitry Andric           CI->getType(), BC,
3731bdd1243dSDimitry Andric           Align(CI->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
373206c3fb27SDimitry Andric       LI->setMetadata(LLVMContext::MD_nontemporal, Node);
37330b57cec5SDimitry Andric       Rep = LI;
37345f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("fma.vfmadd.") ||
37355f757f3fSDimitry Andric                          Name.starts_with("fma.vfmsub.") ||
37365f757f3fSDimitry Andric                          Name.starts_with("fma.vfnmadd.") ||
37375f757f3fSDimitry Andric                          Name.starts_with("fma.vfnmsub."))) {
37380b57cec5SDimitry Andric       bool NegMul = Name[6] == 'n';
37390b57cec5SDimitry Andric       bool NegAcc = NegMul ? Name[8] == 's' : Name[7] == 's';
37400b57cec5SDimitry Andric       bool IsScalar = NegMul ? Name[12] == 's' : Name[11] == 's';
37410b57cec5SDimitry Andric 
37420b57cec5SDimitry Andric       Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
37430b57cec5SDimitry Andric                        CI->getArgOperand(2) };
37440b57cec5SDimitry Andric 
37450b57cec5SDimitry Andric       if (IsScalar) {
37460b57cec5SDimitry Andric         Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
37470b57cec5SDimitry Andric         Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
37480b57cec5SDimitry Andric         Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
37490b57cec5SDimitry Andric       }
37500b57cec5SDimitry Andric 
37510b57cec5SDimitry Andric       if (NegMul && !IsScalar)
37520b57cec5SDimitry Andric         Ops[0] = Builder.CreateFNeg(Ops[0]);
37530b57cec5SDimitry Andric       if (NegMul && IsScalar)
37540b57cec5SDimitry Andric         Ops[1] = Builder.CreateFNeg(Ops[1]);
37550b57cec5SDimitry Andric       if (NegAcc)
37560b57cec5SDimitry Andric         Ops[2] = Builder.CreateFNeg(Ops[2]);
37570b57cec5SDimitry Andric 
37580b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
37590b57cec5SDimitry Andric                                                          Intrinsic::fma,
37600b57cec5SDimitry Andric                                                          Ops[0]->getType()),
37610b57cec5SDimitry Andric                                Ops);
37620b57cec5SDimitry Andric 
37630b57cec5SDimitry Andric       if (IsScalar)
37640b57cec5SDimitry Andric         Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep,
37650b57cec5SDimitry Andric                                           (uint64_t)0);
37665f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("fma4.vfmadd.s")) {
37670b57cec5SDimitry Andric       Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
37680b57cec5SDimitry Andric                        CI->getArgOperand(2) };
37690b57cec5SDimitry Andric 
37700b57cec5SDimitry Andric       Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
37710b57cec5SDimitry Andric       Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
37720b57cec5SDimitry Andric       Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
37730b57cec5SDimitry Andric 
37740b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
37750b57cec5SDimitry Andric                                                          Intrinsic::fma,
37760b57cec5SDimitry Andric                                                          Ops[0]->getType()),
37770b57cec5SDimitry Andric                                Ops);
37780b57cec5SDimitry Andric 
37790b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(Constant::getNullValue(CI->getType()),
37800b57cec5SDimitry Andric                                         Rep, (uint64_t)0);
37815f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vfmadd.s") ||
37825f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vfmadd.s") ||
37835f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmadd.s") ||
37845f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmsub.s") ||
37855f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfnmsub.s"))) {
37860b57cec5SDimitry Andric       bool IsMask3 = Name[11] == '3';
37870b57cec5SDimitry Andric       bool IsMaskZ = Name[11] == 'z';
37880b57cec5SDimitry Andric       // Drop the "avx512.mask." to make it easier.
37890b57cec5SDimitry Andric       Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
37900b57cec5SDimitry Andric       bool NegMul = Name[2] == 'n';
37910b57cec5SDimitry Andric       bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
37920b57cec5SDimitry Andric 
37930b57cec5SDimitry Andric       Value *A = CI->getArgOperand(0);
37940b57cec5SDimitry Andric       Value *B = CI->getArgOperand(1);
37950b57cec5SDimitry Andric       Value *C = CI->getArgOperand(2);
37960b57cec5SDimitry Andric 
37970b57cec5SDimitry Andric       if (NegMul && (IsMask3 || IsMaskZ))
37980b57cec5SDimitry Andric         A = Builder.CreateFNeg(A);
37990b57cec5SDimitry Andric       if (NegMul && !(IsMask3 || IsMaskZ))
38000b57cec5SDimitry Andric         B = Builder.CreateFNeg(B);
38010b57cec5SDimitry Andric       if (NegAcc)
38020b57cec5SDimitry Andric         C = Builder.CreateFNeg(C);
38030b57cec5SDimitry Andric 
38040b57cec5SDimitry Andric       A = Builder.CreateExtractElement(A, (uint64_t)0);
38050b57cec5SDimitry Andric       B = Builder.CreateExtractElement(B, (uint64_t)0);
38060b57cec5SDimitry Andric       C = Builder.CreateExtractElement(C, (uint64_t)0);
38070b57cec5SDimitry Andric 
38080b57cec5SDimitry Andric       if (!isa<ConstantInt>(CI->getArgOperand(4)) ||
38090b57cec5SDimitry Andric           cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4) {
38100b57cec5SDimitry Andric         Value *Ops[] = { A, B, C, CI->getArgOperand(4) };
38110b57cec5SDimitry Andric 
38120b57cec5SDimitry Andric         Intrinsic::ID IID;
38130b57cec5SDimitry Andric         if (Name.back() == 'd')
38140b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmadd_f64;
38150b57cec5SDimitry Andric         else
38160b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmadd_f32;
38170b57cec5SDimitry Andric         Function *FMA = Intrinsic::getDeclaration(CI->getModule(), IID);
38180b57cec5SDimitry Andric         Rep = Builder.CreateCall(FMA, Ops);
38190b57cec5SDimitry Andric       } else {
38200b57cec5SDimitry Andric         Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
38210b57cec5SDimitry Andric                                                   Intrinsic::fma,
38220b57cec5SDimitry Andric                                                   A->getType());
38230b57cec5SDimitry Andric         Rep = Builder.CreateCall(FMA, { A, B, C });
38240b57cec5SDimitry Andric       }
38250b57cec5SDimitry Andric 
38260b57cec5SDimitry Andric       Value *PassThru = IsMaskZ ? Constant::getNullValue(Rep->getType()) :
38270b57cec5SDimitry Andric                         IsMask3 ? C : A;
38280b57cec5SDimitry Andric 
38290b57cec5SDimitry Andric       // For Mask3 with NegAcc, we need to create a new extractelement that
38300b57cec5SDimitry Andric       // avoids the negation above.
38310b57cec5SDimitry Andric       if (NegAcc && IsMask3)
38320b57cec5SDimitry Andric         PassThru = Builder.CreateExtractElement(CI->getArgOperand(2),
38330b57cec5SDimitry Andric                                                 (uint64_t)0);
38340b57cec5SDimitry Andric 
38357a6dacacSDimitry Andric       Rep = emitX86ScalarSelect(Builder, CI->getArgOperand(3), Rep, PassThru);
38360b57cec5SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(IsMask3 ? 2 : 0),
38370b57cec5SDimitry Andric                                         Rep, (uint64_t)0);
38385f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vfmadd.p") ||
38395f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vfnmadd.p") ||
38405f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vfnmsub.p") ||
38415f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmadd.p") ||
38425f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmsub.p") ||
38435f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfnmsub.p") ||
38445f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vfmadd.p"))) {
38450b57cec5SDimitry Andric       bool IsMask3 = Name[11] == '3';
38460b57cec5SDimitry Andric       bool IsMaskZ = Name[11] == 'z';
38470b57cec5SDimitry Andric       // Drop the "avx512.mask." to make it easier.
38480b57cec5SDimitry Andric       Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
38490b57cec5SDimitry Andric       bool NegMul = Name[2] == 'n';
38500b57cec5SDimitry Andric       bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
38510b57cec5SDimitry Andric 
38520b57cec5SDimitry Andric       Value *A = CI->getArgOperand(0);
38530b57cec5SDimitry Andric       Value *B = CI->getArgOperand(1);
38540b57cec5SDimitry Andric       Value *C = CI->getArgOperand(2);
38550b57cec5SDimitry Andric 
38560b57cec5SDimitry Andric       if (NegMul && (IsMask3 || IsMaskZ))
38570b57cec5SDimitry Andric         A = Builder.CreateFNeg(A);
38580b57cec5SDimitry Andric       if (NegMul && !(IsMask3 || IsMaskZ))
38590b57cec5SDimitry Andric         B = Builder.CreateFNeg(B);
38600b57cec5SDimitry Andric       if (NegAcc)
38610b57cec5SDimitry Andric         C = Builder.CreateFNeg(C);
38620b57cec5SDimitry Andric 
3863349cc55cSDimitry Andric       if (CI->arg_size() == 5 &&
38640b57cec5SDimitry Andric           (!isa<ConstantInt>(CI->getArgOperand(4)) ||
38650b57cec5SDimitry Andric            cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
38660b57cec5SDimitry Andric         Intrinsic::ID IID;
38670b57cec5SDimitry Andric         // Check the character before ".512" in string.
38680b57cec5SDimitry Andric         if (Name[Name.size()-5] == 's')
38690b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmadd_ps_512;
38700b57cec5SDimitry Andric         else
38710b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmadd_pd_512;
38720b57cec5SDimitry Andric 
38730b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
38740b57cec5SDimitry Andric                                  { A, B, C, CI->getArgOperand(4) });
38750b57cec5SDimitry Andric       } else {
38760b57cec5SDimitry Andric         Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
38770b57cec5SDimitry Andric                                                   Intrinsic::fma,
38780b57cec5SDimitry Andric                                                   A->getType());
38790b57cec5SDimitry Andric         Rep = Builder.CreateCall(FMA, { A, B, C });
38800b57cec5SDimitry Andric       }
38810b57cec5SDimitry Andric 
38820b57cec5SDimitry Andric       Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
38830b57cec5SDimitry Andric                         IsMask3 ? CI->getArgOperand(2) :
38840b57cec5SDimitry Andric                                   CI->getArgOperand(0);
38850b57cec5SDimitry Andric 
38867a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
38875f757f3fSDimitry Andric     } else if (IsX86 &&  Name.starts_with("fma.vfmsubadd.p")) {
38885ffd83dbSDimitry Andric       unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
38895ffd83dbSDimitry Andric       unsigned EltWidth = CI->getType()->getScalarSizeInBits();
38905ffd83dbSDimitry Andric       Intrinsic::ID IID;
38915ffd83dbSDimitry Andric       if (VecWidth == 128 && EltWidth == 32)
38925ffd83dbSDimitry Andric         IID = Intrinsic::x86_fma_vfmaddsub_ps;
38935ffd83dbSDimitry Andric       else if (VecWidth == 256 && EltWidth == 32)
38945ffd83dbSDimitry Andric         IID = Intrinsic::x86_fma_vfmaddsub_ps_256;
38955ffd83dbSDimitry Andric       else if (VecWidth == 128 && EltWidth == 64)
38965ffd83dbSDimitry Andric         IID = Intrinsic::x86_fma_vfmaddsub_pd;
38975ffd83dbSDimitry Andric       else if (VecWidth == 256 && EltWidth == 64)
38985ffd83dbSDimitry Andric         IID = Intrinsic::x86_fma_vfmaddsub_pd_256;
38995ffd83dbSDimitry Andric       else
39005ffd83dbSDimitry Andric         llvm_unreachable("Unexpected intrinsic");
39010b57cec5SDimitry Andric 
39020b57cec5SDimitry Andric       Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
39030b57cec5SDimitry Andric                        CI->getArgOperand(2) };
39040b57cec5SDimitry Andric       Ops[2] = Builder.CreateFNeg(Ops[2]);
39055ffd83dbSDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
39065ffd83dbSDimitry Andric                                Ops);
39075f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vfmaddsub.p") ||
39085f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmaddsub.p") ||
39095f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vfmaddsub.p") ||
39105f757f3fSDimitry Andric                          Name.starts_with("avx512.mask3.vfmsubadd.p"))) {
39110b57cec5SDimitry Andric       bool IsMask3 = Name[11] == '3';
39120b57cec5SDimitry Andric       bool IsMaskZ = Name[11] == 'z';
39130b57cec5SDimitry Andric       // Drop the "avx512.mask." to make it easier.
39140b57cec5SDimitry Andric       Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
39150b57cec5SDimitry Andric       bool IsSubAdd = Name[3] == 's';
3916349cc55cSDimitry Andric       if (CI->arg_size() == 5) {
39170b57cec5SDimitry Andric         Intrinsic::ID IID;
39180b57cec5SDimitry Andric         // Check the character before ".512" in string.
39190b57cec5SDimitry Andric         if (Name[Name.size()-5] == 's')
39200b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;
39210b57cec5SDimitry Andric         else
39220b57cec5SDimitry Andric           IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;
39230b57cec5SDimitry Andric 
39240b57cec5SDimitry Andric         Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
39250b57cec5SDimitry Andric                          CI->getArgOperand(2), CI->getArgOperand(4) };
39260b57cec5SDimitry Andric         if (IsSubAdd)
39270b57cec5SDimitry Andric           Ops[2] = Builder.CreateFNeg(Ops[2]);
39280b57cec5SDimitry Andric 
39290b57cec5SDimitry Andric         Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
39305ffd83dbSDimitry Andric                                  Ops);
39310b57cec5SDimitry Andric       } else {
3932e8d8bef9SDimitry Andric         int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
39330b57cec5SDimitry Andric 
39340b57cec5SDimitry Andric         Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
39350b57cec5SDimitry Andric                          CI->getArgOperand(2) };
39360b57cec5SDimitry Andric 
39370b57cec5SDimitry Andric         Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
39380b57cec5SDimitry Andric                                                   Ops[0]->getType());
39390b57cec5SDimitry Andric         Value *Odd = Builder.CreateCall(FMA, Ops);
39400b57cec5SDimitry Andric         Ops[2] = Builder.CreateFNeg(Ops[2]);
39410b57cec5SDimitry Andric         Value *Even = Builder.CreateCall(FMA, Ops);
39420b57cec5SDimitry Andric 
39430b57cec5SDimitry Andric         if (IsSubAdd)
39440b57cec5SDimitry Andric           std::swap(Even, Odd);
39450b57cec5SDimitry Andric 
39465ffd83dbSDimitry Andric         SmallVector<int, 32> Idxs(NumElts);
39470b57cec5SDimitry Andric         for (int i = 0; i != NumElts; ++i)
39480b57cec5SDimitry Andric           Idxs[i] = i + (i % 2) * NumElts;
39490b57cec5SDimitry Andric 
39500b57cec5SDimitry Andric         Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
39510b57cec5SDimitry Andric       }
39520b57cec5SDimitry Andric 
39530b57cec5SDimitry Andric       Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
39540b57cec5SDimitry Andric                         IsMask3 ? CI->getArgOperand(2) :
39550b57cec5SDimitry Andric                                   CI->getArgOperand(0);
39560b57cec5SDimitry Andric 
39577a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
39585f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.pternlog.") ||
39595f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.pternlog."))) {
39600b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
39610b57cec5SDimitry Andric       unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
39620b57cec5SDimitry Andric       unsigned EltWidth = CI->getType()->getScalarSizeInBits();
39630b57cec5SDimitry Andric       Intrinsic::ID IID;
39640b57cec5SDimitry Andric       if (VecWidth == 128 && EltWidth == 32)
39650b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_d_128;
39660b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 32)
39670b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_d_256;
39680b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 32)
39690b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_d_512;
39700b57cec5SDimitry Andric       else if (VecWidth == 128 && EltWidth == 64)
39710b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_q_128;
39720b57cec5SDimitry Andric       else if (VecWidth == 256 && EltWidth == 64)
39730b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_q_256;
39740b57cec5SDimitry Andric       else if (VecWidth == 512 && EltWidth == 64)
39750b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_pternlog_q_512;
39760b57cec5SDimitry Andric       else
39770b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
39780b57cec5SDimitry Andric 
39790b57cec5SDimitry Andric       Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
39800b57cec5SDimitry Andric                         CI->getArgOperand(2), CI->getArgOperand(3) };
39810b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
39820b57cec5SDimitry Andric                                Args);
39830b57cec5SDimitry Andric       Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
39840b57cec5SDimitry Andric                                  : CI->getArgOperand(0);
39857a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep, PassThru);
39865f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vpmadd52") ||
39875f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpmadd52"))) {
39880b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
39890b57cec5SDimitry Andric       bool High = Name[20] == 'h' || Name[21] == 'h';
39900b57cec5SDimitry Andric       unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
39910b57cec5SDimitry Andric       Intrinsic::ID IID;
39920b57cec5SDimitry Andric       if (VecWidth == 128 && !High)
39930b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52l_uq_128;
39940b57cec5SDimitry Andric       else if (VecWidth == 256 && !High)
39950b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52l_uq_256;
39960b57cec5SDimitry Andric       else if (VecWidth == 512 && !High)
39970b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52l_uq_512;
39980b57cec5SDimitry Andric       else if (VecWidth == 128 && High)
39990b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52h_uq_128;
40000b57cec5SDimitry Andric       else if (VecWidth == 256 && High)
40010b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52h_uq_256;
40020b57cec5SDimitry Andric       else if (VecWidth == 512 && High)
40030b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
40040b57cec5SDimitry Andric       else
40050b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
40060b57cec5SDimitry Andric 
40070b57cec5SDimitry Andric       Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
40080b57cec5SDimitry Andric                         CI->getArgOperand(2) };
40090b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
40100b57cec5SDimitry Andric                                Args);
40110b57cec5SDimitry Andric       Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
40120b57cec5SDimitry Andric                                  : CI->getArgOperand(0);
40137a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
40145f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vpermi2var.") ||
40155f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpermt2var.") ||
40165f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpermt2var."))) {
40170b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
40180b57cec5SDimitry Andric       bool IndexForm = Name[17] == 'i';
40197a6dacacSDimitry Andric       Rep = upgradeX86VPERMT2Intrinsics(Builder, *CI, ZeroMask, IndexForm);
40205f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vpdpbusd.") ||
40215f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpdpbusd.") ||
40225f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpdpbusds.") ||
40235f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpdpbusds."))) {
40240b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
40250b57cec5SDimitry Andric       bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
40260b57cec5SDimitry Andric       unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
40270b57cec5SDimitry Andric       Intrinsic::ID IID;
40280b57cec5SDimitry Andric       if (VecWidth == 128 && !IsSaturating)
40290b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusd_128;
40300b57cec5SDimitry Andric       else if (VecWidth == 256 && !IsSaturating)
40310b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusd_256;
40320b57cec5SDimitry Andric       else if (VecWidth == 512 && !IsSaturating)
40330b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusd_512;
40340b57cec5SDimitry Andric       else if (VecWidth == 128 && IsSaturating)
40350b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusds_128;
40360b57cec5SDimitry Andric       else if (VecWidth == 256 && IsSaturating)
40370b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusds_256;
40380b57cec5SDimitry Andric       else if (VecWidth == 512 && IsSaturating)
40390b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpbusds_512;
40400b57cec5SDimitry Andric       else
40410b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
40420b57cec5SDimitry Andric 
40430b57cec5SDimitry Andric       Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
40440b57cec5SDimitry Andric                         CI->getArgOperand(2)  };
40450b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
40460b57cec5SDimitry Andric                                Args);
40470b57cec5SDimitry Andric       Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
40480b57cec5SDimitry Andric                                  : CI->getArgOperand(0);
40497a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
40505f757f3fSDimitry Andric     } else if (IsX86 && (Name.starts_with("avx512.mask.vpdpwssd.") ||
40515f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpdpwssd.") ||
40525f757f3fSDimitry Andric                          Name.starts_with("avx512.mask.vpdpwssds.") ||
40535f757f3fSDimitry Andric                          Name.starts_with("avx512.maskz.vpdpwssds."))) {
40540b57cec5SDimitry Andric       bool ZeroMask = Name[11] == 'z';
40550b57cec5SDimitry Andric       bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
40560b57cec5SDimitry Andric       unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
40570b57cec5SDimitry Andric       Intrinsic::ID IID;
40580b57cec5SDimitry Andric       if (VecWidth == 128 && !IsSaturating)
40590b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssd_128;
40600b57cec5SDimitry Andric       else if (VecWidth == 256 && !IsSaturating)
40610b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssd_256;
40620b57cec5SDimitry Andric       else if (VecWidth == 512 && !IsSaturating)
40630b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssd_512;
40640b57cec5SDimitry Andric       else if (VecWidth == 128 && IsSaturating)
40650b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssds_128;
40660b57cec5SDimitry Andric       else if (VecWidth == 256 && IsSaturating)
40670b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssds_256;
40680b57cec5SDimitry Andric       else if (VecWidth == 512 && IsSaturating)
40690b57cec5SDimitry Andric         IID = Intrinsic::x86_avx512_vpdpwssds_512;
40700b57cec5SDimitry Andric       else
40710b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
40720b57cec5SDimitry Andric 
40730b57cec5SDimitry Andric       Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
40740b57cec5SDimitry Andric                         CI->getArgOperand(2)  };
40750b57cec5SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
40760b57cec5SDimitry Andric                                Args);
40770b57cec5SDimitry Andric       Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
40780b57cec5SDimitry Andric                                  : CI->getArgOperand(0);
40797a6dacacSDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
40800b57cec5SDimitry Andric     } else if (IsX86 && (Name == "addcarryx.u32" || Name == "addcarryx.u64" ||
40810b57cec5SDimitry Andric                          Name == "addcarry.u32" || Name == "addcarry.u64" ||
40820b57cec5SDimitry Andric                          Name == "subborrow.u32" || Name == "subborrow.u64")) {
40830b57cec5SDimitry Andric       Intrinsic::ID IID;
40840b57cec5SDimitry Andric       if (Name[0] == 'a' && Name.back() == '2')
40850b57cec5SDimitry Andric         IID = Intrinsic::x86_addcarry_32;
40860b57cec5SDimitry Andric       else if (Name[0] == 'a' && Name.back() == '4')
40870b57cec5SDimitry Andric         IID = Intrinsic::x86_addcarry_64;
40880b57cec5SDimitry Andric       else if (Name[0] == 's' && Name.back() == '2')
40890b57cec5SDimitry Andric         IID = Intrinsic::x86_subborrow_32;
40900b57cec5SDimitry Andric       else if (Name[0] == 's' && Name.back() == '4')
40910b57cec5SDimitry Andric         IID = Intrinsic::x86_subborrow_64;
40920b57cec5SDimitry Andric       else
40930b57cec5SDimitry Andric         llvm_unreachable("Unexpected intrinsic");
40940b57cec5SDimitry Andric 
40950b57cec5SDimitry Andric       // Make a call with 3 operands.
40960b57cec5SDimitry Andric       Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
40970b57cec5SDimitry Andric                         CI->getArgOperand(2)};
40980b57cec5SDimitry Andric       Value *NewCall = Builder.CreateCall(
40990b57cec5SDimitry Andric                                 Intrinsic::getDeclaration(CI->getModule(), IID),
41000b57cec5SDimitry Andric                                 Args);
41010b57cec5SDimitry Andric 
41020b57cec5SDimitry Andric       // Extract the second result and store it.
41030b57cec5SDimitry Andric       Value *Data = Builder.CreateExtractValue(NewCall, 1);
41040b57cec5SDimitry Andric       // Cast the pointer to the right type.
41050b57cec5SDimitry Andric       Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(3),
41060b57cec5SDimitry Andric                                  llvm::PointerType::getUnqual(Data->getType()));
41075ffd83dbSDimitry Andric       Builder.CreateAlignedStore(Data, Ptr, Align(1));
41080b57cec5SDimitry Andric       // Replace the original call result with the first result of the new call.
41090b57cec5SDimitry Andric       Value *CF = Builder.CreateExtractValue(NewCall, 0);
41100b57cec5SDimitry Andric 
41110b57cec5SDimitry Andric       CI->replaceAllUsesWith(CF);
41120b57cec5SDimitry Andric       Rep = nullptr;
41135f757f3fSDimitry Andric     } else if (IsX86 && Name.starts_with("avx512.mask.") &&
41140b57cec5SDimitry Andric                upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
41150b57cec5SDimitry Andric       // Rep will be updated by the call in the condition.
41160b57cec5SDimitry Andric     } else if (IsNVVM && (Name == "abs.i" || Name == "abs.ll")) {
41170b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
41180b57cec5SDimitry Andric       Value *Neg = Builder.CreateNeg(Arg, "neg");
41190b57cec5SDimitry Andric       Value *Cmp = Builder.CreateICmpSGE(
41200b57cec5SDimitry Andric           Arg, llvm::Constant::getNullValue(Arg->getType()), "abs.cond");
41210b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg, Neg, "abs");
41225f757f3fSDimitry Andric     } else if (IsNVVM && (Name.starts_with("atomic.load.add.f32.p") ||
41235f757f3fSDimitry Andric                           Name.starts_with("atomic.load.add.f64.p"))) {
41240b57cec5SDimitry Andric       Value *Ptr = CI->getArgOperand(0);
41250b57cec5SDimitry Andric       Value *Val = CI->getArgOperand(1);
4126fe6060f1SDimitry Andric       Rep = Builder.CreateAtomicRMW(AtomicRMWInst::FAdd, Ptr, Val, MaybeAlign(),
41270b57cec5SDimitry Andric                                     AtomicOrdering::SequentiallyConsistent);
41287a6dacacSDimitry Andric     } else if (IsNVVM && Name.consume_front("max.") &&
41297a6dacacSDimitry Andric                (Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
41307a6dacacSDimitry Andric                 Name == "ui" || Name == "ull")) {
41310b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
41320b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
41337a6dacacSDimitry Andric       Value *Cmp = Name.starts_with("u")
41340b57cec5SDimitry Andric                        ? Builder.CreateICmpUGE(Arg0, Arg1, "max.cond")
41350b57cec5SDimitry Andric                        : Builder.CreateICmpSGE(Arg0, Arg1, "max.cond");
41360b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "max");
41377a6dacacSDimitry Andric     } else if (IsNVVM && Name.consume_front("min.") &&
41387a6dacacSDimitry Andric                (Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
41397a6dacacSDimitry Andric                 Name == "ui" || Name == "ull")) {
41400b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
41410b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
41427a6dacacSDimitry Andric       Value *Cmp = Name.starts_with("u")
41430b57cec5SDimitry Andric                        ? Builder.CreateICmpULE(Arg0, Arg1, "min.cond")
41440b57cec5SDimitry Andric                        : Builder.CreateICmpSLE(Arg0, Arg1, "min.cond");
41450b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "min");
41460b57cec5SDimitry Andric     } else if (IsNVVM && Name == "clz.ll") {
41477a6dacacSDimitry Andric       // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 returns an i64.
41480b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
41490b57cec5SDimitry Andric       Value *Ctlz = Builder.CreateCall(
41500b57cec5SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
41510b57cec5SDimitry Andric                                     {Arg->getType()}),
41520b57cec5SDimitry Andric           {Arg, Builder.getFalse()}, "ctlz");
41530b57cec5SDimitry Andric       Rep = Builder.CreateTrunc(Ctlz, Builder.getInt32Ty(), "ctlz.trunc");
41540b57cec5SDimitry Andric     } else if (IsNVVM && Name == "popc.ll") {
41557a6dacacSDimitry Andric       // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 returns an
41560b57cec5SDimitry Andric       // i64.
41570b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
41580b57cec5SDimitry Andric       Value *Popc = Builder.CreateCall(
41590b57cec5SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop,
41600b57cec5SDimitry Andric                                     {Arg->getType()}),
41610b57cec5SDimitry Andric           Arg, "ctpop");
41620b57cec5SDimitry Andric       Rep = Builder.CreateTrunc(Popc, Builder.getInt32Ty(), "ctpop.trunc");
416306c3fb27SDimitry Andric     } else if (IsNVVM) {
416406c3fb27SDimitry Andric       if (Name == "h2f") {
416506c3fb27SDimitry Andric         Rep =
416606c3fb27SDimitry Andric             Builder.CreateCall(Intrinsic::getDeclaration(
41670b57cec5SDimitry Andric                                    F->getParent(), Intrinsic::convert_from_fp16,
41680b57cec5SDimitry Andric                                    {Builder.getFloatTy()}),
41690b57cec5SDimitry Andric                                CI->getArgOperand(0), "h2f");
417006c3fb27SDimitry Andric       } else {
41717a6dacacSDimitry Andric         Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic(Name);
417206c3fb27SDimitry Andric         if (IID != Intrinsic::not_intrinsic &&
417306c3fb27SDimitry Andric             !F->getReturnType()->getScalarType()->isBFloatTy()) {
417406c3fb27SDimitry Andric           rename(F);
417506c3fb27SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
417606c3fb27SDimitry Andric           SmallVector<Value *, 2> Args;
417706c3fb27SDimitry Andric           for (size_t I = 0; I < NewFn->arg_size(); ++I) {
417806c3fb27SDimitry Andric             Value *Arg = CI->getArgOperand(I);
417906c3fb27SDimitry Andric             Type *OldType = Arg->getType();
418006c3fb27SDimitry Andric             Type *NewType = NewFn->getArg(I)->getType();
418106c3fb27SDimitry Andric             Args.push_back((OldType->isIntegerTy() &&
418206c3fb27SDimitry Andric                             NewType->getScalarType()->isBFloatTy())
418306c3fb27SDimitry Andric                                ? Builder.CreateBitCast(Arg, NewType)
418406c3fb27SDimitry Andric                                : Arg);
418506c3fb27SDimitry Andric           }
418606c3fb27SDimitry Andric           Rep = Builder.CreateCall(NewFn, Args);
418706c3fb27SDimitry Andric           if (F->getReturnType()->isIntegerTy())
418806c3fb27SDimitry Andric             Rep = Builder.CreateBitCast(Rep, F->getReturnType());
418906c3fb27SDimitry Andric         }
419006c3fb27SDimitry Andric       }
41910eae32dcSDimitry Andric     } else if (IsARM) {
41927a6dacacSDimitry Andric       Rep = upgradeARMIntrinsicCall(Name, CI, F, Builder);
419306c3fb27SDimitry Andric     } else if (IsAMDGCN) {
41947a6dacacSDimitry Andric       Rep = upgradeAMDGCNIntrinsicCall(Name, CI, F, Builder);
41950b57cec5SDimitry Andric     } else {
419681ad6265SDimitry Andric       llvm_unreachable("Unknown function for CallBase upgrade.");
41970b57cec5SDimitry Andric     }
41980b57cec5SDimitry Andric 
41990b57cec5SDimitry Andric     if (Rep)
42000b57cec5SDimitry Andric       CI->replaceAllUsesWith(Rep);
42010b57cec5SDimitry Andric     CI->eraseFromParent();
42020b57cec5SDimitry Andric     return;
42030b57cec5SDimitry Andric   }
42040b57cec5SDimitry Andric 
420581ad6265SDimitry Andric   const auto &DefaultCase = [&]() -> void {
420681ad6265SDimitry Andric     if (CI->getFunctionType() == NewFn->getFunctionType()) {
420781ad6265SDimitry Andric       // Handle generic mangling change.
42080b57cec5SDimitry Andric       assert(
42090b57cec5SDimitry Andric           (CI->getCalledFunction()->getName() != NewFn->getName()) &&
421081ad6265SDimitry Andric           "Unknown function for CallBase upgrade and isn't just a name change");
42110b57cec5SDimitry Andric       CI->setCalledFunction(NewFn);
421281ad6265SDimitry Andric       return;
421381ad6265SDimitry Andric     }
421481ad6265SDimitry Andric 
421581ad6265SDimitry Andric     // This must be an upgrade from a named to a literal struct.
4216bdd1243dSDimitry Andric     if (auto *OldST = dyn_cast<StructType>(CI->getType())) {
4217bdd1243dSDimitry Andric       assert(OldST != NewFn->getReturnType() &&
4218bdd1243dSDimitry Andric              "Return type must have changed");
421981ad6265SDimitry Andric       assert(OldST->getNumElements() ==
422081ad6265SDimitry Andric                  cast<StructType>(NewFn->getReturnType())->getNumElements() &&
422181ad6265SDimitry Andric              "Must have same number of elements");
422281ad6265SDimitry Andric 
422381ad6265SDimitry Andric       SmallVector<Value *> Args(CI->args());
422481ad6265SDimitry Andric       Value *NewCI = Builder.CreateCall(NewFn, Args);
422581ad6265SDimitry Andric       Value *Res = PoisonValue::get(OldST);
422681ad6265SDimitry Andric       for (unsigned Idx = 0; Idx < OldST->getNumElements(); ++Idx) {
422781ad6265SDimitry Andric         Value *Elem = Builder.CreateExtractValue(NewCI, Idx);
422881ad6265SDimitry Andric         Res = Builder.CreateInsertValue(Res, Elem, Idx);
422981ad6265SDimitry Andric       }
423081ad6265SDimitry Andric       CI->replaceAllUsesWith(Res);
423181ad6265SDimitry Andric       CI->eraseFromParent();
423281ad6265SDimitry Andric       return;
4233bdd1243dSDimitry Andric     }
4234bdd1243dSDimitry Andric 
4235bdd1243dSDimitry Andric     // We're probably about to produce something invalid. Let the verifier catch
4236bdd1243dSDimitry Andric     // it instead of dying here.
4237bdd1243dSDimitry Andric     CI->setCalledOperand(
4238bdd1243dSDimitry Andric         ConstantExpr::getPointerCast(NewFn, CI->getCalledOperand()->getType()));
4239bdd1243dSDimitry Andric     return;
42400b57cec5SDimitry Andric   };
42410b57cec5SDimitry Andric   CallInst *NewCall = nullptr;
42420b57cec5SDimitry Andric   switch (NewFn->getIntrinsicID()) {
42430b57cec5SDimitry Andric   default: {
42440b57cec5SDimitry Andric     DefaultCase();
42450b57cec5SDimitry Andric     return;
42460b57cec5SDimitry Andric   }
42470b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst1:
42480b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst2:
42490b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst3:
42500b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst4:
42510b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst2lane:
42520b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst3lane:
42530b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst4lane: {
4254349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
42550b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
42560b57cec5SDimitry Andric     break;
42570b57cec5SDimitry Andric   }
4258bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfmlalb_lane_v2:
4259bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfmlalt_lane_v2:
4260bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfdot_lane_v2: {
4261bdd1243dSDimitry Andric     LLVMContext &Ctx = F->getParent()->getContext();
4262bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4263bdd1243dSDimitry Andric     Args[3] = ConstantInt::get(Type::getInt32Ty(Ctx),
4264bdd1243dSDimitry Andric                                cast<ConstantInt>(Args[3])->getZExtValue());
4265bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4266bdd1243dSDimitry Andric     break;
4267bdd1243dSDimitry Andric   }
4268bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld3_sret:
4269bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld4_sret:
4270bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld2_sret: {
4271bdd1243dSDimitry Andric     StringRef Name = F->getName();
4272bdd1243dSDimitry Andric     Name = Name.substr(5);
4273bdd1243dSDimitry Andric     unsigned N = StringSwitch<unsigned>(Name)
4274bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld2", 2)
4275bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld3", 3)
4276bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld4", 4)
4277bdd1243dSDimitry Andric                      .Default(0);
4278bdd1243dSDimitry Andric     ScalableVectorType *RetTy =
4279bdd1243dSDimitry Andric         dyn_cast<ScalableVectorType>(F->getReturnType());
4280bdd1243dSDimitry Andric     unsigned MinElts = RetTy->getMinNumElements() / N;
4281bdd1243dSDimitry Andric     SmallVector<Value *, 2> Args(CI->args());
4282bdd1243dSDimitry Andric     Value *NewLdCall = Builder.CreateCall(NewFn, Args);
4283bdd1243dSDimitry Andric     Value *Ret = llvm::PoisonValue::get(RetTy);
4284bdd1243dSDimitry Andric     for (unsigned I = 0; I < N; I++) {
4285bdd1243dSDimitry Andric       Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4286bdd1243dSDimitry Andric       Value *SRet = Builder.CreateExtractValue(NewLdCall, I);
4287bdd1243dSDimitry Andric       Ret = Builder.CreateInsertVector(RetTy, Ret, SRet, Idx);
4288bdd1243dSDimitry Andric     }
4289bdd1243dSDimitry Andric     NewCall = dyn_cast<CallInst>(Ret);
4290bdd1243dSDimitry Andric     break;
4291bdd1243dSDimitry Andric   }
4292bdd1243dSDimitry Andric 
42935f757f3fSDimitry Andric   case Intrinsic::coro_end: {
42945f757f3fSDimitry Andric     SmallVector<Value *, 3> Args(CI->args());
42955f757f3fSDimitry Andric     Args.push_back(ConstantTokenNone::get(CI->getContext()));
42965f757f3fSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
42975f757f3fSDimitry Andric     break;
42985f757f3fSDimitry Andric   }
42995f757f3fSDimitry Andric 
4300bdd1243dSDimitry Andric   case Intrinsic::vector_extract: {
4301bdd1243dSDimitry Andric     StringRef Name = F->getName();
4302bdd1243dSDimitry Andric     Name = Name.substr(5); // Strip llvm
43035f757f3fSDimitry Andric     if (!Name.starts_with("aarch64.sve.tuple.get")) {
4304bdd1243dSDimitry Andric       DefaultCase();
4305bdd1243dSDimitry Andric       return;
4306bdd1243dSDimitry Andric     }
4307bdd1243dSDimitry Andric     ScalableVectorType *RetTy =
4308bdd1243dSDimitry Andric         dyn_cast<ScalableVectorType>(F->getReturnType());
4309bdd1243dSDimitry Andric     unsigned MinElts = RetTy->getMinNumElements();
4310bdd1243dSDimitry Andric     unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4311bdd1243dSDimitry Andric     Value *NewIdx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4312bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0), NewIdx});
4313bdd1243dSDimitry Andric     break;
4314bdd1243dSDimitry Andric   }
4315bdd1243dSDimitry Andric 
4316bdd1243dSDimitry Andric   case Intrinsic::vector_insert: {
4317bdd1243dSDimitry Andric     StringRef Name = F->getName();
4318bdd1243dSDimitry Andric     Name = Name.substr(5);
43195f757f3fSDimitry Andric     if (!Name.starts_with("aarch64.sve.tuple")) {
4320bdd1243dSDimitry Andric       DefaultCase();
4321bdd1243dSDimitry Andric       return;
4322bdd1243dSDimitry Andric     }
43235f757f3fSDimitry Andric     if (Name.starts_with("aarch64.sve.tuple.set")) {
4324bdd1243dSDimitry Andric       unsigned I = dyn_cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4325bdd1243dSDimitry Andric       ScalableVectorType *Ty =
4326bdd1243dSDimitry Andric           dyn_cast<ScalableVectorType>(CI->getArgOperand(2)->getType());
4327bdd1243dSDimitry Andric       Value *NewIdx =
4328bdd1243dSDimitry Andric           ConstantInt::get(Type::getInt64Ty(C), I * Ty->getMinNumElements());
4329bdd1243dSDimitry Andric       NewCall = Builder.CreateCall(
4330bdd1243dSDimitry Andric           NewFn, {CI->getArgOperand(0), CI->getArgOperand(2), NewIdx});
4331bdd1243dSDimitry Andric       break;
4332bdd1243dSDimitry Andric     }
43335f757f3fSDimitry Andric     if (Name.starts_with("aarch64.sve.tuple.create")) {
4334bdd1243dSDimitry Andric       unsigned N = StringSwitch<unsigned>(Name)
4335bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create2", 2)
4336bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create3", 3)
4337bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create4", 4)
4338bdd1243dSDimitry Andric                        .Default(0);
4339bdd1243dSDimitry Andric       assert(N > 1 && "Create is expected to be between 2-4");
4340bdd1243dSDimitry Andric       ScalableVectorType *RetTy =
4341bdd1243dSDimitry Andric           dyn_cast<ScalableVectorType>(F->getReturnType());
4342bdd1243dSDimitry Andric       Value *Ret = llvm::PoisonValue::get(RetTy);
4343bdd1243dSDimitry Andric       unsigned MinElts = RetTy->getMinNumElements() / N;
4344bdd1243dSDimitry Andric       for (unsigned I = 0; I < N; I++) {
4345bdd1243dSDimitry Andric         Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4346bdd1243dSDimitry Andric         Value *V = CI->getArgOperand(I);
4347bdd1243dSDimitry Andric         Ret = Builder.CreateInsertVector(RetTy, Ret, V, Idx);
4348bdd1243dSDimitry Andric       }
4349bdd1243dSDimitry Andric       NewCall = dyn_cast<CallInst>(Ret);
4350bdd1243dSDimitry Andric     }
4351bdd1243dSDimitry Andric     break;
4352bdd1243dSDimitry Andric   }
43530b57cec5SDimitry Andric 
4354e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfdot:
4355e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmmla:
4356e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmlalb:
4357e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmlalt:
4358e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfdot:
4359e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmmla:
4360e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmlalb:
4361e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmlalt: {
4362e8d8bef9SDimitry Andric     SmallVector<Value *, 3> Args;
4363349cc55cSDimitry Andric     assert(CI->arg_size() == 3 &&
4364e8d8bef9SDimitry Andric            "Mismatch between function args and call args");
4365e8d8bef9SDimitry Andric     size_t OperandWidth =
4366e8d8bef9SDimitry Andric         CI->getArgOperand(1)->getType()->getPrimitiveSizeInBits();
4367e8d8bef9SDimitry Andric     assert((OperandWidth == 64 || OperandWidth == 128) &&
4368e8d8bef9SDimitry Andric            "Unexpected operand width");
4369e8d8bef9SDimitry Andric     Type *NewTy = FixedVectorType::get(Type::getBFloatTy(C), OperandWidth / 16);
4370349cc55cSDimitry Andric     auto Iter = CI->args().begin();
4371e8d8bef9SDimitry Andric     Args.push_back(*Iter++);
4372e8d8bef9SDimitry Andric     Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
4373e8d8bef9SDimitry Andric     Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
4374e8d8bef9SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4375e8d8bef9SDimitry Andric     break;
4376e8d8bef9SDimitry Andric   }
4377e8d8bef9SDimitry Andric 
43780b57cec5SDimitry Andric   case Intrinsic::bitreverse:
43790b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
43800b57cec5SDimitry Andric     break;
43810b57cec5SDimitry Andric 
43820b57cec5SDimitry Andric   case Intrinsic::ctlz:
43830b57cec5SDimitry Andric   case Intrinsic::cttz:
4384349cc55cSDimitry Andric     assert(CI->arg_size() == 1 &&
43850b57cec5SDimitry Andric            "Mismatch between function args and call args");
43860b57cec5SDimitry Andric     NewCall =
43870b57cec5SDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()});
43880b57cec5SDimitry Andric     break;
43890b57cec5SDimitry Andric 
43900b57cec5SDimitry Andric   case Intrinsic::objectsize: {
4391349cc55cSDimitry Andric     Value *NullIsUnknownSize =
4392349cc55cSDimitry Andric         CI->arg_size() == 2 ? Builder.getFalse() : CI->getArgOperand(2);
43930b57cec5SDimitry Andric     Value *Dynamic =
4394349cc55cSDimitry Andric         CI->arg_size() < 4 ? Builder.getFalse() : CI->getArgOperand(3);
43950b57cec5SDimitry Andric     NewCall = Builder.CreateCall(
43960b57cec5SDimitry Andric         NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic});
43970b57cec5SDimitry Andric     break;
43980b57cec5SDimitry Andric   }
43990b57cec5SDimitry Andric 
44000b57cec5SDimitry Andric   case Intrinsic::ctpop:
44010b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
44020b57cec5SDimitry Andric     break;
44030b57cec5SDimitry Andric 
44040b57cec5SDimitry Andric   case Intrinsic::convert_from_fp16:
44050b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
44060b57cec5SDimitry Andric     break;
44070b57cec5SDimitry Andric 
440806c3fb27SDimitry Andric   case Intrinsic::dbg_value: {
440906c3fb27SDimitry Andric     StringRef Name = F->getName();
441006c3fb27SDimitry Andric     Name = Name.substr(5); // Strip llvm.
441106c3fb27SDimitry Andric     // Upgrade `dbg.addr` to `dbg.value` with `DW_OP_deref`.
44125f757f3fSDimitry Andric     if (Name.starts_with("dbg.addr")) {
441306c3fb27SDimitry Andric       DIExpression *Expr = cast<DIExpression>(
441406c3fb27SDimitry Andric           cast<MetadataAsValue>(CI->getArgOperand(2))->getMetadata());
441506c3fb27SDimitry Andric       Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
441606c3fb27SDimitry Andric       NewCall =
441706c3fb27SDimitry Andric           Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
441806c3fb27SDimitry Andric                                      MetadataAsValue::get(C, Expr)});
441906c3fb27SDimitry Andric       break;
442006c3fb27SDimitry Andric     }
442106c3fb27SDimitry Andric 
44220b57cec5SDimitry Andric     // Upgrade from the old version that had an extra offset argument.
4423349cc55cSDimitry Andric     assert(CI->arg_size() == 4);
44240b57cec5SDimitry Andric     // Drop nonzero offsets instead of attempting to upgrade them.
44250b57cec5SDimitry Andric     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
44260b57cec5SDimitry Andric       if (Offset->isZeroValue()) {
44270b57cec5SDimitry Andric         NewCall = Builder.CreateCall(
44280b57cec5SDimitry Andric             NewFn,
44290b57cec5SDimitry Andric             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
44300b57cec5SDimitry Andric         break;
44310b57cec5SDimitry Andric       }
44320b57cec5SDimitry Andric     CI->eraseFromParent();
44330b57cec5SDimitry Andric     return;
443406c3fb27SDimitry Andric   }
44350b57cec5SDimitry Andric 
4436d409305fSDimitry Andric   case Intrinsic::ptr_annotation:
4437d409305fSDimitry Andric     // Upgrade from versions that lacked the annotation attribute argument.
443881ad6265SDimitry Andric     if (CI->arg_size() != 4) {
443981ad6265SDimitry Andric       DefaultCase();
444081ad6265SDimitry Andric       return;
444181ad6265SDimitry Andric     }
444281ad6265SDimitry Andric 
4443d409305fSDimitry Andric     // Create a new call with an added null annotation attribute argument.
44445f757f3fSDimitry Andric     NewCall =
44455f757f3fSDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
44465f757f3fSDimitry Andric                                    CI->getArgOperand(2), CI->getArgOperand(3),
44475f757f3fSDimitry Andric                                    Constant::getNullValue(Builder.getPtrTy())});
4448d409305fSDimitry Andric     NewCall->takeName(CI);
4449d409305fSDimitry Andric     CI->replaceAllUsesWith(NewCall);
4450d409305fSDimitry Andric     CI->eraseFromParent();
4451d409305fSDimitry Andric     return;
4452d409305fSDimitry Andric 
4453d409305fSDimitry Andric   case Intrinsic::var_annotation:
4454d409305fSDimitry Andric     // Upgrade from versions that lacked the annotation attribute argument.
4455bdd1243dSDimitry Andric     if (CI->arg_size() != 4) {
4456bdd1243dSDimitry Andric       DefaultCase();
4457bdd1243dSDimitry Andric       return;
4458bdd1243dSDimitry Andric     }
4459d409305fSDimitry Andric     // Create a new call with an added null annotation attribute argument.
44605f757f3fSDimitry Andric     NewCall =
44615f757f3fSDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
44625f757f3fSDimitry Andric                                    CI->getArgOperand(2), CI->getArgOperand(3),
44635f757f3fSDimitry Andric                                    Constant::getNullValue(Builder.getPtrTy())});
4464bdd1243dSDimitry Andric     NewCall->takeName(CI);
4465bdd1243dSDimitry Andric     CI->replaceAllUsesWith(NewCall);
4466d409305fSDimitry Andric     CI->eraseFromParent();
4467d409305fSDimitry Andric     return;
4468d409305fSDimitry Andric 
446906c3fb27SDimitry Andric   case Intrinsic::riscv_aes32dsi:
447006c3fb27SDimitry Andric   case Intrinsic::riscv_aes32dsmi:
447106c3fb27SDimitry Andric   case Intrinsic::riscv_aes32esi:
447206c3fb27SDimitry Andric   case Intrinsic::riscv_aes32esmi:
447306c3fb27SDimitry Andric   case Intrinsic::riscv_sm4ks:
447406c3fb27SDimitry Andric   case Intrinsic::riscv_sm4ed: {
447506c3fb27SDimitry Andric     // The last argument to these intrinsics used to be i8 and changed to i32.
447606c3fb27SDimitry Andric     // The type overload for sm4ks and sm4ed was removed.
447706c3fb27SDimitry Andric     Value *Arg2 = CI->getArgOperand(2);
447806c3fb27SDimitry Andric     if (Arg2->getType()->isIntegerTy(32) && !CI->getType()->isIntegerTy(64))
447906c3fb27SDimitry Andric       return;
448006c3fb27SDimitry Andric 
448106c3fb27SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
448206c3fb27SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
448306c3fb27SDimitry Andric     if (CI->getType()->isIntegerTy(64)) {
448406c3fb27SDimitry Andric       Arg0 = Builder.CreateTrunc(Arg0, Builder.getInt32Ty());
448506c3fb27SDimitry Andric       Arg1 = Builder.CreateTrunc(Arg1, Builder.getInt32Ty());
448606c3fb27SDimitry Andric     }
448706c3fb27SDimitry Andric 
448806c3fb27SDimitry Andric     Arg2 = ConstantInt::get(Type::getInt32Ty(C),
448906c3fb27SDimitry Andric                             cast<ConstantInt>(Arg2)->getZExtValue());
449006c3fb27SDimitry Andric 
449106c3fb27SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {Arg0, Arg1, Arg2});
449206c3fb27SDimitry Andric     Value *Res = NewCall;
449306c3fb27SDimitry Andric     if (Res->getType() != CI->getType())
449406c3fb27SDimitry Andric       Res = Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
449506c3fb27SDimitry Andric     NewCall->takeName(CI);
449606c3fb27SDimitry Andric     CI->replaceAllUsesWith(Res);
449706c3fb27SDimitry Andric     CI->eraseFromParent();
449806c3fb27SDimitry Andric     return;
449906c3fb27SDimitry Andric   }
450006c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sig0:
450106c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sig1:
450206c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sum0:
450306c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sum1:
450406c3fb27SDimitry Andric   case Intrinsic::riscv_sm3p0:
450506c3fb27SDimitry Andric   case Intrinsic::riscv_sm3p1: {
450606c3fb27SDimitry Andric     // The last argument to these intrinsics used to be i8 and changed to i32.
450706c3fb27SDimitry Andric     // The type overload for sm4ks and sm4ed was removed.
450806c3fb27SDimitry Andric     if (!CI->getType()->isIntegerTy(64))
450906c3fb27SDimitry Andric       return;
451006c3fb27SDimitry Andric 
451106c3fb27SDimitry Andric     Value *Arg =
451206c3fb27SDimitry Andric         Builder.CreateTrunc(CI->getArgOperand(0), Builder.getInt32Ty());
451306c3fb27SDimitry Andric 
451406c3fb27SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Arg);
451506c3fb27SDimitry Andric     Value *Res =
451606c3fb27SDimitry Andric         Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
451706c3fb27SDimitry Andric     NewCall->takeName(CI);
451806c3fb27SDimitry Andric     CI->replaceAllUsesWith(Res);
451906c3fb27SDimitry Andric     CI->eraseFromParent();
452006c3fb27SDimitry Andric     return;
452106c3fb27SDimitry Andric   }
452206c3fb27SDimitry Andric 
45230b57cec5SDimitry Andric   case Intrinsic::x86_xop_vfrcz_ss:
45240b57cec5SDimitry Andric   case Intrinsic::x86_xop_vfrcz_sd:
45250b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)});
45260b57cec5SDimitry Andric     break;
45270b57cec5SDimitry Andric 
45280b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2pd:
45290b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2ps:
45300b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2pd_256:
45310b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2ps_256: {
4532349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
45330b57cec5SDimitry Andric     VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType());
45340b57cec5SDimitry Andric     VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy);
45350b57cec5SDimitry Andric     Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy);
45360b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
45370b57cec5SDimitry Andric     break;
45380b57cec5SDimitry Andric   }
45390b57cec5SDimitry Andric 
45400b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestc:
45410b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestz:
45420b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestnzc: {
45430b57cec5SDimitry Andric     // The arguments for these intrinsics used to be v4f32, and changed
45440b57cec5SDimitry Andric     // to v2i64. This is purely a nop, since those are bitwise intrinsics.
45450b57cec5SDimitry Andric     // So, the only thing required is a bitcast for both arguments.
45460b57cec5SDimitry Andric     // First, check the arguments have the old type.
45470b57cec5SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
45485ffd83dbSDimitry Andric     if (Arg0->getType() != FixedVectorType::get(Type::getFloatTy(C), 4))
45490b57cec5SDimitry Andric       return;
45500b57cec5SDimitry Andric 
45510b57cec5SDimitry Andric     // Old intrinsic, add bitcasts
45520b57cec5SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
45530b57cec5SDimitry Andric 
45545ffd83dbSDimitry Andric     auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
45550b57cec5SDimitry Andric 
45560b57cec5SDimitry Andric     Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast");
45570b57cec5SDimitry Andric     Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
45580b57cec5SDimitry Andric 
45590b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {BC0, BC1});
45600b57cec5SDimitry Andric     break;
45610b57cec5SDimitry Andric   }
45620b57cec5SDimitry Andric 
45630b57cec5SDimitry Andric   case Intrinsic::x86_rdtscp: {
45640b57cec5SDimitry Andric     // This used to take 1 arguments. If we have no arguments, it is already
45650b57cec5SDimitry Andric     // upgraded.
45660b57cec5SDimitry Andric     if (CI->getNumOperands() == 0)
45670b57cec5SDimitry Andric       return;
45680b57cec5SDimitry Andric 
45690b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn);
45700b57cec5SDimitry Andric     // Extract the second result and store it.
45710b57cec5SDimitry Andric     Value *Data = Builder.CreateExtractValue(NewCall, 1);
45720b57cec5SDimitry Andric     // Cast the pointer to the right type.
45730b57cec5SDimitry Andric     Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(0),
45740b57cec5SDimitry Andric                                  llvm::PointerType::getUnqual(Data->getType()));
45755ffd83dbSDimitry Andric     Builder.CreateAlignedStore(Data, Ptr, Align(1));
45760b57cec5SDimitry Andric     // Replace the original call result with the first result of the new call.
45770b57cec5SDimitry Andric     Value *TSC = Builder.CreateExtractValue(NewCall, 0);
45780b57cec5SDimitry Andric 
4579e8d8bef9SDimitry Andric     NewCall->takeName(CI);
45800b57cec5SDimitry Andric     CI->replaceAllUsesWith(TSC);
45810b57cec5SDimitry Andric     CI->eraseFromParent();
45820b57cec5SDimitry Andric     return;
45830b57cec5SDimitry Andric   }
45840b57cec5SDimitry Andric 
45850b57cec5SDimitry Andric   case Intrinsic::x86_sse41_insertps:
45860b57cec5SDimitry Andric   case Intrinsic::x86_sse41_dppd:
45870b57cec5SDimitry Andric   case Intrinsic::x86_sse41_dpps:
45880b57cec5SDimitry Andric   case Intrinsic::x86_sse41_mpsadbw:
45890b57cec5SDimitry Andric   case Intrinsic::x86_avx_dp_ps_256:
45900b57cec5SDimitry Andric   case Intrinsic::x86_avx2_mpsadbw: {
45910b57cec5SDimitry Andric     // Need to truncate the last argument from i32 to i8 -- this argument models
45920b57cec5SDimitry Andric     // an inherently 8-bit immediate operand to these x86 instructions.
4593349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
45940b57cec5SDimitry Andric 
45950b57cec5SDimitry Andric     // Replace the last argument with a trunc.
45960b57cec5SDimitry Andric     Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
45970b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
45980b57cec5SDimitry Andric     break;
45990b57cec5SDimitry Andric   }
46000b57cec5SDimitry Andric 
4601e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_128:
4602e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_256:
4603e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_512:
4604e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_128:
4605e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_256:
4606e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_512: {
4607349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4608e8d8bef9SDimitry Andric     unsigned NumElts =
4609e8d8bef9SDimitry Andric         cast<FixedVectorType>(Args[0]->getType())->getNumElements();
4610e8d8bef9SDimitry Andric     Args[3] = getX86MaskVec(Builder, Args[3], NumElts);
4611e8d8bef9SDimitry Andric 
4612e8d8bef9SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
46137a6dacacSDimitry Andric     Value *Res = applyX86MaskOn1BitsVec(Builder, NewCall, nullptr);
4614e8d8bef9SDimitry Andric 
4615e8d8bef9SDimitry Andric     NewCall->takeName(CI);
4616e8d8bef9SDimitry Andric     CI->replaceAllUsesWith(Res);
4617e8d8bef9SDimitry Andric     CI->eraseFromParent();
4618e8d8bef9SDimitry Andric     return;
4619e8d8bef9SDimitry Andric   }
4620e8d8bef9SDimitry Andric 
4621bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128:
4622bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256:
4623bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512:
4624bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128:
4625bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtneps2bf16_256:
4626bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtneps2bf16_512: {
4627bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4628bdd1243dSDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
4629bdd1243dSDimitry Andric     if (NewFn->getIntrinsicID() ==
4630bdd1243dSDimitry Andric         Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
4631bdd1243dSDimitry Andric       Args[1] = Builder.CreateBitCast(
4632bdd1243dSDimitry Andric           Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4633bdd1243dSDimitry Andric 
4634bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4635bdd1243dSDimitry Andric     Value *Res = Builder.CreateBitCast(
4636bdd1243dSDimitry Andric         NewCall, FixedVectorType::get(Builder.getInt16Ty(), NumElts));
4637bdd1243dSDimitry Andric 
4638bdd1243dSDimitry Andric     NewCall->takeName(CI);
4639bdd1243dSDimitry Andric     CI->replaceAllUsesWith(Res);
4640bdd1243dSDimitry Andric     CI->eraseFromParent();
4641bdd1243dSDimitry Andric     return;
4642bdd1243dSDimitry Andric   }
4643bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_128:
4644bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_256:
4645bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_512:{
4646bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4647bdd1243dSDimitry Andric     unsigned NumElts =
4648bdd1243dSDimitry Andric         cast<FixedVectorType>(CI->getType())->getNumElements() * 2;
4649bdd1243dSDimitry Andric     Args[1] = Builder.CreateBitCast(
4650bdd1243dSDimitry Andric         Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4651bdd1243dSDimitry Andric     Args[2] = Builder.CreateBitCast(
4652bdd1243dSDimitry Andric         Args[2], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4653bdd1243dSDimitry Andric 
4654bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4655bdd1243dSDimitry Andric     break;
4656bdd1243dSDimitry Andric   }
4657bdd1243dSDimitry Andric 
46580b57cec5SDimitry Andric   case Intrinsic::thread_pointer: {
46590b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {});
46600b57cec5SDimitry Andric     break;
46610b57cec5SDimitry Andric   }
46620b57cec5SDimitry Andric 
46630b57cec5SDimitry Andric   case Intrinsic::memcpy:
46640b57cec5SDimitry Andric   case Intrinsic::memmove:
46650b57cec5SDimitry Andric   case Intrinsic::memset: {
46660b57cec5SDimitry Andric     // We have to make sure that the call signature is what we're expecting.
46670b57cec5SDimitry Andric     // We only want to change the old signatures by removing the alignment arg:
46680b57cec5SDimitry Andric     //  @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i32, i1)
46690b57cec5SDimitry Andric     //    -> @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i1)
46700b57cec5SDimitry Andric     //  @llvm.memset...(i8*, i8, i[32|64], i32, i1)
46710b57cec5SDimitry Andric     //    -> @llvm.memset...(i8*, i8, i[32|64], i1)
46720b57cec5SDimitry Andric     // Note: i8*'s in the above can be any pointer type
4673349cc55cSDimitry Andric     if (CI->arg_size() != 5) {
46740b57cec5SDimitry Andric       DefaultCase();
46750b57cec5SDimitry Andric       return;
46760b57cec5SDimitry Andric     }
46770b57cec5SDimitry Andric     // Remove alignment argument (3), and add alignment attributes to the
46780b57cec5SDimitry Andric     // dest/src pointers.
46790b57cec5SDimitry Andric     Value *Args[4] = {CI->getArgOperand(0), CI->getArgOperand(1),
46800b57cec5SDimitry Andric                       CI->getArgOperand(2), CI->getArgOperand(4)};
46810b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
468281ad6265SDimitry Andric     AttributeList OldAttrs = CI->getAttributes();
468381ad6265SDimitry Andric     AttributeList NewAttrs = AttributeList::get(
468481ad6265SDimitry Andric         C, OldAttrs.getFnAttrs(), OldAttrs.getRetAttrs(),
468581ad6265SDimitry Andric         {OldAttrs.getParamAttrs(0), OldAttrs.getParamAttrs(1),
468681ad6265SDimitry Andric          OldAttrs.getParamAttrs(2), OldAttrs.getParamAttrs(4)});
468781ad6265SDimitry Andric     NewCall->setAttributes(NewAttrs);
46880b57cec5SDimitry Andric     auto *MemCI = cast<MemIntrinsic>(NewCall);
46890b57cec5SDimitry Andric     // All mem intrinsics support dest alignment.
46900b57cec5SDimitry Andric     const ConstantInt *Align = cast<ConstantInt>(CI->getArgOperand(3));
46915ffd83dbSDimitry Andric     MemCI->setDestAlignment(Align->getMaybeAlignValue());
46920b57cec5SDimitry Andric     // Memcpy/Memmove also support source alignment.
46930b57cec5SDimitry Andric     if (auto *MTI = dyn_cast<MemTransferInst>(MemCI))
46945ffd83dbSDimitry Andric       MTI->setSourceAlignment(Align->getMaybeAlignValue());
46950b57cec5SDimitry Andric     break;
46960b57cec5SDimitry Andric   }
46970b57cec5SDimitry Andric   }
46980b57cec5SDimitry Andric   assert(NewCall && "Should have either set this variable or returned through "
46990b57cec5SDimitry Andric                     "the default case");
4700e8d8bef9SDimitry Andric   NewCall->takeName(CI);
47010b57cec5SDimitry Andric   CI->replaceAllUsesWith(NewCall);
47020b57cec5SDimitry Andric   CI->eraseFromParent();
47030b57cec5SDimitry Andric }
47040b57cec5SDimitry Andric 
UpgradeCallsToIntrinsic(Function * F)47050b57cec5SDimitry Andric void llvm::UpgradeCallsToIntrinsic(Function *F) {
47060b57cec5SDimitry Andric   assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
47070b57cec5SDimitry Andric 
47080b57cec5SDimitry Andric   // Check if this function should be upgraded and get the replacement function
47090b57cec5SDimitry Andric   // if there is one.
47100b57cec5SDimitry Andric   Function *NewFn;
47110b57cec5SDimitry Andric   if (UpgradeIntrinsicFunction(F, NewFn)) {
47120b57cec5SDimitry Andric     // Replace all users of the old function with the new function or new
47130b57cec5SDimitry Andric     // instructions. This is not a range loop because the call is deleted.
4714e8d8bef9SDimitry Andric     for (User *U : make_early_inc_range(F->users()))
471581ad6265SDimitry Andric       if (CallBase *CB = dyn_cast<CallBase>(U))
471681ad6265SDimitry Andric         UpgradeIntrinsicCall(CB, NewFn);
47170b57cec5SDimitry Andric 
47180b57cec5SDimitry Andric     // Remove old function, no longer used, from the module.
47190b57cec5SDimitry Andric     F->eraseFromParent();
47200b57cec5SDimitry Andric   }
47210b57cec5SDimitry Andric }
47220b57cec5SDimitry Andric 
UpgradeTBAANode(MDNode & MD)47230b57cec5SDimitry Andric MDNode *llvm::UpgradeTBAANode(MDNode &MD) {
472406c3fb27SDimitry Andric   const unsigned NumOperands = MD.getNumOperands();
472506c3fb27SDimitry Andric   if (NumOperands == 0)
472606c3fb27SDimitry Andric     return &MD; // Invalid, punt to a verifier error.
472706c3fb27SDimitry Andric 
47280b57cec5SDimitry Andric   // Check if the tag uses struct-path aware TBAA format.
472906c3fb27SDimitry Andric   if (isa<MDNode>(MD.getOperand(0)) && NumOperands >= 3)
47300b57cec5SDimitry Andric     return &MD;
47310b57cec5SDimitry Andric 
47320b57cec5SDimitry Andric   auto &Context = MD.getContext();
473306c3fb27SDimitry Andric   if (NumOperands == 3) {
47340b57cec5SDimitry Andric     Metadata *Elts[] = {MD.getOperand(0), MD.getOperand(1)};
47350b57cec5SDimitry Andric     MDNode *ScalarType = MDNode::get(Context, Elts);
47360b57cec5SDimitry Andric     // Create a MDNode <ScalarType, ScalarType, offset 0, const>
47370b57cec5SDimitry Andric     Metadata *Elts2[] = {ScalarType, ScalarType,
47380b57cec5SDimitry Andric                          ConstantAsMetadata::get(
47390b57cec5SDimitry Andric                              Constant::getNullValue(Type::getInt64Ty(Context))),
47400b57cec5SDimitry Andric                          MD.getOperand(2)};
47410b57cec5SDimitry Andric     return MDNode::get(Context, Elts2);
47420b57cec5SDimitry Andric   }
47430b57cec5SDimitry Andric   // Create a MDNode <MD, MD, offset 0>
47440b57cec5SDimitry Andric   Metadata *Elts[] = {&MD, &MD, ConstantAsMetadata::get(Constant::getNullValue(
47450b57cec5SDimitry Andric                                     Type::getInt64Ty(Context)))};
47460b57cec5SDimitry Andric   return MDNode::get(Context, Elts);
47470b57cec5SDimitry Andric }
47480b57cec5SDimitry Andric 
UpgradeBitCastInst(unsigned Opc,Value * V,Type * DestTy,Instruction * & Temp)47490b57cec5SDimitry Andric Instruction *llvm::UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,
47500b57cec5SDimitry Andric                                       Instruction *&Temp) {
47510b57cec5SDimitry Andric   if (Opc != Instruction::BitCast)
47520b57cec5SDimitry Andric     return nullptr;
47530b57cec5SDimitry Andric 
47540b57cec5SDimitry Andric   Temp = nullptr;
47550b57cec5SDimitry Andric   Type *SrcTy = V->getType();
47560b57cec5SDimitry Andric   if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
47570b57cec5SDimitry Andric       SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
47580b57cec5SDimitry Andric     LLVMContext &Context = V->getContext();
47590b57cec5SDimitry Andric 
47600b57cec5SDimitry Andric     // We have no information about target data layout, so we assume that
47610b57cec5SDimitry Andric     // the maximum pointer size is 64bit.
47620b57cec5SDimitry Andric     Type *MidTy = Type::getInt64Ty(Context);
47630b57cec5SDimitry Andric     Temp = CastInst::Create(Instruction::PtrToInt, V, MidTy);
47640b57cec5SDimitry Andric 
47650b57cec5SDimitry Andric     return CastInst::Create(Instruction::IntToPtr, Temp, DestTy);
47660b57cec5SDimitry Andric   }
47670b57cec5SDimitry Andric 
47680b57cec5SDimitry Andric   return nullptr;
47690b57cec5SDimitry Andric }
47700b57cec5SDimitry Andric 
UpgradeBitCastExpr(unsigned Opc,Constant * C,Type * DestTy)477181ad6265SDimitry Andric Constant *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {
47720b57cec5SDimitry Andric   if (Opc != Instruction::BitCast)
47730b57cec5SDimitry Andric     return nullptr;
47740b57cec5SDimitry Andric 
47750b57cec5SDimitry Andric   Type *SrcTy = C->getType();
47760b57cec5SDimitry Andric   if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
47770b57cec5SDimitry Andric       SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
47780b57cec5SDimitry Andric     LLVMContext &Context = C->getContext();
47790b57cec5SDimitry Andric 
47800b57cec5SDimitry Andric     // We have no information about target data layout, so we assume that
47810b57cec5SDimitry Andric     // the maximum pointer size is 64bit.
47820b57cec5SDimitry Andric     Type *MidTy = Type::getInt64Ty(Context);
47830b57cec5SDimitry Andric 
47840b57cec5SDimitry Andric     return ConstantExpr::getIntToPtr(ConstantExpr::getPtrToInt(C, MidTy),
47850b57cec5SDimitry Andric                                      DestTy);
47860b57cec5SDimitry Andric   }
47870b57cec5SDimitry Andric 
47880b57cec5SDimitry Andric   return nullptr;
47890b57cec5SDimitry Andric }
47900b57cec5SDimitry Andric 
47910b57cec5SDimitry Andric /// Check the debug info version number, if it is out-dated, drop the debug
47920b57cec5SDimitry Andric /// info. Return true if module is modified.
UpgradeDebugInfo(Module & M)47930b57cec5SDimitry Andric bool llvm::UpgradeDebugInfo(Module &M) {
479406c3fb27SDimitry Andric   if (DisableAutoUpgradeDebugInfo)
479506c3fb27SDimitry Andric     return false;
479606c3fb27SDimitry Andric 
47970b57cec5SDimitry Andric   unsigned Version = getDebugMetadataVersionFromModule(M);
47980b57cec5SDimitry Andric   if (Version == DEBUG_METADATA_VERSION) {
47990b57cec5SDimitry Andric     bool BrokenDebugInfo = false;
48000b57cec5SDimitry Andric     if (verifyModule(M, &llvm::errs(), &BrokenDebugInfo))
48010b57cec5SDimitry Andric       report_fatal_error("Broken module found, compilation aborted!");
48020b57cec5SDimitry Andric     if (!BrokenDebugInfo)
48030b57cec5SDimitry Andric       // Everything is ok.
48040b57cec5SDimitry Andric       return false;
48050b57cec5SDimitry Andric     else {
48060b57cec5SDimitry Andric       // Diagnose malformed debug info.
48070b57cec5SDimitry Andric       DiagnosticInfoIgnoringInvalidDebugMetadata Diag(M);
48080b57cec5SDimitry Andric       M.getContext().diagnose(Diag);
48090b57cec5SDimitry Andric     }
48100b57cec5SDimitry Andric   }
48110b57cec5SDimitry Andric   bool Modified = StripDebugInfo(M);
48120b57cec5SDimitry Andric   if (Modified && Version != DEBUG_METADATA_VERSION) {
48130b57cec5SDimitry Andric     // Diagnose a version mismatch.
48140b57cec5SDimitry Andric     DiagnosticInfoDebugMetadataVersion DiagVersion(M, Version);
48150b57cec5SDimitry Andric     M.getContext().diagnose(DiagVersion);
48160b57cec5SDimitry Andric   }
48170b57cec5SDimitry Andric   return Modified;
48180b57cec5SDimitry Andric }
48190b57cec5SDimitry Andric 
48208bcb0991SDimitry Andric /// This checks for objc retain release marker which should be upgraded. It
48218bcb0991SDimitry Andric /// returns true if module is modified.
upgradeRetainReleaseMarker(Module & M)48227a6dacacSDimitry Andric static bool upgradeRetainReleaseMarker(Module &M) {
48230b57cec5SDimitry Andric   bool Changed = false;
48240b57cec5SDimitry Andric   const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
48250b57cec5SDimitry Andric   NamedMDNode *ModRetainReleaseMarker = M.getNamedMetadata(MarkerKey);
48260b57cec5SDimitry Andric   if (ModRetainReleaseMarker) {
48270b57cec5SDimitry Andric     MDNode *Op = ModRetainReleaseMarker->getOperand(0);
48280b57cec5SDimitry Andric     if (Op) {
48290b57cec5SDimitry Andric       MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(0));
48300b57cec5SDimitry Andric       if (ID) {
48310b57cec5SDimitry Andric         SmallVector<StringRef, 4> ValueComp;
48320b57cec5SDimitry Andric         ID->getString().split(ValueComp, "#");
48330b57cec5SDimitry Andric         if (ValueComp.size() == 2) {
48340b57cec5SDimitry Andric           std::string NewValue = ValueComp[0].str() + ";" + ValueComp[1].str();
48350b57cec5SDimitry Andric           ID = MDString::get(M.getContext(), NewValue);
48360b57cec5SDimitry Andric         }
48370b57cec5SDimitry Andric         M.addModuleFlag(Module::Error, MarkerKey, ID);
48380b57cec5SDimitry Andric         M.eraseNamedMetadata(ModRetainReleaseMarker);
48390b57cec5SDimitry Andric         Changed = true;
48400b57cec5SDimitry Andric       }
48410b57cec5SDimitry Andric     }
48420b57cec5SDimitry Andric   }
48430b57cec5SDimitry Andric   return Changed;
48440b57cec5SDimitry Andric }
48450b57cec5SDimitry Andric 
UpgradeARCRuntime(Module & M)48468bcb0991SDimitry Andric void llvm::UpgradeARCRuntime(Module &M) {
48478bcb0991SDimitry Andric   // This lambda converts normal function calls to ARC runtime functions to
48488bcb0991SDimitry Andric   // intrinsic calls.
48498bcb0991SDimitry Andric   auto UpgradeToIntrinsic = [&](const char *OldFunc,
48508bcb0991SDimitry Andric                                 llvm::Intrinsic::ID IntrinsicFunc) {
48518bcb0991SDimitry Andric     Function *Fn = M.getFunction(OldFunc);
48528bcb0991SDimitry Andric 
48538bcb0991SDimitry Andric     if (!Fn)
48548bcb0991SDimitry Andric       return;
48558bcb0991SDimitry Andric 
48568bcb0991SDimitry Andric     Function *NewFn = llvm::Intrinsic::getDeclaration(&M, IntrinsicFunc);
48578bcb0991SDimitry Andric 
4858e8d8bef9SDimitry Andric     for (User *U : make_early_inc_range(Fn->users())) {
4859e8d8bef9SDimitry Andric       CallInst *CI = dyn_cast<CallInst>(U);
48608bcb0991SDimitry Andric       if (!CI || CI->getCalledFunction() != Fn)
48618bcb0991SDimitry Andric         continue;
48628bcb0991SDimitry Andric 
48638bcb0991SDimitry Andric       IRBuilder<> Builder(CI->getParent(), CI->getIterator());
48648bcb0991SDimitry Andric       FunctionType *NewFuncTy = NewFn->getFunctionType();
48658bcb0991SDimitry Andric       SmallVector<Value *, 2> Args;
48668bcb0991SDimitry Andric 
4867480093f4SDimitry Andric       // Don't upgrade the intrinsic if it's not valid to bitcast the return
4868480093f4SDimitry Andric       // value to the return type of the old function.
4869480093f4SDimitry Andric       if (NewFuncTy->getReturnType() != CI->getType() &&
4870480093f4SDimitry Andric           !CastInst::castIsValid(Instruction::BitCast, CI,
4871480093f4SDimitry Andric                                  NewFuncTy->getReturnType()))
4872480093f4SDimitry Andric         continue;
4873480093f4SDimitry Andric 
4874480093f4SDimitry Andric       bool InvalidCast = false;
4875480093f4SDimitry Andric 
4876349cc55cSDimitry Andric       for (unsigned I = 0, E = CI->arg_size(); I != E; ++I) {
48778bcb0991SDimitry Andric         Value *Arg = CI->getArgOperand(I);
4878480093f4SDimitry Andric 
48798bcb0991SDimitry Andric         // Bitcast argument to the parameter type of the new function if it's
48808bcb0991SDimitry Andric         // not a variadic argument.
4881480093f4SDimitry Andric         if (I < NewFuncTy->getNumParams()) {
4882480093f4SDimitry Andric           // Don't upgrade the intrinsic if it's not valid to bitcast the argument
4883480093f4SDimitry Andric           // to the parameter type of the new function.
4884480093f4SDimitry Andric           if (!CastInst::castIsValid(Instruction::BitCast, Arg,
4885480093f4SDimitry Andric                                      NewFuncTy->getParamType(I))) {
4886480093f4SDimitry Andric             InvalidCast = true;
4887480093f4SDimitry Andric             break;
4888480093f4SDimitry Andric           }
48898bcb0991SDimitry Andric           Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
4890480093f4SDimitry Andric         }
48918bcb0991SDimitry Andric         Args.push_back(Arg);
48928bcb0991SDimitry Andric       }
48938bcb0991SDimitry Andric 
4894480093f4SDimitry Andric       if (InvalidCast)
4895480093f4SDimitry Andric         continue;
4896480093f4SDimitry Andric 
48978bcb0991SDimitry Andric       // Create a call instruction that calls the new function.
48988bcb0991SDimitry Andric       CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
48998bcb0991SDimitry Andric       NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
4900e8d8bef9SDimitry Andric       NewCall->takeName(CI);
49018bcb0991SDimitry Andric 
49028bcb0991SDimitry Andric       // Bitcast the return value back to the type of the old call.
49038bcb0991SDimitry Andric       Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType());
49048bcb0991SDimitry Andric 
49058bcb0991SDimitry Andric       if (!CI->use_empty())
49068bcb0991SDimitry Andric         CI->replaceAllUsesWith(NewRetVal);
49078bcb0991SDimitry Andric       CI->eraseFromParent();
49088bcb0991SDimitry Andric     }
49098bcb0991SDimitry Andric 
49108bcb0991SDimitry Andric     if (Fn->use_empty())
49118bcb0991SDimitry Andric       Fn->eraseFromParent();
49128bcb0991SDimitry Andric   };
49138bcb0991SDimitry Andric 
49148bcb0991SDimitry Andric   // Unconditionally convert a call to "clang.arc.use" to a call to
49158bcb0991SDimitry Andric   // "llvm.objc.clang.arc.use".
49168bcb0991SDimitry Andric   UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use);
49178bcb0991SDimitry Andric 
49188bcb0991SDimitry Andric   // Upgrade the retain release marker. If there is no need to upgrade
49198bcb0991SDimitry Andric   // the marker, that means either the module is already new enough to contain
49208bcb0991SDimitry Andric   // new intrinsics or it is not ARC. There is no need to upgrade runtime call.
49217a6dacacSDimitry Andric   if (!upgradeRetainReleaseMarker(M))
49228bcb0991SDimitry Andric     return;
49238bcb0991SDimitry Andric 
49248bcb0991SDimitry Andric   std::pair<const char *, llvm::Intrinsic::ID> RuntimeFuncs[] = {
49258bcb0991SDimitry Andric       {"objc_autorelease", llvm::Intrinsic::objc_autorelease},
49268bcb0991SDimitry Andric       {"objc_autoreleasePoolPop", llvm::Intrinsic::objc_autoreleasePoolPop},
49278bcb0991SDimitry Andric       {"objc_autoreleasePoolPush", llvm::Intrinsic::objc_autoreleasePoolPush},
49288bcb0991SDimitry Andric       {"objc_autoreleaseReturnValue",
49298bcb0991SDimitry Andric        llvm::Intrinsic::objc_autoreleaseReturnValue},
49308bcb0991SDimitry Andric       {"objc_copyWeak", llvm::Intrinsic::objc_copyWeak},
49318bcb0991SDimitry Andric       {"objc_destroyWeak", llvm::Intrinsic::objc_destroyWeak},
49328bcb0991SDimitry Andric       {"objc_initWeak", llvm::Intrinsic::objc_initWeak},
49338bcb0991SDimitry Andric       {"objc_loadWeak", llvm::Intrinsic::objc_loadWeak},
49348bcb0991SDimitry Andric       {"objc_loadWeakRetained", llvm::Intrinsic::objc_loadWeakRetained},
49358bcb0991SDimitry Andric       {"objc_moveWeak", llvm::Intrinsic::objc_moveWeak},
49368bcb0991SDimitry Andric       {"objc_release", llvm::Intrinsic::objc_release},
49378bcb0991SDimitry Andric       {"objc_retain", llvm::Intrinsic::objc_retain},
49388bcb0991SDimitry Andric       {"objc_retainAutorelease", llvm::Intrinsic::objc_retainAutorelease},
49398bcb0991SDimitry Andric       {"objc_retainAutoreleaseReturnValue",
49408bcb0991SDimitry Andric        llvm::Intrinsic::objc_retainAutoreleaseReturnValue},
49418bcb0991SDimitry Andric       {"objc_retainAutoreleasedReturnValue",
49428bcb0991SDimitry Andric        llvm::Intrinsic::objc_retainAutoreleasedReturnValue},
49438bcb0991SDimitry Andric       {"objc_retainBlock", llvm::Intrinsic::objc_retainBlock},
49448bcb0991SDimitry Andric       {"objc_storeStrong", llvm::Intrinsic::objc_storeStrong},
49458bcb0991SDimitry Andric       {"objc_storeWeak", llvm::Intrinsic::objc_storeWeak},
49468bcb0991SDimitry Andric       {"objc_unsafeClaimAutoreleasedReturnValue",
49478bcb0991SDimitry Andric        llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue},
49488bcb0991SDimitry Andric       {"objc_retainedObject", llvm::Intrinsic::objc_retainedObject},
49498bcb0991SDimitry Andric       {"objc_unretainedObject", llvm::Intrinsic::objc_unretainedObject},
49508bcb0991SDimitry Andric       {"objc_unretainedPointer", llvm::Intrinsic::objc_unretainedPointer},
49518bcb0991SDimitry Andric       {"objc_retain_autorelease", llvm::Intrinsic::objc_retain_autorelease},
49528bcb0991SDimitry Andric       {"objc_sync_enter", llvm::Intrinsic::objc_sync_enter},
49538bcb0991SDimitry Andric       {"objc_sync_exit", llvm::Intrinsic::objc_sync_exit},
49548bcb0991SDimitry Andric       {"objc_arc_annotation_topdown_bbstart",
49558bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_topdown_bbstart},
49568bcb0991SDimitry Andric       {"objc_arc_annotation_topdown_bbend",
49578bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_topdown_bbend},
49588bcb0991SDimitry Andric       {"objc_arc_annotation_bottomup_bbstart",
49598bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_bottomup_bbstart},
49608bcb0991SDimitry Andric       {"objc_arc_annotation_bottomup_bbend",
49618bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_bottomup_bbend}};
49628bcb0991SDimitry Andric 
49638bcb0991SDimitry Andric   for (auto &I : RuntimeFuncs)
49648bcb0991SDimitry Andric     UpgradeToIntrinsic(I.first, I.second);
49658bcb0991SDimitry Andric }
49668bcb0991SDimitry Andric 
UpgradeModuleFlags(Module & M)49670b57cec5SDimitry Andric bool llvm::UpgradeModuleFlags(Module &M) {
49680b57cec5SDimitry Andric   NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
49690b57cec5SDimitry Andric   if (!ModFlags)
49700b57cec5SDimitry Andric     return false;
49710b57cec5SDimitry Andric 
49720b57cec5SDimitry Andric   bool HasObjCFlag = false, HasClassProperties = false, Changed = false;
49735ffd83dbSDimitry Andric   bool HasSwiftVersionFlag = false;
49745ffd83dbSDimitry Andric   uint8_t SwiftMajorVersion, SwiftMinorVersion;
49755ffd83dbSDimitry Andric   uint32_t SwiftABIVersion;
49765ffd83dbSDimitry Andric   auto Int8Ty = Type::getInt8Ty(M.getContext());
49775ffd83dbSDimitry Andric   auto Int32Ty = Type::getInt32Ty(M.getContext());
49785ffd83dbSDimitry Andric 
49790b57cec5SDimitry Andric   for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
49800b57cec5SDimitry Andric     MDNode *Op = ModFlags->getOperand(I);
49810b57cec5SDimitry Andric     if (Op->getNumOperands() != 3)
49820b57cec5SDimitry Andric       continue;
49830b57cec5SDimitry Andric     MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
49840b57cec5SDimitry Andric     if (!ID)
49850b57cec5SDimitry Andric       continue;
4986bdd1243dSDimitry Andric     auto SetBehavior = [&](Module::ModFlagBehavior B) {
4987bdd1243dSDimitry Andric       Metadata *Ops[3] = {ConstantAsMetadata::get(ConstantInt::get(
4988bdd1243dSDimitry Andric                               Type::getInt32Ty(M.getContext()), B)),
49890b57cec5SDimitry Andric                           MDString::get(M.getContext(), ID->getString()),
49900b57cec5SDimitry Andric                           Op->getOperand(2)};
49910b57cec5SDimitry Andric       ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
49920b57cec5SDimitry Andric       Changed = true;
4993bdd1243dSDimitry Andric     };
4994bdd1243dSDimitry Andric 
4995bdd1243dSDimitry Andric     if (ID->getString() == "Objective-C Image Info Version")
4996bdd1243dSDimitry Andric       HasObjCFlag = true;
4997bdd1243dSDimitry Andric     if (ID->getString() == "Objective-C Class Properties")
4998bdd1243dSDimitry Andric       HasClassProperties = true;
4999bdd1243dSDimitry Andric     // Upgrade PIC from Error/Max to Min.
5000bdd1243dSDimitry Andric     if (ID->getString() == "PIC Level") {
5001bdd1243dSDimitry Andric       if (auto *Behavior =
5002bdd1243dSDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
5003bdd1243dSDimitry Andric         uint64_t V = Behavior->getLimitedValue();
5004bdd1243dSDimitry Andric         if (V == Module::Error || V == Module::Max)
5005bdd1243dSDimitry Andric           SetBehavior(Module::Min);
50060b57cec5SDimitry Andric       }
50070b57cec5SDimitry Andric     }
5008bdd1243dSDimitry Andric     // Upgrade "PIE Level" from Error to Max.
5009bdd1243dSDimitry Andric     if (ID->getString() == "PIE Level")
5010bdd1243dSDimitry Andric       if (auto *Behavior =
5011bdd1243dSDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)))
5012bdd1243dSDimitry Andric         if (Behavior->getLimitedValue() == Module::Error)
5013bdd1243dSDimitry Andric           SetBehavior(Module::Max);
501481ad6265SDimitry Andric 
501581ad6265SDimitry Andric     // Upgrade branch protection and return address signing module flags. The
501681ad6265SDimitry Andric     // module flag behavior for these fields were Error and now they are Min.
501781ad6265SDimitry Andric     if (ID->getString() == "branch-target-enforcement" ||
50185f757f3fSDimitry Andric         ID->getString().starts_with("sign-return-address")) {
501981ad6265SDimitry Andric       if (auto *Behavior =
502081ad6265SDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
502181ad6265SDimitry Andric         if (Behavior->getLimitedValue() == Module::Error) {
502281ad6265SDimitry Andric           Type *Int32Ty = Type::getInt32Ty(M.getContext());
502381ad6265SDimitry Andric           Metadata *Ops[3] = {
502481ad6265SDimitry Andric               ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Min)),
502581ad6265SDimitry Andric               Op->getOperand(1), Op->getOperand(2)};
502681ad6265SDimitry Andric           ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
502781ad6265SDimitry Andric           Changed = true;
502881ad6265SDimitry Andric         }
502981ad6265SDimitry Andric       }
503081ad6265SDimitry Andric     }
503181ad6265SDimitry Andric 
50320b57cec5SDimitry Andric     // Upgrade Objective-C Image Info Section. Removed the whitespce in the
50330b57cec5SDimitry Andric     // section name so that llvm-lto will not complain about mismatching
50340b57cec5SDimitry Andric     // module flags that is functionally the same.
50350b57cec5SDimitry Andric     if (ID->getString() == "Objective-C Image Info Section") {
50360b57cec5SDimitry Andric       if (auto *Value = dyn_cast_or_null<MDString>(Op->getOperand(2))) {
50370b57cec5SDimitry Andric         SmallVector<StringRef, 4> ValueComp;
50380b57cec5SDimitry Andric         Value->getString().split(ValueComp, " ");
50390b57cec5SDimitry Andric         if (ValueComp.size() != 1) {
50400b57cec5SDimitry Andric           std::string NewValue;
50410b57cec5SDimitry Andric           for (auto &S : ValueComp)
50420b57cec5SDimitry Andric             NewValue += S.str();
50430b57cec5SDimitry Andric           Metadata *Ops[3] = {Op->getOperand(0), Op->getOperand(1),
50440b57cec5SDimitry Andric                               MDString::get(M.getContext(), NewValue)};
50450b57cec5SDimitry Andric           ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
50460b57cec5SDimitry Andric           Changed = true;
50470b57cec5SDimitry Andric         }
50480b57cec5SDimitry Andric       }
50490b57cec5SDimitry Andric     }
50505ffd83dbSDimitry Andric 
50515ffd83dbSDimitry Andric     // IRUpgrader turns a i32 type "Objective-C Garbage Collection" into i8 value.
50525ffd83dbSDimitry Andric     // If the higher bits are set, it adds new module flag for swift info.
50535ffd83dbSDimitry Andric     if (ID->getString() == "Objective-C Garbage Collection") {
50545ffd83dbSDimitry Andric       auto Md = dyn_cast<ConstantAsMetadata>(Op->getOperand(2));
50555ffd83dbSDimitry Andric       if (Md) {
50565ffd83dbSDimitry Andric         assert(Md->getValue() && "Expected non-empty metadata");
50575ffd83dbSDimitry Andric         auto Type = Md->getValue()->getType();
50585ffd83dbSDimitry Andric         if (Type == Int8Ty)
50595ffd83dbSDimitry Andric           continue;
50605ffd83dbSDimitry Andric         unsigned Val = Md->getValue()->getUniqueInteger().getZExtValue();
50615ffd83dbSDimitry Andric         if ((Val & 0xff) != Val) {
50625ffd83dbSDimitry Andric           HasSwiftVersionFlag = true;
50635ffd83dbSDimitry Andric           SwiftABIVersion = (Val & 0xff00) >> 8;
50645ffd83dbSDimitry Andric           SwiftMajorVersion = (Val & 0xff000000) >> 24;
50655ffd83dbSDimitry Andric           SwiftMinorVersion = (Val & 0xff0000) >> 16;
50665ffd83dbSDimitry Andric         }
50675ffd83dbSDimitry Andric         Metadata *Ops[3] = {
50685ffd83dbSDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Int32Ty,Module::Error)),
50695ffd83dbSDimitry Andric           Op->getOperand(1),
50705ffd83dbSDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Int8Ty,Val & 0xff))};
50715ffd83dbSDimitry Andric         ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
50725ffd83dbSDimitry Andric         Changed = true;
50735ffd83dbSDimitry Andric       }
50745ffd83dbSDimitry Andric     }
50750b57cec5SDimitry Andric   }
50760b57cec5SDimitry Andric 
50770b57cec5SDimitry Andric   // "Objective-C Class Properties" is recently added for Objective-C. We
50780b57cec5SDimitry Andric   // upgrade ObjC bitcodes to contain a "Objective-C Class Properties" module
50790b57cec5SDimitry Andric   // flag of value 0, so we can correclty downgrade this flag when trying to
50800b57cec5SDimitry Andric   // link an ObjC bitcode without this module flag with an ObjC bitcode with
50810b57cec5SDimitry Andric   // this module flag.
50820b57cec5SDimitry Andric   if (HasObjCFlag && !HasClassProperties) {
50830b57cec5SDimitry Andric     M.addModuleFlag(llvm::Module::Override, "Objective-C Class Properties",
50840b57cec5SDimitry Andric                     (uint32_t)0);
50850b57cec5SDimitry Andric     Changed = true;
50860b57cec5SDimitry Andric   }
50870b57cec5SDimitry Andric 
50885ffd83dbSDimitry Andric   if (HasSwiftVersionFlag) {
50895ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift ABI Version",
50905ffd83dbSDimitry Andric                     SwiftABIVersion);
50915ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift Major Version",
50925ffd83dbSDimitry Andric                     ConstantInt::get(Int8Ty, SwiftMajorVersion));
50935ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift Minor Version",
50945ffd83dbSDimitry Andric                     ConstantInt::get(Int8Ty, SwiftMinorVersion));
50955ffd83dbSDimitry Andric     Changed = true;
50965ffd83dbSDimitry Andric   }
50975ffd83dbSDimitry Andric 
50980b57cec5SDimitry Andric   return Changed;
50990b57cec5SDimitry Andric }
51000b57cec5SDimitry Andric 
UpgradeSectionAttributes(Module & M)51010b57cec5SDimitry Andric void llvm::UpgradeSectionAttributes(Module &M) {
51020b57cec5SDimitry Andric   auto TrimSpaces = [](StringRef Section) -> std::string {
51030b57cec5SDimitry Andric     SmallVector<StringRef, 5> Components;
51040b57cec5SDimitry Andric     Section.split(Components, ',');
51050b57cec5SDimitry Andric 
51060b57cec5SDimitry Andric     SmallString<32> Buffer;
51070b57cec5SDimitry Andric     raw_svector_ostream OS(Buffer);
51080b57cec5SDimitry Andric 
51090b57cec5SDimitry Andric     for (auto Component : Components)
51100b57cec5SDimitry Andric       OS << ',' << Component.trim();
51110b57cec5SDimitry Andric 
51125ffd83dbSDimitry Andric     return std::string(OS.str().substr(1));
51130b57cec5SDimitry Andric   };
51140b57cec5SDimitry Andric 
51150b57cec5SDimitry Andric   for (auto &GV : M.globals()) {
51160b57cec5SDimitry Andric     if (!GV.hasSection())
51170b57cec5SDimitry Andric       continue;
51180b57cec5SDimitry Andric 
51190b57cec5SDimitry Andric     StringRef Section = GV.getSection();
51200b57cec5SDimitry Andric 
51215f757f3fSDimitry Andric     if (!Section.starts_with("__DATA, __objc_catlist"))
51220b57cec5SDimitry Andric       continue;
51230b57cec5SDimitry Andric 
51240b57cec5SDimitry Andric     // __DATA, __objc_catlist, regular, no_dead_strip
51250b57cec5SDimitry Andric     // __DATA,__objc_catlist,regular,no_dead_strip
51260b57cec5SDimitry Andric     GV.setSection(TrimSpaces(Section));
51270b57cec5SDimitry Andric   }
51280b57cec5SDimitry Andric }
51290b57cec5SDimitry Andric 
51305ffd83dbSDimitry Andric namespace {
51315ffd83dbSDimitry Andric // Prior to LLVM 10.0, the strictfp attribute could be used on individual
51325ffd83dbSDimitry Andric // callsites within a function that did not also have the strictfp attribute.
51335ffd83dbSDimitry Andric // Since 10.0, if strict FP semantics are needed within a function, the
51345ffd83dbSDimitry Andric // function must have the strictfp attribute and all calls within the function
51355ffd83dbSDimitry Andric // must also have the strictfp attribute. This latter restriction is
51365ffd83dbSDimitry Andric // necessary to prevent unwanted libcall simplification when a function is
51375ffd83dbSDimitry Andric // being cloned (such as for inlining).
51385ffd83dbSDimitry Andric //
51395ffd83dbSDimitry Andric // The "dangling" strictfp attribute usage was only used to prevent constant
51405ffd83dbSDimitry Andric // folding and other libcall simplification. The nobuiltin attribute on the
51415ffd83dbSDimitry Andric // callsite has the same effect.
51425ffd83dbSDimitry Andric struct StrictFPUpgradeVisitor : public InstVisitor<StrictFPUpgradeVisitor> {
514381ad6265SDimitry Andric   StrictFPUpgradeVisitor() = default;
51445ffd83dbSDimitry Andric 
visitCallBase__anon68d474a30511::StrictFPUpgradeVisitor51455ffd83dbSDimitry Andric   void visitCallBase(CallBase &Call) {
51465ffd83dbSDimitry Andric     if (!Call.isStrictFP())
51475ffd83dbSDimitry Andric       return;
51485ffd83dbSDimitry Andric     if (isa<ConstrainedFPIntrinsic>(&Call))
51495ffd83dbSDimitry Andric       return;
51505ffd83dbSDimitry Andric     // If we get here, the caller doesn't have the strictfp attribute
51515ffd83dbSDimitry Andric     // but this callsite does. Replace the strictfp attribute with nobuiltin.
5152349cc55cSDimitry Andric     Call.removeFnAttr(Attribute::StrictFP);
5153349cc55cSDimitry Andric     Call.addFnAttr(Attribute::NoBuiltin);
51545ffd83dbSDimitry Andric   }
51555ffd83dbSDimitry Andric };
51565ffd83dbSDimitry Andric } // namespace
51575ffd83dbSDimitry Andric 
UpgradeFunctionAttributes(Function & F)51585ffd83dbSDimitry Andric void llvm::UpgradeFunctionAttributes(Function &F) {
51595ffd83dbSDimitry Andric   // If a function definition doesn't have the strictfp attribute,
51605ffd83dbSDimitry Andric   // convert any callsite strictfp attributes to nobuiltin.
51615ffd83dbSDimitry Andric   if (!F.isDeclaration() && !F.hasFnAttribute(Attribute::StrictFP)) {
51625ffd83dbSDimitry Andric     StrictFPUpgradeVisitor SFPV;
51635ffd83dbSDimitry Andric     SFPV.visit(F);
51645ffd83dbSDimitry Andric   }
5165e8d8bef9SDimitry Andric 
5166fe6060f1SDimitry Andric   // Remove all incompatibile attributes from function.
5167349cc55cSDimitry Andric   F.removeRetAttrs(AttributeFuncs::typeIncompatible(F.getReturnType()));
5168fe6060f1SDimitry Andric   for (auto &Arg : F.args())
5169fe6060f1SDimitry Andric     Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
51705ffd83dbSDimitry Andric }
51715ffd83dbSDimitry Andric 
isOldLoopArgument(Metadata * MD)51720b57cec5SDimitry Andric static bool isOldLoopArgument(Metadata *MD) {
51730b57cec5SDimitry Andric   auto *T = dyn_cast_or_null<MDTuple>(MD);
51740b57cec5SDimitry Andric   if (!T)
51750b57cec5SDimitry Andric     return false;
51760b57cec5SDimitry Andric   if (T->getNumOperands() < 1)
51770b57cec5SDimitry Andric     return false;
51780b57cec5SDimitry Andric   auto *S = dyn_cast_or_null<MDString>(T->getOperand(0));
51790b57cec5SDimitry Andric   if (!S)
51800b57cec5SDimitry Andric     return false;
51815f757f3fSDimitry Andric   return S->getString().starts_with("llvm.vectorizer.");
51820b57cec5SDimitry Andric }
51830b57cec5SDimitry Andric 
upgradeLoopTag(LLVMContext & C,StringRef OldTag)51840b57cec5SDimitry Andric static MDString *upgradeLoopTag(LLVMContext &C, StringRef OldTag) {
51850b57cec5SDimitry Andric   StringRef OldPrefix = "llvm.vectorizer.";
51865f757f3fSDimitry Andric   assert(OldTag.starts_with(OldPrefix) && "Expected old prefix");
51870b57cec5SDimitry Andric 
51880b57cec5SDimitry Andric   if (OldTag == "llvm.vectorizer.unroll")
51890b57cec5SDimitry Andric     return MDString::get(C, "llvm.loop.interleave.count");
51900b57cec5SDimitry Andric 
51910b57cec5SDimitry Andric   return MDString::get(
51920b57cec5SDimitry Andric       C, (Twine("llvm.loop.vectorize.") + OldTag.drop_front(OldPrefix.size()))
51930b57cec5SDimitry Andric              .str());
51940b57cec5SDimitry Andric }
51950b57cec5SDimitry Andric 
upgradeLoopArgument(Metadata * MD)51960b57cec5SDimitry Andric static Metadata *upgradeLoopArgument(Metadata *MD) {
51970b57cec5SDimitry Andric   auto *T = dyn_cast_or_null<MDTuple>(MD);
51980b57cec5SDimitry Andric   if (!T)
51990b57cec5SDimitry Andric     return MD;
52000b57cec5SDimitry Andric   if (T->getNumOperands() < 1)
52010b57cec5SDimitry Andric     return MD;
52020b57cec5SDimitry Andric   auto *OldTag = dyn_cast_or_null<MDString>(T->getOperand(0));
52030b57cec5SDimitry Andric   if (!OldTag)
52040b57cec5SDimitry Andric     return MD;
52055f757f3fSDimitry Andric   if (!OldTag->getString().starts_with("llvm.vectorizer."))
52060b57cec5SDimitry Andric     return MD;
52070b57cec5SDimitry Andric 
52080b57cec5SDimitry Andric   // This has an old tag.  Upgrade it.
52090b57cec5SDimitry Andric   SmallVector<Metadata *, 8> Ops;
52100b57cec5SDimitry Andric   Ops.reserve(T->getNumOperands());
52110b57cec5SDimitry Andric   Ops.push_back(upgradeLoopTag(T->getContext(), OldTag->getString()));
52120b57cec5SDimitry Andric   for (unsigned I = 1, E = T->getNumOperands(); I != E; ++I)
52130b57cec5SDimitry Andric     Ops.push_back(T->getOperand(I));
52140b57cec5SDimitry Andric 
52150b57cec5SDimitry Andric   return MDTuple::get(T->getContext(), Ops);
52160b57cec5SDimitry Andric }
52170b57cec5SDimitry Andric 
upgradeInstructionLoopAttachment(MDNode & N)52180b57cec5SDimitry Andric MDNode *llvm::upgradeInstructionLoopAttachment(MDNode &N) {
52190b57cec5SDimitry Andric   auto *T = dyn_cast<MDTuple>(&N);
52200b57cec5SDimitry Andric   if (!T)
52210b57cec5SDimitry Andric     return &N;
52220b57cec5SDimitry Andric 
52230b57cec5SDimitry Andric   if (none_of(T->operands(), isOldLoopArgument))
52240b57cec5SDimitry Andric     return &N;
52250b57cec5SDimitry Andric 
52260b57cec5SDimitry Andric   SmallVector<Metadata *, 8> Ops;
52270b57cec5SDimitry Andric   Ops.reserve(T->getNumOperands());
52280b57cec5SDimitry Andric   for (Metadata *MD : T->operands())
52290b57cec5SDimitry Andric     Ops.push_back(upgradeLoopArgument(MD));
52300b57cec5SDimitry Andric 
52310b57cec5SDimitry Andric   return MDTuple::get(T->getContext(), Ops);
52320b57cec5SDimitry Andric }
52338bcb0991SDimitry Andric 
UpgradeDataLayoutString(StringRef DL,StringRef TT)52348bcb0991SDimitry Andric std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) {
5235e8d8bef9SDimitry Andric   Triple T(TT);
523606c3fb27SDimitry Andric   // The only data layout upgrades needed for pre-GCN are setting the address
523706c3fb27SDimitry Andric   // space of globals to 1.
523806c3fb27SDimitry Andric   if (T.isAMDGPU() && !T.isAMDGCN() && !DL.contains("-G") &&
52395f757f3fSDimitry Andric       !DL.starts_with("G")) {
5240e8d8bef9SDimitry Andric     return DL.empty() ? std::string("G1") : (DL + "-G1").str();
5241e8d8bef9SDimitry Andric   }
52428bcb0991SDimitry Andric 
5243bdd1243dSDimitry Andric   if (T.isRISCV64()) {
5244bdd1243dSDimitry Andric     // Make i32 a native type for 64-bit RISC-V.
5245bdd1243dSDimitry Andric     auto I = DL.find("-n64-");
5246bdd1243dSDimitry Andric     if (I != StringRef::npos)
5247bdd1243dSDimitry Andric       return (DL.take_front(I) + "-n32:64-" + DL.drop_front(I + 5)).str();
5248bdd1243dSDimitry Andric     return DL.str();
5249bdd1243dSDimitry Andric   }
5250bdd1243dSDimitry Andric 
525104eeddc0SDimitry Andric   std::string Res = DL.str();
525206c3fb27SDimitry Andric   // AMDGCN data layout upgrades.
525306c3fb27SDimitry Andric   if (T.isAMDGCN()) {
525406c3fb27SDimitry Andric     // Define address spaces for constants.
525506c3fb27SDimitry Andric     if (!DL.contains("-G") && !DL.starts_with("G"))
525606c3fb27SDimitry Andric       Res.append(Res.empty() ? "G1" : "-G1");
525706c3fb27SDimitry Andric 
525806c3fb27SDimitry Andric     // Add missing non-integral declarations.
525906c3fb27SDimitry Andric     // This goes before adding new address spaces to prevent incoherent string
526006c3fb27SDimitry Andric     // values.
52615f757f3fSDimitry Andric     if (!DL.contains("-ni") && !DL.starts_with("ni"))
52625f757f3fSDimitry Andric       Res.append("-ni:7:8:9");
52635f757f3fSDimitry Andric     // Update ni:7 to ni:7:8:9.
526406c3fb27SDimitry Andric     if (DL.ends_with("ni:7"))
52655f757f3fSDimitry Andric       Res.append(":8:9");
52665f757f3fSDimitry Andric     if (DL.ends_with("ni:7:8"))
52675f757f3fSDimitry Andric       Res.append(":9");
526806c3fb27SDimitry Andric 
526906c3fb27SDimitry Andric     // Add sizing for address spaces 7 and 8 (fat raw buffers and buffer
527006c3fb27SDimitry Andric     // resources) An empty data layout has already been upgraded to G1 by now.
52715f757f3fSDimitry Andric     if (!DL.contains("-p7") && !DL.starts_with("p7"))
527206c3fb27SDimitry Andric       Res.append("-p7:160:256:256:32");
52735f757f3fSDimitry Andric     if (!DL.contains("-p8") && !DL.starts_with("p8"))
527406c3fb27SDimitry Andric       Res.append("-p8:128:128");
52755f757f3fSDimitry Andric     if (!DL.contains("-p9") && !DL.starts_with("p9"))
52765f757f3fSDimitry Andric       Res.append("-p9:192:256:256:32");
527706c3fb27SDimitry Andric 
527806c3fb27SDimitry Andric     return Res;
527906c3fb27SDimitry Andric   }
528006c3fb27SDimitry Andric 
528104eeddc0SDimitry Andric   if (!T.isX86())
528204eeddc0SDimitry Andric     return Res;
52838bcb0991SDimitry Andric 
528404eeddc0SDimitry Andric   // If the datalayout matches the expected format, add pointer size address
528504eeddc0SDimitry Andric   // spaces to the datalayout.
528604eeddc0SDimitry Andric   std::string AddrSpaces = "-p270:32:32-p271:32:32-p272:64:64";
52875f757f3fSDimitry Andric   if (StringRef Ref = Res; !Ref.contains(AddrSpaces)) {
52888bcb0991SDimitry Andric     SmallVector<StringRef, 4> Groups;
52898bcb0991SDimitry Andric     Regex R("(e-m:[a-z](-p:32:32)?)(-[if]64:.*$)");
52905f757f3fSDimitry Andric     if (R.match(Res, &Groups))
529104eeddc0SDimitry Andric       Res = (Groups[1] + AddrSpaces + Groups[3]).str();
529204eeddc0SDimitry Andric   }
52938bcb0991SDimitry Andric 
52945f757f3fSDimitry Andric   // i128 values need to be 16-byte-aligned. LLVM already called into libgcc
52955f757f3fSDimitry Andric   // for i128 operations prior to this being reflected in the data layout, and
52965f757f3fSDimitry Andric   // clang mostly produced LLVM IR that already aligned i128 to 16 byte
52975f757f3fSDimitry Andric   // boundaries, so although this is a breaking change, the upgrade is expected
52985f757f3fSDimitry Andric   // to fix more IR than it breaks.
52995f757f3fSDimitry Andric   // Intel MCU is an exception and uses 4-byte-alignment.
53005f757f3fSDimitry Andric   if (!T.isOSIAMCU()) {
53015f757f3fSDimitry Andric     std::string I128 = "-i128:128";
53025f757f3fSDimitry Andric     if (StringRef Ref = Res; !Ref.contains(I128)) {
53035f757f3fSDimitry Andric       SmallVector<StringRef, 4> Groups;
53045f757f3fSDimitry Andric       Regex R("^(e(-[mpi][^-]*)*)((-[^mpi][^-]*)*)$");
53055f757f3fSDimitry Andric       if (R.match(Res, &Groups))
53065f757f3fSDimitry Andric         Res = (Groups[1] + I128 + Groups[3]).str();
53075f757f3fSDimitry Andric     }
53085f757f3fSDimitry Andric   }
53095f757f3fSDimitry Andric 
531004eeddc0SDimitry Andric   // For 32-bit MSVC targets, raise the alignment of f80 values to 16 bytes.
531104eeddc0SDimitry Andric   // Raising the alignment is safe because Clang did not produce f80 values in
531204eeddc0SDimitry Andric   // the MSVC environment before this upgrade was added.
531304eeddc0SDimitry Andric   if (T.isWindowsMSVCEnvironment() && !T.isArch64Bit()) {
531404eeddc0SDimitry Andric     StringRef Ref = Res;
531504eeddc0SDimitry Andric     auto I = Ref.find("-f80:32-");
531604eeddc0SDimitry Andric     if (I != StringRef::npos)
531704eeddc0SDimitry Andric       Res = (Ref.take_front(I) + "-f80:128-" + Ref.drop_front(I + 8)).str();
531804eeddc0SDimitry Andric   }
531904eeddc0SDimitry Andric 
532004eeddc0SDimitry Andric   return Res;
53218bcb0991SDimitry Andric }
5322480093f4SDimitry Andric 
UpgradeAttributes(AttrBuilder & B)53235ffd83dbSDimitry Andric void llvm::UpgradeAttributes(AttrBuilder &B) {
5324480093f4SDimitry Andric   StringRef FramePointer;
532504eeddc0SDimitry Andric   Attribute A = B.getAttribute("no-frame-pointer-elim");
532604eeddc0SDimitry Andric   if (A.isValid()) {
5327480093f4SDimitry Andric     // The value can be "true" or "false".
532804eeddc0SDimitry Andric     FramePointer = A.getValueAsString() == "true" ? "all" : "none";
5329480093f4SDimitry Andric     B.removeAttribute("no-frame-pointer-elim");
5330480093f4SDimitry Andric   }
5331480093f4SDimitry Andric   if (B.contains("no-frame-pointer-elim-non-leaf")) {
5332480093f4SDimitry Andric     // The value is ignored. "no-frame-pointer-elim"="true" takes priority.
5333480093f4SDimitry Andric     if (FramePointer != "all")
5334480093f4SDimitry Andric       FramePointer = "non-leaf";
5335480093f4SDimitry Andric     B.removeAttribute("no-frame-pointer-elim-non-leaf");
5336480093f4SDimitry Andric   }
5337480093f4SDimitry Andric   if (!FramePointer.empty())
5338480093f4SDimitry Andric     B.addAttribute("frame-pointer", FramePointer);
53395ffd83dbSDimitry Andric 
534004eeddc0SDimitry Andric   A = B.getAttribute("null-pointer-is-valid");
534104eeddc0SDimitry Andric   if (A.isValid()) {
53425ffd83dbSDimitry Andric     // The value can be "true" or "false".
534304eeddc0SDimitry Andric     bool NullPointerIsValid = A.getValueAsString() == "true";
53445ffd83dbSDimitry Andric     B.removeAttribute("null-pointer-is-valid");
53455ffd83dbSDimitry Andric     if (NullPointerIsValid)
53465ffd83dbSDimitry Andric       B.addAttribute(Attribute::NullPointerIsValid);
53475ffd83dbSDimitry Andric   }
5348480093f4SDimitry Andric }
534981ad6265SDimitry Andric 
UpgradeOperandBundles(std::vector<OperandBundleDef> & Bundles)535081ad6265SDimitry Andric void llvm::UpgradeOperandBundles(std::vector<OperandBundleDef> &Bundles) {
535181ad6265SDimitry Andric   // clang.arc.attachedcall bundles are now required to have an operand.
535281ad6265SDimitry Andric   // If they don't, it's okay to drop them entirely: when there is an operand,
535381ad6265SDimitry Andric   // the "attachedcall" is meaningful and required, but without an operand,
535481ad6265SDimitry Andric   // it's just a marker NOP.  Dropping it merely prevents an optimization.
535581ad6265SDimitry Andric   erase_if(Bundles, [&](OperandBundleDef &OBD) {
535681ad6265SDimitry Andric     return OBD.getTag() == "clang.arc.attachedcall" &&
535781ad6265SDimitry Andric            OBD.inputs().empty();
535881ad6265SDimitry Andric   });
535981ad6265SDimitry Andric }
5360