xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/AutoUpgrade.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
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.
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.
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.
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 
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 
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 
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 
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.*'.
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.*'.
650*0fca6ea1SDimitry Andric       Intrinsic::ID ID =
651*0fca6ea1SDimitry Andric           StringSwitch<Intrinsic::ID>(Name)
6521db9f3b2SDimitry Andric               .Cases("v2f32.v8i8", "v4f32.v16i8",
653*0fca6ea1SDimitry Andric                      IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfdot
654*0fca6ea1SDimitry Andric                            : (Intrinsic::ID)Intrinsic::aarch64_neon_bfdot)
6551db9f3b2SDimitry Andric               .Default(Intrinsic::not_intrinsic);
6561db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
6571db9f3b2SDimitry Andric         size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits();
6581db9f3b2SDimitry Andric         assert((OperandWidth == 64 || OperandWidth == 128) &&
6591db9f3b2SDimitry Andric                "Unexpected operand width");
6601db9f3b2SDimitry Andric         LLVMContext &Ctx = F->getParent()->getContext();
6611db9f3b2SDimitry Andric         std::array<Type *, 2> Tys{
6621db9f3b2SDimitry Andric             {F->getReturnType(),
6631db9f3b2SDimitry Andric              FixedVectorType::get(Type::getBFloatTy(Ctx), OperandWidth / 16)}};
6641db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
6651db9f3b2SDimitry Andric         return true;
6661db9f3b2SDimitry Andric       }
6671db9f3b2SDimitry Andric       return false; // No other '(arm|aarch64).neon.bfdot.*'.
6681db9f3b2SDimitry Andric     }
6691db9f3b2SDimitry Andric 
6701db9f3b2SDimitry Andric     // Changed in 12.0: bfmmla, bfmlalb and bfmlalt are not polymorphic
6711db9f3b2SDimitry Andric     // anymore and accept v8bf16 instead of v16i8.
6721db9f3b2SDimitry Andric     if (Name.consume_front("bfm")) {
6731db9f3b2SDimitry Andric       // (arm|aarch64).neon.bfm*'.
6741db9f3b2SDimitry Andric       if (Name.consume_back(".v4f32.v16i8")) {
6751db9f3b2SDimitry Andric         // (arm|aarch64).neon.bfm*.v4f32.v16i8'.
6761db9f3b2SDimitry Andric         Intrinsic::ID ID =
6771db9f3b2SDimitry Andric             StringSwitch<Intrinsic::ID>(Name)
678*0fca6ea1SDimitry Andric                 .Case("mla",
679*0fca6ea1SDimitry Andric                       IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmmla
680*0fca6ea1SDimitry Andric                             : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmmla)
681*0fca6ea1SDimitry Andric                 .Case("lalb",
682*0fca6ea1SDimitry Andric                       IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalb
683*0fca6ea1SDimitry Andric                             : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalb)
684*0fca6ea1SDimitry Andric                 .Case("lalt",
685*0fca6ea1SDimitry Andric                       IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalt
686*0fca6ea1SDimitry Andric                             : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalt)
6871db9f3b2SDimitry Andric                 .Default(Intrinsic::not_intrinsic);
6881db9f3b2SDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
6891db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
6901db9f3b2SDimitry Andric           return true;
6911db9f3b2SDimitry Andric         }
6921db9f3b2SDimitry Andric         return false; // No other '(arm|aarch64).neon.bfm*.v16i8'.
6931db9f3b2SDimitry Andric       }
6941db9f3b2SDimitry Andric       return false; // No other '(arm|aarch64).neon.bfm*.
6951db9f3b2SDimitry Andric     }
6961db9f3b2SDimitry Andric     // Continue on to Aarch64 Neon or Arm Neon.
6971db9f3b2SDimitry Andric   }
6981db9f3b2SDimitry Andric   // Continue on to Arm or Aarch64.
6991db9f3b2SDimitry Andric 
7001db9f3b2SDimitry Andric   if (IsArm) {
7011db9f3b2SDimitry Andric     // 'arm.*'.
7021db9f3b2SDimitry Andric     if (Neon) {
7031db9f3b2SDimitry Andric       // 'arm.neon.*'.
7041db9f3b2SDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
7051db9f3b2SDimitry Andric                              .StartsWith("vclz.", Intrinsic::ctlz)
7061db9f3b2SDimitry Andric                              .StartsWith("vcnt.", Intrinsic::ctpop)
7071db9f3b2SDimitry Andric                              .StartsWith("vqadds.", Intrinsic::sadd_sat)
7081db9f3b2SDimitry Andric                              .StartsWith("vqaddu.", Intrinsic::uadd_sat)
7091db9f3b2SDimitry Andric                              .StartsWith("vqsubs.", Intrinsic::ssub_sat)
7101db9f3b2SDimitry Andric                              .StartsWith("vqsubu.", Intrinsic::usub_sat)
7111db9f3b2SDimitry Andric                              .Default(Intrinsic::not_intrinsic);
7121db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
7131db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
7141db9f3b2SDimitry Andric                                           F->arg_begin()->getType());
7151db9f3b2SDimitry Andric         return true;
7161db9f3b2SDimitry Andric       }
7171db9f3b2SDimitry Andric 
7181db9f3b2SDimitry Andric       if (Name.consume_front("vst")) {
7191db9f3b2SDimitry Andric         // 'arm.neon.vst*'.
7201db9f3b2SDimitry Andric         static const Regex vstRegex("^([1234]|[234]lane)\\.v[a-z0-9]*$");
7211db9f3b2SDimitry Andric         SmallVector<StringRef, 2> Groups;
7221db9f3b2SDimitry Andric         if (vstRegex.match(Name, &Groups)) {
7231db9f3b2SDimitry Andric           static const Intrinsic::ID StoreInts[] = {
7241db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst1, Intrinsic::arm_neon_vst2,
7251db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst3, Intrinsic::arm_neon_vst4};
7261db9f3b2SDimitry Andric 
7271db9f3b2SDimitry Andric           static const Intrinsic::ID StoreLaneInts[] = {
7281db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst2lane, Intrinsic::arm_neon_vst3lane,
7291db9f3b2SDimitry Andric               Intrinsic::arm_neon_vst4lane};
7301db9f3b2SDimitry Andric 
7311db9f3b2SDimitry Andric           auto fArgs = F->getFunctionType()->params();
7321db9f3b2SDimitry Andric           Type *Tys[] = {fArgs[0], fArgs[1]};
7331db9f3b2SDimitry Andric           if (Groups[1].size() == 1)
7341db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(F->getParent(),
7351db9f3b2SDimitry Andric                                               StoreInts[fArgs.size() - 3], Tys);
7361db9f3b2SDimitry Andric           else
7371db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(
7381db9f3b2SDimitry Andric                 F->getParent(), StoreLaneInts[fArgs.size() - 5], Tys);
7391db9f3b2SDimitry Andric           return true;
7401db9f3b2SDimitry Andric         }
7411db9f3b2SDimitry Andric         return false; // No other 'arm.neon.vst*'.
7421db9f3b2SDimitry Andric       }
7431db9f3b2SDimitry Andric 
7441db9f3b2SDimitry Andric       return false; // No other 'arm.neon.*'.
7451db9f3b2SDimitry Andric     }
7461db9f3b2SDimitry Andric 
7471db9f3b2SDimitry Andric     if (Name.consume_front("mve.")) {
7481db9f3b2SDimitry Andric       // 'arm.mve.*'.
7491db9f3b2SDimitry Andric       if (Name == "vctp64") {
7501db9f3b2SDimitry Andric         if (cast<FixedVectorType>(F->getReturnType())->getNumElements() == 4) {
7511db9f3b2SDimitry Andric           // A vctp64 returning a v4i1 is converted to return a v2i1. Rename
7521db9f3b2SDimitry Andric           // the function and deal with it below in UpgradeIntrinsicCall.
7531db9f3b2SDimitry Andric           rename(F);
7541db9f3b2SDimitry Andric           return true;
7551db9f3b2SDimitry Andric         }
7561db9f3b2SDimitry Andric         return false; // Not 'arm.mve.vctp64'.
7571db9f3b2SDimitry Andric       }
7581db9f3b2SDimitry Andric 
7591db9f3b2SDimitry Andric       // These too are changed to accept a v2i1 instead of the old v4i1.
7601db9f3b2SDimitry Andric       if (Name.consume_back(".v4i1")) {
7611db9f3b2SDimitry Andric         // 'arm.mve.*.v4i1'.
7621db9f3b2SDimitry Andric         if (Name.consume_back(".predicated.v2i64.v4i32"))
7631db9f3b2SDimitry Andric           // 'arm.mve.*.predicated.v2i64.v4i32.v4i1'
7641db9f3b2SDimitry Andric           return Name == "mull.int" || Name == "vqdmull";
7651db9f3b2SDimitry Andric 
7661db9f3b2SDimitry Andric         if (Name.consume_back(".v2i64")) {
7671db9f3b2SDimitry Andric           // 'arm.mve.*.v2i64.v4i1'
7681db9f3b2SDimitry Andric           bool IsGather = Name.consume_front("vldr.gather.");
7691db9f3b2SDimitry Andric           if (IsGather || Name.consume_front("vstr.scatter.")) {
7701db9f3b2SDimitry Andric             if (Name.consume_front("base.")) {
7711db9f3b2SDimitry Andric               // Optional 'wb.' prefix.
7721db9f3b2SDimitry Andric               Name.consume_front("wb.");
7731db9f3b2SDimitry Andric               // 'arm.mve.(vldr.gather|vstr.scatter).base.(wb.)?
7741db9f3b2SDimitry Andric               // predicated.v2i64.v2i64.v4i1'.
7751db9f3b2SDimitry Andric               return Name == "predicated.v2i64";
7761db9f3b2SDimitry Andric             }
7771db9f3b2SDimitry Andric 
7781db9f3b2SDimitry Andric             if (Name.consume_front("offset.predicated."))
7791db9f3b2SDimitry Andric               return Name == (IsGather ? "v2i64.p0i64" : "p0i64.v2i64") ||
7801db9f3b2SDimitry Andric                      Name == (IsGather ? "v2i64.p0" : "p0.v2i64");
7811db9f3b2SDimitry Andric 
7821db9f3b2SDimitry Andric             // No other 'arm.mve.(vldr.gather|vstr.scatter).*.v2i64.v4i1'.
7831db9f3b2SDimitry Andric             return false;
7841db9f3b2SDimitry Andric           }
7851db9f3b2SDimitry Andric 
7861db9f3b2SDimitry Andric           return false; // No other 'arm.mve.*.v2i64.v4i1'.
7871db9f3b2SDimitry Andric         }
7881db9f3b2SDimitry Andric         return false; // No other 'arm.mve.*.v4i1'.
7891db9f3b2SDimitry Andric       }
7901db9f3b2SDimitry Andric       return false; // No other 'arm.mve.*'.
7911db9f3b2SDimitry Andric     }
7921db9f3b2SDimitry Andric 
7931db9f3b2SDimitry Andric     if (Name.consume_front("cde.vcx")) {
7941db9f3b2SDimitry Andric       // 'arm.cde.vcx*'.
7951db9f3b2SDimitry Andric       if (Name.consume_back(".predicated.v2i64.v4i1"))
7961db9f3b2SDimitry Andric         // 'arm.cde.vcx*.predicated.v2i64.v4i1'.
7971db9f3b2SDimitry Andric         return Name == "1q" || Name == "1qa" || Name == "2q" || Name == "2qa" ||
7981db9f3b2SDimitry Andric                Name == "3q" || Name == "3qa";
7991db9f3b2SDimitry Andric 
8001db9f3b2SDimitry Andric       return false; // No other 'arm.cde.vcx*'.
8011db9f3b2SDimitry Andric     }
8021db9f3b2SDimitry Andric   } else {
8031db9f3b2SDimitry Andric     // 'aarch64.*'.
8041db9f3b2SDimitry Andric     if (Neon) {
8051db9f3b2SDimitry Andric       // 'aarch64.neon.*'.
8061db9f3b2SDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
8071db9f3b2SDimitry Andric                              .StartsWith("frintn", Intrinsic::roundeven)
8081db9f3b2SDimitry Andric                              .StartsWith("rbit", Intrinsic::bitreverse)
8091db9f3b2SDimitry Andric                              .Default(Intrinsic::not_intrinsic);
8101db9f3b2SDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
8111db9f3b2SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
8121db9f3b2SDimitry Andric                                           F->arg_begin()->getType());
8131db9f3b2SDimitry Andric         return true;
8141db9f3b2SDimitry Andric       }
8151db9f3b2SDimitry Andric 
8161db9f3b2SDimitry Andric       if (Name.starts_with("addp")) {
8171db9f3b2SDimitry Andric         // 'aarch64.neon.addp*'.
8181db9f3b2SDimitry Andric         if (F->arg_size() != 2)
8191db9f3b2SDimitry Andric           return false; // Invalid IR.
8201db9f3b2SDimitry Andric         VectorType *Ty = dyn_cast<VectorType>(F->getReturnType());
8211db9f3b2SDimitry Andric         if (Ty && Ty->getElementType()->isFloatingPointTy()) {
8221db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8231db9f3b2SDimitry Andric                                             Intrinsic::aarch64_neon_faddp, Ty);
8241db9f3b2SDimitry Andric           return true;
8251db9f3b2SDimitry Andric         }
8261db9f3b2SDimitry Andric       }
8271db9f3b2SDimitry Andric       return false; // No other 'aarch64.neon.*'.
8281db9f3b2SDimitry Andric     }
8291db9f3b2SDimitry Andric     if (Name.consume_front("sve.")) {
8301db9f3b2SDimitry Andric       // 'aarch64.sve.*'.
8311db9f3b2SDimitry Andric       if (Name.consume_front("bf")) {
8321db9f3b2SDimitry Andric         if (Name.consume_back(".lane")) {
8331db9f3b2SDimitry Andric           // 'aarch64.sve.bf*.lane'.
8341db9f3b2SDimitry Andric           Intrinsic::ID ID =
8351db9f3b2SDimitry Andric               StringSwitch<Intrinsic::ID>(Name)
8361db9f3b2SDimitry Andric                   .Case("dot", Intrinsic::aarch64_sve_bfdot_lane_v2)
8371db9f3b2SDimitry Andric                   .Case("mlalb", Intrinsic::aarch64_sve_bfmlalb_lane_v2)
8381db9f3b2SDimitry Andric                   .Case("mlalt", Intrinsic::aarch64_sve_bfmlalt_lane_v2)
8391db9f3b2SDimitry Andric                   .Default(Intrinsic::not_intrinsic);
8401db9f3b2SDimitry Andric           if (ID != Intrinsic::not_intrinsic) {
8411db9f3b2SDimitry Andric             NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
8421db9f3b2SDimitry Andric             return true;
8431db9f3b2SDimitry Andric           }
8441db9f3b2SDimitry Andric           return false; // No other 'aarch64.sve.bf*.lane'.
8451db9f3b2SDimitry Andric         }
8461db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.bf*'.
8471db9f3b2SDimitry Andric       }
8481db9f3b2SDimitry Andric 
849*0fca6ea1SDimitry Andric       if (Name.consume_front("addqv")) {
850*0fca6ea1SDimitry Andric         // 'aarch64.sve.addqv'.
851*0fca6ea1SDimitry Andric         if (!F->getReturnType()->isFPOrFPVectorTy())
852*0fca6ea1SDimitry Andric           return false;
853*0fca6ea1SDimitry Andric 
854*0fca6ea1SDimitry Andric         auto Args = F->getFunctionType()->params();
855*0fca6ea1SDimitry Andric         Type *Tys[] = {F->getReturnType(), Args[1]};
856*0fca6ea1SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(),
857*0fca6ea1SDimitry Andric                                           Intrinsic::aarch64_sve_faddqv, Tys);
858*0fca6ea1SDimitry Andric         return true;
859*0fca6ea1SDimitry Andric       }
860*0fca6ea1SDimitry Andric 
8611db9f3b2SDimitry Andric       if (Name.consume_front("ld")) {
8621db9f3b2SDimitry Andric         // 'aarch64.sve.ld*'.
8631db9f3b2SDimitry Andric         static const Regex LdRegex("^[234](.nxv[a-z0-9]+|$)");
8641db9f3b2SDimitry Andric         if (LdRegex.match(Name)) {
8651db9f3b2SDimitry Andric           Type *ScalarTy =
866*0fca6ea1SDimitry Andric               cast<VectorType>(F->getReturnType())->getElementType();
867*0fca6ea1SDimitry Andric           ElementCount EC =
868*0fca6ea1SDimitry Andric               cast<VectorType>(F->arg_begin()->getType())->getElementCount();
8691db9f3b2SDimitry Andric           Type *Ty = VectorType::get(ScalarTy, EC);
8701db9f3b2SDimitry Andric           static const Intrinsic::ID LoadIDs[] = {
8711db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld2_sret,
8721db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld3_sret,
8731db9f3b2SDimitry Andric               Intrinsic::aarch64_sve_ld4_sret,
8741db9f3b2SDimitry Andric           };
8751db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8761db9f3b2SDimitry Andric                                             LoadIDs[Name[0] - '2'], Ty);
8771db9f3b2SDimitry Andric           return true;
8781db9f3b2SDimitry Andric         }
8791db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.ld*'.
8801db9f3b2SDimitry Andric       }
8811db9f3b2SDimitry Andric 
8821db9f3b2SDimitry Andric       if (Name.consume_front("tuple.")) {
8831db9f3b2SDimitry Andric         // 'aarch64.sve.tuple.*'.
8841db9f3b2SDimitry Andric         if (Name.starts_with("get")) {
8851db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.get*'.
8861db9f3b2SDimitry Andric           Type *Tys[] = {F->getReturnType(), F->arg_begin()->getType()};
8871db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8881db9f3b2SDimitry Andric                                             Intrinsic::vector_extract, Tys);
8891db9f3b2SDimitry Andric           return true;
8901db9f3b2SDimitry Andric         }
8911db9f3b2SDimitry Andric 
8921db9f3b2SDimitry Andric         if (Name.starts_with("set")) {
8931db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.set*'.
8941db9f3b2SDimitry Andric           auto Args = F->getFunctionType()->params();
8951db9f3b2SDimitry Andric           Type *Tys[] = {Args[0], Args[2], Args[1]};
8961db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
8971db9f3b2SDimitry Andric                                             Intrinsic::vector_insert, Tys);
8981db9f3b2SDimitry Andric           return true;
8991db9f3b2SDimitry Andric         }
9001db9f3b2SDimitry Andric 
9011db9f3b2SDimitry Andric         static const Regex CreateTupleRegex("^create[234](.nxv[a-z0-9]+|$)");
9021db9f3b2SDimitry Andric         if (CreateTupleRegex.match(Name)) {
9031db9f3b2SDimitry Andric           // 'aarch64.sve.tuple.create*'.
9041db9f3b2SDimitry Andric           auto Args = F->getFunctionType()->params();
9051db9f3b2SDimitry Andric           Type *Tys[] = {F->getReturnType(), Args[1]};
9061db9f3b2SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(),
9071db9f3b2SDimitry Andric                                             Intrinsic::vector_insert, Tys);
9081db9f3b2SDimitry Andric           return true;
9091db9f3b2SDimitry Andric         }
9101db9f3b2SDimitry Andric         return false; // No other 'aarch64.sve.tuple.*'.
9111db9f3b2SDimitry Andric       }
9121db9f3b2SDimitry Andric       return false; // No other 'aarch64.sve.*'.
9131db9f3b2SDimitry Andric     }
9141db9f3b2SDimitry Andric   }
9151db9f3b2SDimitry Andric   return false; // No other 'arm.*', 'aarch64.*'.
9161db9f3b2SDimitry Andric }
9171db9f3b2SDimitry Andric 
9187a6dacacSDimitry Andric static Intrinsic::ID shouldUpgradeNVPTXBF16Intrinsic(StringRef Name) {
9195f757f3fSDimitry Andric   if (Name.consume_front("abs."))
92006c3fb27SDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9215f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_abs_bf16)
9225f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_abs_bf16x2)
92306c3fb27SDimitry Andric         .Default(Intrinsic::not_intrinsic);
9245f757f3fSDimitry Andric 
9255f757f3fSDimitry Andric   if (Name.consume_front("fma.rn."))
9265f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9275f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fma_rn_bf16)
9285f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fma_rn_bf16x2)
9295f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fma_rn_ftz_bf16)
9305f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fma_rn_ftz_bf16x2)
9315f757f3fSDimitry Andric         .Case("ftz.relu.bf16", Intrinsic::nvvm_fma_rn_ftz_relu_bf16)
9325f757f3fSDimitry Andric         .Case("ftz.relu.bf16x2", Intrinsic::nvvm_fma_rn_ftz_relu_bf16x2)
9335f757f3fSDimitry Andric         .Case("ftz.sat.bf16", Intrinsic::nvvm_fma_rn_ftz_sat_bf16)
9345f757f3fSDimitry Andric         .Case("ftz.sat.bf16x2", Intrinsic::nvvm_fma_rn_ftz_sat_bf16x2)
9355f757f3fSDimitry Andric         .Case("relu.bf16", Intrinsic::nvvm_fma_rn_relu_bf16)
9365f757f3fSDimitry Andric         .Case("relu.bf16x2", Intrinsic::nvvm_fma_rn_relu_bf16x2)
9375f757f3fSDimitry Andric         .Case("sat.bf16", Intrinsic::nvvm_fma_rn_sat_bf16)
9385f757f3fSDimitry Andric         .Case("sat.bf16x2", Intrinsic::nvvm_fma_rn_sat_bf16x2)
9395f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9405f757f3fSDimitry Andric 
9415f757f3fSDimitry Andric   if (Name.consume_front("fmax."))
9425f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9435f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fmax_bf16)
9445f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fmax_bf16x2)
9455f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fmax_ftz_bf16)
9465f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fmax_ftz_bf16x2)
9475f757f3fSDimitry Andric         .Case("ftz.nan.bf16", Intrinsic::nvvm_fmax_ftz_nan_bf16)
9485f757f3fSDimitry Andric         .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmax_ftz_nan_bf16x2)
9495f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16",
9505f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16)
9515f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16x2",
9525f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_nan_xorsign_abs_bf16x2)
9535f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16)
9545f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16x2",
9555f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_ftz_xorsign_abs_bf16x2)
9565f757f3fSDimitry Andric         .Case("nan.bf16", Intrinsic::nvvm_fmax_nan_bf16)
9575f757f3fSDimitry Andric         .Case("nan.bf16x2", Intrinsic::nvvm_fmax_nan_bf16x2)
9585f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16)
9595f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16x2",
9605f757f3fSDimitry Andric               Intrinsic::nvvm_fmax_nan_xorsign_abs_bf16x2)
9615f757f3fSDimitry Andric         .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmax_xorsign_abs_bf16)
9625f757f3fSDimitry Andric         .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmax_xorsign_abs_bf16x2)
9635f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9645f757f3fSDimitry Andric 
9655f757f3fSDimitry Andric   if (Name.consume_front("fmin."))
9665f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9675f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_fmin_bf16)
9685f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_fmin_bf16x2)
9695f757f3fSDimitry Andric         .Case("ftz.bf16", Intrinsic::nvvm_fmin_ftz_bf16)
9705f757f3fSDimitry Andric         .Case("ftz.bf16x2", Intrinsic::nvvm_fmin_ftz_bf16x2)
9715f757f3fSDimitry Andric         .Case("ftz.nan.bf16", Intrinsic::nvvm_fmin_ftz_nan_bf16)
9725f757f3fSDimitry Andric         .Case("ftz.nan.bf16x2", Intrinsic::nvvm_fmin_ftz_nan_bf16x2)
9735f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16",
9745f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16)
9755f757f3fSDimitry Andric         .Case("ftz.nan.xorsign.abs.bf16x2",
9765f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_nan_xorsign_abs_bf16x2)
9775f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16", Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16)
9785f757f3fSDimitry Andric         .Case("ftz.xorsign.abs.bf16x2",
9795f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_ftz_xorsign_abs_bf16x2)
9805f757f3fSDimitry Andric         .Case("nan.bf16", Intrinsic::nvvm_fmin_nan_bf16)
9815f757f3fSDimitry Andric         .Case("nan.bf16x2", Intrinsic::nvvm_fmin_nan_bf16x2)
9825f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16", Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16)
9835f757f3fSDimitry Andric         .Case("nan.xorsign.abs.bf16x2",
9845f757f3fSDimitry Andric               Intrinsic::nvvm_fmin_nan_xorsign_abs_bf16x2)
9855f757f3fSDimitry Andric         .Case("xorsign.abs.bf16", Intrinsic::nvvm_fmin_xorsign_abs_bf16)
9865f757f3fSDimitry Andric         .Case("xorsign.abs.bf16x2", Intrinsic::nvvm_fmin_xorsign_abs_bf16x2)
9875f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9885f757f3fSDimitry Andric 
9895f757f3fSDimitry Andric   if (Name.consume_front("neg."))
9905f757f3fSDimitry Andric     return StringSwitch<Intrinsic::ID>(Name)
9915f757f3fSDimitry Andric         .Case("bf16", Intrinsic::nvvm_neg_bf16)
9925f757f3fSDimitry Andric         .Case("bf16x2", Intrinsic::nvvm_neg_bf16x2)
9935f757f3fSDimitry Andric         .Default(Intrinsic::not_intrinsic);
9945f757f3fSDimitry Andric 
9955f757f3fSDimitry Andric   return Intrinsic::not_intrinsic;
99606c3fb27SDimitry Andric }
99706c3fb27SDimitry Andric 
998*0fca6ea1SDimitry Andric static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn,
999*0fca6ea1SDimitry Andric                                       bool CanUpgradeDebugIntrinsicsToRecords) {
10000b57cec5SDimitry Andric   assert(F && "Illegal to upgrade a non-existent Function.");
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   StringRef Name = F->getName();
10035f757f3fSDimitry Andric 
10045f757f3fSDimitry Andric   // Quickly eliminate it, if it's not a candidate.
10055f757f3fSDimitry Andric   if (!Name.consume_front("llvm.") || Name.empty())
10060b57cec5SDimitry Andric     return false;
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric   switch (Name[0]) {
10090b57cec5SDimitry Andric   default: break;
10100b57cec5SDimitry Andric   case 'a': {
10111db9f3b2SDimitry Andric     bool IsArm = Name.consume_front("arm.");
10121db9f3b2SDimitry Andric     if (IsArm || Name.consume_front("aarch64.")) {
10137a6dacacSDimitry Andric       if (upgradeArmOrAarch64IntrinsicFunction(IsArm, F, Name, NewFn))
10140b57cec5SDimitry Andric         return true;
1015e8d8bef9SDimitry Andric       break;
1016e8d8bef9SDimitry Andric     }
1017e8d8bef9SDimitry Andric 
10185f757f3fSDimitry Andric     if (Name.consume_front("amdgcn.")) {
101906c3fb27SDimitry Andric       if (Name == "alignbit") {
102004eeddc0SDimitry Andric         // Target specific intrinsic became redundant
102104eeddc0SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::fshr,
102204eeddc0SDimitry Andric                                           {F->getReturnType()});
102304eeddc0SDimitry Andric         return true;
102404eeddc0SDimitry Andric       }
102504eeddc0SDimitry Andric 
10265f757f3fSDimitry Andric       if (Name.consume_front("atomic.")) {
10275f757f3fSDimitry Andric         if (Name.starts_with("inc") || Name.starts_with("dec")) {
10285f757f3fSDimitry Andric           // These were replaced with atomicrmw uinc_wrap and udec_wrap, so
10295f757f3fSDimitry Andric           // there's no new declaration.
103006c3fb27SDimitry Andric           NewFn = nullptr;
103106c3fb27SDimitry Andric           return true;
10320b57cec5SDimitry Andric         }
10335f757f3fSDimitry Andric         break; // No other 'amdgcn.atomic.*'
10345f757f3fSDimitry Andric       }
10355f757f3fSDimitry Andric 
1036*0fca6ea1SDimitry Andric       if (Name.starts_with("ds.fadd") || Name.starts_with("ds.fmin") ||
1037*0fca6ea1SDimitry Andric           Name.starts_with("ds.fmax")) {
1038*0fca6ea1SDimitry Andric         // Replaced with atomicrmw fadd/fmin/fmax, so there's no new
1039*0fca6ea1SDimitry Andric         // declaration.
1040*0fca6ea1SDimitry Andric         NewFn = nullptr;
1041*0fca6ea1SDimitry Andric         return true;
1042*0fca6ea1SDimitry Andric       }
1043*0fca6ea1SDimitry Andric 
10445f757f3fSDimitry Andric       if (Name.starts_with("ldexp.")) {
10455f757f3fSDimitry Andric         // Target specific intrinsic became redundant
10465f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(
10475f757f3fSDimitry Andric           F->getParent(), Intrinsic::ldexp,
10485f757f3fSDimitry Andric           {F->getReturnType(), F->getArg(1)->getType()});
10495f757f3fSDimitry Andric         return true;
10505f757f3fSDimitry Andric       }
10515f757f3fSDimitry Andric       break; // No other 'amdgcn.*'
10525f757f3fSDimitry Andric     }
10530b57cec5SDimitry Andric 
105406c3fb27SDimitry Andric     break;
105506c3fb27SDimitry Andric   }
10560b57cec5SDimitry Andric   case 'c': {
10575f757f3fSDimitry Andric     if (F->arg_size() == 1) {
10585f757f3fSDimitry Andric       Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name)
10595f757f3fSDimitry Andric                              .StartsWith("ctlz.", Intrinsic::ctlz)
10605f757f3fSDimitry Andric                              .StartsWith("cttz.", Intrinsic::cttz)
10615f757f3fSDimitry Andric                              .Default(Intrinsic::not_intrinsic);
10625f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
10630b57cec5SDimitry Andric         rename(F);
10645f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID,
10650b57cec5SDimitry Andric                                           F->arg_begin()->getType());
10660b57cec5SDimitry Andric         return true;
10670b57cec5SDimitry Andric       }
10685f757f3fSDimitry Andric     }
10695f757f3fSDimitry Andric 
1070*0fca6ea1SDimitry Andric     if (F->arg_size() == 2 && Name == "coro.end") {
10710b57cec5SDimitry Andric       rename(F);
10725f757f3fSDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::coro_end);
10730b57cec5SDimitry Andric       return true;
10740b57cec5SDimitry Andric     }
10755f757f3fSDimitry Andric 
10760b57cec5SDimitry Andric     break;
10770b57cec5SDimitry Andric   }
10785f757f3fSDimitry Andric   case 'd':
10795f757f3fSDimitry Andric     if (Name.consume_front("dbg.")) {
1080*0fca6ea1SDimitry Andric       // Mark debug intrinsics for upgrade to new debug format.
1081*0fca6ea1SDimitry Andric       if (CanUpgradeDebugIntrinsicsToRecords &&
1082*0fca6ea1SDimitry Andric           F->getParent()->IsNewDbgInfoFormat) {
1083*0fca6ea1SDimitry Andric         if (Name == "addr" || Name == "value" || Name == "assign" ||
1084*0fca6ea1SDimitry Andric             Name == "declare" || Name == "label") {
1085*0fca6ea1SDimitry Andric           // There's no function to replace these with.
1086*0fca6ea1SDimitry Andric           NewFn = nullptr;
1087*0fca6ea1SDimitry Andric           // But we do want these to get upgraded.
1088*0fca6ea1SDimitry Andric           return true;
1089*0fca6ea1SDimitry Andric         }
1090*0fca6ea1SDimitry Andric       }
1091*0fca6ea1SDimitry Andric       // Update llvm.dbg.addr intrinsics even in "new debug mode"; they'll get
1092*0fca6ea1SDimitry Andric       // converted to DbgVariableRecords later.
10935f757f3fSDimitry Andric       if (Name == "addr" || (Name == "value" && F->arg_size() == 4)) {
109406c3fb27SDimitry Andric         rename(F);
109506c3fb27SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value);
109606c3fb27SDimitry Andric         return true;
109706c3fb27SDimitry Andric       }
10985f757f3fSDimitry Andric       break; // No other 'dbg.*'.
10990b57cec5SDimitry Andric     }
11000b57cec5SDimitry Andric     break;
11015f757f3fSDimitry Andric   case 'e':
11025f757f3fSDimitry Andric     if (Name.consume_front("experimental.vector.")) {
1103*0fca6ea1SDimitry Andric       Intrinsic::ID ID =
1104*0fca6ea1SDimitry Andric           StringSwitch<Intrinsic::ID>(Name)
11055f757f3fSDimitry Andric               .StartsWith("extract.", Intrinsic::vector_extract)
11065f757f3fSDimitry Andric               .StartsWith("insert.", Intrinsic::vector_insert)
1107*0fca6ea1SDimitry Andric               .StartsWith("splice.", Intrinsic::vector_splice)
1108*0fca6ea1SDimitry Andric               .StartsWith("reverse.", Intrinsic::vector_reverse)
1109*0fca6ea1SDimitry Andric               .StartsWith("interleave2.", Intrinsic::vector_interleave2)
1110*0fca6ea1SDimitry Andric               .StartsWith("deinterleave2.", Intrinsic::vector_deinterleave2)
11115f757f3fSDimitry Andric               .Default(Intrinsic::not_intrinsic);
11125f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
11135f757f3fSDimitry Andric         const auto *FT = F->getFunctionType();
11145f757f3fSDimitry Andric         SmallVector<Type *, 2> Tys;
1115*0fca6ea1SDimitry Andric         if (ID == Intrinsic::vector_extract ||
1116*0fca6ea1SDimitry Andric             ID == Intrinsic::vector_interleave2)
11175f757f3fSDimitry Andric           // Extracting overloads the return type.
11185f757f3fSDimitry Andric           Tys.push_back(FT->getReturnType());
1119*0fca6ea1SDimitry Andric         if (ID != Intrinsic::vector_interleave2)
11205f757f3fSDimitry Andric           Tys.push_back(FT->getParamType(0));
11215f757f3fSDimitry Andric         if (ID == Intrinsic::vector_insert)
11225f757f3fSDimitry Andric           // Inserting overloads the inserted type.
11235f757f3fSDimitry Andric           Tys.push_back(FT->getParamType(1));
112481ad6265SDimitry Andric         rename(F);
11255f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
112681ad6265SDimitry Andric         return true;
112781ad6265SDimitry Andric       }
112881ad6265SDimitry Andric 
11295f757f3fSDimitry Andric       if (Name.consume_front("reduce.")) {
11300b57cec5SDimitry Andric         SmallVector<StringRef, 2> Groups;
11315f757f3fSDimitry Andric         static const Regex R("^([a-z]+)\\.[a-z][0-9]+");
11325f757f3fSDimitry Andric         if (R.match(Name, &Groups))
1133e8d8bef9SDimitry Andric           ID = StringSwitch<Intrinsic::ID>(Groups[1])
1134e8d8bef9SDimitry Andric                    .Case("add", Intrinsic::vector_reduce_add)
1135e8d8bef9SDimitry Andric                    .Case("mul", Intrinsic::vector_reduce_mul)
1136e8d8bef9SDimitry Andric                    .Case("and", Intrinsic::vector_reduce_and)
1137e8d8bef9SDimitry Andric                    .Case("or", Intrinsic::vector_reduce_or)
1138e8d8bef9SDimitry Andric                    .Case("xor", Intrinsic::vector_reduce_xor)
1139e8d8bef9SDimitry Andric                    .Case("smax", Intrinsic::vector_reduce_smax)
1140e8d8bef9SDimitry Andric                    .Case("smin", Intrinsic::vector_reduce_smin)
1141e8d8bef9SDimitry Andric                    .Case("umax", Intrinsic::vector_reduce_umax)
1142e8d8bef9SDimitry Andric                    .Case("umin", Intrinsic::vector_reduce_umin)
1143e8d8bef9SDimitry Andric                    .Case("fmax", Intrinsic::vector_reduce_fmax)
1144e8d8bef9SDimitry Andric                    .Case("fmin", Intrinsic::vector_reduce_fmin)
1145e8d8bef9SDimitry Andric                    .Default(Intrinsic::not_intrinsic);
11465f757f3fSDimitry Andric 
11475f757f3fSDimitry Andric         bool V2 = false;
11485f757f3fSDimitry Andric         if (ID == Intrinsic::not_intrinsic) {
11495f757f3fSDimitry Andric           static const Regex R2("^v2\\.([a-z]+)\\.[fi][0-9]+");
1150e8d8bef9SDimitry Andric           Groups.clear();
11515f757f3fSDimitry Andric           V2 = true;
11525f757f3fSDimitry Andric           if (R2.match(Name, &Groups))
11535f757f3fSDimitry Andric             ID = StringSwitch<Intrinsic::ID>(Groups[1])
11545f757f3fSDimitry Andric                      .Case("fadd", Intrinsic::vector_reduce_fadd)
11555f757f3fSDimitry Andric                      .Case("fmul", Intrinsic::vector_reduce_fmul)
11565f757f3fSDimitry Andric                      .Default(Intrinsic::not_intrinsic);
11575f757f3fSDimitry Andric         }
1158e8d8bef9SDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
1159e8d8bef9SDimitry Andric           rename(F);
1160e8d8bef9SDimitry Andric           auto Args = F->getFunctionType()->params();
11615f757f3fSDimitry Andric           NewFn =
11625f757f3fSDimitry Andric               Intrinsic::getDeclaration(F->getParent(), ID, {Args[V2 ? 1 : 0]});
11630b57cec5SDimitry Andric           return true;
11640b57cec5SDimitry Andric         }
11655f757f3fSDimitry Andric         break; // No other 'expermental.vector.reduce.*'.
11660b57cec5SDimitry Andric       }
11675f757f3fSDimitry Andric       break; // No other 'experimental.vector.*'.
11680b57cec5SDimitry Andric     }
11695f757f3fSDimitry Andric     break; // No other 'e*'.
1170bdd1243dSDimitry Andric   case 'f':
11715f757f3fSDimitry Andric     if (Name.starts_with("flt.rounds")) {
1172bdd1243dSDimitry Andric       rename(F);
1173bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::get_rounding);
1174bdd1243dSDimitry Andric       return true;
1175bdd1243dSDimitry Andric     }
1176bdd1243dSDimitry Andric     break;
11770b57cec5SDimitry Andric   case 'i':
11785f757f3fSDimitry Andric     if (Name.starts_with("invariant.group.barrier")) {
11790b57cec5SDimitry Andric       // Rename invariant.group.barrier to launder.invariant.group
11800b57cec5SDimitry Andric       auto Args = F->getFunctionType()->params();
11810b57cec5SDimitry Andric       Type* ObjectPtr[1] = {Args[0]};
11820b57cec5SDimitry Andric       rename(F);
11830b57cec5SDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(),
11840b57cec5SDimitry Andric           Intrinsic::launder_invariant_group, ObjectPtr);
11850b57cec5SDimitry Andric       return true;
11860b57cec5SDimitry Andric     }
11870b57cec5SDimitry Andric     break;
11880b57cec5SDimitry Andric   case 'm': {
11890b57cec5SDimitry Andric     // Updating the memory intrinsics (memcpy/memmove/memset) that have an
11900b57cec5SDimitry Andric     // alignment parameter to embedding the alignment as an attribute of
11910b57cec5SDimitry Andric     // the pointer args.
11925f757f3fSDimitry Andric     if (unsigned ID = StringSwitch<unsigned>(Name)
11935f757f3fSDimitry Andric                           .StartsWith("memcpy.", Intrinsic::memcpy)
11945f757f3fSDimitry Andric                           .StartsWith("memmove.", Intrinsic::memmove)
11955f757f3fSDimitry Andric                           .Default(0)) {
11965f757f3fSDimitry Andric       if (F->arg_size() == 5) {
11970b57cec5SDimitry Andric         rename(F);
11980b57cec5SDimitry Andric         // Get the types of dest, src, and len
11995f757f3fSDimitry Andric         ArrayRef<Type *> ParamTypes =
12005f757f3fSDimitry Andric             F->getFunctionType()->params().slice(0, 3);
12015f757f3fSDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), ID, ParamTypes);
12020b57cec5SDimitry Andric         return true;
12030b57cec5SDimitry Andric       }
12040b57cec5SDimitry Andric     }
12055f757f3fSDimitry Andric     if (Name.starts_with("memset.") && F->arg_size() == 5) {
12060b57cec5SDimitry Andric       rename(F);
12070b57cec5SDimitry Andric       // Get the types of dest, and len
12080b57cec5SDimitry Andric       const auto *FT = F->getFunctionType();
12090b57cec5SDimitry Andric       Type *ParamTypes[2] = {
12100b57cec5SDimitry Andric           FT->getParamType(0), // Dest
12110b57cec5SDimitry Andric           FT->getParamType(2)  // len
12120b57cec5SDimitry Andric       };
12130b57cec5SDimitry Andric       NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memset,
12140b57cec5SDimitry Andric                                         ParamTypes);
12150b57cec5SDimitry Andric       return true;
12160b57cec5SDimitry Andric     }
12170b57cec5SDimitry Andric     break;
12180b57cec5SDimitry Andric   }
12190b57cec5SDimitry Andric   case 'n': {
12205f757f3fSDimitry Andric     if (Name.consume_front("nvvm.")) {
12215f757f3fSDimitry Andric       // Check for nvvm intrinsics corresponding exactly to an LLVM intrinsic.
12225f757f3fSDimitry Andric       if (F->arg_size() == 1) {
12235f757f3fSDimitry Andric         Intrinsic::ID IID =
12245f757f3fSDimitry Andric             StringSwitch<Intrinsic::ID>(Name)
12250b57cec5SDimitry Andric                 .Cases("brev32", "brev64", Intrinsic::bitreverse)
12260b57cec5SDimitry Andric                 .Case("clz.i", Intrinsic::ctlz)
12270b57cec5SDimitry Andric                 .Case("popc.i", Intrinsic::ctpop)
12280b57cec5SDimitry Andric                 .Default(Intrinsic::not_intrinsic);
12295f757f3fSDimitry Andric         if (IID != Intrinsic::not_intrinsic) {
12300b57cec5SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), IID,
12310b57cec5SDimitry Andric                                             {F->getReturnType()});
12320b57cec5SDimitry Andric           return true;
12330b57cec5SDimitry Andric         }
12345f757f3fSDimitry Andric       }
12355f757f3fSDimitry Andric 
12365f757f3fSDimitry Andric       // Check for nvvm intrinsics that need a return type adjustment.
12375f757f3fSDimitry Andric       if (!F->getReturnType()->getScalarType()->isBFloatTy()) {
12387a6dacacSDimitry Andric         Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic(Name);
12395f757f3fSDimitry Andric         if (IID != Intrinsic::not_intrinsic) {
124006c3fb27SDimitry Andric           NewFn = nullptr;
124106c3fb27SDimitry Andric           return true;
124206c3fb27SDimitry Andric         }
12435f757f3fSDimitry Andric       }
12445f757f3fSDimitry Andric 
12450b57cec5SDimitry Andric       // The following nvvm intrinsics correspond exactly to an LLVM idiom, but
12460b57cec5SDimitry Andric       // not to an intrinsic alone.  We expand them in UpgradeIntrinsicCall.
12470b57cec5SDimitry Andric       //
12480b57cec5SDimitry Andric       // TODO: We could add lohi.i2d.
12495f757f3fSDimitry Andric       bool Expand = false;
12505f757f3fSDimitry Andric       if (Name.consume_front("abs."))
12515f757f3fSDimitry Andric         // nvvm.abs.{i,ii}
12525f757f3fSDimitry Andric         Expand = Name == "i" || Name == "ll";
12535f757f3fSDimitry Andric       else if (Name == "clz.ll" || Name == "popc.ll" || Name == "h2f")
12545f757f3fSDimitry Andric         Expand = true;
12555f757f3fSDimitry Andric       else if (Name.consume_front("max.") || Name.consume_front("min."))
12565f757f3fSDimitry Andric         // nvvm.{min,max}.{i,ii,ui,ull}
12577a6dacacSDimitry Andric         Expand = Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
12587a6dacacSDimitry Andric                  Name == "ui" || Name == "ull";
12595f757f3fSDimitry Andric       else if (Name.consume_front("atomic.load.add."))
12605f757f3fSDimitry Andric         // nvvm.atomic.load.add.{f32.p,f64.p}
12615f757f3fSDimitry Andric         Expand = Name.starts_with("f32.p") || Name.starts_with("f64.p");
12625f757f3fSDimitry Andric       else
12635f757f3fSDimitry Andric         Expand = false;
12645f757f3fSDimitry Andric 
12650b57cec5SDimitry Andric       if (Expand) {
12660b57cec5SDimitry Andric         NewFn = nullptr;
12670b57cec5SDimitry Andric         return true;
12680b57cec5SDimitry Andric       }
12695f757f3fSDimitry Andric       break; // No other 'nvvm.*'.
12700b57cec5SDimitry Andric     }
12710b57cec5SDimitry Andric     break;
12720b57cec5SDimitry Andric   }
12730b57cec5SDimitry Andric   case 'o':
12740b57cec5SDimitry Andric     // We only need to change the name to match the mangling including the
12750b57cec5SDimitry Andric     // address space.
12765f757f3fSDimitry Andric     if (Name.starts_with("objectsize.")) {
12770b57cec5SDimitry Andric       Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
12780b57cec5SDimitry Andric       if (F->arg_size() == 2 || F->arg_size() == 3 ||
1279fe6060f1SDimitry Andric           F->getName() !=
1280fe6060f1SDimitry Andric               Intrinsic::getName(Intrinsic::objectsize, Tys, F->getParent())) {
12810b57cec5SDimitry Andric         rename(F);
12820b57cec5SDimitry Andric         NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::objectsize,
12830b57cec5SDimitry Andric                                           Tys);
12840b57cec5SDimitry Andric         return true;
12850b57cec5SDimitry Andric       }
12860b57cec5SDimitry Andric     }
12870b57cec5SDimitry Andric     break;
12880b57cec5SDimitry Andric 
12898bcb0991SDimitry Andric   case 'p':
12905f757f3fSDimitry Andric     if (Name.starts_with("ptr.annotation.") && F->arg_size() == 4) {
1291d409305fSDimitry Andric       rename(F);
1292bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(
1293bdd1243dSDimitry Andric           F->getParent(), Intrinsic::ptr_annotation,
1294bdd1243dSDimitry Andric           {F->arg_begin()->getType(), F->getArg(1)->getType()});
1295d409305fSDimitry Andric       return true;
12968bcb0991SDimitry Andric     }
12978bcb0991SDimitry Andric     break;
12988bcb0991SDimitry Andric 
12995f757f3fSDimitry Andric   case 'r': {
13005f757f3fSDimitry Andric     if (Name.consume_front("riscv.")) {
13015f757f3fSDimitry Andric       Intrinsic::ID ID;
13025f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
13035f757f3fSDimitry Andric                .Case("aes32dsi", Intrinsic::riscv_aes32dsi)
13045f757f3fSDimitry Andric                .Case("aes32dsmi", Intrinsic::riscv_aes32dsmi)
13055f757f3fSDimitry Andric                .Case("aes32esi", Intrinsic::riscv_aes32esi)
13065f757f3fSDimitry Andric                .Case("aes32esmi", Intrinsic::riscv_aes32esmi)
13075f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
13085f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
13095f757f3fSDimitry Andric         if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32)) {
131006c3fb27SDimitry Andric           rename(F);
13115f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
131206c3fb27SDimitry Andric           return true;
131306c3fb27SDimitry Andric         }
13145f757f3fSDimitry Andric         break; // No other applicable upgrades.
131506c3fb27SDimitry Andric       }
13165f757f3fSDimitry Andric 
13175f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
13185f757f3fSDimitry Andric                .StartsWith("sm4ks", Intrinsic::riscv_sm4ks)
13195f757f3fSDimitry Andric                .StartsWith("sm4ed", Intrinsic::riscv_sm4ed)
13205f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
13215f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
13225f757f3fSDimitry Andric         if (!F->getFunctionType()->getParamType(2)->isIntegerTy(32) ||
132306c3fb27SDimitry Andric             F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
132406c3fb27SDimitry Andric           rename(F);
13255f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
132606c3fb27SDimitry Andric           return true;
132706c3fb27SDimitry Andric         }
13285f757f3fSDimitry Andric         break; // No other applicable upgrades.
13295f757f3fSDimitry Andric       }
13305f757f3fSDimitry Andric 
13315f757f3fSDimitry Andric       ID = StringSwitch<Intrinsic::ID>(Name)
13325f757f3fSDimitry Andric                .StartsWith("sha256sig0", Intrinsic::riscv_sha256sig0)
13335f757f3fSDimitry Andric                .StartsWith("sha256sig1", Intrinsic::riscv_sha256sig1)
13345f757f3fSDimitry Andric                .StartsWith("sha256sum0", Intrinsic::riscv_sha256sum0)
13355f757f3fSDimitry Andric                .StartsWith("sha256sum1", Intrinsic::riscv_sha256sum1)
13365f757f3fSDimitry Andric                .StartsWith("sm3p0", Intrinsic::riscv_sm3p0)
13375f757f3fSDimitry Andric                .StartsWith("sm3p1", Intrinsic::riscv_sm3p1)
13385f757f3fSDimitry Andric                .Default(Intrinsic::not_intrinsic);
13395f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
13405f757f3fSDimitry Andric         if (F->getFunctionType()->getReturnType()->isIntegerTy(64)) {
134106c3fb27SDimitry Andric           rename(F);
13425f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
134306c3fb27SDimitry Andric           return true;
134406c3fb27SDimitry Andric         }
13455f757f3fSDimitry Andric         break; // No other applicable upgrades.
134606c3fb27SDimitry Andric       }
13475f757f3fSDimitry Andric       break; // No other 'riscv.*' intrinsics
134806c3fb27SDimitry Andric     }
13495f757f3fSDimitry Andric   } break;
135006c3fb27SDimitry Andric 
13510b57cec5SDimitry Andric   case 's':
13520b57cec5SDimitry Andric     if (Name == "stackprotectorcheck") {
13530b57cec5SDimitry Andric       NewFn = nullptr;
13540b57cec5SDimitry Andric       return true;
13550b57cec5SDimitry Andric     }
13560b57cec5SDimitry Andric     break;
13570b57cec5SDimitry Andric 
1358d409305fSDimitry Andric   case 'v': {
1359d409305fSDimitry Andric     if (Name == "var.annotation" && F->arg_size() == 4) {
1360d409305fSDimitry Andric       rename(F);
1361bdd1243dSDimitry Andric       NewFn = Intrinsic::getDeclaration(
1362bdd1243dSDimitry Andric           F->getParent(), Intrinsic::var_annotation,
1363bdd1243dSDimitry Andric           {{F->arg_begin()->getType(), F->getArg(1)->getType()}});
1364d409305fSDimitry Andric       return true;
1365d409305fSDimitry Andric     }
1366d409305fSDimitry Andric     break;
1367d409305fSDimitry Andric   }
1368d409305fSDimitry Andric 
13691ac55f4cSDimitry Andric   case 'w':
13705f757f3fSDimitry Andric     if (Name.consume_front("wasm.")) {
13715f757f3fSDimitry Andric       Intrinsic::ID ID =
13725f757f3fSDimitry Andric           StringSwitch<Intrinsic::ID>(Name)
13735f757f3fSDimitry Andric               .StartsWith("fma.", Intrinsic::wasm_relaxed_madd)
13745f757f3fSDimitry Andric               .StartsWith("fms.", Intrinsic::wasm_relaxed_nmadd)
13755f757f3fSDimitry Andric               .StartsWith("laneselect.", Intrinsic::wasm_relaxed_laneselect)
13765f757f3fSDimitry Andric               .Default(Intrinsic::not_intrinsic);
13775f757f3fSDimitry Andric       if (ID != Intrinsic::not_intrinsic) {
13781ac55f4cSDimitry Andric         rename(F);
13795f757f3fSDimitry Andric         NewFn =
13805f757f3fSDimitry Andric             Intrinsic::getDeclaration(F->getParent(), ID, F->getReturnType());
13811ac55f4cSDimitry Andric         return true;
13821ac55f4cSDimitry Andric       }
13835f757f3fSDimitry Andric 
13845f757f3fSDimitry Andric       if (Name.consume_front("dot.i8x16.i7x16.")) {
13855f757f3fSDimitry Andric         ID = StringSwitch<Intrinsic::ID>(Name)
13865f757f3fSDimitry Andric                  .Case("signed", Intrinsic::wasm_relaxed_dot_i8x16_i7x16_signed)
13875f757f3fSDimitry Andric                  .Case("add.signed",
13885f757f3fSDimitry Andric                        Intrinsic::wasm_relaxed_dot_i8x16_i7x16_add_signed)
13895f757f3fSDimitry Andric                  .Default(Intrinsic::not_intrinsic);
13905f757f3fSDimitry Andric         if (ID != Intrinsic::not_intrinsic) {
13911ac55f4cSDimitry Andric           rename(F);
13925f757f3fSDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), ID);
13931ac55f4cSDimitry Andric           return true;
13941ac55f4cSDimitry Andric         }
13955f757f3fSDimitry Andric         break; // No other 'wasm.dot.i8x16.i7x16.*'.
13961ac55f4cSDimitry Andric       }
13975f757f3fSDimitry Andric       break; // No other 'wasm.*'.
13981ac55f4cSDimitry Andric     }
13991ac55f4cSDimitry Andric     break;
14001ac55f4cSDimitry Andric 
14010b57cec5SDimitry Andric   case 'x':
14027a6dacacSDimitry Andric     if (upgradeX86IntrinsicFunction(F, Name, NewFn))
14030b57cec5SDimitry Andric       return true;
14040b57cec5SDimitry Andric   }
140581ad6265SDimitry Andric 
140681ad6265SDimitry Andric   auto *ST = dyn_cast<StructType>(F->getReturnType());
14075f757f3fSDimitry Andric   if (ST && (!ST->isLiteral() || ST->isPacked()) &&
14085f757f3fSDimitry Andric       F->getIntrinsicID() != Intrinsic::not_intrinsic) {
140981ad6265SDimitry Andric     // Replace return type with literal non-packed struct. Only do this for
141081ad6265SDimitry Andric     // intrinsics declared to return a struct, not for intrinsics with
141181ad6265SDimitry Andric     // overloaded return type, in which case the exact struct type will be
141281ad6265SDimitry Andric     // mangled into the name.
141381ad6265SDimitry Andric     SmallVector<Intrinsic::IITDescriptor> Desc;
141481ad6265SDimitry Andric     Intrinsic::getIntrinsicInfoTableEntries(F->getIntrinsicID(), Desc);
141581ad6265SDimitry Andric     if (Desc.front().Kind == Intrinsic::IITDescriptor::Struct) {
141681ad6265SDimitry Andric       auto *FT = F->getFunctionType();
141781ad6265SDimitry Andric       auto *NewST = StructType::get(ST->getContext(), ST->elements());
141881ad6265SDimitry Andric       auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());
141981ad6265SDimitry Andric       std::string Name = F->getName().str();
142081ad6265SDimitry Andric       rename(F);
142181ad6265SDimitry Andric       NewFn = Function::Create(NewFT, F->getLinkage(), F->getAddressSpace(),
142281ad6265SDimitry Andric                                Name, F->getParent());
142381ad6265SDimitry Andric 
142481ad6265SDimitry Andric       // The new function may also need remangling.
1425f3fd488fSDimitry Andric       if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(NewFn))
142681ad6265SDimitry Andric         NewFn = *Result;
142781ad6265SDimitry Andric       return true;
142881ad6265SDimitry Andric     }
142981ad6265SDimitry Andric   }
143081ad6265SDimitry Andric 
14310b57cec5SDimitry Andric   // Remangle our intrinsic since we upgrade the mangling
14320b57cec5SDimitry Andric   auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F);
1433bdd1243dSDimitry Andric   if (Result != std::nullopt) {
143481ad6265SDimitry Andric     NewFn = *Result;
14350b57cec5SDimitry Andric     return true;
14360b57cec5SDimitry Andric   }
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   //  This may not belong here. This function is effectively being overloaded
14390b57cec5SDimitry Andric   //  to both detect an intrinsic which needs upgrading, and to provide the
14400b57cec5SDimitry Andric   //  upgraded form of the intrinsic. We should perhaps have two separate
14410b57cec5SDimitry Andric   //  functions for this.
14420b57cec5SDimitry Andric   return false;
14430b57cec5SDimitry Andric }
14440b57cec5SDimitry Andric 
1445*0fca6ea1SDimitry Andric bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
1446*0fca6ea1SDimitry Andric                                     bool CanUpgradeDebugIntrinsicsToRecords) {
14470b57cec5SDimitry Andric   NewFn = nullptr;
1448*0fca6ea1SDimitry Andric   bool Upgraded =
1449*0fca6ea1SDimitry Andric       upgradeIntrinsicFunction1(F, NewFn, CanUpgradeDebugIntrinsicsToRecords);
14500b57cec5SDimitry Andric   assert(F != NewFn && "Intrinsic function upgraded to the same function");
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   // Upgrade intrinsic attributes.  This does not change the function.
14530b57cec5SDimitry Andric   if (NewFn)
14540b57cec5SDimitry Andric     F = NewFn;
14550b57cec5SDimitry Andric   if (Intrinsic::ID id = F->getIntrinsicID())
14560b57cec5SDimitry Andric     F->setAttributes(Intrinsic::getAttributes(F->getContext(), id));
14570b57cec5SDimitry Andric   return Upgraded;
14580b57cec5SDimitry Andric }
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric GlobalVariable *llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
14610b57cec5SDimitry Andric   if (!(GV->hasName() && (GV->getName() == "llvm.global_ctors" ||
14620b57cec5SDimitry Andric                           GV->getName() == "llvm.global_dtors")) ||
14630b57cec5SDimitry Andric       !GV->hasInitializer())
14640b57cec5SDimitry Andric     return nullptr;
14650b57cec5SDimitry Andric   ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType());
14660b57cec5SDimitry Andric   if (!ATy)
14670b57cec5SDimitry Andric     return nullptr;
14680b57cec5SDimitry Andric   StructType *STy = dyn_cast<StructType>(ATy->getElementType());
14690b57cec5SDimitry Andric   if (!STy || STy->getNumElements() != 2)
14700b57cec5SDimitry Andric     return nullptr;
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric   LLVMContext &C = GV->getContext();
14730b57cec5SDimitry Andric   IRBuilder<> IRB(C);
14740b57cec5SDimitry Andric   auto EltTy = StructType::get(STy->getElementType(0), STy->getElementType(1),
14755f757f3fSDimitry Andric                                IRB.getPtrTy());
14760b57cec5SDimitry Andric   Constant *Init = GV->getInitializer();
14770b57cec5SDimitry Andric   unsigned N = Init->getNumOperands();
14780b57cec5SDimitry Andric   std::vector<Constant *> NewCtors(N);
14790b57cec5SDimitry Andric   for (unsigned i = 0; i != N; ++i) {
14800b57cec5SDimitry Andric     auto Ctor = cast<Constant>(Init->getOperand(i));
14815f757f3fSDimitry Andric     NewCtors[i] = ConstantStruct::get(EltTy, Ctor->getAggregateElement(0u),
14825f757f3fSDimitry Andric                                       Ctor->getAggregateElement(1),
14835f757f3fSDimitry Andric                                       Constant::getNullValue(IRB.getPtrTy()));
14840b57cec5SDimitry Andric   }
14850b57cec5SDimitry Andric   Constant *NewInit = ConstantArray::get(ArrayType::get(EltTy, N), NewCtors);
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric   return new GlobalVariable(NewInit->getType(), false, GV->getLinkage(),
14880b57cec5SDimitry Andric                             NewInit, GV->getName());
14890b57cec5SDimitry Andric }
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric // Handles upgrading SSE2/AVX2/AVX512BW PSLLDQ intrinsics by converting them
14920b57cec5SDimitry Andric // to byte shuffles.
14937a6dacacSDimitry Andric static Value *upgradeX86PSLLDQIntrinsics(IRBuilder<> &Builder, Value *Op,
14947a6dacacSDimitry Andric                                          unsigned Shift) {
1495e8d8bef9SDimitry Andric   auto *ResultTy = cast<FixedVectorType>(Op->getType());
14965ffd83dbSDimitry Andric   unsigned NumElts = ResultTy->getNumElements() * 8;
14970b57cec5SDimitry Andric 
14980b57cec5SDimitry Andric   // Bitcast from a 64-bit element type to a byte element type.
14995ffd83dbSDimitry Andric   Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
15000b57cec5SDimitry Andric   Op = Builder.CreateBitCast(Op, VecTy, "cast");
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric   // We'll be shuffling in zeroes.
15030b57cec5SDimitry Andric   Value *Res = Constant::getNullValue(VecTy);
15040b57cec5SDimitry Andric 
15050b57cec5SDimitry Andric   // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
15060b57cec5SDimitry Andric   // we'll just return the zero vector.
15070b57cec5SDimitry Andric   if (Shift < 16) {
15085ffd83dbSDimitry Andric     int Idxs[64];
15090b57cec5SDimitry Andric     // 256/512-bit version is split into 2/4 16-byte lanes.
15100b57cec5SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 16)
15110b57cec5SDimitry Andric       for (unsigned i = 0; i != 16; ++i) {
15120b57cec5SDimitry Andric         unsigned Idx = NumElts + i - Shift;
15130b57cec5SDimitry Andric         if (Idx < NumElts)
15140b57cec5SDimitry Andric           Idx -= NumElts - 16; // end of lane, switch operand.
15150b57cec5SDimitry Andric         Idxs[l + i] = Idx + l;
15160b57cec5SDimitry Andric       }
15170b57cec5SDimitry Andric 
1518bdd1243dSDimitry Andric     Res = Builder.CreateShuffleVector(Res, Op, ArrayRef(Idxs, NumElts));
15190b57cec5SDimitry Andric   }
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric   // Bitcast back to a 64-bit element type.
15220b57cec5SDimitry Andric   return Builder.CreateBitCast(Res, ResultTy, "cast");
15230b57cec5SDimitry Andric }
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric // Handles upgrading SSE2/AVX2/AVX512BW PSRLDQ intrinsics by converting them
15260b57cec5SDimitry Andric // to byte shuffles.
15277a6dacacSDimitry Andric static Value *upgradeX86PSRLDQIntrinsics(IRBuilder<> &Builder, Value *Op,
15280b57cec5SDimitry Andric                                          unsigned Shift) {
1529e8d8bef9SDimitry Andric   auto *ResultTy = cast<FixedVectorType>(Op->getType());
15305ffd83dbSDimitry Andric   unsigned NumElts = ResultTy->getNumElements() * 8;
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric   // Bitcast from a 64-bit element type to a byte element type.
15335ffd83dbSDimitry Andric   Type *VecTy = FixedVectorType::get(Builder.getInt8Ty(), NumElts);
15340b57cec5SDimitry Andric   Op = Builder.CreateBitCast(Op, VecTy, "cast");
15350b57cec5SDimitry Andric 
15360b57cec5SDimitry Andric   // We'll be shuffling in zeroes.
15370b57cec5SDimitry Andric   Value *Res = Constant::getNullValue(VecTy);
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric   // If shift is less than 16, emit a shuffle to move the bytes. Otherwise,
15400b57cec5SDimitry Andric   // we'll just return the zero vector.
15410b57cec5SDimitry Andric   if (Shift < 16) {
15425ffd83dbSDimitry Andric     int Idxs[64];
15430b57cec5SDimitry Andric     // 256/512-bit version is split into 2/4 16-byte lanes.
15440b57cec5SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 16)
15450b57cec5SDimitry Andric       for (unsigned i = 0; i != 16; ++i) {
15460b57cec5SDimitry Andric         unsigned Idx = i + Shift;
15470b57cec5SDimitry Andric         if (Idx >= 16)
15480b57cec5SDimitry Andric           Idx += NumElts - 16; // end of lane, switch operand.
15490b57cec5SDimitry Andric         Idxs[l + i] = Idx + l;
15500b57cec5SDimitry Andric       }
15510b57cec5SDimitry Andric 
1552bdd1243dSDimitry Andric     Res = Builder.CreateShuffleVector(Op, Res, ArrayRef(Idxs, NumElts));
15530b57cec5SDimitry Andric   }
15540b57cec5SDimitry Andric 
15550b57cec5SDimitry Andric   // Bitcast back to a 64-bit element type.
15560b57cec5SDimitry Andric   return Builder.CreateBitCast(Res, ResultTy, "cast");
15570b57cec5SDimitry Andric }
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric static Value *getX86MaskVec(IRBuilder<> &Builder, Value *Mask,
15600b57cec5SDimitry Andric                             unsigned NumElts) {
1561e8d8bef9SDimitry Andric   assert(isPowerOf2_32(NumElts) && "Expected power-of-2 mask elements");
15625ffd83dbSDimitry Andric   llvm::VectorType *MaskTy = FixedVectorType::get(
15635ffd83dbSDimitry Andric       Builder.getInt1Ty(), cast<IntegerType>(Mask->getType())->getBitWidth());
15640b57cec5SDimitry Andric   Mask = Builder.CreateBitCast(Mask, MaskTy);
15650b57cec5SDimitry Andric 
1566e8d8bef9SDimitry Andric   // If we have less than 8 elements (1, 2 or 4), then the starting mask was an
1567e8d8bef9SDimitry Andric   // i8 and we need to extract down to the right number of elements.
1568e8d8bef9SDimitry Andric   if (NumElts <= 4) {
15695ffd83dbSDimitry Andric     int Indices[4];
15700b57cec5SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
15710b57cec5SDimitry Andric       Indices[i] = i;
1572bdd1243dSDimitry Andric     Mask = Builder.CreateShuffleVector(Mask, Mask, ArrayRef(Indices, NumElts),
1573bdd1243dSDimitry Andric                                        "extract");
15740b57cec5SDimitry Andric   }
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   return Mask;
15770b57cec5SDimitry Andric }
15780b57cec5SDimitry Andric 
15797a6dacacSDimitry Andric static Value *emitX86Select(IRBuilder<> &Builder, Value *Mask, Value *Op0,
15807a6dacacSDimitry Andric                             Value *Op1) {
15810b57cec5SDimitry Andric   // If the mask is all ones just emit the first operation.
15820b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
15830b57cec5SDimitry Andric     if (C->isAllOnesValue())
15840b57cec5SDimitry Andric       return Op0;
15850b57cec5SDimitry Andric 
15865ffd83dbSDimitry Andric   Mask = getX86MaskVec(Builder, Mask,
1587e8d8bef9SDimitry Andric                        cast<FixedVectorType>(Op0->getType())->getNumElements());
15880b57cec5SDimitry Andric   return Builder.CreateSelect(Mask, Op0, Op1);
15890b57cec5SDimitry Andric }
15900b57cec5SDimitry Andric 
15917a6dacacSDimitry Andric static Value *emitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask, Value *Op0,
15927a6dacacSDimitry Andric                                   Value *Op1) {
15930b57cec5SDimitry Andric   // If the mask is all ones just emit the first operation.
15940b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
15950b57cec5SDimitry Andric     if (C->isAllOnesValue())
15960b57cec5SDimitry Andric       return Op0;
15970b57cec5SDimitry Andric 
15985ffd83dbSDimitry Andric   auto *MaskTy = FixedVectorType::get(Builder.getInt1Ty(),
15990b57cec5SDimitry Andric                                       Mask->getType()->getIntegerBitWidth());
16000b57cec5SDimitry Andric   Mask = Builder.CreateBitCast(Mask, MaskTy);
16010b57cec5SDimitry Andric   Mask = Builder.CreateExtractElement(Mask, (uint64_t)0);
16020b57cec5SDimitry Andric   return Builder.CreateSelect(Mask, Op0, Op1);
16030b57cec5SDimitry Andric }
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric // Handle autoupgrade for masked PALIGNR and VALIGND/Q intrinsics.
16060b57cec5SDimitry Andric // PALIGNR handles large immediates by shifting while VALIGN masks the immediate
16070b57cec5SDimitry Andric // so we need to handle both cases. VALIGN also doesn't have 128-bit lanes.
16087a6dacacSDimitry Andric static Value *upgradeX86ALIGNIntrinsics(IRBuilder<> &Builder, Value *Op0,
16090b57cec5SDimitry Andric                                         Value *Op1, Value *Shift,
16100b57cec5SDimitry Andric                                         Value *Passthru, Value *Mask,
16110b57cec5SDimitry Andric                                         bool IsVALIGN) {
16120b57cec5SDimitry Andric   unsigned ShiftVal = cast<llvm::ConstantInt>(Shift)->getZExtValue();
16130b57cec5SDimitry Andric 
1614e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
16150b57cec5SDimitry Andric   assert((IsVALIGN || NumElts % 16 == 0) && "Illegal NumElts for PALIGNR!");
16160b57cec5SDimitry Andric   assert((!IsVALIGN || NumElts <= 16) && "NumElts too large for VALIGN!");
16170b57cec5SDimitry Andric   assert(isPowerOf2_32(NumElts) && "NumElts not a power of 2!");
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric   // Mask the immediate for VALIGN.
16200b57cec5SDimitry Andric   if (IsVALIGN)
16210b57cec5SDimitry Andric     ShiftVal &= (NumElts - 1);
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric   // If palignr is shifting the pair of vectors more than the size of two
16240b57cec5SDimitry Andric   // lanes, emit zero.
16250b57cec5SDimitry Andric   if (ShiftVal >= 32)
16260b57cec5SDimitry Andric     return llvm::Constant::getNullValue(Op0->getType());
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric   // If palignr is shifting the pair of input vectors more than one lane,
16290b57cec5SDimitry Andric   // but less than two lanes, convert to shifting in zeroes.
16300b57cec5SDimitry Andric   if (ShiftVal > 16) {
16310b57cec5SDimitry Andric     ShiftVal -= 16;
16320b57cec5SDimitry Andric     Op1 = Op0;
16330b57cec5SDimitry Andric     Op0 = llvm::Constant::getNullValue(Op0->getType());
16340b57cec5SDimitry Andric   }
16350b57cec5SDimitry Andric 
16365ffd83dbSDimitry Andric   int Indices[64];
16370b57cec5SDimitry Andric   // 256-bit palignr operates on 128-bit lanes so we need to handle that
16380b57cec5SDimitry Andric   for (unsigned l = 0; l < NumElts; l += 16) {
16390b57cec5SDimitry Andric     for (unsigned i = 0; i != 16; ++i) {
16400b57cec5SDimitry Andric       unsigned Idx = ShiftVal + i;
16410b57cec5SDimitry Andric       if (!IsVALIGN && Idx >= 16) // Disable wrap for VALIGN.
16420b57cec5SDimitry Andric         Idx += NumElts - 16; // End of lane, switch operand.
16430b57cec5SDimitry Andric       Indices[l + i] = Idx + l;
16440b57cec5SDimitry Andric     }
16450b57cec5SDimitry Andric   }
16460b57cec5SDimitry Andric 
1647bdd1243dSDimitry Andric   Value *Align = Builder.CreateShuffleVector(
1648bdd1243dSDimitry Andric       Op1, Op0, ArrayRef(Indices, NumElts), "palignr");
16490b57cec5SDimitry Andric 
16507a6dacacSDimitry Andric   return emitX86Select(Builder, Mask, Align, Passthru);
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric 
16537a6dacacSDimitry Andric static Value *upgradeX86VPERMT2Intrinsics(IRBuilder<> &Builder, CallBase &CI,
16540b57cec5SDimitry Andric                                           bool ZeroMask, bool IndexForm) {
16550b57cec5SDimitry Andric   Type *Ty = CI.getType();
16560b57cec5SDimitry Andric   unsigned VecWidth = Ty->getPrimitiveSizeInBits();
16570b57cec5SDimitry Andric   unsigned EltWidth = Ty->getScalarSizeInBits();
16580b57cec5SDimitry Andric   bool IsFloat = Ty->isFPOrFPVectorTy();
16590b57cec5SDimitry Andric   Intrinsic::ID IID;
16600b57cec5SDimitry Andric   if (VecWidth == 128 && EltWidth == 32 && IsFloat)
16610b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_128;
16620b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 32 && !IsFloat)
16630b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_128;
16640b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 64 && IsFloat)
16650b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_128;
16660b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 64 && !IsFloat)
16670b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_128;
16680b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 32 && IsFloat)
16690b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_256;
16700b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
16710b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_256;
16720b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
16730b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_256;
16740b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
16750b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_256;
16760b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
16770b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_ps_512;
16780b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
16790b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_d_512;
16800b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
16810b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_pd_512;
16820b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
16830b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_q_512;
16840b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 16)
16850b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_128;
16860b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 16)
16870b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_256;
16880b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 16)
16890b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_hi_512;
16900b57cec5SDimitry Andric   else if (VecWidth == 128 && EltWidth == 8)
16910b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_128;
16920b57cec5SDimitry Andric   else if (VecWidth == 256 && EltWidth == 8)
16930b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_256;
16940b57cec5SDimitry Andric   else if (VecWidth == 512 && EltWidth == 8)
16950b57cec5SDimitry Andric     IID = Intrinsic::x86_avx512_vpermi2var_qi_512;
16960b57cec5SDimitry Andric   else
16970b57cec5SDimitry Andric     llvm_unreachable("Unexpected intrinsic");
16980b57cec5SDimitry Andric 
16990b57cec5SDimitry Andric   Value *Args[] = { CI.getArgOperand(0) , CI.getArgOperand(1),
17000b57cec5SDimitry Andric                     CI.getArgOperand(2) };
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric   // If this isn't index form we need to swap operand 0 and 1.
17030b57cec5SDimitry Andric   if (!IndexForm)
17040b57cec5SDimitry Andric     std::swap(Args[0], Args[1]);
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   Value *V = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
17070b57cec5SDimitry Andric                                 Args);
17080b57cec5SDimitry Andric   Value *PassThru = ZeroMask ? ConstantAggregateZero::get(Ty)
17090b57cec5SDimitry Andric                              : Builder.CreateBitCast(CI.getArgOperand(1),
17100b57cec5SDimitry Andric                                                      Ty);
17117a6dacacSDimitry Andric   return emitX86Select(Builder, CI.getArgOperand(3), V, PassThru);
17120b57cec5SDimitry Andric }
17130b57cec5SDimitry Andric 
17147a6dacacSDimitry Andric static Value *upgradeX86BinaryIntrinsics(IRBuilder<> &Builder, CallBase &CI,
1715e8d8bef9SDimitry Andric                                          Intrinsic::ID IID) {
17160b57cec5SDimitry Andric   Type *Ty = CI.getType();
17170b57cec5SDimitry Andric   Value *Op0 = CI.getOperand(0);
17180b57cec5SDimitry Andric   Value *Op1 = CI.getOperand(1);
17190b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
17200b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Op0, Op1});
17210b57cec5SDimitry Andric 
1722349cc55cSDimitry Andric   if (CI.arg_size() == 4) { // For masked intrinsics.
17230b57cec5SDimitry Andric     Value *VecSrc = CI.getOperand(2);
17240b57cec5SDimitry Andric     Value *Mask = CI.getOperand(3);
17257a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
17260b57cec5SDimitry Andric   }
17270b57cec5SDimitry Andric   return Res;
17280b57cec5SDimitry Andric }
17290b57cec5SDimitry Andric 
173081ad6265SDimitry Andric static Value *upgradeX86Rotate(IRBuilder<> &Builder, CallBase &CI,
17310b57cec5SDimitry Andric                                bool IsRotateRight) {
17320b57cec5SDimitry Andric   Type *Ty = CI.getType();
17330b57cec5SDimitry Andric   Value *Src = CI.getArgOperand(0);
17340b57cec5SDimitry Andric   Value *Amt = CI.getArgOperand(1);
17350b57cec5SDimitry Andric 
17360b57cec5SDimitry Andric   // Amount may be scalar immediate, in which case create a splat vector.
17370b57cec5SDimitry Andric   // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
17380b57cec5SDimitry Andric   // we only care about the lowest log2 bits anyway.
17390b57cec5SDimitry Andric   if (Amt->getType() != Ty) {
1740e8d8bef9SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
17410b57cec5SDimitry Andric     Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
17420b57cec5SDimitry Andric     Amt = Builder.CreateVectorSplat(NumElts, Amt);
17430b57cec5SDimitry Andric   }
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric   Intrinsic::ID IID = IsRotateRight ? Intrinsic::fshr : Intrinsic::fshl;
17460b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
17470b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Src, Src, Amt});
17480b57cec5SDimitry Andric 
1749349cc55cSDimitry Andric   if (CI.arg_size() == 4) { // For masked intrinsics.
17500b57cec5SDimitry Andric     Value *VecSrc = CI.getOperand(2);
17510b57cec5SDimitry Andric     Value *Mask = CI.getOperand(3);
17527a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
17530b57cec5SDimitry Andric   }
17540b57cec5SDimitry Andric   return Res;
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric 
175781ad6265SDimitry Andric static Value *upgradeX86vpcom(IRBuilder<> &Builder, CallBase &CI, unsigned Imm,
17580b57cec5SDimitry Andric                               bool IsSigned) {
17590b57cec5SDimitry Andric   Type *Ty = CI.getType();
17600b57cec5SDimitry Andric   Value *LHS = CI.getArgOperand(0);
17610b57cec5SDimitry Andric   Value *RHS = CI.getArgOperand(1);
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric   CmpInst::Predicate Pred;
17640b57cec5SDimitry Andric   switch (Imm) {
17650b57cec5SDimitry Andric   case 0x0:
17660b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
17670b57cec5SDimitry Andric     break;
17680b57cec5SDimitry Andric   case 0x1:
17690b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
17700b57cec5SDimitry Andric     break;
17710b57cec5SDimitry Andric   case 0x2:
17720b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
17730b57cec5SDimitry Andric     break;
17740b57cec5SDimitry Andric   case 0x3:
17750b57cec5SDimitry Andric     Pred = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
17760b57cec5SDimitry Andric     break;
17770b57cec5SDimitry Andric   case 0x4:
17780b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_EQ;
17790b57cec5SDimitry Andric     break;
17800b57cec5SDimitry Andric   case 0x5:
17810b57cec5SDimitry Andric     Pred = ICmpInst::ICMP_NE;
17820b57cec5SDimitry Andric     break;
17830b57cec5SDimitry Andric   case 0x6:
17840b57cec5SDimitry Andric     return Constant::getNullValue(Ty); // FALSE
17850b57cec5SDimitry Andric   case 0x7:
17860b57cec5SDimitry Andric     return Constant::getAllOnesValue(Ty); // TRUE
17870b57cec5SDimitry Andric   default:
17880b57cec5SDimitry Andric     llvm_unreachable("Unknown XOP vpcom/vpcomu predicate");
17890b57cec5SDimitry Andric   }
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   Value *Cmp = Builder.CreateICmp(Pred, LHS, RHS);
17920b57cec5SDimitry Andric   Value *Ext = Builder.CreateSExt(Cmp, Ty);
17930b57cec5SDimitry Andric   return Ext;
17940b57cec5SDimitry Andric }
17950b57cec5SDimitry Andric 
179681ad6265SDimitry Andric static Value *upgradeX86ConcatShift(IRBuilder<> &Builder, CallBase &CI,
17970b57cec5SDimitry Andric                                     bool IsShiftRight, bool ZeroMask) {
17980b57cec5SDimitry Andric   Type *Ty = CI.getType();
17990b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
18000b57cec5SDimitry Andric   Value *Op1 = CI.getArgOperand(1);
18010b57cec5SDimitry Andric   Value *Amt = CI.getArgOperand(2);
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   if (IsShiftRight)
18040b57cec5SDimitry Andric     std::swap(Op0, Op1);
18050b57cec5SDimitry Andric 
18060b57cec5SDimitry Andric   // Amount may be scalar immediate, in which case create a splat vector.
18070b57cec5SDimitry Andric   // Funnel shifts amounts are treated as modulo and types are all power-of-2 so
18080b57cec5SDimitry Andric   // we only care about the lowest log2 bits anyway.
18090b57cec5SDimitry Andric   if (Amt->getType() != Ty) {
1810e8d8bef9SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(Ty)->getNumElements();
18110b57cec5SDimitry Andric     Amt = Builder.CreateIntCast(Amt, Ty->getScalarType(), false);
18120b57cec5SDimitry Andric     Amt = Builder.CreateVectorSplat(NumElts, Amt);
18130b57cec5SDimitry Andric   }
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric   Intrinsic::ID IID = IsShiftRight ? Intrinsic::fshr : Intrinsic::fshl;
18160b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty);
18170b57cec5SDimitry Andric   Value *Res = Builder.CreateCall(Intrin, {Op0, Op1, Amt});
18180b57cec5SDimitry Andric 
1819349cc55cSDimitry Andric   unsigned NumArgs = CI.arg_size();
18200b57cec5SDimitry Andric   if (NumArgs >= 4) { // For masked intrinsics.
18210b57cec5SDimitry Andric     Value *VecSrc = NumArgs == 5 ? CI.getArgOperand(3) :
18220b57cec5SDimitry Andric                     ZeroMask     ? ConstantAggregateZero::get(CI.getType()) :
18230b57cec5SDimitry Andric                                    CI.getArgOperand(0);
18240b57cec5SDimitry Andric     Value *Mask = CI.getOperand(NumArgs - 1);
18257a6dacacSDimitry Andric     Res = emitX86Select(Builder, Mask, Res, VecSrc);
18260b57cec5SDimitry Andric   }
18270b57cec5SDimitry Andric   return Res;
18280b57cec5SDimitry Andric }
18290b57cec5SDimitry Andric 
18307a6dacacSDimitry Andric static Value *upgradeMaskedStore(IRBuilder<> &Builder, Value *Ptr, Value *Data,
18317a6dacacSDimitry Andric                                  Value *Mask, bool Aligned) {
18320b57cec5SDimitry Andric   // Cast the pointer to the right type.
18330b57cec5SDimitry Andric   Ptr = Builder.CreateBitCast(Ptr,
18340b57cec5SDimitry Andric                               llvm::PointerType::getUnqual(Data->getType()));
18355ffd83dbSDimitry Andric   const Align Alignment =
18365ffd83dbSDimitry Andric       Aligned
1837bdd1243dSDimitry Andric           ? Align(Data->getType()->getPrimitiveSizeInBits().getFixedValue() / 8)
18385ffd83dbSDimitry Andric           : Align(1);
18390b57cec5SDimitry Andric 
18400b57cec5SDimitry Andric   // If the mask is all ones just emit a regular store.
18410b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
18420b57cec5SDimitry Andric     if (C->isAllOnesValue())
18435ffd83dbSDimitry Andric       return Builder.CreateAlignedStore(Data, Ptr, Alignment);
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric   // Convert the mask from an integer type to a vector of i1.
1846e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Data->getType())->getNumElements();
18470b57cec5SDimitry Andric   Mask = getX86MaskVec(Builder, Mask, NumElts);
18485ffd83dbSDimitry Andric   return Builder.CreateMaskedStore(Data, Ptr, Alignment, Mask);
18490b57cec5SDimitry Andric }
18500b57cec5SDimitry Andric 
18517a6dacacSDimitry Andric static Value *upgradeMaskedLoad(IRBuilder<> &Builder, Value *Ptr,
18527a6dacacSDimitry Andric                                 Value *Passthru, Value *Mask, bool Aligned) {
18530b57cec5SDimitry Andric   Type *ValTy = Passthru->getType();
18540b57cec5SDimitry Andric   // Cast the pointer to the right type.
18550b57cec5SDimitry Andric   Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(ValTy));
18565ffd83dbSDimitry Andric   const Align Alignment =
18575ffd83dbSDimitry Andric       Aligned
1858bdd1243dSDimitry Andric           ? Align(
1859bdd1243dSDimitry Andric                 Passthru->getType()->getPrimitiveSizeInBits().getFixedValue() /
18605ffd83dbSDimitry Andric                 8)
18615ffd83dbSDimitry Andric           : Align(1);
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   // If the mask is all ones just emit a regular store.
18640b57cec5SDimitry Andric   if (const auto *C = dyn_cast<Constant>(Mask))
18650b57cec5SDimitry Andric     if (C->isAllOnesValue())
18665ffd83dbSDimitry Andric       return Builder.CreateAlignedLoad(ValTy, Ptr, Alignment);
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric   // Convert the mask from an integer type to a vector of i1.
1869fe6060f1SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(ValTy)->getNumElements();
18700b57cec5SDimitry Andric   Mask = getX86MaskVec(Builder, Mask, NumElts);
1871fe6060f1SDimitry Andric   return Builder.CreateMaskedLoad(ValTy, Ptr, Alignment, Mask, Passthru);
18720b57cec5SDimitry Andric }
18730b57cec5SDimitry Andric 
187481ad6265SDimitry Andric static Value *upgradeAbs(IRBuilder<> &Builder, CallBase &CI) {
1875e8d8bef9SDimitry Andric   Type *Ty = CI.getType();
18760b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
1877e8d8bef9SDimitry Andric   Function *F = Intrinsic::getDeclaration(CI.getModule(), Intrinsic::abs, Ty);
1878e8d8bef9SDimitry Andric   Value *Res = Builder.CreateCall(F, {Op0, Builder.getInt1(false)});
1879349cc55cSDimitry Andric   if (CI.arg_size() == 3)
18807a6dacacSDimitry Andric     Res = emitX86Select(Builder, CI.getArgOperand(2), Res, CI.getArgOperand(1));
18810b57cec5SDimitry Andric   return Res;
18820b57cec5SDimitry Andric }
18830b57cec5SDimitry Andric 
188481ad6265SDimitry Andric static Value *upgradePMULDQ(IRBuilder<> &Builder, CallBase &CI, bool IsSigned) {
18850b57cec5SDimitry Andric   Type *Ty = CI.getType();
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric   // Arguments have a vXi32 type so cast to vXi64.
18880b57cec5SDimitry Andric   Value *LHS = Builder.CreateBitCast(CI.getArgOperand(0), Ty);
18890b57cec5SDimitry Andric   Value *RHS = Builder.CreateBitCast(CI.getArgOperand(1), Ty);
18900b57cec5SDimitry Andric 
18910b57cec5SDimitry Andric   if (IsSigned) {
18920b57cec5SDimitry Andric     // Shift left then arithmetic shift right.
18930b57cec5SDimitry Andric     Constant *ShiftAmt = ConstantInt::get(Ty, 32);
18940b57cec5SDimitry Andric     LHS = Builder.CreateShl(LHS, ShiftAmt);
18950b57cec5SDimitry Andric     LHS = Builder.CreateAShr(LHS, ShiftAmt);
18960b57cec5SDimitry Andric     RHS = Builder.CreateShl(RHS, ShiftAmt);
18970b57cec5SDimitry Andric     RHS = Builder.CreateAShr(RHS, ShiftAmt);
18980b57cec5SDimitry Andric   } else {
18990b57cec5SDimitry Andric     // Clear the upper bits.
19000b57cec5SDimitry Andric     Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
19010b57cec5SDimitry Andric     LHS = Builder.CreateAnd(LHS, Mask);
19020b57cec5SDimitry Andric     RHS = Builder.CreateAnd(RHS, Mask);
19030b57cec5SDimitry Andric   }
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric   Value *Res = Builder.CreateMul(LHS, RHS);
19060b57cec5SDimitry Andric 
1907349cc55cSDimitry Andric   if (CI.arg_size() == 4)
19087a6dacacSDimitry Andric     Res = emitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2));
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   return Res;
19110b57cec5SDimitry Andric }
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric // Applying mask on vector of i1's and make sure result is at least 8 bits wide.
19147a6dacacSDimitry Andric static Value *applyX86MaskOn1BitsVec(IRBuilder<> &Builder, Value *Vec,
19150b57cec5SDimitry Andric                                      Value *Mask) {
1916e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
19170b57cec5SDimitry Andric   if (Mask) {
19180b57cec5SDimitry Andric     const auto *C = dyn_cast<Constant>(Mask);
19190b57cec5SDimitry Andric     if (!C || !C->isAllOnesValue())
19200b57cec5SDimitry Andric       Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
19210b57cec5SDimitry Andric   }
19220b57cec5SDimitry Andric 
19230b57cec5SDimitry Andric   if (NumElts < 8) {
19245ffd83dbSDimitry Andric     int Indices[8];
19250b57cec5SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
19260b57cec5SDimitry Andric       Indices[i] = i;
19270b57cec5SDimitry Andric     for (unsigned i = NumElts; i != 8; ++i)
19280b57cec5SDimitry Andric       Indices[i] = NumElts + i % NumElts;
19290b57cec5SDimitry Andric     Vec = Builder.CreateShuffleVector(Vec,
19300b57cec5SDimitry Andric                                       Constant::getNullValue(Vec->getType()),
19310b57cec5SDimitry Andric                                       Indices);
19320b57cec5SDimitry Andric   }
19330b57cec5SDimitry Andric   return Builder.CreateBitCast(Vec, Builder.getIntNTy(std::max(NumElts, 8U)));
19340b57cec5SDimitry Andric }
19350b57cec5SDimitry Andric 
193681ad6265SDimitry Andric static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallBase &CI,
19370b57cec5SDimitry Andric                                    unsigned CC, bool Signed) {
19380b57cec5SDimitry Andric   Value *Op0 = CI.getArgOperand(0);
1939e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(Op0->getType())->getNumElements();
19400b57cec5SDimitry Andric 
19410b57cec5SDimitry Andric   Value *Cmp;
19420b57cec5SDimitry Andric   if (CC == 3) {
19435ffd83dbSDimitry Andric     Cmp = Constant::getNullValue(
19445ffd83dbSDimitry Andric         FixedVectorType::get(Builder.getInt1Ty(), NumElts));
19450b57cec5SDimitry Andric   } else if (CC == 7) {
19465ffd83dbSDimitry Andric     Cmp = Constant::getAllOnesValue(
19475ffd83dbSDimitry Andric         FixedVectorType::get(Builder.getInt1Ty(), NumElts));
19480b57cec5SDimitry Andric   } else {
19490b57cec5SDimitry Andric     ICmpInst::Predicate Pred;
19500b57cec5SDimitry Andric     switch (CC) {
19510b57cec5SDimitry Andric     default: llvm_unreachable("Unknown condition code");
19520b57cec5SDimitry Andric     case 0: Pred = ICmpInst::ICMP_EQ;  break;
19530b57cec5SDimitry Andric     case 1: Pred = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break;
19540b57cec5SDimitry Andric     case 2: Pred = Signed ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break;
19550b57cec5SDimitry Andric     case 4: Pred = ICmpInst::ICMP_NE;  break;
19560b57cec5SDimitry Andric     case 5: Pred = Signed ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break;
19570b57cec5SDimitry Andric     case 6: Pred = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break;
19580b57cec5SDimitry Andric     }
19590b57cec5SDimitry Andric     Cmp = Builder.CreateICmp(Pred, Op0, CI.getArgOperand(1));
19600b57cec5SDimitry Andric   }
19610b57cec5SDimitry Andric 
1962349cc55cSDimitry Andric   Value *Mask = CI.getArgOperand(CI.arg_size() - 1);
19630b57cec5SDimitry Andric 
19647a6dacacSDimitry Andric   return applyX86MaskOn1BitsVec(Builder, Cmp, Mask);
19650b57cec5SDimitry Andric }
19660b57cec5SDimitry Andric 
19670b57cec5SDimitry Andric // Replace a masked intrinsic with an older unmasked intrinsic.
19687a6dacacSDimitry Andric static Value *upgradeX86MaskedShift(IRBuilder<> &Builder, CallBase &CI,
19690b57cec5SDimitry Andric                                     Intrinsic::ID IID) {
19700b57cec5SDimitry Andric   Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID);
19710b57cec5SDimitry Andric   Value *Rep = Builder.CreateCall(Intrin,
19720b57cec5SDimitry Andric                                  { CI.getArgOperand(0), CI.getArgOperand(1) });
19737a6dacacSDimitry Andric   return emitX86Select(Builder, CI.getArgOperand(3), Rep, CI.getArgOperand(2));
19740b57cec5SDimitry Andric }
19750b57cec5SDimitry Andric 
197681ad6265SDimitry Andric static Value *upgradeMaskedMove(IRBuilder<> &Builder, CallBase &CI) {
19770b57cec5SDimitry Andric   Value* A = CI.getArgOperand(0);
19780b57cec5SDimitry Andric   Value* B = CI.getArgOperand(1);
19790b57cec5SDimitry Andric   Value* Src = CI.getArgOperand(2);
19800b57cec5SDimitry Andric   Value* Mask = CI.getArgOperand(3);
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric   Value* AndNode = Builder.CreateAnd(Mask, APInt(8, 1));
19830b57cec5SDimitry Andric   Value* Cmp = Builder.CreateIsNotNull(AndNode);
19840b57cec5SDimitry Andric   Value* Extract1 = Builder.CreateExtractElement(B, (uint64_t)0);
19850b57cec5SDimitry Andric   Value* Extract2 = Builder.CreateExtractElement(Src, (uint64_t)0);
19860b57cec5SDimitry Andric   Value* Select = Builder.CreateSelect(Cmp, Extract1, Extract2);
19870b57cec5SDimitry Andric   return Builder.CreateInsertElement(A, Select, (uint64_t)0);
19880b57cec5SDimitry Andric }
19890b57cec5SDimitry Andric 
19907a6dacacSDimitry Andric static Value *upgradeMaskToInt(IRBuilder<> &Builder, CallBase &CI) {
19910b57cec5SDimitry Andric   Value* Op = CI.getArgOperand(0);
19920b57cec5SDimitry Andric   Type* ReturnOp = CI.getType();
1993e8d8bef9SDimitry Andric   unsigned NumElts = cast<FixedVectorType>(CI.getType())->getNumElements();
19940b57cec5SDimitry Andric   Value *Mask = getX86MaskVec(Builder, Op, NumElts);
19950b57cec5SDimitry Andric   return Builder.CreateSExt(Mask, ReturnOp, "vpmovm2");
19960b57cec5SDimitry Andric }
19970b57cec5SDimitry Andric 
19980b57cec5SDimitry Andric // Replace intrinsic with unmasked version and a select.
19990b57cec5SDimitry Andric static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder,
200081ad6265SDimitry Andric                                       CallBase &CI, Value *&Rep) {
20010b57cec5SDimitry Andric   Name = Name.substr(12); // Remove avx512.mask.
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric   unsigned VecWidth = CI.getType()->getPrimitiveSizeInBits();
20040b57cec5SDimitry Andric   unsigned EltWidth = CI.getType()->getScalarSizeInBits();
20050b57cec5SDimitry Andric   Intrinsic::ID IID;
20065f757f3fSDimitry Andric   if (Name.starts_with("max.p")) {
20070b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
20080b57cec5SDimitry Andric       IID = Intrinsic::x86_sse_max_ps;
20090b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
20100b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_max_pd;
20110b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
20120b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_max_ps_256;
20130b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
20140b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_max_pd_256;
20150b57cec5SDimitry Andric     else
20160b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20175f757f3fSDimitry Andric   } else if (Name.starts_with("min.p")) {
20180b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
20190b57cec5SDimitry Andric       IID = Intrinsic::x86_sse_min_ps;
20200b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
20210b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_min_pd;
20220b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
20230b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_min_ps_256;
20240b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
20250b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_min_pd_256;
20260b57cec5SDimitry Andric     else
20270b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20285f757f3fSDimitry Andric   } else if (Name.starts_with("pshuf.b.")) {
20290b57cec5SDimitry Andric     if (VecWidth == 128)
20300b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pshuf_b_128;
20310b57cec5SDimitry Andric     else if (VecWidth == 256)
20320b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pshuf_b;
20330b57cec5SDimitry Andric     else if (VecWidth == 512)
20340b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pshuf_b_512;
20350b57cec5SDimitry Andric     else
20360b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20375f757f3fSDimitry Andric   } else if (Name.starts_with("pmul.hr.sw.")) {
20380b57cec5SDimitry Andric     if (VecWidth == 128)
20390b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pmul_hr_sw_128;
20400b57cec5SDimitry Andric     else if (VecWidth == 256)
20410b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmul_hr_sw;
20420b57cec5SDimitry Andric     else if (VecWidth == 512)
20430b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmul_hr_sw_512;
20440b57cec5SDimitry Andric     else
20450b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20465f757f3fSDimitry Andric   } else if (Name.starts_with("pmulh.w.")) {
20470b57cec5SDimitry Andric     if (VecWidth == 128)
20480b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmulh_w;
20490b57cec5SDimitry Andric     else if (VecWidth == 256)
20500b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmulh_w;
20510b57cec5SDimitry Andric     else if (VecWidth == 512)
20520b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmulh_w_512;
20530b57cec5SDimitry Andric     else
20540b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20555f757f3fSDimitry Andric   } else if (Name.starts_with("pmulhu.w.")) {
20560b57cec5SDimitry Andric     if (VecWidth == 128)
20570b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmulhu_w;
20580b57cec5SDimitry Andric     else if (VecWidth == 256)
20590b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmulhu_w;
20600b57cec5SDimitry Andric     else if (VecWidth == 512)
20610b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmulhu_w_512;
20620b57cec5SDimitry Andric     else
20630b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20645f757f3fSDimitry Andric   } else if (Name.starts_with("pmaddw.d.")) {
20650b57cec5SDimitry Andric     if (VecWidth == 128)
20660b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pmadd_wd;
20670b57cec5SDimitry Andric     else if (VecWidth == 256)
20680b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmadd_wd;
20690b57cec5SDimitry Andric     else if (VecWidth == 512)
20700b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmaddw_d_512;
20710b57cec5SDimitry Andric     else
20720b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20735f757f3fSDimitry Andric   } else if (Name.starts_with("pmaddubs.w.")) {
20740b57cec5SDimitry Andric     if (VecWidth == 128)
20750b57cec5SDimitry Andric       IID = Intrinsic::x86_ssse3_pmadd_ub_sw_128;
20760b57cec5SDimitry Andric     else if (VecWidth == 256)
20770b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pmadd_ub_sw;
20780b57cec5SDimitry Andric     else if (VecWidth == 512)
20790b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmaddubs_w_512;
20800b57cec5SDimitry Andric     else
20810b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20825f757f3fSDimitry Andric   } else if (Name.starts_with("packsswb.")) {
20830b57cec5SDimitry Andric     if (VecWidth == 128)
20840b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packsswb_128;
20850b57cec5SDimitry Andric     else if (VecWidth == 256)
20860b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packsswb;
20870b57cec5SDimitry Andric     else if (VecWidth == 512)
20880b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packsswb_512;
20890b57cec5SDimitry Andric     else
20900b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
20915f757f3fSDimitry Andric   } else if (Name.starts_with("packssdw.")) {
20920b57cec5SDimitry Andric     if (VecWidth == 128)
20930b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packssdw_128;
20940b57cec5SDimitry Andric     else if (VecWidth == 256)
20950b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packssdw;
20960b57cec5SDimitry Andric     else if (VecWidth == 512)
20970b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packssdw_512;
20980b57cec5SDimitry Andric     else
20990b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21005f757f3fSDimitry Andric   } else if (Name.starts_with("packuswb.")) {
21010b57cec5SDimitry Andric     if (VecWidth == 128)
21020b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_packuswb_128;
21030b57cec5SDimitry Andric     else if (VecWidth == 256)
21040b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packuswb;
21050b57cec5SDimitry Andric     else if (VecWidth == 512)
21060b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packuswb_512;
21070b57cec5SDimitry Andric     else
21080b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21095f757f3fSDimitry Andric   } else if (Name.starts_with("packusdw.")) {
21100b57cec5SDimitry Andric     if (VecWidth == 128)
21110b57cec5SDimitry Andric       IID = Intrinsic::x86_sse41_packusdw;
21120b57cec5SDimitry Andric     else if (VecWidth == 256)
21130b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_packusdw;
21140b57cec5SDimitry Andric     else if (VecWidth == 512)
21150b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_packusdw_512;
21160b57cec5SDimitry Andric     else
21170b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21185f757f3fSDimitry Andric   } else if (Name.starts_with("vpermilvar.")) {
21190b57cec5SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
21200b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_ps;
21210b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
21220b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_pd;
21230b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
21240b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_ps_256;
21250b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
21260b57cec5SDimitry Andric       IID = Intrinsic::x86_avx_vpermilvar_pd_256;
21270b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32)
21280b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
21290b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64)
21300b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
21310b57cec5SDimitry Andric     else
21320b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21330b57cec5SDimitry Andric   } else if (Name == "cvtpd2dq.256") {
21340b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvt_pd2dq_256;
21350b57cec5SDimitry Andric   } else if (Name == "cvtpd2ps.256") {
21360b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvt_pd2_ps_256;
21370b57cec5SDimitry Andric   } else if (Name == "cvttpd2dq.256") {
21380b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvtt_pd2dq_256;
21390b57cec5SDimitry Andric   } else if (Name == "cvttps2dq.128") {
21400b57cec5SDimitry Andric     IID = Intrinsic::x86_sse2_cvttps2dq;
21410b57cec5SDimitry Andric   } else if (Name == "cvttps2dq.256") {
21420b57cec5SDimitry Andric     IID = Intrinsic::x86_avx_cvtt_ps2dq_256;
21435f757f3fSDimitry Andric   } else if (Name.starts_with("permvar.")) {
21440b57cec5SDimitry Andric     bool IsFloat = CI.getType()->isFPOrFPVectorTy();
21450b57cec5SDimitry Andric     if (VecWidth == 256 && EltWidth == 32 && IsFloat)
21460b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_permps;
21470b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
21480b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_permd;
21490b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
21500b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_df_256;
21510b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
21520b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_di_256;
21530b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
21540b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_sf_512;
21550b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
21560b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_si_512;
21570b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
21580b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_df_512;
21590b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
21600b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_di_512;
21610b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 16)
21620b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_128;
21630b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 16)
21640b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_256;
21650b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 16)
21660b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_hi_512;
21670b57cec5SDimitry Andric     else if (VecWidth == 128 && EltWidth == 8)
21680b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_128;
21690b57cec5SDimitry Andric     else if (VecWidth == 256 && EltWidth == 8)
21700b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_256;
21710b57cec5SDimitry Andric     else if (VecWidth == 512 && EltWidth == 8)
21720b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_permvar_qi_512;
21730b57cec5SDimitry Andric     else
21740b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21755f757f3fSDimitry Andric   } else if (Name.starts_with("dbpsadbw.")) {
21760b57cec5SDimitry Andric     if (VecWidth == 128)
21770b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_128;
21780b57cec5SDimitry Andric     else if (VecWidth == 256)
21790b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_256;
21800b57cec5SDimitry Andric     else if (VecWidth == 512)
21810b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_dbpsadbw_512;
21820b57cec5SDimitry Andric     else
21830b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21845f757f3fSDimitry Andric   } else if (Name.starts_with("pmultishift.qb.")) {
21850b57cec5SDimitry Andric     if (VecWidth == 128)
21860b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_128;
21870b57cec5SDimitry Andric     else if (VecWidth == 256)
21880b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_256;
21890b57cec5SDimitry Andric     else if (VecWidth == 512)
21900b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pmultishift_qb_512;
21910b57cec5SDimitry Andric     else
21920b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
21935f757f3fSDimitry Andric   } else if (Name.starts_with("conflict.")) {
21940b57cec5SDimitry Andric     if (Name[9] == 'd' && VecWidth == 128)
21950b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_128;
21960b57cec5SDimitry Andric     else if (Name[9] == 'd' && VecWidth == 256)
21970b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_256;
21980b57cec5SDimitry Andric     else if (Name[9] == 'd' && VecWidth == 512)
21990b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_d_512;
22000b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 128)
22010b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_128;
22020b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 256)
22030b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_256;
22040b57cec5SDimitry Andric     else if (Name[9] == 'q' && VecWidth == 512)
22050b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_conflict_q_512;
22060b57cec5SDimitry Andric     else
22070b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
22085f757f3fSDimitry Andric   } else if (Name.starts_with("pavg.")) {
22090b57cec5SDimitry Andric     if (Name[5] == 'b' && VecWidth == 128)
22100b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pavg_b;
22110b57cec5SDimitry Andric     else if (Name[5] == 'b' && VecWidth == 256)
22120b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pavg_b;
22130b57cec5SDimitry Andric     else if (Name[5] == 'b' && VecWidth == 512)
22140b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pavg_b_512;
22150b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 128)
22160b57cec5SDimitry Andric       IID = Intrinsic::x86_sse2_pavg_w;
22170b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 256)
22180b57cec5SDimitry Andric       IID = Intrinsic::x86_avx2_pavg_w;
22190b57cec5SDimitry Andric     else if (Name[5] == 'w' && VecWidth == 512)
22200b57cec5SDimitry Andric       IID = Intrinsic::x86_avx512_pavg_w_512;
22210b57cec5SDimitry Andric     else
22220b57cec5SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
22230b57cec5SDimitry Andric   } else
22240b57cec5SDimitry Andric     return false;
22250b57cec5SDimitry Andric 
2226349cc55cSDimitry Andric   SmallVector<Value *, 4> Args(CI.args());
22270b57cec5SDimitry Andric   Args.pop_back();
22280b57cec5SDimitry Andric   Args.pop_back();
22290b57cec5SDimitry Andric   Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
22300b57cec5SDimitry Andric                            Args);
2231349cc55cSDimitry Andric   unsigned NumArgs = CI.arg_size();
22327a6dacacSDimitry Andric   Rep = emitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep,
22330b57cec5SDimitry Andric                       CI.getArgOperand(NumArgs - 2));
22340b57cec5SDimitry Andric   return true;
22350b57cec5SDimitry Andric }
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric /// Upgrade comment in call to inline asm that represents an objc retain release
22380b57cec5SDimitry Andric /// marker.
22390b57cec5SDimitry Andric void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
22400b57cec5SDimitry Andric   size_t Pos;
22410b57cec5SDimitry Andric   if (AsmStr->find("mov\tfp") == 0 &&
22420b57cec5SDimitry Andric       AsmStr->find("objc_retainAutoreleaseReturnValue") != std::string::npos &&
22430b57cec5SDimitry Andric       (Pos = AsmStr->find("# marker")) != std::string::npos) {
22440b57cec5SDimitry Andric     AsmStr->replace(Pos, 1, ";");
22450b57cec5SDimitry Andric   }
22460b57cec5SDimitry Andric }
22470b57cec5SDimitry Andric 
2248*0fca6ea1SDimitry Andric static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
2249*0fca6ea1SDimitry Andric                                       IRBuilder<> &Builder) {
2250*0fca6ea1SDimitry Andric   LLVMContext &C = F->getContext();
2251*0fca6ea1SDimitry Andric   Value *Rep = nullptr;
2252*0fca6ea1SDimitry Andric 
2253*0fca6ea1SDimitry Andric   if (Name.starts_with("sse4a.movnt.")) {
2254*0fca6ea1SDimitry Andric     SmallVector<Metadata *, 1> Elts;
2255*0fca6ea1SDimitry Andric     Elts.push_back(
2256*0fca6ea1SDimitry Andric         ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
2257*0fca6ea1SDimitry Andric     MDNode *Node = MDNode::get(C, Elts);
2258*0fca6ea1SDimitry Andric 
2259*0fca6ea1SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
2260*0fca6ea1SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
2261*0fca6ea1SDimitry Andric 
2262*0fca6ea1SDimitry Andric     // Nontemporal (unaligned) store of the 0'th element of the float/double
2263*0fca6ea1SDimitry Andric     // vector.
2264*0fca6ea1SDimitry Andric     Type *SrcEltTy = cast<VectorType>(Arg1->getType())->getElementType();
2265*0fca6ea1SDimitry Andric     PointerType *EltPtrTy = PointerType::getUnqual(SrcEltTy);
2266*0fca6ea1SDimitry Andric     Value *Addr = Builder.CreateBitCast(Arg0, EltPtrTy, "cast");
2267*0fca6ea1SDimitry Andric     Value *Extract =
2268*0fca6ea1SDimitry Andric         Builder.CreateExtractElement(Arg1, (uint64_t)0, "extractelement");
2269*0fca6ea1SDimitry Andric 
2270*0fca6ea1SDimitry Andric     StoreInst *SI = Builder.CreateAlignedStore(Extract, Addr, Align(1));
2271*0fca6ea1SDimitry Andric     SI->setMetadata(LLVMContext::MD_nontemporal, Node);
2272*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.movnt.") ||
2273*0fca6ea1SDimitry Andric              Name.starts_with("avx512.storent.")) {
2274*0fca6ea1SDimitry Andric     SmallVector<Metadata *, 1> Elts;
2275*0fca6ea1SDimitry Andric     Elts.push_back(
2276*0fca6ea1SDimitry Andric         ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
2277*0fca6ea1SDimitry Andric     MDNode *Node = MDNode::get(C, Elts);
2278*0fca6ea1SDimitry Andric 
2279*0fca6ea1SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
2280*0fca6ea1SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
2281*0fca6ea1SDimitry Andric 
2282*0fca6ea1SDimitry Andric     // Convert the type of the pointer to a pointer to the stored type.
2283*0fca6ea1SDimitry Andric     Value *BC = Builder.CreateBitCast(
2284*0fca6ea1SDimitry Andric         Arg0, PointerType::getUnqual(Arg1->getType()), "cast");
2285*0fca6ea1SDimitry Andric     StoreInst *SI = Builder.CreateAlignedStore(
2286*0fca6ea1SDimitry Andric         Arg1, BC,
2287*0fca6ea1SDimitry Andric         Align(Arg1->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
2288*0fca6ea1SDimitry Andric     SI->setMetadata(LLVMContext::MD_nontemporal, Node);
2289*0fca6ea1SDimitry Andric   } else if (Name == "sse2.storel.dq") {
2290*0fca6ea1SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
2291*0fca6ea1SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
2292*0fca6ea1SDimitry Andric 
2293*0fca6ea1SDimitry Andric     auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
2294*0fca6ea1SDimitry Andric     Value *BC0 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
2295*0fca6ea1SDimitry Andric     Value *Elt = Builder.CreateExtractElement(BC0, (uint64_t)0);
2296*0fca6ea1SDimitry Andric     Value *BC = Builder.CreateBitCast(
2297*0fca6ea1SDimitry Andric         Arg0, PointerType::getUnqual(Elt->getType()), "cast");
2298*0fca6ea1SDimitry Andric     Builder.CreateAlignedStore(Elt, BC, Align(1));
2299*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse.storeu.") ||
2300*0fca6ea1SDimitry Andric              Name.starts_with("sse2.storeu.") ||
2301*0fca6ea1SDimitry Andric              Name.starts_with("avx.storeu.")) {
2302*0fca6ea1SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
2303*0fca6ea1SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
2304*0fca6ea1SDimitry Andric 
2305*0fca6ea1SDimitry Andric     Arg0 = Builder.CreateBitCast(Arg0, PointerType::getUnqual(Arg1->getType()),
2306*0fca6ea1SDimitry Andric                                  "cast");
2307*0fca6ea1SDimitry Andric     Builder.CreateAlignedStore(Arg1, Arg0, Align(1));
2308*0fca6ea1SDimitry Andric   } else if (Name == "avx512.mask.store.ss") {
2309*0fca6ea1SDimitry Andric     Value *Mask = Builder.CreateAnd(CI->getArgOperand(2), Builder.getInt8(1));
2310*0fca6ea1SDimitry Andric     upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
2311*0fca6ea1SDimitry Andric                        Mask, false);
2312*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.store")) {
2313*0fca6ea1SDimitry Andric     // "avx512.mask.storeu." or "avx512.mask.store."
2314*0fca6ea1SDimitry Andric     bool Aligned = Name[17] != 'u'; // "avx512.mask.storeu".
2315*0fca6ea1SDimitry Andric     upgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
2316*0fca6ea1SDimitry Andric                        CI->getArgOperand(2), Aligned);
2317*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse2.pcmp") || Name.starts_with("avx2.pcmp")) {
2318*0fca6ea1SDimitry Andric     // Upgrade packed integer vector compare intrinsics to compare instructions.
2319*0fca6ea1SDimitry Andric     // "sse2.pcpmpeq." "sse2.pcmpgt." "avx2.pcmpeq." or "avx2.pcmpgt."
2320*0fca6ea1SDimitry Andric     bool CmpEq = Name[9] == 'e';
2321*0fca6ea1SDimitry Andric     Rep = Builder.CreateICmp(CmpEq ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_SGT,
2322*0fca6ea1SDimitry Andric                              CI->getArgOperand(0), CI->getArgOperand(1));
2323*0fca6ea1SDimitry Andric     Rep = Builder.CreateSExt(Rep, CI->getType(), "");
2324*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.broadcastm")) {
2325*0fca6ea1SDimitry Andric     Type *ExtTy = Type::getInt32Ty(C);
2326*0fca6ea1SDimitry Andric     if (CI->getOperand(0)->getType()->isIntegerTy(8))
2327*0fca6ea1SDimitry Andric       ExtTy = Type::getInt64Ty(C);
2328*0fca6ea1SDimitry Andric     unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() /
2329*0fca6ea1SDimitry Andric                        ExtTy->getPrimitiveSizeInBits();
2330*0fca6ea1SDimitry Andric     Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy);
2331*0fca6ea1SDimitry Andric     Rep = Builder.CreateVectorSplat(NumElts, Rep);
2332*0fca6ea1SDimitry Andric   } else if (Name == "sse.sqrt.ss" || Name == "sse2.sqrt.sd") {
2333*0fca6ea1SDimitry Andric     Value *Vec = CI->getArgOperand(0);
2334*0fca6ea1SDimitry Andric     Value *Elt0 = Builder.CreateExtractElement(Vec, (uint64_t)0);
2335*0fca6ea1SDimitry Andric     Function *Intr = Intrinsic::getDeclaration(F->getParent(), Intrinsic::sqrt,
2336*0fca6ea1SDimitry Andric                                                Elt0->getType());
2337*0fca6ea1SDimitry Andric     Elt0 = Builder.CreateCall(Intr, Elt0);
2338*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(Vec, Elt0, (uint64_t)0);
2339*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.sqrt.p") ||
2340*0fca6ea1SDimitry Andric              Name.starts_with("sse2.sqrt.p") ||
2341*0fca6ea1SDimitry Andric              Name.starts_with("sse.sqrt.p")) {
2342*0fca6ea1SDimitry Andric     Rep =
2343*0fca6ea1SDimitry Andric         Builder.CreateCall(Intrinsic::getDeclaration(
2344*0fca6ea1SDimitry Andric                                F->getParent(), Intrinsic::sqrt, CI->getType()),
2345*0fca6ea1SDimitry Andric                            {CI->getArgOperand(0)});
2346*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.sqrt.p")) {
2347*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4 &&
2348*0fca6ea1SDimitry Andric         (!isa<ConstantInt>(CI->getArgOperand(3)) ||
2349*0fca6ea1SDimitry Andric          cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
2350*0fca6ea1SDimitry Andric       Intrinsic::ID IID = Name[18] == 's' ? Intrinsic::x86_avx512_sqrt_ps_512
2351*0fca6ea1SDimitry Andric                                           : Intrinsic::x86_avx512_sqrt_pd_512;
2352*0fca6ea1SDimitry Andric 
2353*0fca6ea1SDimitry Andric       Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(3)};
2354*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
2355*0fca6ea1SDimitry Andric                                Args);
2356*0fca6ea1SDimitry Andric     } else {
2357*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
2358*0fca6ea1SDimitry Andric                                                          Intrinsic::sqrt,
2359*0fca6ea1SDimitry Andric                                                          CI->getType()),
2360*0fca6ea1SDimitry Andric                                {CI->getArgOperand(0)});
2361*0fca6ea1SDimitry Andric     }
2362*0fca6ea1SDimitry Andric     Rep =
2363*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
2364*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.ptestm") ||
2365*0fca6ea1SDimitry Andric              Name.starts_with("avx512.ptestnm")) {
2366*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
2367*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
2368*0fca6ea1SDimitry Andric     Value *Mask = CI->getArgOperand(2);
2369*0fca6ea1SDimitry Andric     Rep = Builder.CreateAnd(Op0, Op1);
2370*0fca6ea1SDimitry Andric     llvm::Type *Ty = Op0->getType();
2371*0fca6ea1SDimitry Andric     Value *Zero = llvm::Constant::getNullValue(Ty);
2372*0fca6ea1SDimitry Andric     ICmpInst::Predicate Pred = Name.starts_with("avx512.ptestm")
2373*0fca6ea1SDimitry Andric                                    ? ICmpInst::ICMP_NE
2374*0fca6ea1SDimitry Andric                                    : ICmpInst::ICMP_EQ;
2375*0fca6ea1SDimitry Andric     Rep = Builder.CreateICmp(Pred, Rep, Zero);
2376*0fca6ea1SDimitry Andric     Rep = applyX86MaskOn1BitsVec(Builder, Rep, Mask);
2377*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.pbroadcast")) {
2378*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getArgOperand(1)->getType())
2379*0fca6ea1SDimitry Andric                            ->getNumElements();
2380*0fca6ea1SDimitry Andric     Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0));
2381*0fca6ea1SDimitry Andric     Rep =
2382*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
2383*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.kunpck")) {
2384*0fca6ea1SDimitry Andric     unsigned NumElts = CI->getType()->getScalarSizeInBits();
2385*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), NumElts);
2386*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), NumElts);
2387*0fca6ea1SDimitry Andric     int Indices[64];
2388*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
2389*0fca6ea1SDimitry Andric       Indices[i] = i;
2390*0fca6ea1SDimitry Andric 
2391*0fca6ea1SDimitry Andric     // First extract half of each vector. This gives better codegen than
2392*0fca6ea1SDimitry Andric     // doing it in a single shuffle.
2393*0fca6ea1SDimitry Andric     LHS = Builder.CreateShuffleVector(LHS, LHS, ArrayRef(Indices, NumElts / 2));
2394*0fca6ea1SDimitry Andric     RHS = Builder.CreateShuffleVector(RHS, RHS, ArrayRef(Indices, NumElts / 2));
2395*0fca6ea1SDimitry Andric     // Concat the vectors.
2396*0fca6ea1SDimitry Andric     // NOTE: Operands have to be swapped to match intrinsic definition.
2397*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(RHS, LHS, ArrayRef(Indices, NumElts));
2398*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2399*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kand.w") {
2400*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2401*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2402*0fca6ea1SDimitry Andric     Rep = Builder.CreateAnd(LHS, RHS);
2403*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2404*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kandn.w") {
2405*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2406*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2407*0fca6ea1SDimitry Andric     LHS = Builder.CreateNot(LHS);
2408*0fca6ea1SDimitry Andric     Rep = Builder.CreateAnd(LHS, RHS);
2409*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2410*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kor.w") {
2411*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2412*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2413*0fca6ea1SDimitry Andric     Rep = Builder.CreateOr(LHS, RHS);
2414*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2415*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kxor.w") {
2416*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2417*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2418*0fca6ea1SDimitry Andric     Rep = Builder.CreateXor(LHS, RHS);
2419*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2420*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kxnor.w") {
2421*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2422*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2423*0fca6ea1SDimitry Andric     LHS = Builder.CreateNot(LHS);
2424*0fca6ea1SDimitry Andric     Rep = Builder.CreateXor(LHS, RHS);
2425*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2426*0fca6ea1SDimitry Andric   } else if (Name == "avx512.knot.w") {
2427*0fca6ea1SDimitry Andric     Rep = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2428*0fca6ea1SDimitry Andric     Rep = Builder.CreateNot(Rep);
2429*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, CI->getType());
2430*0fca6ea1SDimitry Andric   } else if (Name == "avx512.kortestz.w" || Name == "avx512.kortestc.w") {
2431*0fca6ea1SDimitry Andric     Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
2432*0fca6ea1SDimitry Andric     Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
2433*0fca6ea1SDimitry Andric     Rep = Builder.CreateOr(LHS, RHS);
2434*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, Builder.getInt16Ty());
2435*0fca6ea1SDimitry Andric     Value *C;
2436*0fca6ea1SDimitry Andric     if (Name[14] == 'c')
2437*0fca6ea1SDimitry Andric       C = ConstantInt::getAllOnesValue(Builder.getInt16Ty());
2438*0fca6ea1SDimitry Andric     else
2439*0fca6ea1SDimitry Andric       C = ConstantInt::getNullValue(Builder.getInt16Ty());
2440*0fca6ea1SDimitry Andric     Rep = Builder.CreateICmpEQ(Rep, C);
2441*0fca6ea1SDimitry Andric     Rep = Builder.CreateZExt(Rep, Builder.getInt32Ty());
2442*0fca6ea1SDimitry Andric   } else if (Name == "sse.add.ss" || Name == "sse2.add.sd" ||
2443*0fca6ea1SDimitry Andric              Name == "sse.sub.ss" || Name == "sse2.sub.sd" ||
2444*0fca6ea1SDimitry Andric              Name == "sse.mul.ss" || Name == "sse2.mul.sd" ||
2445*0fca6ea1SDimitry Andric              Name == "sse.div.ss" || Name == "sse2.div.sd") {
2446*0fca6ea1SDimitry Andric     Type *I32Ty = Type::getInt32Ty(C);
2447*0fca6ea1SDimitry Andric     Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0),
2448*0fca6ea1SDimitry Andric                                                ConstantInt::get(I32Ty, 0));
2449*0fca6ea1SDimitry Andric     Value *Elt1 = Builder.CreateExtractElement(CI->getArgOperand(1),
2450*0fca6ea1SDimitry Andric                                                ConstantInt::get(I32Ty, 0));
2451*0fca6ea1SDimitry Andric     Value *EltOp;
2452*0fca6ea1SDimitry Andric     if (Name.contains(".add."))
2453*0fca6ea1SDimitry Andric       EltOp = Builder.CreateFAdd(Elt0, Elt1);
2454*0fca6ea1SDimitry Andric     else if (Name.contains(".sub."))
2455*0fca6ea1SDimitry Andric       EltOp = Builder.CreateFSub(Elt0, Elt1);
2456*0fca6ea1SDimitry Andric     else if (Name.contains(".mul."))
2457*0fca6ea1SDimitry Andric       EltOp = Builder.CreateFMul(Elt0, Elt1);
2458*0fca6ea1SDimitry Andric     else
2459*0fca6ea1SDimitry Andric       EltOp = Builder.CreateFDiv(Elt0, Elt1);
2460*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(CI->getArgOperand(0), EltOp,
2461*0fca6ea1SDimitry Andric                                       ConstantInt::get(I32Ty, 0));
2462*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.pcmp")) {
2463*0fca6ea1SDimitry Andric     // "avx512.mask.pcmpeq." or "avx512.mask.pcmpgt."
2464*0fca6ea1SDimitry Andric     bool CmpEq = Name[16] == 'e';
2465*0fca6ea1SDimitry Andric     Rep = upgradeMaskedCompare(Builder, *CI, CmpEq ? 0 : 6, true);
2466*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vpshufbitqmb.")) {
2467*0fca6ea1SDimitry Andric     Type *OpTy = CI->getArgOperand(0)->getType();
2468*0fca6ea1SDimitry Andric     unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
2469*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
2470*0fca6ea1SDimitry Andric     switch (VecWidth) {
2471*0fca6ea1SDimitry Andric     default:
2472*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
2473*0fca6ea1SDimitry Andric     case 128:
2474*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpshufbitqmb_128;
2475*0fca6ea1SDimitry Andric       break;
2476*0fca6ea1SDimitry Andric     case 256:
2477*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpshufbitqmb_256;
2478*0fca6ea1SDimitry Andric       break;
2479*0fca6ea1SDimitry Andric     case 512:
2480*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpshufbitqmb_512;
2481*0fca6ea1SDimitry Andric       break;
2482*0fca6ea1SDimitry Andric     }
2483*0fca6ea1SDimitry Andric 
2484*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
2485*0fca6ea1SDimitry Andric                              {CI->getOperand(0), CI->getArgOperand(1)});
2486*0fca6ea1SDimitry Andric     Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
2487*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.fpclass.p")) {
2488*0fca6ea1SDimitry Andric     Type *OpTy = CI->getArgOperand(0)->getType();
2489*0fca6ea1SDimitry Andric     unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
2490*0fca6ea1SDimitry Andric     unsigned EltWidth = OpTy->getScalarSizeInBits();
2491*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
2492*0fca6ea1SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
2493*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_ps_128;
2494*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
2495*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_ps_256;
2496*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32)
2497*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_ps_512;
2498*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
2499*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_pd_128;
2500*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
2501*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_pd_256;
2502*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64)
2503*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_fpclass_pd_512;
2504*0fca6ea1SDimitry Andric     else
2505*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
2506*0fca6ea1SDimitry Andric 
2507*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
2508*0fca6ea1SDimitry Andric                              {CI->getOperand(0), CI->getArgOperand(1)});
2509*0fca6ea1SDimitry Andric     Rep = applyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
2510*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.cmp.p")) {
2511*0fca6ea1SDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
2512*0fca6ea1SDimitry Andric     Type *OpTy = Args[0]->getType();
2513*0fca6ea1SDimitry Andric     unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
2514*0fca6ea1SDimitry Andric     unsigned EltWidth = OpTy->getScalarSizeInBits();
2515*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
2516*0fca6ea1SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
2517*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_ps_128;
2518*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
2519*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_ps_256;
2520*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32)
2521*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_ps_512;
2522*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
2523*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_pd_128;
2524*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
2525*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_pd_256;
2526*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64)
2527*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_mask_cmp_pd_512;
2528*0fca6ea1SDimitry Andric     else
2529*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
2530*0fca6ea1SDimitry Andric 
2531*0fca6ea1SDimitry Andric     Value *Mask = Constant::getAllOnesValue(CI->getType());
2532*0fca6ea1SDimitry Andric     if (VecWidth == 512)
2533*0fca6ea1SDimitry Andric       std::swap(Mask, Args.back());
2534*0fca6ea1SDimitry Andric     Args.push_back(Mask);
2535*0fca6ea1SDimitry Andric 
2536*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
2537*0fca6ea1SDimitry Andric                              Args);
2538*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.cmp.")) {
2539*0fca6ea1SDimitry Andric     // Integer compare intrinsics.
2540*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2541*0fca6ea1SDimitry Andric     Rep = upgradeMaskedCompare(Builder, *CI, Imm, true);
2542*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.ucmp.")) {
2543*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2544*0fca6ea1SDimitry Andric     Rep = upgradeMaskedCompare(Builder, *CI, Imm, false);
2545*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.cvtb2mask.") ||
2546*0fca6ea1SDimitry Andric              Name.starts_with("avx512.cvtw2mask.") ||
2547*0fca6ea1SDimitry Andric              Name.starts_with("avx512.cvtd2mask.") ||
2548*0fca6ea1SDimitry Andric              Name.starts_with("avx512.cvtq2mask.")) {
2549*0fca6ea1SDimitry Andric     Value *Op = CI->getArgOperand(0);
2550*0fca6ea1SDimitry Andric     Value *Zero = llvm::Constant::getNullValue(Op->getType());
2551*0fca6ea1SDimitry Andric     Rep = Builder.CreateICmp(ICmpInst::ICMP_SLT, Op, Zero);
2552*0fca6ea1SDimitry Andric     Rep = applyX86MaskOn1BitsVec(Builder, Rep, nullptr);
2553*0fca6ea1SDimitry Andric   } else if (Name == "ssse3.pabs.b.128" || Name == "ssse3.pabs.w.128" ||
2554*0fca6ea1SDimitry Andric              Name == "ssse3.pabs.d.128" || Name.starts_with("avx2.pabs") ||
2555*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pabs")) {
2556*0fca6ea1SDimitry Andric     Rep = upgradeAbs(Builder, *CI);
2557*0fca6ea1SDimitry Andric   } else if (Name == "sse41.pmaxsb" || Name == "sse2.pmaxs.w" ||
2558*0fca6ea1SDimitry Andric              Name == "sse41.pmaxsd" || Name.starts_with("avx2.pmaxs") ||
2559*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmaxs")) {
2560*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smax);
2561*0fca6ea1SDimitry Andric   } else if (Name == "sse2.pmaxu.b" || Name == "sse41.pmaxuw" ||
2562*0fca6ea1SDimitry Andric              Name == "sse41.pmaxud" || Name.starts_with("avx2.pmaxu") ||
2563*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmaxu")) {
2564*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umax);
2565*0fca6ea1SDimitry Andric   } else if (Name == "sse41.pminsb" || Name == "sse2.pmins.w" ||
2566*0fca6ea1SDimitry Andric              Name == "sse41.pminsd" || Name.starts_with("avx2.pmins") ||
2567*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmins")) {
2568*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::smin);
2569*0fca6ea1SDimitry Andric   } else if (Name == "sse2.pminu.b" || Name == "sse41.pminuw" ||
2570*0fca6ea1SDimitry Andric              Name == "sse41.pminud" || Name.starts_with("avx2.pminu") ||
2571*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pminu")) {
2572*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::umin);
2573*0fca6ea1SDimitry Andric   } else if (Name == "sse2.pmulu.dq" || Name == "avx2.pmulu.dq" ||
2574*0fca6ea1SDimitry Andric              Name == "avx512.pmulu.dq.512" ||
2575*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmulu.dq.")) {
2576*0fca6ea1SDimitry Andric     Rep = upgradePMULDQ(Builder, *CI, /*Signed*/ false);
2577*0fca6ea1SDimitry Andric   } else if (Name == "sse41.pmuldq" || Name == "avx2.pmul.dq" ||
2578*0fca6ea1SDimitry Andric              Name == "avx512.pmul.dq.512" ||
2579*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmul.dq.")) {
2580*0fca6ea1SDimitry Andric     Rep = upgradePMULDQ(Builder, *CI, /*Signed*/ true);
2581*0fca6ea1SDimitry Andric   } else if (Name == "sse.cvtsi2ss" || Name == "sse2.cvtsi2sd" ||
2582*0fca6ea1SDimitry Andric              Name == "sse.cvtsi642ss" || Name == "sse2.cvtsi642sd") {
2583*0fca6ea1SDimitry Andric     Rep =
2584*0fca6ea1SDimitry Andric         Builder.CreateSIToFP(CI->getArgOperand(1),
2585*0fca6ea1SDimitry Andric                              cast<VectorType>(CI->getType())->getElementType());
2586*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
2587*0fca6ea1SDimitry Andric   } else if (Name == "avx512.cvtusi2sd") {
2588*0fca6ea1SDimitry Andric     Rep =
2589*0fca6ea1SDimitry Andric         Builder.CreateUIToFP(CI->getArgOperand(1),
2590*0fca6ea1SDimitry Andric                              cast<VectorType>(CI->getType())->getElementType());
2591*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
2592*0fca6ea1SDimitry Andric   } else if (Name == "sse2.cvtss2sd") {
2593*0fca6ea1SDimitry Andric     Rep = Builder.CreateExtractElement(CI->getArgOperand(1), (uint64_t)0);
2594*0fca6ea1SDimitry Andric     Rep = Builder.CreateFPExt(
2595*0fca6ea1SDimitry Andric         Rep, cast<VectorType>(CI->getType())->getElementType());
2596*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
2597*0fca6ea1SDimitry Andric   } else if (Name == "sse2.cvtdq2pd" || Name == "sse2.cvtdq2ps" ||
2598*0fca6ea1SDimitry Andric              Name == "avx.cvtdq2.pd.256" || Name == "avx.cvtdq2.ps.256" ||
2599*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtdq2pd.") ||
2600*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtudq2pd.") ||
2601*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtdq2ps.") ||
2602*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtudq2ps.") ||
2603*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtqq2pd.") ||
2604*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.cvtuqq2pd.") ||
2605*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtqq2ps.256" ||
2606*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtqq2ps.512" ||
2607*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtuqq2ps.256" ||
2608*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtuqq2ps.512" || Name == "sse2.cvtps2pd" ||
2609*0fca6ea1SDimitry Andric              Name == "avx.cvt.ps2.pd.256" ||
2610*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtps2pd.128" ||
2611*0fca6ea1SDimitry Andric              Name == "avx512.mask.cvtps2pd.256") {
2612*0fca6ea1SDimitry Andric     auto *DstTy = cast<FixedVectorType>(CI->getType());
2613*0fca6ea1SDimitry Andric     Rep = CI->getArgOperand(0);
2614*0fca6ea1SDimitry Andric     auto *SrcTy = cast<FixedVectorType>(Rep->getType());
2615*0fca6ea1SDimitry Andric 
2616*0fca6ea1SDimitry Andric     unsigned NumDstElts = DstTy->getNumElements();
2617*0fca6ea1SDimitry Andric     if (NumDstElts < SrcTy->getNumElements()) {
2618*0fca6ea1SDimitry Andric       assert(NumDstElts == 2 && "Unexpected vector size");
2619*0fca6ea1SDimitry Andric       Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1});
2620*0fca6ea1SDimitry Andric     }
2621*0fca6ea1SDimitry Andric 
2622*0fca6ea1SDimitry Andric     bool IsPS2PD = SrcTy->getElementType()->isFloatTy();
2623*0fca6ea1SDimitry Andric     bool IsUnsigned = Name.contains("cvtu");
2624*0fca6ea1SDimitry Andric     if (IsPS2PD)
2625*0fca6ea1SDimitry Andric       Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd");
2626*0fca6ea1SDimitry Andric     else if (CI->arg_size() == 4 &&
2627*0fca6ea1SDimitry Andric              (!isa<ConstantInt>(CI->getArgOperand(3)) ||
2628*0fca6ea1SDimitry Andric               cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
2629*0fca6ea1SDimitry Andric       Intrinsic::ID IID = IsUnsigned ? Intrinsic::x86_avx512_uitofp_round
2630*0fca6ea1SDimitry Andric                                      : Intrinsic::x86_avx512_sitofp_round;
2631*0fca6ea1SDimitry Andric       Function *F =
2632*0fca6ea1SDimitry Andric           Intrinsic::getDeclaration(CI->getModule(), IID, {DstTy, SrcTy});
2633*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(F, {Rep, CI->getArgOperand(3)});
2634*0fca6ea1SDimitry Andric     } else {
2635*0fca6ea1SDimitry Andric       Rep = IsUnsigned ? Builder.CreateUIToFP(Rep, DstTy, "cvt")
2636*0fca6ea1SDimitry Andric                        : Builder.CreateSIToFP(Rep, DstTy, "cvt");
2637*0fca6ea1SDimitry Andric     }
2638*0fca6ea1SDimitry Andric 
2639*0fca6ea1SDimitry Andric     if (CI->arg_size() >= 3)
2640*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
2641*0fca6ea1SDimitry Andric                           CI->getArgOperand(1));
2642*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vcvtph2ps.") ||
2643*0fca6ea1SDimitry Andric              Name.starts_with("vcvtph2ps.")) {
2644*0fca6ea1SDimitry Andric     auto *DstTy = cast<FixedVectorType>(CI->getType());
2645*0fca6ea1SDimitry Andric     Rep = CI->getArgOperand(0);
2646*0fca6ea1SDimitry Andric     auto *SrcTy = cast<FixedVectorType>(Rep->getType());
2647*0fca6ea1SDimitry Andric     unsigned NumDstElts = DstTy->getNumElements();
2648*0fca6ea1SDimitry Andric     if (NumDstElts != SrcTy->getNumElements()) {
2649*0fca6ea1SDimitry Andric       assert(NumDstElts == 4 && "Unexpected vector size");
2650*0fca6ea1SDimitry Andric       Rep = Builder.CreateShuffleVector(Rep, Rep, ArrayRef<int>{0, 1, 2, 3});
2651*0fca6ea1SDimitry Andric     }
2652*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(
2653*0fca6ea1SDimitry Andric         Rep, FixedVectorType::get(Type::getHalfTy(C), NumDstElts));
2654*0fca6ea1SDimitry Andric     Rep = Builder.CreateFPExt(Rep, DstTy, "cvtph2ps");
2655*0fca6ea1SDimitry Andric     if (CI->arg_size() >= 3)
2656*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
2657*0fca6ea1SDimitry Andric                           CI->getArgOperand(1));
2658*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.load")) {
2659*0fca6ea1SDimitry Andric     // "avx512.mask.loadu." or "avx512.mask.load."
2660*0fca6ea1SDimitry Andric     bool Aligned = Name[16] != 'u'; // "avx512.mask.loadu".
2661*0fca6ea1SDimitry Andric     Rep = upgradeMaskedLoad(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
2662*0fca6ea1SDimitry Andric                             CI->getArgOperand(2), Aligned);
2663*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.expand.load.")) {
2664*0fca6ea1SDimitry Andric     auto *ResultTy = cast<FixedVectorType>(CI->getType());
2665*0fca6ea1SDimitry Andric     Type *PtrTy = ResultTy->getElementType();
2666*0fca6ea1SDimitry Andric 
2667*0fca6ea1SDimitry Andric     // Cast the pointer to element type.
2668*0fca6ea1SDimitry Andric     Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
2669*0fca6ea1SDimitry Andric                                        llvm::PointerType::getUnqual(PtrTy));
2670*0fca6ea1SDimitry Andric 
2671*0fca6ea1SDimitry Andric     Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
2672*0fca6ea1SDimitry Andric                                    ResultTy->getNumElements());
2673*0fca6ea1SDimitry Andric 
2674*0fca6ea1SDimitry Andric     Function *ELd = Intrinsic::getDeclaration(
2675*0fca6ea1SDimitry Andric         F->getParent(), Intrinsic::masked_expandload, ResultTy);
2676*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(ELd, {Ptr, MaskVec, CI->getOperand(1)});
2677*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.compress.store.")) {
2678*0fca6ea1SDimitry Andric     auto *ResultTy = cast<VectorType>(CI->getArgOperand(1)->getType());
2679*0fca6ea1SDimitry Andric     Type *PtrTy = ResultTy->getElementType();
2680*0fca6ea1SDimitry Andric 
2681*0fca6ea1SDimitry Andric     // Cast the pointer to element type.
2682*0fca6ea1SDimitry Andric     Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
2683*0fca6ea1SDimitry Andric                                        llvm::PointerType::getUnqual(PtrTy));
2684*0fca6ea1SDimitry Andric 
2685*0fca6ea1SDimitry Andric     Value *MaskVec =
2686*0fca6ea1SDimitry Andric         getX86MaskVec(Builder, CI->getArgOperand(2),
2687*0fca6ea1SDimitry Andric                       cast<FixedVectorType>(ResultTy)->getNumElements());
2688*0fca6ea1SDimitry Andric 
2689*0fca6ea1SDimitry Andric     Function *CSt = Intrinsic::getDeclaration(
2690*0fca6ea1SDimitry Andric         F->getParent(), Intrinsic::masked_compressstore, ResultTy);
2691*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(CSt, {CI->getArgOperand(1), Ptr, MaskVec});
2692*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.compress.") ||
2693*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.expand.")) {
2694*0fca6ea1SDimitry Andric     auto *ResultTy = cast<FixedVectorType>(CI->getType());
2695*0fca6ea1SDimitry Andric 
2696*0fca6ea1SDimitry Andric     Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
2697*0fca6ea1SDimitry Andric                                    ResultTy->getNumElements());
2698*0fca6ea1SDimitry Andric 
2699*0fca6ea1SDimitry Andric     bool IsCompress = Name[12] == 'c';
2700*0fca6ea1SDimitry Andric     Intrinsic::ID IID = IsCompress ? Intrinsic::x86_avx512_mask_compress
2701*0fca6ea1SDimitry Andric                                    : Intrinsic::x86_avx512_mask_expand;
2702*0fca6ea1SDimitry Andric     Function *Intr = Intrinsic::getDeclaration(F->getParent(), IID, ResultTy);
2703*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intr,
2704*0fca6ea1SDimitry Andric                              {CI->getOperand(0), CI->getOperand(1), MaskVec});
2705*0fca6ea1SDimitry Andric   } else if (Name.starts_with("xop.vpcom")) {
2706*0fca6ea1SDimitry Andric     bool IsSigned;
2707*0fca6ea1SDimitry Andric     if (Name.ends_with("ub") || Name.ends_with("uw") || Name.ends_with("ud") ||
2708*0fca6ea1SDimitry Andric         Name.ends_with("uq"))
2709*0fca6ea1SDimitry Andric       IsSigned = false;
2710*0fca6ea1SDimitry Andric     else if (Name.ends_with("b") || Name.ends_with("w") ||
2711*0fca6ea1SDimitry Andric              Name.ends_with("d") || Name.ends_with("q"))
2712*0fca6ea1SDimitry Andric       IsSigned = true;
2713*0fca6ea1SDimitry Andric     else
2714*0fca6ea1SDimitry Andric       llvm_unreachable("Unknown suffix");
2715*0fca6ea1SDimitry Andric 
2716*0fca6ea1SDimitry Andric     unsigned Imm;
2717*0fca6ea1SDimitry Andric     if (CI->arg_size() == 3) {
2718*0fca6ea1SDimitry Andric       Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2719*0fca6ea1SDimitry Andric     } else {
2720*0fca6ea1SDimitry Andric       Name = Name.substr(9); // strip off "xop.vpcom"
2721*0fca6ea1SDimitry Andric       if (Name.starts_with("lt"))
2722*0fca6ea1SDimitry Andric         Imm = 0;
2723*0fca6ea1SDimitry Andric       else if (Name.starts_with("le"))
2724*0fca6ea1SDimitry Andric         Imm = 1;
2725*0fca6ea1SDimitry Andric       else if (Name.starts_with("gt"))
2726*0fca6ea1SDimitry Andric         Imm = 2;
2727*0fca6ea1SDimitry Andric       else if (Name.starts_with("ge"))
2728*0fca6ea1SDimitry Andric         Imm = 3;
2729*0fca6ea1SDimitry Andric       else if (Name.starts_with("eq"))
2730*0fca6ea1SDimitry Andric         Imm = 4;
2731*0fca6ea1SDimitry Andric       else if (Name.starts_with("ne"))
2732*0fca6ea1SDimitry Andric         Imm = 5;
2733*0fca6ea1SDimitry Andric       else if (Name.starts_with("false"))
2734*0fca6ea1SDimitry Andric         Imm = 6;
2735*0fca6ea1SDimitry Andric       else if (Name.starts_with("true"))
2736*0fca6ea1SDimitry Andric         Imm = 7;
2737*0fca6ea1SDimitry Andric       else
2738*0fca6ea1SDimitry Andric         llvm_unreachable("Unknown condition");
2739*0fca6ea1SDimitry Andric     }
2740*0fca6ea1SDimitry Andric 
2741*0fca6ea1SDimitry Andric     Rep = upgradeX86vpcom(Builder, *CI, Imm, IsSigned);
2742*0fca6ea1SDimitry Andric   } else if (Name.starts_with("xop.vpcmov")) {
2743*0fca6ea1SDimitry Andric     Value *Sel = CI->getArgOperand(2);
2744*0fca6ea1SDimitry Andric     Value *NotSel = Builder.CreateNot(Sel);
2745*0fca6ea1SDimitry Andric     Value *Sel0 = Builder.CreateAnd(CI->getArgOperand(0), Sel);
2746*0fca6ea1SDimitry Andric     Value *Sel1 = Builder.CreateAnd(CI->getArgOperand(1), NotSel);
2747*0fca6ea1SDimitry Andric     Rep = Builder.CreateOr(Sel0, Sel1);
2748*0fca6ea1SDimitry Andric   } else if (Name.starts_with("xop.vprot") || Name.starts_with("avx512.prol") ||
2749*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.prol")) {
2750*0fca6ea1SDimitry Andric     Rep = upgradeX86Rotate(Builder, *CI, false);
2751*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.pror") ||
2752*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pror")) {
2753*0fca6ea1SDimitry Andric     Rep = upgradeX86Rotate(Builder, *CI, true);
2754*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.vpshld.") ||
2755*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpshld") ||
2756*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpshld")) {
2757*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
2758*0fca6ea1SDimitry Andric     Rep = upgradeX86ConcatShift(Builder, *CI, false, ZeroMask);
2759*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.vpshrd.") ||
2760*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpshrd") ||
2761*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpshrd")) {
2762*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
2763*0fca6ea1SDimitry Andric     Rep = upgradeX86ConcatShift(Builder, *CI, true, ZeroMask);
2764*0fca6ea1SDimitry Andric   } else if (Name == "sse42.crc32.64.8") {
2765*0fca6ea1SDimitry Andric     Function *CRC32 = Intrinsic::getDeclaration(
2766*0fca6ea1SDimitry Andric         F->getParent(), Intrinsic::x86_sse42_crc32_32_8);
2767*0fca6ea1SDimitry Andric     Value *Trunc0 =
2768*0fca6ea1SDimitry Andric         Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
2769*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(CRC32, {Trunc0, CI->getArgOperand(1)});
2770*0fca6ea1SDimitry Andric     Rep = Builder.CreateZExt(Rep, CI->getType(), "");
2771*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vbroadcast.s") ||
2772*0fca6ea1SDimitry Andric              Name.starts_with("avx512.vbroadcast.s")) {
2773*0fca6ea1SDimitry Andric     // Replace broadcasts with a series of insertelements.
2774*0fca6ea1SDimitry Andric     auto *VecTy = cast<FixedVectorType>(CI->getType());
2775*0fca6ea1SDimitry Andric     Type *EltTy = VecTy->getElementType();
2776*0fca6ea1SDimitry Andric     unsigned EltNum = VecTy->getNumElements();
2777*0fca6ea1SDimitry Andric     Value *Load = Builder.CreateLoad(EltTy, CI->getArgOperand(0));
2778*0fca6ea1SDimitry Andric     Type *I32Ty = Type::getInt32Ty(C);
2779*0fca6ea1SDimitry Andric     Rep = PoisonValue::get(VecTy);
2780*0fca6ea1SDimitry Andric     for (unsigned I = 0; I < EltNum; ++I)
2781*0fca6ea1SDimitry Andric       Rep = Builder.CreateInsertElement(Rep, Load, ConstantInt::get(I32Ty, I));
2782*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse41.pmovsx") ||
2783*0fca6ea1SDimitry Andric              Name.starts_with("sse41.pmovzx") ||
2784*0fca6ea1SDimitry Andric              Name.starts_with("avx2.pmovsx") ||
2785*0fca6ea1SDimitry Andric              Name.starts_with("avx2.pmovzx") ||
2786*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmovsx") ||
2787*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pmovzx")) {
2788*0fca6ea1SDimitry Andric     auto *DstTy = cast<FixedVectorType>(CI->getType());
2789*0fca6ea1SDimitry Andric     unsigned NumDstElts = DstTy->getNumElements();
2790*0fca6ea1SDimitry Andric 
2791*0fca6ea1SDimitry Andric     // Extract a subvector of the first NumDstElts lanes and sign/zero extend.
2792*0fca6ea1SDimitry Andric     SmallVector<int, 8> ShuffleMask(NumDstElts);
2793*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumDstElts; ++i)
2794*0fca6ea1SDimitry Andric       ShuffleMask[i] = i;
2795*0fca6ea1SDimitry Andric 
2796*0fca6ea1SDimitry Andric     Value *SV = Builder.CreateShuffleVector(CI->getArgOperand(0), ShuffleMask);
2797*0fca6ea1SDimitry Andric 
2798*0fca6ea1SDimitry Andric     bool DoSext = Name.contains("pmovsx");
2799*0fca6ea1SDimitry Andric     Rep =
2800*0fca6ea1SDimitry Andric         DoSext ? Builder.CreateSExt(SV, DstTy) : Builder.CreateZExt(SV, DstTy);
2801*0fca6ea1SDimitry Andric     // If there are 3 arguments, it's a masked intrinsic so we need a select.
2802*0fca6ea1SDimitry Andric     if (CI->arg_size() == 3)
2803*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
2804*0fca6ea1SDimitry Andric                           CI->getArgOperand(1));
2805*0fca6ea1SDimitry Andric   } else if (Name == "avx512.mask.pmov.qd.256" ||
2806*0fca6ea1SDimitry Andric              Name == "avx512.mask.pmov.qd.512" ||
2807*0fca6ea1SDimitry Andric              Name == "avx512.mask.pmov.wb.256" ||
2808*0fca6ea1SDimitry Andric              Name == "avx512.mask.pmov.wb.512") {
2809*0fca6ea1SDimitry Andric     Type *Ty = CI->getArgOperand(1)->getType();
2810*0fca6ea1SDimitry Andric     Rep = Builder.CreateTrunc(CI->getArgOperand(0), Ty);
2811*0fca6ea1SDimitry Andric     Rep =
2812*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
2813*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vbroadcastf128") ||
2814*0fca6ea1SDimitry Andric              Name == "avx2.vbroadcasti128") {
2815*0fca6ea1SDimitry Andric     // Replace vbroadcastf128/vbroadcasti128 with a vector load+shuffle.
2816*0fca6ea1SDimitry Andric     Type *EltTy = cast<VectorType>(CI->getType())->getElementType();
2817*0fca6ea1SDimitry Andric     unsigned NumSrcElts = 128 / EltTy->getPrimitiveSizeInBits();
2818*0fca6ea1SDimitry Andric     auto *VT = FixedVectorType::get(EltTy, NumSrcElts);
2819*0fca6ea1SDimitry Andric     Value *Op = Builder.CreatePointerCast(CI->getArgOperand(0),
2820*0fca6ea1SDimitry Andric                                           PointerType::getUnqual(VT));
2821*0fca6ea1SDimitry Andric     Value *Load = Builder.CreateAlignedLoad(VT, Op, Align(1));
2822*0fca6ea1SDimitry Andric     if (NumSrcElts == 2)
2823*0fca6ea1SDimitry Andric       Rep = Builder.CreateShuffleVector(Load, ArrayRef<int>{0, 1, 0, 1});
2824*0fca6ea1SDimitry Andric     else
2825*0fca6ea1SDimitry Andric       Rep = Builder.CreateShuffleVector(Load,
2826*0fca6ea1SDimitry Andric                                         ArrayRef<int>{0, 1, 2, 3, 0, 1, 2, 3});
2827*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.shuf.i") ||
2828*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.shuf.f")) {
2829*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2830*0fca6ea1SDimitry Andric     Type *VT = CI->getType();
2831*0fca6ea1SDimitry Andric     unsigned NumLanes = VT->getPrimitiveSizeInBits() / 128;
2832*0fca6ea1SDimitry Andric     unsigned NumElementsInLane = 128 / VT->getScalarSizeInBits();
2833*0fca6ea1SDimitry Andric     unsigned ControlBitsMask = NumLanes - 1;
2834*0fca6ea1SDimitry Andric     unsigned NumControlBits = NumLanes / 2;
2835*0fca6ea1SDimitry Andric     SmallVector<int, 8> ShuffleMask(0);
2836*0fca6ea1SDimitry Andric 
2837*0fca6ea1SDimitry Andric     for (unsigned l = 0; l != NumLanes; ++l) {
2838*0fca6ea1SDimitry Andric       unsigned LaneMask = (Imm >> (l * NumControlBits)) & ControlBitsMask;
2839*0fca6ea1SDimitry Andric       // We actually need the other source.
2840*0fca6ea1SDimitry Andric       if (l >= NumLanes / 2)
2841*0fca6ea1SDimitry Andric         LaneMask += NumLanes;
2842*0fca6ea1SDimitry Andric       for (unsigned i = 0; i != NumElementsInLane; ++i)
2843*0fca6ea1SDimitry Andric         ShuffleMask.push_back(LaneMask * NumElementsInLane + i);
2844*0fca6ea1SDimitry Andric     }
2845*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
2846*0fca6ea1SDimitry Andric                                       CI->getArgOperand(1), ShuffleMask);
2847*0fca6ea1SDimitry Andric     Rep =
2848*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(4), Rep, CI->getArgOperand(3));
2849*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.broadcastf") ||
2850*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.broadcasti")) {
2851*0fca6ea1SDimitry Andric     unsigned NumSrcElts = cast<FixedVectorType>(CI->getArgOperand(0)->getType())
2852*0fca6ea1SDimitry Andric                               ->getNumElements();
2853*0fca6ea1SDimitry Andric     unsigned NumDstElts =
2854*0fca6ea1SDimitry Andric         cast<FixedVectorType>(CI->getType())->getNumElements();
2855*0fca6ea1SDimitry Andric 
2856*0fca6ea1SDimitry Andric     SmallVector<int, 8> ShuffleMask(NumDstElts);
2857*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumDstElts; ++i)
2858*0fca6ea1SDimitry Andric       ShuffleMask[i] = i % NumSrcElts;
2859*0fca6ea1SDimitry Andric 
2860*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(CI->getArgOperand(0),
2861*0fca6ea1SDimitry Andric                                       CI->getArgOperand(0), ShuffleMask);
2862*0fca6ea1SDimitry Andric     Rep =
2863*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
2864*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx2.pbroadcast") ||
2865*0fca6ea1SDimitry Andric              Name.starts_with("avx2.vbroadcast") ||
2866*0fca6ea1SDimitry Andric              Name.starts_with("avx512.pbroadcast") ||
2867*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.broadcast.s")) {
2868*0fca6ea1SDimitry Andric     // Replace vp?broadcasts with a vector shuffle.
2869*0fca6ea1SDimitry Andric     Value *Op = CI->getArgOperand(0);
2870*0fca6ea1SDimitry Andric     ElementCount EC = cast<VectorType>(CI->getType())->getElementCount();
2871*0fca6ea1SDimitry Andric     Type *MaskTy = VectorType::get(Type::getInt32Ty(C), EC);
2872*0fca6ea1SDimitry Andric     SmallVector<int, 8> M;
2873*0fca6ea1SDimitry Andric     ShuffleVectorInst::getShuffleMask(Constant::getNullValue(MaskTy), M);
2874*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op, M);
2875*0fca6ea1SDimitry Andric 
2876*0fca6ea1SDimitry Andric     if (CI->arg_size() == 3)
2877*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(2), Rep,
2878*0fca6ea1SDimitry Andric                           CI->getArgOperand(1));
2879*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse2.padds.") ||
2880*0fca6ea1SDimitry Andric              Name.starts_with("avx2.padds.") ||
2881*0fca6ea1SDimitry Andric              Name.starts_with("avx512.padds.") ||
2882*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.padds.")) {
2883*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::sadd_sat);
2884*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse2.psubs.") ||
2885*0fca6ea1SDimitry Andric              Name.starts_with("avx2.psubs.") ||
2886*0fca6ea1SDimitry Andric              Name.starts_with("avx512.psubs.") ||
2887*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.psubs.")) {
2888*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::ssub_sat);
2889*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse2.paddus.") ||
2890*0fca6ea1SDimitry Andric              Name.starts_with("avx2.paddus.") ||
2891*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.paddus.")) {
2892*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::uadd_sat);
2893*0fca6ea1SDimitry Andric   } else if (Name.starts_with("sse2.psubus.") ||
2894*0fca6ea1SDimitry Andric              Name.starts_with("avx2.psubus.") ||
2895*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.psubus.")) {
2896*0fca6ea1SDimitry Andric     Rep = upgradeX86BinaryIntrinsics(Builder, *CI, Intrinsic::usub_sat);
2897*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.palignr.")) {
2898*0fca6ea1SDimitry Andric     Rep = upgradeX86ALIGNIntrinsics(Builder, CI->getArgOperand(0),
2899*0fca6ea1SDimitry Andric                                     CI->getArgOperand(1), CI->getArgOperand(2),
2900*0fca6ea1SDimitry Andric                                     CI->getArgOperand(3), CI->getArgOperand(4),
2901*0fca6ea1SDimitry Andric                                     false);
2902*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.valign.")) {
2903*0fca6ea1SDimitry Andric     Rep = upgradeX86ALIGNIntrinsics(
2904*0fca6ea1SDimitry Andric         Builder, CI->getArgOperand(0), CI->getArgOperand(1),
2905*0fca6ea1SDimitry Andric         CI->getArgOperand(2), CI->getArgOperand(3), CI->getArgOperand(4), true);
2906*0fca6ea1SDimitry Andric   } else if (Name == "sse2.psll.dq" || Name == "avx2.psll.dq") {
2907*0fca6ea1SDimitry Andric     // 128/256-bit shift left specified in bits.
2908*0fca6ea1SDimitry Andric     unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
2909*0fca6ea1SDimitry Andric     Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0),
2910*0fca6ea1SDimitry Andric                                      Shift / 8); // Shift is in bits.
2911*0fca6ea1SDimitry Andric   } else if (Name == "sse2.psrl.dq" || Name == "avx2.psrl.dq") {
2912*0fca6ea1SDimitry Andric     // 128/256-bit shift right specified in bits.
2913*0fca6ea1SDimitry Andric     unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
2914*0fca6ea1SDimitry Andric     Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0),
2915*0fca6ea1SDimitry Andric                                      Shift / 8); // Shift is in bits.
2916*0fca6ea1SDimitry Andric   } else if (Name == "sse2.psll.dq.bs" || Name == "avx2.psll.dq.bs" ||
2917*0fca6ea1SDimitry Andric              Name == "avx512.psll.dq.512") {
2918*0fca6ea1SDimitry Andric     // 128/256/512-bit shift left specified in bytes.
2919*0fca6ea1SDimitry Andric     unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
2920*0fca6ea1SDimitry Andric     Rep = upgradeX86PSLLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
2921*0fca6ea1SDimitry Andric   } else if (Name == "sse2.psrl.dq.bs" || Name == "avx2.psrl.dq.bs" ||
2922*0fca6ea1SDimitry Andric              Name == "avx512.psrl.dq.512") {
2923*0fca6ea1SDimitry Andric     // 128/256/512-bit shift right specified in bytes.
2924*0fca6ea1SDimitry Andric     unsigned Shift = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
2925*0fca6ea1SDimitry Andric     Rep = upgradeX86PSRLDQIntrinsics(Builder, CI->getArgOperand(0), Shift);
2926*0fca6ea1SDimitry Andric   } else if (Name == "sse41.pblendw" || Name.starts_with("sse41.blendp") ||
2927*0fca6ea1SDimitry Andric              Name.starts_with("avx.blend.p") || Name == "avx2.pblendw" ||
2928*0fca6ea1SDimitry Andric              Name.starts_with("avx2.pblendd.")) {
2929*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
2930*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
2931*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2932*0fca6ea1SDimitry Andric     auto *VecTy = cast<FixedVectorType>(CI->getType());
2933*0fca6ea1SDimitry Andric     unsigned NumElts = VecTy->getNumElements();
2934*0fca6ea1SDimitry Andric 
2935*0fca6ea1SDimitry Andric     SmallVector<int, 16> Idxs(NumElts);
2936*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
2937*0fca6ea1SDimitry Andric       Idxs[i] = ((Imm >> (i % 8)) & 1) ? i + NumElts : i;
2938*0fca6ea1SDimitry Andric 
2939*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
2940*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vinsertf128.") ||
2941*0fca6ea1SDimitry Andric              Name == "avx2.vinserti128" ||
2942*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.insert")) {
2943*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
2944*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
2945*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
2946*0fca6ea1SDimitry Andric     unsigned DstNumElts =
2947*0fca6ea1SDimitry Andric         cast<FixedVectorType>(CI->getType())->getNumElements();
2948*0fca6ea1SDimitry Andric     unsigned SrcNumElts =
2949*0fca6ea1SDimitry Andric         cast<FixedVectorType>(Op1->getType())->getNumElements();
2950*0fca6ea1SDimitry Andric     unsigned Scale = DstNumElts / SrcNumElts;
2951*0fca6ea1SDimitry Andric 
2952*0fca6ea1SDimitry Andric     // Mask off the high bits of the immediate value; hardware ignores those.
2953*0fca6ea1SDimitry Andric     Imm = Imm % Scale;
2954*0fca6ea1SDimitry Andric 
2955*0fca6ea1SDimitry Andric     // Extend the second operand into a vector the size of the destination.
2956*0fca6ea1SDimitry Andric     SmallVector<int, 8> Idxs(DstNumElts);
2957*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != SrcNumElts; ++i)
2958*0fca6ea1SDimitry Andric       Idxs[i] = i;
2959*0fca6ea1SDimitry Andric     for (unsigned i = SrcNumElts; i != DstNumElts; ++i)
2960*0fca6ea1SDimitry Andric       Idxs[i] = SrcNumElts;
2961*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op1, Idxs);
2962*0fca6ea1SDimitry Andric 
2963*0fca6ea1SDimitry Andric     // Insert the second operand into the first operand.
2964*0fca6ea1SDimitry Andric 
2965*0fca6ea1SDimitry Andric     // Note that there is no guarantee that instruction lowering will actually
2966*0fca6ea1SDimitry Andric     // produce a vinsertf128 instruction for the created shuffles. In
2967*0fca6ea1SDimitry Andric     // particular, the 0 immediate case involves no lane changes, so it can
2968*0fca6ea1SDimitry Andric     // be handled as a blend.
2969*0fca6ea1SDimitry Andric 
2970*0fca6ea1SDimitry Andric     // Example of shuffle mask for 32-bit elements:
2971*0fca6ea1SDimitry Andric     // Imm = 1  <i32 0, i32 1, i32 2,  i32 3,  i32 8, i32 9, i32 10, i32 11>
2972*0fca6ea1SDimitry Andric     // Imm = 0  <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6,  i32 7 >
2973*0fca6ea1SDimitry Andric 
2974*0fca6ea1SDimitry Andric     // First fill with identify mask.
2975*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != DstNumElts; ++i)
2976*0fca6ea1SDimitry Andric       Idxs[i] = i;
2977*0fca6ea1SDimitry Andric     // Then replace the elements where we need to insert.
2978*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != SrcNumElts; ++i)
2979*0fca6ea1SDimitry Andric       Idxs[i + Imm * SrcNumElts] = i + DstNumElts;
2980*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Rep, Idxs);
2981*0fca6ea1SDimitry Andric 
2982*0fca6ea1SDimitry Andric     // If the intrinsic has a mask operand, handle that.
2983*0fca6ea1SDimitry Andric     if (CI->arg_size() == 5)
2984*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep,
2985*0fca6ea1SDimitry Andric                           CI->getArgOperand(3));
2986*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vextractf128.") ||
2987*0fca6ea1SDimitry Andric              Name == "avx2.vextracti128" ||
2988*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vextract")) {
2989*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
2990*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
2991*0fca6ea1SDimitry Andric     unsigned DstNumElts =
2992*0fca6ea1SDimitry Andric         cast<FixedVectorType>(CI->getType())->getNumElements();
2993*0fca6ea1SDimitry Andric     unsigned SrcNumElts =
2994*0fca6ea1SDimitry Andric         cast<FixedVectorType>(Op0->getType())->getNumElements();
2995*0fca6ea1SDimitry Andric     unsigned Scale = SrcNumElts / DstNumElts;
2996*0fca6ea1SDimitry Andric 
2997*0fca6ea1SDimitry Andric     // Mask off the high bits of the immediate value; hardware ignores those.
2998*0fca6ea1SDimitry Andric     Imm = Imm % Scale;
2999*0fca6ea1SDimitry Andric 
3000*0fca6ea1SDimitry Andric     // Get indexes for the subvector of the input vector.
3001*0fca6ea1SDimitry Andric     SmallVector<int, 8> Idxs(DstNumElts);
3002*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != DstNumElts; ++i) {
3003*0fca6ea1SDimitry Andric       Idxs[i] = i + (Imm * DstNumElts);
3004*0fca6ea1SDimitry Andric     }
3005*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3006*0fca6ea1SDimitry Andric 
3007*0fca6ea1SDimitry Andric     // If the intrinsic has a mask operand, handle that.
3008*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4)
3009*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3010*0fca6ea1SDimitry Andric                           CI->getArgOperand(2));
3011*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.perm.df.") ||
3012*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.perm.di.")) {
3013*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3014*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3015*0fca6ea1SDimitry Andric     auto *VecTy = cast<FixedVectorType>(CI->getType());
3016*0fca6ea1SDimitry Andric     unsigned NumElts = VecTy->getNumElements();
3017*0fca6ea1SDimitry Andric 
3018*0fca6ea1SDimitry Andric     SmallVector<int, 8> Idxs(NumElts);
3019*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
3020*0fca6ea1SDimitry Andric       Idxs[i] = (i & ~0x3) + ((Imm >> (2 * (i & 0x3))) & 3);
3021*0fca6ea1SDimitry Andric 
3022*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3023*0fca6ea1SDimitry Andric 
3024*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4)
3025*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3026*0fca6ea1SDimitry Andric                           CI->getArgOperand(2));
3027*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vperm2f128.") || Name == "avx2.vperm2i128") {
3028*0fca6ea1SDimitry Andric     // The immediate permute control byte looks like this:
3029*0fca6ea1SDimitry Andric     //    [1:0] - select 128 bits from sources for low half of destination
3030*0fca6ea1SDimitry Andric     //    [2]   - ignore
3031*0fca6ea1SDimitry Andric     //    [3]   - zero low half of destination
3032*0fca6ea1SDimitry Andric     //    [5:4] - select 128 bits from sources for high half of destination
3033*0fca6ea1SDimitry Andric     //    [6]   - ignore
3034*0fca6ea1SDimitry Andric     //    [7]   - zero high half of destination
3035*0fca6ea1SDimitry Andric 
3036*0fca6ea1SDimitry Andric     uint8_t Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3037*0fca6ea1SDimitry Andric 
3038*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3039*0fca6ea1SDimitry Andric     unsigned HalfSize = NumElts / 2;
3040*0fca6ea1SDimitry Andric     SmallVector<int, 8> ShuffleMask(NumElts);
3041*0fca6ea1SDimitry Andric 
3042*0fca6ea1SDimitry Andric     // Determine which operand(s) are actually in use for this instruction.
3043*0fca6ea1SDimitry Andric     Value *V0 = (Imm & 0x02) ? CI->getArgOperand(1) : CI->getArgOperand(0);
3044*0fca6ea1SDimitry Andric     Value *V1 = (Imm & 0x20) ? CI->getArgOperand(1) : CI->getArgOperand(0);
3045*0fca6ea1SDimitry Andric 
3046*0fca6ea1SDimitry Andric     // If needed, replace operands based on zero mask.
3047*0fca6ea1SDimitry Andric     V0 = (Imm & 0x08) ? ConstantAggregateZero::get(CI->getType()) : V0;
3048*0fca6ea1SDimitry Andric     V1 = (Imm & 0x80) ? ConstantAggregateZero::get(CI->getType()) : V1;
3049*0fca6ea1SDimitry Andric 
3050*0fca6ea1SDimitry Andric     // Permute low half of result.
3051*0fca6ea1SDimitry Andric     unsigned StartIndex = (Imm & 0x01) ? HalfSize : 0;
3052*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < HalfSize; ++i)
3053*0fca6ea1SDimitry Andric       ShuffleMask[i] = StartIndex + i;
3054*0fca6ea1SDimitry Andric 
3055*0fca6ea1SDimitry Andric     // Permute high half of result.
3056*0fca6ea1SDimitry Andric     StartIndex = (Imm & 0x10) ? HalfSize : 0;
3057*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < HalfSize; ++i)
3058*0fca6ea1SDimitry Andric       ShuffleMask[i + HalfSize] = NumElts + StartIndex + i;
3059*0fca6ea1SDimitry Andric 
3060*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(V0, V1, ShuffleMask);
3061*0fca6ea1SDimitry Andric 
3062*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx.vpermil.") || Name == "sse2.pshuf.d" ||
3063*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpermil.p") ||
3064*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pshuf.d.")) {
3065*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3066*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3067*0fca6ea1SDimitry Andric     auto *VecTy = cast<FixedVectorType>(CI->getType());
3068*0fca6ea1SDimitry Andric     unsigned NumElts = VecTy->getNumElements();
3069*0fca6ea1SDimitry Andric     // Calculate the size of each index in the immediate.
3070*0fca6ea1SDimitry Andric     unsigned IdxSize = 64 / VecTy->getScalarSizeInBits();
3071*0fca6ea1SDimitry Andric     unsigned IdxMask = ((1 << IdxSize) - 1);
3072*0fca6ea1SDimitry Andric 
3073*0fca6ea1SDimitry Andric     SmallVector<int, 8> Idxs(NumElts);
3074*0fca6ea1SDimitry Andric     // Lookup the bits for this element, wrapping around the immediate every
3075*0fca6ea1SDimitry Andric     // 8-bits. Elements are grouped into sets of 2 or 4 elements so we need
3076*0fca6ea1SDimitry Andric     // to offset by the first index of each group.
3077*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i)
3078*0fca6ea1SDimitry Andric       Idxs[i] = ((Imm >> ((i * IdxSize) % 8)) & IdxMask) | (i & ~IdxMask);
3079*0fca6ea1SDimitry Andric 
3080*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3081*0fca6ea1SDimitry Andric 
3082*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4)
3083*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3084*0fca6ea1SDimitry Andric                           CI->getArgOperand(2));
3085*0fca6ea1SDimitry Andric   } else if (Name == "sse2.pshufl.w" ||
3086*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pshufl.w.")) {
3087*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3088*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3089*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3090*0fca6ea1SDimitry Andric 
3091*0fca6ea1SDimitry Andric     SmallVector<int, 16> Idxs(NumElts);
3092*0fca6ea1SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 8) {
3093*0fca6ea1SDimitry Andric       for (unsigned i = 0; i != 4; ++i)
3094*0fca6ea1SDimitry Andric         Idxs[i + l] = ((Imm >> (2 * i)) & 0x3) + l;
3095*0fca6ea1SDimitry Andric       for (unsigned i = 4; i != 8; ++i)
3096*0fca6ea1SDimitry Andric         Idxs[i + l] = i + l;
3097*0fca6ea1SDimitry Andric     }
3098*0fca6ea1SDimitry Andric 
3099*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3100*0fca6ea1SDimitry Andric 
3101*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4)
3102*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3103*0fca6ea1SDimitry Andric                           CI->getArgOperand(2));
3104*0fca6ea1SDimitry Andric   } else if (Name == "sse2.pshufh.w" ||
3105*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pshufh.w.")) {
3106*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3107*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
3108*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3109*0fca6ea1SDimitry Andric 
3110*0fca6ea1SDimitry Andric     SmallVector<int, 16> Idxs(NumElts);
3111*0fca6ea1SDimitry Andric     for (unsigned l = 0; l != NumElts; l += 8) {
3112*0fca6ea1SDimitry Andric       for (unsigned i = 0; i != 4; ++i)
3113*0fca6ea1SDimitry Andric         Idxs[i + l] = i + l;
3114*0fca6ea1SDimitry Andric       for (unsigned i = 0; i != 4; ++i)
3115*0fca6ea1SDimitry Andric         Idxs[i + l + 4] = ((Imm >> (2 * i)) & 0x3) + 4 + l;
3116*0fca6ea1SDimitry Andric     }
3117*0fca6ea1SDimitry Andric 
3118*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3119*0fca6ea1SDimitry Andric 
3120*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4)
3121*0fca6ea1SDimitry Andric       Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep,
3122*0fca6ea1SDimitry Andric                           CI->getArgOperand(2));
3123*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.shuf.p")) {
3124*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3125*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
3126*0fca6ea1SDimitry Andric     unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
3127*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3128*0fca6ea1SDimitry Andric 
3129*0fca6ea1SDimitry Andric     unsigned NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3130*0fca6ea1SDimitry Andric     unsigned HalfLaneElts = NumLaneElts / 2;
3131*0fca6ea1SDimitry Andric 
3132*0fca6ea1SDimitry Andric     SmallVector<int, 16> Idxs(NumElts);
3133*0fca6ea1SDimitry Andric     for (unsigned i = 0; i != NumElts; ++i) {
3134*0fca6ea1SDimitry Andric       // Base index is the starting element of the lane.
3135*0fca6ea1SDimitry Andric       Idxs[i] = i - (i % NumLaneElts);
3136*0fca6ea1SDimitry Andric       // If we are half way through the lane switch to the other source.
3137*0fca6ea1SDimitry Andric       if ((i % NumLaneElts) >= HalfLaneElts)
3138*0fca6ea1SDimitry Andric         Idxs[i] += NumElts;
3139*0fca6ea1SDimitry Andric       // Now select the specific element. By adding HalfLaneElts bits from
3140*0fca6ea1SDimitry Andric       // the immediate. Wrapping around the immediate every 8-bits.
3141*0fca6ea1SDimitry Andric       Idxs[i] += (Imm >> ((i * HalfLaneElts) % 8)) & ((1 << HalfLaneElts) - 1);
3142*0fca6ea1SDimitry Andric     }
3143*0fca6ea1SDimitry Andric 
3144*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
3145*0fca6ea1SDimitry Andric 
3146*0fca6ea1SDimitry Andric     Rep =
3147*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(4), Rep, CI->getArgOperand(3));
3148*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.movddup") ||
3149*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.movshdup") ||
3150*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.movsldup")) {
3151*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3152*0fca6ea1SDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3153*0fca6ea1SDimitry Andric     unsigned NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3154*0fca6ea1SDimitry Andric 
3155*0fca6ea1SDimitry Andric     unsigned Offset = 0;
3156*0fca6ea1SDimitry Andric     if (Name.starts_with("avx512.mask.movshdup."))
3157*0fca6ea1SDimitry Andric       Offset = 1;
3158*0fca6ea1SDimitry Andric 
3159*0fca6ea1SDimitry Andric     SmallVector<int, 16> Idxs(NumElts);
3160*0fca6ea1SDimitry Andric     for (unsigned l = 0; l != NumElts; l += NumLaneElts)
3161*0fca6ea1SDimitry Andric       for (unsigned i = 0; i != NumLaneElts; i += 2) {
3162*0fca6ea1SDimitry Andric         Idxs[i + l + 0] = i + l + Offset;
3163*0fca6ea1SDimitry Andric         Idxs[i + l + 1] = i + l + Offset;
3164*0fca6ea1SDimitry Andric       }
3165*0fca6ea1SDimitry Andric 
3166*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs);
3167*0fca6ea1SDimitry Andric 
3168*0fca6ea1SDimitry Andric     Rep =
3169*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3170*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.punpckl") ||
3171*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.unpckl.")) {
3172*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3173*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
3174*0fca6ea1SDimitry Andric     int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3175*0fca6ea1SDimitry Andric     int NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3176*0fca6ea1SDimitry Andric 
3177*0fca6ea1SDimitry Andric     SmallVector<int, 64> Idxs(NumElts);
3178*0fca6ea1SDimitry Andric     for (int l = 0; l != NumElts; l += NumLaneElts)
3179*0fca6ea1SDimitry Andric       for (int i = 0; i != NumLaneElts; ++i)
3180*0fca6ea1SDimitry Andric         Idxs[i + l] = l + (i / 2) + NumElts * (i % 2);
3181*0fca6ea1SDimitry Andric 
3182*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
3183*0fca6ea1SDimitry Andric 
3184*0fca6ea1SDimitry Andric     Rep =
3185*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3186*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.punpckh") ||
3187*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.unpckh.")) {
3188*0fca6ea1SDimitry Andric     Value *Op0 = CI->getArgOperand(0);
3189*0fca6ea1SDimitry Andric     Value *Op1 = CI->getArgOperand(1);
3190*0fca6ea1SDimitry Andric     int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3191*0fca6ea1SDimitry Andric     int NumLaneElts = 128 / CI->getType()->getScalarSizeInBits();
3192*0fca6ea1SDimitry Andric 
3193*0fca6ea1SDimitry Andric     SmallVector<int, 64> Idxs(NumElts);
3194*0fca6ea1SDimitry Andric     for (int l = 0; l != NumElts; l += NumLaneElts)
3195*0fca6ea1SDimitry Andric       for (int i = 0; i != NumLaneElts; ++i)
3196*0fca6ea1SDimitry Andric         Idxs[i + l] = (NumLaneElts / 2) + l + (i / 2) + NumElts * (i % 2);
3197*0fca6ea1SDimitry Andric 
3198*0fca6ea1SDimitry Andric     Rep = Builder.CreateShuffleVector(Op0, Op1, Idxs);
3199*0fca6ea1SDimitry Andric 
3200*0fca6ea1SDimitry Andric     Rep =
3201*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3202*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.and.") ||
3203*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pand.")) {
3204*0fca6ea1SDimitry Andric     VectorType *FTy = cast<VectorType>(CI->getType());
3205*0fca6ea1SDimitry Andric     VectorType *ITy = VectorType::getInteger(FTy);
3206*0fca6ea1SDimitry Andric     Rep = Builder.CreateAnd(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
3207*0fca6ea1SDimitry Andric                             Builder.CreateBitCast(CI->getArgOperand(1), ITy));
3208*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, FTy);
3209*0fca6ea1SDimitry Andric     Rep =
3210*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3211*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.andn.") ||
3212*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pandn.")) {
3213*0fca6ea1SDimitry Andric     VectorType *FTy = cast<VectorType>(CI->getType());
3214*0fca6ea1SDimitry Andric     VectorType *ITy = VectorType::getInteger(FTy);
3215*0fca6ea1SDimitry Andric     Rep = Builder.CreateNot(Builder.CreateBitCast(CI->getArgOperand(0), ITy));
3216*0fca6ea1SDimitry Andric     Rep = Builder.CreateAnd(Rep,
3217*0fca6ea1SDimitry Andric                             Builder.CreateBitCast(CI->getArgOperand(1), ITy));
3218*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, FTy);
3219*0fca6ea1SDimitry Andric     Rep =
3220*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3221*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.or.") ||
3222*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.por.")) {
3223*0fca6ea1SDimitry Andric     VectorType *FTy = cast<VectorType>(CI->getType());
3224*0fca6ea1SDimitry Andric     VectorType *ITy = VectorType::getInteger(FTy);
3225*0fca6ea1SDimitry Andric     Rep = Builder.CreateOr(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
3226*0fca6ea1SDimitry Andric                            Builder.CreateBitCast(CI->getArgOperand(1), ITy));
3227*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, FTy);
3228*0fca6ea1SDimitry Andric     Rep =
3229*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3230*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.xor.") ||
3231*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.pxor.")) {
3232*0fca6ea1SDimitry Andric     VectorType *FTy = cast<VectorType>(CI->getType());
3233*0fca6ea1SDimitry Andric     VectorType *ITy = VectorType::getInteger(FTy);
3234*0fca6ea1SDimitry Andric     Rep = Builder.CreateXor(Builder.CreateBitCast(CI->getArgOperand(0), ITy),
3235*0fca6ea1SDimitry Andric                             Builder.CreateBitCast(CI->getArgOperand(1), ITy));
3236*0fca6ea1SDimitry Andric     Rep = Builder.CreateBitCast(Rep, FTy);
3237*0fca6ea1SDimitry Andric     Rep =
3238*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3239*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.padd.")) {
3240*0fca6ea1SDimitry Andric     Rep = Builder.CreateAdd(CI->getArgOperand(0), CI->getArgOperand(1));
3241*0fca6ea1SDimitry Andric     Rep =
3242*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3243*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.psub.")) {
3244*0fca6ea1SDimitry Andric     Rep = Builder.CreateSub(CI->getArgOperand(0), CI->getArgOperand(1));
3245*0fca6ea1SDimitry Andric     Rep =
3246*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3247*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.pmull.")) {
3248*0fca6ea1SDimitry Andric     Rep = Builder.CreateMul(CI->getArgOperand(0), CI->getArgOperand(1));
3249*0fca6ea1SDimitry Andric     Rep =
3250*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3251*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.add.p")) {
3252*0fca6ea1SDimitry Andric     if (Name.ends_with(".512")) {
3253*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3254*0fca6ea1SDimitry Andric       if (Name[17] == 's')
3255*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_add_ps_512;
3256*0fca6ea1SDimitry Andric       else
3257*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_add_pd_512;
3258*0fca6ea1SDimitry Andric 
3259*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(
3260*0fca6ea1SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), IID),
3261*0fca6ea1SDimitry Andric           {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
3262*0fca6ea1SDimitry Andric     } else {
3263*0fca6ea1SDimitry Andric       Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
3264*0fca6ea1SDimitry Andric     }
3265*0fca6ea1SDimitry Andric     Rep =
3266*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3267*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.div.p")) {
3268*0fca6ea1SDimitry Andric     if (Name.ends_with(".512")) {
3269*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3270*0fca6ea1SDimitry Andric       if (Name[17] == 's')
3271*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_div_ps_512;
3272*0fca6ea1SDimitry Andric       else
3273*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_div_pd_512;
3274*0fca6ea1SDimitry Andric 
3275*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(
3276*0fca6ea1SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), IID),
3277*0fca6ea1SDimitry Andric           {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
3278*0fca6ea1SDimitry Andric     } else {
3279*0fca6ea1SDimitry Andric       Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
3280*0fca6ea1SDimitry Andric     }
3281*0fca6ea1SDimitry Andric     Rep =
3282*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3283*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.mul.p")) {
3284*0fca6ea1SDimitry Andric     if (Name.ends_with(".512")) {
3285*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3286*0fca6ea1SDimitry Andric       if (Name[17] == 's')
3287*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_mul_ps_512;
3288*0fca6ea1SDimitry Andric       else
3289*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_mul_pd_512;
3290*0fca6ea1SDimitry Andric 
3291*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(
3292*0fca6ea1SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), IID),
3293*0fca6ea1SDimitry Andric           {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
3294*0fca6ea1SDimitry Andric     } else {
3295*0fca6ea1SDimitry Andric       Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
3296*0fca6ea1SDimitry Andric     }
3297*0fca6ea1SDimitry Andric     Rep =
3298*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3299*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.sub.p")) {
3300*0fca6ea1SDimitry Andric     if (Name.ends_with(".512")) {
3301*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3302*0fca6ea1SDimitry Andric       if (Name[17] == 's')
3303*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_sub_ps_512;
3304*0fca6ea1SDimitry Andric       else
3305*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_sub_pd_512;
3306*0fca6ea1SDimitry Andric 
3307*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(
3308*0fca6ea1SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), IID),
3309*0fca6ea1SDimitry Andric           {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
3310*0fca6ea1SDimitry Andric     } else {
3311*0fca6ea1SDimitry Andric       Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
3312*0fca6ea1SDimitry Andric     }
3313*0fca6ea1SDimitry Andric     Rep =
3314*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3315*0fca6ea1SDimitry Andric   } else if ((Name.starts_with("avx512.mask.max.p") ||
3316*0fca6ea1SDimitry Andric               Name.starts_with("avx512.mask.min.p")) &&
3317*0fca6ea1SDimitry Andric              Name.drop_front(18) == ".512") {
3318*0fca6ea1SDimitry Andric     bool IsDouble = Name[17] == 'd';
3319*0fca6ea1SDimitry Andric     bool IsMin = Name[13] == 'i';
3320*0fca6ea1SDimitry Andric     static const Intrinsic::ID MinMaxTbl[2][2] = {
3321*0fca6ea1SDimitry Andric         {Intrinsic::x86_avx512_max_ps_512, Intrinsic::x86_avx512_max_pd_512},
3322*0fca6ea1SDimitry Andric         {Intrinsic::x86_avx512_min_ps_512, Intrinsic::x86_avx512_min_pd_512}};
3323*0fca6ea1SDimitry Andric     Intrinsic::ID IID = MinMaxTbl[IsMin][IsDouble];
3324*0fca6ea1SDimitry Andric 
3325*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(
3326*0fca6ea1SDimitry Andric         Intrinsic::getDeclaration(F->getParent(), IID),
3327*0fca6ea1SDimitry Andric         {CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(4)});
3328*0fca6ea1SDimitry Andric     Rep =
3329*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2));
3330*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.lzcnt.")) {
3331*0fca6ea1SDimitry Andric     Rep =
3332*0fca6ea1SDimitry Andric         Builder.CreateCall(Intrinsic::getDeclaration(
3333*0fca6ea1SDimitry Andric                                F->getParent(), Intrinsic::ctlz, CI->getType()),
3334*0fca6ea1SDimitry Andric                            {CI->getArgOperand(0), Builder.getInt1(false)});
3335*0fca6ea1SDimitry Andric     Rep =
3336*0fca6ea1SDimitry Andric         emitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1));
3337*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.psll")) {
3338*0fca6ea1SDimitry Andric     bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
3339*0fca6ea1SDimitry Andric     bool IsVariable = Name[16] == 'v';
3340*0fca6ea1SDimitry Andric     char Size = Name[16] == '.'   ? Name[17]
3341*0fca6ea1SDimitry Andric                 : Name[17] == '.' ? Name[18]
3342*0fca6ea1SDimitry Andric                 : Name[18] == '.' ? Name[19]
3343*0fca6ea1SDimitry Andric                                   : Name[20];
3344*0fca6ea1SDimitry Andric 
3345*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3346*0fca6ea1SDimitry Andric     if (IsVariable && Name[17] != '.') {
3347*0fca6ea1SDimitry Andric       if (Size == 'd' && Name[17] == '2') // avx512.mask.psllv2.di
3348*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psllv_q;
3349*0fca6ea1SDimitry Andric       else if (Size == 'd' && Name[17] == '4') // avx512.mask.psllv4.di
3350*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psllv_q_256;
3351*0fca6ea1SDimitry Andric       else if (Size == 's' && Name[17] == '4') // avx512.mask.psllv4.si
3352*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psllv_d;
3353*0fca6ea1SDimitry Andric       else if (Size == 's' && Name[17] == '8') // avx512.mask.psllv8.si
3354*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psllv_d_256;
3355*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '8') // avx512.mask.psllv8.hi
3356*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psllv_w_128;
3357*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '1') // avx512.mask.psllv16.hi
3358*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psllv_w_256;
3359*0fca6ea1SDimitry Andric       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psllv32hi
3360*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psllv_w_512;
3361*0fca6ea1SDimitry Andric       else
3362*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3363*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".128")) {
3364*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psll.d.128, avx512.mask.psll.di.128
3365*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_pslli_d
3366*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psll_d;
3367*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psll.q.128, avx512.mask.psll.qi.128
3368*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_pslli_q
3369*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psll_q;
3370*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psll.w.128, avx512.mask.psll.wi.128
3371*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_pslli_w
3372*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psll_w;
3373*0fca6ea1SDimitry Andric       else
3374*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3375*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".256")) {
3376*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psll.d.256, avx512.mask.psll.di.256
3377*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_pslli_d
3378*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psll_d;
3379*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psll.q.256, avx512.mask.psll.qi.256
3380*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_pslli_q
3381*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psll_q;
3382*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psll.w.256, avx512.mask.psll.wi.256
3383*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_pslli_w
3384*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psll_w;
3385*0fca6ea1SDimitry Andric       else
3386*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3387*0fca6ea1SDimitry Andric     } else {
3388*0fca6ea1SDimitry Andric       if (Size == 'd') // psll.di.512, pslli.d, psll.d, psllv.d.512
3389*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_pslli_d_512
3390*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psllv_d_512
3391*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psll_d_512;
3392*0fca6ea1SDimitry Andric       else if (Size == 'q') // psll.qi.512, pslli.q, psll.q, psllv.q.512
3393*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_pslli_q_512
3394*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psllv_q_512
3395*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psll_q_512;
3396*0fca6ea1SDimitry Andric       else if (Size == 'w') // psll.wi.512, pslli.w, psll.w
3397*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx512_pslli_w_512
3398*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx512_psll_w_512;
3399*0fca6ea1SDimitry Andric       else
3400*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3401*0fca6ea1SDimitry Andric     }
3402*0fca6ea1SDimitry Andric 
3403*0fca6ea1SDimitry Andric     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
3404*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.psrl")) {
3405*0fca6ea1SDimitry Andric     bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
3406*0fca6ea1SDimitry Andric     bool IsVariable = Name[16] == 'v';
3407*0fca6ea1SDimitry Andric     char Size = Name[16] == '.'   ? Name[17]
3408*0fca6ea1SDimitry Andric                 : Name[17] == '.' ? Name[18]
3409*0fca6ea1SDimitry Andric                 : Name[18] == '.' ? Name[19]
3410*0fca6ea1SDimitry Andric                                   : Name[20];
3411*0fca6ea1SDimitry Andric 
3412*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3413*0fca6ea1SDimitry Andric     if (IsVariable && Name[17] != '.') {
3414*0fca6ea1SDimitry Andric       if (Size == 'd' && Name[17] == '2') // avx512.mask.psrlv2.di
3415*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrlv_q;
3416*0fca6ea1SDimitry Andric       else if (Size == 'd' && Name[17] == '4') // avx512.mask.psrlv4.di
3417*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrlv_q_256;
3418*0fca6ea1SDimitry Andric       else if (Size == 's' && Name[17] == '4') // avx512.mask.psrlv4.si
3419*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrlv_d;
3420*0fca6ea1SDimitry Andric       else if (Size == 's' && Name[17] == '8') // avx512.mask.psrlv8.si
3421*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrlv_d_256;
3422*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrlv8.hi
3423*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrlv_w_128;
3424*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrlv16.hi
3425*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrlv_w_256;
3426*0fca6ea1SDimitry Andric       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrlv32hi
3427*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrlv_w_512;
3428*0fca6ea1SDimitry Andric       else
3429*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3430*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".128")) {
3431*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psrl.d.128, avx512.mask.psrl.di.128
3432*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_psrli_d
3433*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psrl_d;
3434*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psrl.q.128, avx512.mask.psrl.qi.128
3435*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_psrli_q
3436*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psrl_q;
3437*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psrl.w.128, avx512.mask.psrl.wi.128
3438*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_psrli_w
3439*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psrl_w;
3440*0fca6ea1SDimitry Andric       else
3441*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3442*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".256")) {
3443*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psrl.d.256, avx512.mask.psrl.di.256
3444*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_psrli_d
3445*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psrl_d;
3446*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psrl.q.256, avx512.mask.psrl.qi.256
3447*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_psrli_q
3448*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psrl_q;
3449*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psrl.w.256, avx512.mask.psrl.wi.256
3450*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_psrli_w
3451*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psrl_w;
3452*0fca6ea1SDimitry Andric       else
3453*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3454*0fca6ea1SDimitry Andric     } else {
3455*0fca6ea1SDimitry Andric       if (Size == 'd') // psrl.di.512, psrli.d, psrl.d, psrl.d.512
3456*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrli_d_512
3457*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrlv_d_512
3458*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psrl_d_512;
3459*0fca6ea1SDimitry Andric       else if (Size == 'q') // psrl.qi.512, psrli.q, psrl.q, psrl.q.512
3460*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrli_q_512
3461*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrlv_q_512
3462*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psrl_q_512;
3463*0fca6ea1SDimitry Andric       else if (Size == 'w') // psrl.wi.512, psrli.w, psrl.w)
3464*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx512_psrli_w_512
3465*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx512_psrl_w_512;
3466*0fca6ea1SDimitry Andric       else
3467*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3468*0fca6ea1SDimitry Andric     }
3469*0fca6ea1SDimitry Andric 
3470*0fca6ea1SDimitry Andric     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
3471*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.psra")) {
3472*0fca6ea1SDimitry Andric     bool IsImmediate = Name[16] == 'i' || (Name.size() > 18 && Name[18] == 'i');
3473*0fca6ea1SDimitry Andric     bool IsVariable = Name[16] == 'v';
3474*0fca6ea1SDimitry Andric     char Size = Name[16] == '.'   ? Name[17]
3475*0fca6ea1SDimitry Andric                 : Name[17] == '.' ? Name[18]
3476*0fca6ea1SDimitry Andric                 : Name[18] == '.' ? Name[19]
3477*0fca6ea1SDimitry Andric                                   : Name[20];
3478*0fca6ea1SDimitry Andric 
3479*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3480*0fca6ea1SDimitry Andric     if (IsVariable && Name[17] != '.') {
3481*0fca6ea1SDimitry Andric       if (Size == 's' && Name[17] == '4') // avx512.mask.psrav4.si
3482*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrav_d;
3483*0fca6ea1SDimitry Andric       else if (Size == 's' && Name[17] == '8') // avx512.mask.psrav8.si
3484*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx2_psrav_d_256;
3485*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '8') // avx512.mask.psrav8.hi
3486*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrav_w_128;
3487*0fca6ea1SDimitry Andric       else if (Size == 'h' && Name[17] == '1') // avx512.mask.psrav16.hi
3488*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrav_w_256;
3489*0fca6ea1SDimitry Andric       else if (Name[17] == '3' && Name[18] == '2') // avx512.mask.psrav32hi
3490*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_psrav_w_512;
3491*0fca6ea1SDimitry Andric       else
3492*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3493*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".128")) {
3494*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psra.d.128, avx512.mask.psra.di.128
3495*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_psrai_d
3496*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psra_d;
3497*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psra.q.128, avx512.mask.psra.qi.128
3498*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrai_q_128
3499*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrav_q_128
3500*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psra_q_128;
3501*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psra.w.128, avx512.mask.psra.wi.128
3502*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_sse2_psrai_w
3503*0fca6ea1SDimitry Andric                           : Intrinsic::x86_sse2_psra_w;
3504*0fca6ea1SDimitry Andric       else
3505*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3506*0fca6ea1SDimitry Andric     } else if (Name.ends_with(".256")) {
3507*0fca6ea1SDimitry Andric       if (Size == 'd') // avx512.mask.psra.d.256, avx512.mask.psra.di.256
3508*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_psrai_d
3509*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psra_d;
3510*0fca6ea1SDimitry Andric       else if (Size == 'q') // avx512.mask.psra.q.256, avx512.mask.psra.qi.256
3511*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrai_q_256
3512*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrav_q_256
3513*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psra_q_256;
3514*0fca6ea1SDimitry Andric       else if (Size == 'w') // avx512.mask.psra.w.256, avx512.mask.psra.wi.256
3515*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx2_psrai_w
3516*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx2_psra_w;
3517*0fca6ea1SDimitry Andric       else
3518*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3519*0fca6ea1SDimitry Andric     } else {
3520*0fca6ea1SDimitry Andric       if (Size == 'd') // psra.di.512, psrai.d, psra.d, psrav.d.512
3521*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrai_d_512
3522*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrav_d_512
3523*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psra_d_512;
3524*0fca6ea1SDimitry Andric       else if (Size == 'q') // psra.qi.512, psrai.q, psra.q
3525*0fca6ea1SDimitry Andric         IID = IsImmediate  ? Intrinsic::x86_avx512_psrai_q_512
3526*0fca6ea1SDimitry Andric               : IsVariable ? Intrinsic::x86_avx512_psrav_q_512
3527*0fca6ea1SDimitry Andric                            : Intrinsic::x86_avx512_psra_q_512;
3528*0fca6ea1SDimitry Andric       else if (Size == 'w') // psra.wi.512, psrai.w, psra.w
3529*0fca6ea1SDimitry Andric         IID = IsImmediate ? Intrinsic::x86_avx512_psrai_w_512
3530*0fca6ea1SDimitry Andric                           : Intrinsic::x86_avx512_psra_w_512;
3531*0fca6ea1SDimitry Andric       else
3532*0fca6ea1SDimitry Andric         llvm_unreachable("Unexpected size");
3533*0fca6ea1SDimitry Andric     }
3534*0fca6ea1SDimitry Andric 
3535*0fca6ea1SDimitry Andric     Rep = upgradeX86MaskedShift(Builder, *CI, IID);
3536*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.move.s")) {
3537*0fca6ea1SDimitry Andric     Rep = upgradeMaskedMove(Builder, *CI);
3538*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.cvtmask2")) {
3539*0fca6ea1SDimitry Andric     Rep = upgradeMaskToInt(Builder, *CI);
3540*0fca6ea1SDimitry Andric   } else if (Name.ends_with(".movntdqa")) {
3541*0fca6ea1SDimitry Andric     MDNode *Node = MDNode::get(
3542*0fca6ea1SDimitry Andric         C, ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
3543*0fca6ea1SDimitry Andric 
3544*0fca6ea1SDimitry Andric     Value *Ptr = CI->getArgOperand(0);
3545*0fca6ea1SDimitry Andric 
3546*0fca6ea1SDimitry Andric     // Convert the type of the pointer to a pointer to the stored type.
3547*0fca6ea1SDimitry Andric     Value *BC = Builder.CreateBitCast(
3548*0fca6ea1SDimitry Andric         Ptr, PointerType::getUnqual(CI->getType()), "cast");
3549*0fca6ea1SDimitry Andric     LoadInst *LI = Builder.CreateAlignedLoad(
3550*0fca6ea1SDimitry Andric         CI->getType(), BC,
3551*0fca6ea1SDimitry Andric         Align(CI->getType()->getPrimitiveSizeInBits().getFixedValue() / 8));
3552*0fca6ea1SDimitry Andric     LI->setMetadata(LLVMContext::MD_nontemporal, Node);
3553*0fca6ea1SDimitry Andric     Rep = LI;
3554*0fca6ea1SDimitry Andric   } else if (Name.starts_with("fma.vfmadd.") ||
3555*0fca6ea1SDimitry Andric              Name.starts_with("fma.vfmsub.") ||
3556*0fca6ea1SDimitry Andric              Name.starts_with("fma.vfnmadd.") ||
3557*0fca6ea1SDimitry Andric              Name.starts_with("fma.vfnmsub.")) {
3558*0fca6ea1SDimitry Andric     bool NegMul = Name[6] == 'n';
3559*0fca6ea1SDimitry Andric     bool NegAcc = NegMul ? Name[8] == 's' : Name[7] == 's';
3560*0fca6ea1SDimitry Andric     bool IsScalar = NegMul ? Name[12] == 's' : Name[11] == 's';
3561*0fca6ea1SDimitry Andric 
3562*0fca6ea1SDimitry Andric     Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3563*0fca6ea1SDimitry Andric                     CI->getArgOperand(2)};
3564*0fca6ea1SDimitry Andric 
3565*0fca6ea1SDimitry Andric     if (IsScalar) {
3566*0fca6ea1SDimitry Andric       Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
3567*0fca6ea1SDimitry Andric       Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
3568*0fca6ea1SDimitry Andric       Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
3569*0fca6ea1SDimitry Andric     }
3570*0fca6ea1SDimitry Andric 
3571*0fca6ea1SDimitry Andric     if (NegMul && !IsScalar)
3572*0fca6ea1SDimitry Andric       Ops[0] = Builder.CreateFNeg(Ops[0]);
3573*0fca6ea1SDimitry Andric     if (NegMul && IsScalar)
3574*0fca6ea1SDimitry Andric       Ops[1] = Builder.CreateFNeg(Ops[1]);
3575*0fca6ea1SDimitry Andric     if (NegAcc)
3576*0fca6ea1SDimitry Andric       Ops[2] = Builder.CreateFNeg(Ops[2]);
3577*0fca6ea1SDimitry Andric 
3578*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
3579*0fca6ea1SDimitry Andric                                                        Intrinsic::fma,
3580*0fca6ea1SDimitry Andric                                                        Ops[0]->getType()),
3581*0fca6ea1SDimitry Andric                              Ops);
3582*0fca6ea1SDimitry Andric 
3583*0fca6ea1SDimitry Andric     if (IsScalar)
3584*0fca6ea1SDimitry Andric       Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
3585*0fca6ea1SDimitry Andric   } else if (Name.starts_with("fma4.vfmadd.s")) {
3586*0fca6ea1SDimitry Andric     Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3587*0fca6ea1SDimitry Andric                     CI->getArgOperand(2)};
3588*0fca6ea1SDimitry Andric 
3589*0fca6ea1SDimitry Andric     Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
3590*0fca6ea1SDimitry Andric     Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
3591*0fca6ea1SDimitry Andric     Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
3592*0fca6ea1SDimitry Andric 
3593*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
3594*0fca6ea1SDimitry Andric                                                        Intrinsic::fma,
3595*0fca6ea1SDimitry Andric                                                        Ops[0]->getType()),
3596*0fca6ea1SDimitry Andric                              Ops);
3597*0fca6ea1SDimitry Andric 
3598*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(Constant::getNullValue(CI->getType()),
3599*0fca6ea1SDimitry Andric                                       Rep, (uint64_t)0);
3600*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vfmadd.s") ||
3601*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vfmadd.s") ||
3602*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmadd.s") ||
3603*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmsub.s") ||
3604*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfnmsub.s")) {
3605*0fca6ea1SDimitry Andric     bool IsMask3 = Name[11] == '3';
3606*0fca6ea1SDimitry Andric     bool IsMaskZ = Name[11] == 'z';
3607*0fca6ea1SDimitry Andric     // Drop the "avx512.mask." to make it easier.
3608*0fca6ea1SDimitry Andric     Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
3609*0fca6ea1SDimitry Andric     bool NegMul = Name[2] == 'n';
3610*0fca6ea1SDimitry Andric     bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
3611*0fca6ea1SDimitry Andric 
3612*0fca6ea1SDimitry Andric     Value *A = CI->getArgOperand(0);
3613*0fca6ea1SDimitry Andric     Value *B = CI->getArgOperand(1);
3614*0fca6ea1SDimitry Andric     Value *C = CI->getArgOperand(2);
3615*0fca6ea1SDimitry Andric 
3616*0fca6ea1SDimitry Andric     if (NegMul && (IsMask3 || IsMaskZ))
3617*0fca6ea1SDimitry Andric       A = Builder.CreateFNeg(A);
3618*0fca6ea1SDimitry Andric     if (NegMul && !(IsMask3 || IsMaskZ))
3619*0fca6ea1SDimitry Andric       B = Builder.CreateFNeg(B);
3620*0fca6ea1SDimitry Andric     if (NegAcc)
3621*0fca6ea1SDimitry Andric       C = Builder.CreateFNeg(C);
3622*0fca6ea1SDimitry Andric 
3623*0fca6ea1SDimitry Andric     A = Builder.CreateExtractElement(A, (uint64_t)0);
3624*0fca6ea1SDimitry Andric     B = Builder.CreateExtractElement(B, (uint64_t)0);
3625*0fca6ea1SDimitry Andric     C = Builder.CreateExtractElement(C, (uint64_t)0);
3626*0fca6ea1SDimitry Andric 
3627*0fca6ea1SDimitry Andric     if (!isa<ConstantInt>(CI->getArgOperand(4)) ||
3628*0fca6ea1SDimitry Andric         cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4) {
3629*0fca6ea1SDimitry Andric       Value *Ops[] = {A, B, C, CI->getArgOperand(4)};
3630*0fca6ea1SDimitry Andric 
3631*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3632*0fca6ea1SDimitry Andric       if (Name.back() == 'd')
3633*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmadd_f64;
3634*0fca6ea1SDimitry Andric       else
3635*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmadd_f32;
3636*0fca6ea1SDimitry Andric       Function *FMA = Intrinsic::getDeclaration(CI->getModule(), IID);
3637*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(FMA, Ops);
3638*0fca6ea1SDimitry Andric     } else {
3639*0fca6ea1SDimitry Andric       Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
3640*0fca6ea1SDimitry Andric                                                 A->getType());
3641*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(FMA, {A, B, C});
3642*0fca6ea1SDimitry Andric     }
3643*0fca6ea1SDimitry Andric 
3644*0fca6ea1SDimitry Andric     Value *PassThru = IsMaskZ   ? Constant::getNullValue(Rep->getType())
3645*0fca6ea1SDimitry Andric                       : IsMask3 ? C
3646*0fca6ea1SDimitry Andric                                 : A;
3647*0fca6ea1SDimitry Andric 
3648*0fca6ea1SDimitry Andric     // For Mask3 with NegAcc, we need to create a new extractelement that
3649*0fca6ea1SDimitry Andric     // avoids the negation above.
3650*0fca6ea1SDimitry Andric     if (NegAcc && IsMask3)
3651*0fca6ea1SDimitry Andric       PassThru =
3652*0fca6ea1SDimitry Andric           Builder.CreateExtractElement(CI->getArgOperand(2), (uint64_t)0);
3653*0fca6ea1SDimitry Andric 
3654*0fca6ea1SDimitry Andric     Rep = emitX86ScalarSelect(Builder, CI->getArgOperand(3), Rep, PassThru);
3655*0fca6ea1SDimitry Andric     Rep = Builder.CreateInsertElement(CI->getArgOperand(IsMask3 ? 2 : 0), Rep,
3656*0fca6ea1SDimitry Andric                                       (uint64_t)0);
3657*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vfmadd.p") ||
3658*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vfnmadd.p") ||
3659*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vfnmsub.p") ||
3660*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmadd.p") ||
3661*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmsub.p") ||
3662*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfnmsub.p") ||
3663*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vfmadd.p")) {
3664*0fca6ea1SDimitry Andric     bool IsMask3 = Name[11] == '3';
3665*0fca6ea1SDimitry Andric     bool IsMaskZ = Name[11] == 'z';
3666*0fca6ea1SDimitry Andric     // Drop the "avx512.mask." to make it easier.
3667*0fca6ea1SDimitry Andric     Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
3668*0fca6ea1SDimitry Andric     bool NegMul = Name[2] == 'n';
3669*0fca6ea1SDimitry Andric     bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
3670*0fca6ea1SDimitry Andric 
3671*0fca6ea1SDimitry Andric     Value *A = CI->getArgOperand(0);
3672*0fca6ea1SDimitry Andric     Value *B = CI->getArgOperand(1);
3673*0fca6ea1SDimitry Andric     Value *C = CI->getArgOperand(2);
3674*0fca6ea1SDimitry Andric 
3675*0fca6ea1SDimitry Andric     if (NegMul && (IsMask3 || IsMaskZ))
3676*0fca6ea1SDimitry Andric       A = Builder.CreateFNeg(A);
3677*0fca6ea1SDimitry Andric     if (NegMul && !(IsMask3 || IsMaskZ))
3678*0fca6ea1SDimitry Andric       B = Builder.CreateFNeg(B);
3679*0fca6ea1SDimitry Andric     if (NegAcc)
3680*0fca6ea1SDimitry Andric       C = Builder.CreateFNeg(C);
3681*0fca6ea1SDimitry Andric 
3682*0fca6ea1SDimitry Andric     if (CI->arg_size() == 5 &&
3683*0fca6ea1SDimitry Andric         (!isa<ConstantInt>(CI->getArgOperand(4)) ||
3684*0fca6ea1SDimitry Andric          cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
3685*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3686*0fca6ea1SDimitry Andric       // Check the character before ".512" in string.
3687*0fca6ea1SDimitry Andric       if (Name[Name.size() - 5] == 's')
3688*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmadd_ps_512;
3689*0fca6ea1SDimitry Andric       else
3690*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmadd_pd_512;
3691*0fca6ea1SDimitry Andric 
3692*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
3693*0fca6ea1SDimitry Andric                                {A, B, C, CI->getArgOperand(4)});
3694*0fca6ea1SDimitry Andric     } else {
3695*0fca6ea1SDimitry Andric       Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
3696*0fca6ea1SDimitry Andric                                                 A->getType());
3697*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(FMA, {A, B, C});
3698*0fca6ea1SDimitry Andric     }
3699*0fca6ea1SDimitry Andric 
3700*0fca6ea1SDimitry Andric     Value *PassThru = IsMaskZ   ? llvm::Constant::getNullValue(CI->getType())
3701*0fca6ea1SDimitry Andric                       : IsMask3 ? CI->getArgOperand(2)
3702*0fca6ea1SDimitry Andric                                 : CI->getArgOperand(0);
3703*0fca6ea1SDimitry Andric 
3704*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3705*0fca6ea1SDimitry Andric   } else if (Name.starts_with("fma.vfmsubadd.p")) {
3706*0fca6ea1SDimitry Andric     unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3707*0fca6ea1SDimitry Andric     unsigned EltWidth = CI->getType()->getScalarSizeInBits();
3708*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3709*0fca6ea1SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
3710*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_fma_vfmaddsub_ps;
3711*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
3712*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_fma_vfmaddsub_ps_256;
3713*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
3714*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_fma_vfmaddsub_pd;
3715*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
3716*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_fma_vfmaddsub_pd_256;
3717*0fca6ea1SDimitry Andric     else
3718*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3719*0fca6ea1SDimitry Andric 
3720*0fca6ea1SDimitry Andric     Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3721*0fca6ea1SDimitry Andric                     CI->getArgOperand(2)};
3722*0fca6ea1SDimitry Andric     Ops[2] = Builder.CreateFNeg(Ops[2]);
3723*0fca6ea1SDimitry Andric     Rep =
3724*0fca6ea1SDimitry Andric         Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID), Ops);
3725*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vfmaddsub.p") ||
3726*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmaddsub.p") ||
3727*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vfmaddsub.p") ||
3728*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask3.vfmsubadd.p")) {
3729*0fca6ea1SDimitry Andric     bool IsMask3 = Name[11] == '3';
3730*0fca6ea1SDimitry Andric     bool IsMaskZ = Name[11] == 'z';
3731*0fca6ea1SDimitry Andric     // Drop the "avx512.mask." to make it easier.
3732*0fca6ea1SDimitry Andric     Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
3733*0fca6ea1SDimitry Andric     bool IsSubAdd = Name[3] == 's';
3734*0fca6ea1SDimitry Andric     if (CI->arg_size() == 5) {
3735*0fca6ea1SDimitry Andric       Intrinsic::ID IID;
3736*0fca6ea1SDimitry Andric       // Check the character before ".512" in string.
3737*0fca6ea1SDimitry Andric       if (Name[Name.size() - 5] == 's')
3738*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;
3739*0fca6ea1SDimitry Andric       else
3740*0fca6ea1SDimitry Andric         IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;
3741*0fca6ea1SDimitry Andric 
3742*0fca6ea1SDimitry Andric       Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3743*0fca6ea1SDimitry Andric                       CI->getArgOperand(2), CI->getArgOperand(4)};
3744*0fca6ea1SDimitry Andric       if (IsSubAdd)
3745*0fca6ea1SDimitry Andric         Ops[2] = Builder.CreateFNeg(Ops[2]);
3746*0fca6ea1SDimitry Andric 
3747*0fca6ea1SDimitry Andric       Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
3748*0fca6ea1SDimitry Andric                                Ops);
3749*0fca6ea1SDimitry Andric     } else {
3750*0fca6ea1SDimitry Andric       int NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
3751*0fca6ea1SDimitry Andric 
3752*0fca6ea1SDimitry Andric       Value *Ops[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3753*0fca6ea1SDimitry Andric                       CI->getArgOperand(2)};
3754*0fca6ea1SDimitry Andric 
3755*0fca6ea1SDimitry Andric       Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
3756*0fca6ea1SDimitry Andric                                                 Ops[0]->getType());
3757*0fca6ea1SDimitry Andric       Value *Odd = Builder.CreateCall(FMA, Ops);
3758*0fca6ea1SDimitry Andric       Ops[2] = Builder.CreateFNeg(Ops[2]);
3759*0fca6ea1SDimitry Andric       Value *Even = Builder.CreateCall(FMA, Ops);
3760*0fca6ea1SDimitry Andric 
3761*0fca6ea1SDimitry Andric       if (IsSubAdd)
3762*0fca6ea1SDimitry Andric         std::swap(Even, Odd);
3763*0fca6ea1SDimitry Andric 
3764*0fca6ea1SDimitry Andric       SmallVector<int, 32> Idxs(NumElts);
3765*0fca6ea1SDimitry Andric       for (int i = 0; i != NumElts; ++i)
3766*0fca6ea1SDimitry Andric         Idxs[i] = i + (i % 2) * NumElts;
3767*0fca6ea1SDimitry Andric 
3768*0fca6ea1SDimitry Andric       Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
3769*0fca6ea1SDimitry Andric     }
3770*0fca6ea1SDimitry Andric 
3771*0fca6ea1SDimitry Andric     Value *PassThru = IsMaskZ   ? llvm::Constant::getNullValue(CI->getType())
3772*0fca6ea1SDimitry Andric                       : IsMask3 ? CI->getArgOperand(2)
3773*0fca6ea1SDimitry Andric                                 : CI->getArgOperand(0);
3774*0fca6ea1SDimitry Andric 
3775*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3776*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.pternlog.") ||
3777*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.pternlog.")) {
3778*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
3779*0fca6ea1SDimitry Andric     unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3780*0fca6ea1SDimitry Andric     unsigned EltWidth = CI->getType()->getScalarSizeInBits();
3781*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3782*0fca6ea1SDimitry Andric     if (VecWidth == 128 && EltWidth == 32)
3783*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_d_128;
3784*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 32)
3785*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_d_256;
3786*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 32)
3787*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_d_512;
3788*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && EltWidth == 64)
3789*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_q_128;
3790*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && EltWidth == 64)
3791*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_q_256;
3792*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && EltWidth == 64)
3793*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_pternlog_q_512;
3794*0fca6ea1SDimitry Andric     else
3795*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3796*0fca6ea1SDimitry Andric 
3797*0fca6ea1SDimitry Andric     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3798*0fca6ea1SDimitry Andric                      CI->getArgOperand(2), CI->getArgOperand(3)};
3799*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
3800*0fca6ea1SDimitry Andric                              Args);
3801*0fca6ea1SDimitry Andric     Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
3802*0fca6ea1SDimitry Andric                                : CI->getArgOperand(0);
3803*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(4), Rep, PassThru);
3804*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vpmadd52") ||
3805*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpmadd52")) {
3806*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
3807*0fca6ea1SDimitry Andric     bool High = Name[20] == 'h' || Name[21] == 'h';
3808*0fca6ea1SDimitry Andric     unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3809*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3810*0fca6ea1SDimitry Andric     if (VecWidth == 128 && !High)
3811*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52l_uq_128;
3812*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && !High)
3813*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52l_uq_256;
3814*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && !High)
3815*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52l_uq_512;
3816*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && High)
3817*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52h_uq_128;
3818*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && High)
3819*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52h_uq_256;
3820*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && High)
3821*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
3822*0fca6ea1SDimitry Andric     else
3823*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3824*0fca6ea1SDimitry Andric 
3825*0fca6ea1SDimitry Andric     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3826*0fca6ea1SDimitry Andric                      CI->getArgOperand(2)};
3827*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
3828*0fca6ea1SDimitry Andric                              Args);
3829*0fca6ea1SDimitry Andric     Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
3830*0fca6ea1SDimitry Andric                                : CI->getArgOperand(0);
3831*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3832*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vpermi2var.") ||
3833*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpermt2var.") ||
3834*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpermt2var.")) {
3835*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
3836*0fca6ea1SDimitry Andric     bool IndexForm = Name[17] == 'i';
3837*0fca6ea1SDimitry Andric     Rep = upgradeX86VPERMT2Intrinsics(Builder, *CI, ZeroMask, IndexForm);
3838*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vpdpbusd.") ||
3839*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpdpbusd.") ||
3840*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpdpbusds.") ||
3841*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpdpbusds.")) {
3842*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
3843*0fca6ea1SDimitry Andric     bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
3844*0fca6ea1SDimitry Andric     unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3845*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3846*0fca6ea1SDimitry Andric     if (VecWidth == 128 && !IsSaturating)
3847*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusd_128;
3848*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && !IsSaturating)
3849*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusd_256;
3850*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && !IsSaturating)
3851*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusd_512;
3852*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && IsSaturating)
3853*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusds_128;
3854*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && IsSaturating)
3855*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusds_256;
3856*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && IsSaturating)
3857*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpbusds_512;
3858*0fca6ea1SDimitry Andric     else
3859*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3860*0fca6ea1SDimitry Andric 
3861*0fca6ea1SDimitry Andric     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3862*0fca6ea1SDimitry Andric                      CI->getArgOperand(2)};
3863*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
3864*0fca6ea1SDimitry Andric                              Args);
3865*0fca6ea1SDimitry Andric     Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
3866*0fca6ea1SDimitry Andric                                : CI->getArgOperand(0);
3867*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3868*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.vpdpwssd.") ||
3869*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpdpwssd.") ||
3870*0fca6ea1SDimitry Andric              Name.starts_with("avx512.mask.vpdpwssds.") ||
3871*0fca6ea1SDimitry Andric              Name.starts_with("avx512.maskz.vpdpwssds.")) {
3872*0fca6ea1SDimitry Andric     bool ZeroMask = Name[11] == 'z';
3873*0fca6ea1SDimitry Andric     bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
3874*0fca6ea1SDimitry Andric     unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
3875*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3876*0fca6ea1SDimitry Andric     if (VecWidth == 128 && !IsSaturating)
3877*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssd_128;
3878*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && !IsSaturating)
3879*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssd_256;
3880*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && !IsSaturating)
3881*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssd_512;
3882*0fca6ea1SDimitry Andric     else if (VecWidth == 128 && IsSaturating)
3883*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssds_128;
3884*0fca6ea1SDimitry Andric     else if (VecWidth == 256 && IsSaturating)
3885*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssds_256;
3886*0fca6ea1SDimitry Andric     else if (VecWidth == 512 && IsSaturating)
3887*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_avx512_vpdpwssds_512;
3888*0fca6ea1SDimitry Andric     else
3889*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3890*0fca6ea1SDimitry Andric 
3891*0fca6ea1SDimitry Andric     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3892*0fca6ea1SDimitry Andric                      CI->getArgOperand(2)};
3893*0fca6ea1SDimitry Andric     Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
3894*0fca6ea1SDimitry Andric                              Args);
3895*0fca6ea1SDimitry Andric     Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
3896*0fca6ea1SDimitry Andric                                : CI->getArgOperand(0);
3897*0fca6ea1SDimitry Andric     Rep = emitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
3898*0fca6ea1SDimitry Andric   } else if (Name == "addcarryx.u32" || Name == "addcarryx.u64" ||
3899*0fca6ea1SDimitry Andric              Name == "addcarry.u32" || Name == "addcarry.u64" ||
3900*0fca6ea1SDimitry Andric              Name == "subborrow.u32" || Name == "subborrow.u64") {
3901*0fca6ea1SDimitry Andric     Intrinsic::ID IID;
3902*0fca6ea1SDimitry Andric     if (Name[0] == 'a' && Name.back() == '2')
3903*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_addcarry_32;
3904*0fca6ea1SDimitry Andric     else if (Name[0] == 'a' && Name.back() == '4')
3905*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_addcarry_64;
3906*0fca6ea1SDimitry Andric     else if (Name[0] == 's' && Name.back() == '2')
3907*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_subborrow_32;
3908*0fca6ea1SDimitry Andric     else if (Name[0] == 's' && Name.back() == '4')
3909*0fca6ea1SDimitry Andric       IID = Intrinsic::x86_subborrow_64;
3910*0fca6ea1SDimitry Andric     else
3911*0fca6ea1SDimitry Andric       llvm_unreachable("Unexpected intrinsic");
3912*0fca6ea1SDimitry Andric 
3913*0fca6ea1SDimitry Andric     // Make a call with 3 operands.
3914*0fca6ea1SDimitry Andric     Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
3915*0fca6ea1SDimitry Andric                      CI->getArgOperand(2)};
3916*0fca6ea1SDimitry Andric     Value *NewCall = Builder.CreateCall(
3917*0fca6ea1SDimitry Andric         Intrinsic::getDeclaration(CI->getModule(), IID), Args);
3918*0fca6ea1SDimitry Andric 
3919*0fca6ea1SDimitry Andric     // Extract the second result and store it.
3920*0fca6ea1SDimitry Andric     Value *Data = Builder.CreateExtractValue(NewCall, 1);
3921*0fca6ea1SDimitry Andric     // Cast the pointer to the right type.
3922*0fca6ea1SDimitry Andric     Value *Ptr = Builder.CreateBitCast(
3923*0fca6ea1SDimitry Andric         CI->getArgOperand(3), llvm::PointerType::getUnqual(Data->getType()));
3924*0fca6ea1SDimitry Andric     Builder.CreateAlignedStore(Data, Ptr, Align(1));
3925*0fca6ea1SDimitry Andric     // Replace the original call result with the first result of the new call.
3926*0fca6ea1SDimitry Andric     Value *CF = Builder.CreateExtractValue(NewCall, 0);
3927*0fca6ea1SDimitry Andric 
3928*0fca6ea1SDimitry Andric     CI->replaceAllUsesWith(CF);
3929*0fca6ea1SDimitry Andric     Rep = nullptr;
3930*0fca6ea1SDimitry Andric   } else if (Name.starts_with("avx512.mask.") &&
3931*0fca6ea1SDimitry Andric              upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
3932*0fca6ea1SDimitry Andric     // Rep will be updated by the call in the condition.
3933*0fca6ea1SDimitry Andric   }
3934*0fca6ea1SDimitry Andric 
3935*0fca6ea1SDimitry Andric   return Rep;
3936*0fca6ea1SDimitry Andric }
3937*0fca6ea1SDimitry Andric 
39387a6dacacSDimitry Andric static Value *upgradeARMIntrinsicCall(StringRef Name, CallBase *CI, Function *F,
39390eae32dcSDimitry Andric                                       IRBuilder<> &Builder) {
39400eae32dcSDimitry Andric   if (Name == "mve.vctp64.old") {
39410eae32dcSDimitry Andric     // Replace the old v4i1 vctp64 with a v2i1 vctp and predicate-casts to the
39420eae32dcSDimitry Andric     // correct type.
39430eae32dcSDimitry Andric     Value *VCTP = Builder.CreateCall(
39440eae32dcSDimitry Andric         Intrinsic::getDeclaration(F->getParent(), Intrinsic::arm_mve_vctp64),
39450eae32dcSDimitry Andric         CI->getArgOperand(0), CI->getName());
39460eae32dcSDimitry Andric     Value *C1 = Builder.CreateCall(
39470eae32dcSDimitry Andric         Intrinsic::getDeclaration(
39480eae32dcSDimitry Andric             F->getParent(), Intrinsic::arm_mve_pred_v2i,
39490eae32dcSDimitry Andric             {VectorType::get(Builder.getInt1Ty(), 2, false)}),
39500eae32dcSDimitry Andric         VCTP);
39510eae32dcSDimitry Andric     return Builder.CreateCall(
39520eae32dcSDimitry Andric         Intrinsic::getDeclaration(
39530eae32dcSDimitry Andric             F->getParent(), Intrinsic::arm_mve_pred_i2v,
39540eae32dcSDimitry Andric             {VectorType::get(Builder.getInt1Ty(), 4, false)}),
39550eae32dcSDimitry Andric         C1);
39560eae32dcSDimitry Andric   } else if (Name == "mve.mull.int.predicated.v2i64.v4i32.v4i1" ||
39570eae32dcSDimitry Andric              Name == "mve.vqdmull.predicated.v2i64.v4i32.v4i1" ||
39580eae32dcSDimitry Andric              Name == "mve.vldr.gather.base.predicated.v2i64.v2i64.v4i1" ||
39590eae32dcSDimitry Andric              Name == "mve.vldr.gather.base.wb.predicated.v2i64.v2i64.v4i1" ||
396006c3fb27SDimitry Andric              Name ==
396106c3fb27SDimitry Andric                  "mve.vldr.gather.offset.predicated.v2i64.p0i64.v2i64.v4i1" ||
396206c3fb27SDimitry Andric              Name == "mve.vldr.gather.offset.predicated.v2i64.p0.v2i64.v4i1" ||
39630eae32dcSDimitry Andric              Name == "mve.vstr.scatter.base.predicated.v2i64.v2i64.v4i1" ||
39640eae32dcSDimitry Andric              Name == "mve.vstr.scatter.base.wb.predicated.v2i64.v2i64.v4i1" ||
396506c3fb27SDimitry Andric              Name ==
396606c3fb27SDimitry Andric                  "mve.vstr.scatter.offset.predicated.p0i64.v2i64.v2i64.v4i1" ||
396706c3fb27SDimitry Andric              Name == "mve.vstr.scatter.offset.predicated.p0.v2i64.v2i64.v4i1" ||
39680eae32dcSDimitry Andric              Name == "cde.vcx1q.predicated.v2i64.v4i1" ||
39690eae32dcSDimitry Andric              Name == "cde.vcx1qa.predicated.v2i64.v4i1" ||
39700eae32dcSDimitry Andric              Name == "cde.vcx2q.predicated.v2i64.v4i1" ||
39710eae32dcSDimitry Andric              Name == "cde.vcx2qa.predicated.v2i64.v4i1" ||
39720eae32dcSDimitry Andric              Name == "cde.vcx3q.predicated.v2i64.v4i1" ||
39730eae32dcSDimitry Andric              Name == "cde.vcx3qa.predicated.v2i64.v4i1") {
39740eae32dcSDimitry Andric     std::vector<Type *> Tys;
39750eae32dcSDimitry Andric     unsigned ID = CI->getIntrinsicID();
39760eae32dcSDimitry Andric     Type *V2I1Ty = FixedVectorType::get(Builder.getInt1Ty(), 2);
39770eae32dcSDimitry Andric     switch (ID) {
39780eae32dcSDimitry Andric     case Intrinsic::arm_mve_mull_int_predicated:
39790eae32dcSDimitry Andric     case Intrinsic::arm_mve_vqdmull_predicated:
39800eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_base_predicated:
39810eae32dcSDimitry Andric       Tys = {CI->getType(), CI->getOperand(0)->getType(), V2I1Ty};
39820eae32dcSDimitry Andric       break;
39830eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_base_wb_predicated:
39840eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_base_predicated:
39850eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated:
39860eae32dcSDimitry Andric       Tys = {CI->getOperand(0)->getType(), CI->getOperand(0)->getType(),
39870eae32dcSDimitry Andric              V2I1Ty};
39880eae32dcSDimitry Andric       break;
39890eae32dcSDimitry Andric     case Intrinsic::arm_mve_vldr_gather_offset_predicated:
39900eae32dcSDimitry Andric       Tys = {CI->getType(), CI->getOperand(0)->getType(),
39910eae32dcSDimitry Andric              CI->getOperand(1)->getType(), V2I1Ty};
39920eae32dcSDimitry Andric       break;
39930eae32dcSDimitry Andric     case Intrinsic::arm_mve_vstr_scatter_offset_predicated:
39940eae32dcSDimitry Andric       Tys = {CI->getOperand(0)->getType(), CI->getOperand(1)->getType(),
39950eae32dcSDimitry Andric              CI->getOperand(2)->getType(), V2I1Ty};
39960eae32dcSDimitry Andric       break;
39970eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx1q_predicated:
39980eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx1qa_predicated:
39990eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx2q_predicated:
40000eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx2qa_predicated:
40010eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx3q_predicated:
40020eae32dcSDimitry Andric     case Intrinsic::arm_cde_vcx3qa_predicated:
40030eae32dcSDimitry Andric       Tys = {CI->getOperand(1)->getType(), V2I1Ty};
40040eae32dcSDimitry Andric       break;
40050eae32dcSDimitry Andric     default:
40060eae32dcSDimitry Andric       llvm_unreachable("Unhandled Intrinsic!");
40070eae32dcSDimitry Andric     }
40080eae32dcSDimitry Andric 
40090eae32dcSDimitry Andric     std::vector<Value *> Ops;
40100eae32dcSDimitry Andric     for (Value *Op : CI->args()) {
40110eae32dcSDimitry Andric       Type *Ty = Op->getType();
40120eae32dcSDimitry Andric       if (Ty->getScalarSizeInBits() == 1) {
40130eae32dcSDimitry Andric         Value *C1 = Builder.CreateCall(
40140eae32dcSDimitry Andric             Intrinsic::getDeclaration(
40150eae32dcSDimitry Andric                 F->getParent(), Intrinsic::arm_mve_pred_v2i,
40160eae32dcSDimitry Andric                 {VectorType::get(Builder.getInt1Ty(), 4, false)}),
40170eae32dcSDimitry Andric             Op);
40180eae32dcSDimitry Andric         Op = Builder.CreateCall(
40190eae32dcSDimitry Andric             Intrinsic::getDeclaration(F->getParent(),
40200eae32dcSDimitry Andric                                       Intrinsic::arm_mve_pred_i2v, {V2I1Ty}),
40210eae32dcSDimitry Andric             C1);
40220eae32dcSDimitry Andric       }
40230eae32dcSDimitry Andric       Ops.push_back(Op);
40240eae32dcSDimitry Andric     }
40250eae32dcSDimitry Andric 
40260eae32dcSDimitry Andric     Function *Fn = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
40270eae32dcSDimitry Andric     return Builder.CreateCall(Fn, Ops, CI->getName());
40280eae32dcSDimitry Andric   }
402981ad6265SDimitry Andric   llvm_unreachable("Unknown function for ARM CallBase upgrade.");
40300eae32dcSDimitry Andric }
40310eae32dcSDimitry Andric 
4032*0fca6ea1SDimitry Andric // These are expected to have the arguments:
4033*0fca6ea1SDimitry Andric // atomic.intrin (ptr, rmw_value, ordering, scope, isVolatile)
4034*0fca6ea1SDimitry Andric //
4035*0fca6ea1SDimitry Andric // Except for int_amdgcn_ds_fadd_v2bf16 which only has (ptr, rmw_value).
4036*0fca6ea1SDimitry Andric //
40377a6dacacSDimitry Andric static Value *upgradeAMDGCNIntrinsicCall(StringRef Name, CallBase *CI,
403806c3fb27SDimitry Andric                                          Function *F, IRBuilder<> &Builder) {
4039*0fca6ea1SDimitry Andric   AtomicRMWInst::BinOp RMWOp =
4040*0fca6ea1SDimitry Andric       StringSwitch<AtomicRMWInst::BinOp>(Name)
4041*0fca6ea1SDimitry Andric           .StartsWith("ds.fadd", AtomicRMWInst::FAdd)
4042*0fca6ea1SDimitry Andric           .StartsWith("ds.fmin", AtomicRMWInst::FMin)
4043*0fca6ea1SDimitry Andric           .StartsWith("ds.fmax", AtomicRMWInst::FMax)
4044*0fca6ea1SDimitry Andric           .StartsWith("atomic.inc.", AtomicRMWInst::UIncWrap)
4045*0fca6ea1SDimitry Andric           .StartsWith("atomic.dec.", AtomicRMWInst::UDecWrap);
4046*0fca6ea1SDimitry Andric 
4047*0fca6ea1SDimitry Andric   unsigned NumOperands = CI->getNumOperands();
4048*0fca6ea1SDimitry Andric   if (NumOperands < 3) // Malformed bitcode.
404906c3fb27SDimitry Andric     return nullptr;
405006c3fb27SDimitry Andric 
405106c3fb27SDimitry Andric   Value *Ptr = CI->getArgOperand(0);
4052*0fca6ea1SDimitry Andric   PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType());
4053*0fca6ea1SDimitry Andric   if (!PtrTy) // Malformed.
4054*0fca6ea1SDimitry Andric     return nullptr;
4055*0fca6ea1SDimitry Andric 
405606c3fb27SDimitry Andric   Value *Val = CI->getArgOperand(1);
4057*0fca6ea1SDimitry Andric   if (Val->getType() != CI->getType()) // Malformed.
4058*0fca6ea1SDimitry Andric     return nullptr;
4059*0fca6ea1SDimitry Andric 
4060*0fca6ea1SDimitry Andric   ConstantInt *OrderArg = nullptr;
4061*0fca6ea1SDimitry Andric   bool IsVolatile = false;
4062*0fca6ea1SDimitry Andric 
4063*0fca6ea1SDimitry Andric   // These should have 5 arguments (plus the callee). A separate version of the
4064*0fca6ea1SDimitry Andric   // ds_fadd intrinsic was defined for bf16 which was missing arguments.
4065*0fca6ea1SDimitry Andric   if (NumOperands > 3)
4066*0fca6ea1SDimitry Andric     OrderArg = dyn_cast<ConstantInt>(CI->getArgOperand(2));
4067*0fca6ea1SDimitry Andric 
4068*0fca6ea1SDimitry Andric   // Ignore scope argument at 3
4069*0fca6ea1SDimitry Andric 
4070*0fca6ea1SDimitry Andric   if (NumOperands > 5) {
407106c3fb27SDimitry Andric     ConstantInt *VolatileArg = dyn_cast<ConstantInt>(CI->getArgOperand(4));
4072*0fca6ea1SDimitry Andric     IsVolatile = !VolatileArg || !VolatileArg->isZero();
4073*0fca6ea1SDimitry Andric   }
407406c3fb27SDimitry Andric 
407506c3fb27SDimitry Andric   AtomicOrdering Order = AtomicOrdering::SequentiallyConsistent;
407606c3fb27SDimitry Andric   if (OrderArg && isValidAtomicOrdering(OrderArg->getZExtValue()))
407706c3fb27SDimitry Andric     Order = static_cast<AtomicOrdering>(OrderArg->getZExtValue());
4078*0fca6ea1SDimitry Andric   if (Order == AtomicOrdering::NotAtomic || Order == AtomicOrdering::Unordered)
407906c3fb27SDimitry Andric     Order = AtomicOrdering::SequentiallyConsistent;
408006c3fb27SDimitry Andric 
4081*0fca6ea1SDimitry Andric   LLVMContext &Ctx = F->getContext();
4082*0fca6ea1SDimitry Andric 
4083*0fca6ea1SDimitry Andric   // Handle the v2bf16 intrinsic which used <2 x i16> instead of <2 x bfloat>
4084*0fca6ea1SDimitry Andric   Type *RetTy = CI->getType();
4085*0fca6ea1SDimitry Andric   if (VectorType *VT = dyn_cast<VectorType>(RetTy)) {
4086*0fca6ea1SDimitry Andric     if (VT->getElementType()->isIntegerTy(16)) {
4087*0fca6ea1SDimitry Andric       VectorType *AsBF16 =
4088*0fca6ea1SDimitry Andric           VectorType::get(Type::getBFloatTy(Ctx), VT->getElementCount());
4089*0fca6ea1SDimitry Andric       Val = Builder.CreateBitCast(Val, AsBF16);
4090*0fca6ea1SDimitry Andric     }
4091*0fca6ea1SDimitry Andric   }
4092*0fca6ea1SDimitry Andric 
40935f757f3fSDimitry Andric   // The scope argument never really worked correctly. Use agent as the most
40945f757f3fSDimitry Andric   // conservative option which should still always produce the instruction.
4095*0fca6ea1SDimitry Andric   SyncScope::ID SSID = Ctx.getOrInsertSyncScopeID("agent");
40965f757f3fSDimitry Andric   AtomicRMWInst *RMW =
40975f757f3fSDimitry Andric       Builder.CreateAtomicRMW(RMWOp, Ptr, Val, std::nullopt, Order, SSID);
409806c3fb27SDimitry Andric 
4099*0fca6ea1SDimitry Andric   if (PtrTy->getAddressSpace() != 3) {
4100*0fca6ea1SDimitry Andric     RMW->setMetadata("amdgpu.no.fine.grained.memory",
4101*0fca6ea1SDimitry Andric                      MDNode::get(F->getContext(), {}));
410206c3fb27SDimitry Andric   }
410306c3fb27SDimitry Andric 
4104*0fca6ea1SDimitry Andric   if (IsVolatile)
4105*0fca6ea1SDimitry Andric     RMW->setVolatile(true);
4106*0fca6ea1SDimitry Andric 
4107*0fca6ea1SDimitry Andric   return Builder.CreateBitCast(RMW, RetTy);
4108*0fca6ea1SDimitry Andric }
4109*0fca6ea1SDimitry Andric 
4110*0fca6ea1SDimitry Andric /// Helper to unwrap intrinsic call MetadataAsValue operands.
4111*0fca6ea1SDimitry Andric template <typename MDType>
4112*0fca6ea1SDimitry Andric static MDType *unwrapMAVOp(CallBase *CI, unsigned Op) {
4113*0fca6ea1SDimitry Andric   if (MetadataAsValue *MAV = dyn_cast<MetadataAsValue>(CI->getArgOperand(Op)))
4114*0fca6ea1SDimitry Andric     return dyn_cast<MDType>(MAV->getMetadata());
4115*0fca6ea1SDimitry Andric   return nullptr;
4116*0fca6ea1SDimitry Andric }
4117*0fca6ea1SDimitry Andric 
4118*0fca6ea1SDimitry Andric /// Convert debug intrinsic calls to non-instruction debug records.
4119*0fca6ea1SDimitry Andric /// \p Name - Final part of the intrinsic name, e.g. 'value' in llvm.dbg.value.
4120*0fca6ea1SDimitry Andric /// \p CI - The debug intrinsic call.
4121*0fca6ea1SDimitry Andric static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
4122*0fca6ea1SDimitry Andric   DbgRecord *DR = nullptr;
4123*0fca6ea1SDimitry Andric   if (Name == "label") {
4124*0fca6ea1SDimitry Andric     DR = new DbgLabelRecord(unwrapMAVOp<DILabel>(CI, 0), CI->getDebugLoc());
4125*0fca6ea1SDimitry Andric   } else if (Name == "assign") {
4126*0fca6ea1SDimitry Andric     DR = new DbgVariableRecord(
4127*0fca6ea1SDimitry Andric         unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, 1),
4128*0fca6ea1SDimitry Andric         unwrapMAVOp<DIExpression>(CI, 2), unwrapMAVOp<DIAssignID>(CI, 3),
4129*0fca6ea1SDimitry Andric         unwrapMAVOp<Metadata>(CI, 4), unwrapMAVOp<DIExpression>(CI, 5),
4130*0fca6ea1SDimitry Andric         CI->getDebugLoc());
4131*0fca6ea1SDimitry Andric   } else if (Name == "declare") {
4132*0fca6ea1SDimitry Andric     DR = new DbgVariableRecord(
4133*0fca6ea1SDimitry Andric         unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, 1),
4134*0fca6ea1SDimitry Andric         unwrapMAVOp<DIExpression>(CI, 2), CI->getDebugLoc(),
4135*0fca6ea1SDimitry Andric         DbgVariableRecord::LocationType::Declare);
4136*0fca6ea1SDimitry Andric   } else if (Name == "addr") {
4137*0fca6ea1SDimitry Andric     // Upgrade dbg.addr to dbg.value with DW_OP_deref.
4138*0fca6ea1SDimitry Andric     DIExpression *Expr = unwrapMAVOp<DIExpression>(CI, 2);
4139*0fca6ea1SDimitry Andric     Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
4140*0fca6ea1SDimitry Andric     DR = new DbgVariableRecord(unwrapMAVOp<Metadata>(CI, 0),
4141*0fca6ea1SDimitry Andric                                unwrapMAVOp<DILocalVariable>(CI, 1), Expr,
4142*0fca6ea1SDimitry Andric                                CI->getDebugLoc());
4143*0fca6ea1SDimitry Andric   } else if (Name == "value") {
4144*0fca6ea1SDimitry Andric     // An old version of dbg.value had an extra offset argument.
4145*0fca6ea1SDimitry Andric     unsigned VarOp = 1;
4146*0fca6ea1SDimitry Andric     unsigned ExprOp = 2;
4147*0fca6ea1SDimitry Andric     if (CI->arg_size() == 4) {
4148*0fca6ea1SDimitry Andric       auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1));
4149*0fca6ea1SDimitry Andric       // Nonzero offset dbg.values get dropped without a replacement.
4150*0fca6ea1SDimitry Andric       if (!Offset || !Offset->isZeroValue())
4151*0fca6ea1SDimitry Andric         return;
4152*0fca6ea1SDimitry Andric       VarOp = 2;
4153*0fca6ea1SDimitry Andric       ExprOp = 3;
4154*0fca6ea1SDimitry Andric     }
4155*0fca6ea1SDimitry Andric     DR = new DbgVariableRecord(
4156*0fca6ea1SDimitry Andric         unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, VarOp),
4157*0fca6ea1SDimitry Andric         unwrapMAVOp<DIExpression>(CI, ExprOp), CI->getDebugLoc());
4158*0fca6ea1SDimitry Andric   }
4159*0fca6ea1SDimitry Andric   assert(DR && "Unhandled intrinsic kind in upgrade to DbgRecord");
4160*0fca6ea1SDimitry Andric   CI->getParent()->insertDbgRecordBefore(DR, CI->getIterator());
416106c3fb27SDimitry Andric }
416206c3fb27SDimitry Andric 
41630b57cec5SDimitry Andric /// Upgrade a call to an old intrinsic. All argument and return casting must be
41640b57cec5SDimitry Andric /// provided to seamlessly integrate with existing context.
416581ad6265SDimitry Andric void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
4166bdd1243dSDimitry Andric   // Note dyn_cast to Function is not quite the same as getCalledFunction, which
4167bdd1243dSDimitry Andric   // checks the callee's function type matches. It's likely we need to handle
4168bdd1243dSDimitry Andric   // type changes here.
4169bdd1243dSDimitry Andric   Function *F = dyn_cast<Function>(CI->getCalledOperand());
4170bdd1243dSDimitry Andric   if (!F)
4171bdd1243dSDimitry Andric     return;
4172bdd1243dSDimitry Andric 
41730b57cec5SDimitry Andric   LLVMContext &C = CI->getContext();
41740b57cec5SDimitry Andric   IRBuilder<> Builder(C);
41750b57cec5SDimitry Andric   Builder.SetInsertPoint(CI->getParent(), CI->getIterator());
41760b57cec5SDimitry Andric 
41770b57cec5SDimitry Andric   if (!NewFn) {
4178*0fca6ea1SDimitry Andric     bool FallthroughToDefaultUpgrade = false;
41790b57cec5SDimitry Andric     // Get the Function's name.
41800b57cec5SDimitry Andric     StringRef Name = F->getName();
41810b57cec5SDimitry Andric 
41825f757f3fSDimitry Andric     assert(Name.starts_with("llvm.") && "Intrinsic doesn't start with 'llvm.'");
41830b57cec5SDimitry Andric     Name = Name.substr(5);
41840b57cec5SDimitry Andric 
41857a6dacacSDimitry Andric     bool IsX86 = Name.consume_front("x86.");
41867a6dacacSDimitry Andric     bool IsNVVM = Name.consume_front("nvvm.");
41877a6dacacSDimitry Andric     bool IsARM = Name.consume_front("arm.");
41887a6dacacSDimitry Andric     bool IsAMDGCN = Name.consume_front("amdgcn.");
4189*0fca6ea1SDimitry Andric     bool IsDbg = Name.consume_front("dbg.");
4190*0fca6ea1SDimitry Andric     Value *Rep = nullptr;
41910b57cec5SDimitry Andric 
4192*0fca6ea1SDimitry Andric     if (!IsX86 && Name == "stackprotectorcheck") {
41930b57cec5SDimitry Andric       Rep = nullptr;
41940b57cec5SDimitry Andric     } else if (IsNVVM && (Name == "abs.i" || Name == "abs.ll")) {
41950b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
41960b57cec5SDimitry Andric       Value *Neg = Builder.CreateNeg(Arg, "neg");
41970b57cec5SDimitry Andric       Value *Cmp = Builder.CreateICmpSGE(
41980b57cec5SDimitry Andric           Arg, llvm::Constant::getNullValue(Arg->getType()), "abs.cond");
41990b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg, Neg, "abs");
42005f757f3fSDimitry Andric     } else if (IsNVVM && (Name.starts_with("atomic.load.add.f32.p") ||
42015f757f3fSDimitry Andric                           Name.starts_with("atomic.load.add.f64.p"))) {
42020b57cec5SDimitry Andric       Value *Ptr = CI->getArgOperand(0);
42030b57cec5SDimitry Andric       Value *Val = CI->getArgOperand(1);
4204fe6060f1SDimitry Andric       Rep = Builder.CreateAtomicRMW(AtomicRMWInst::FAdd, Ptr, Val, MaybeAlign(),
42050b57cec5SDimitry Andric                                     AtomicOrdering::SequentiallyConsistent);
42067a6dacacSDimitry Andric     } else if (IsNVVM && Name.consume_front("max.") &&
42077a6dacacSDimitry Andric                (Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
42087a6dacacSDimitry Andric                 Name == "ui" || Name == "ull")) {
42090b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
42100b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
42117a6dacacSDimitry Andric       Value *Cmp = Name.starts_with("u")
42120b57cec5SDimitry Andric                        ? Builder.CreateICmpUGE(Arg0, Arg1, "max.cond")
42130b57cec5SDimitry Andric                        : Builder.CreateICmpSGE(Arg0, Arg1, "max.cond");
42140b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "max");
42157a6dacacSDimitry Andric     } else if (IsNVVM && Name.consume_front("min.") &&
42167a6dacacSDimitry Andric                (Name == "s" || Name == "i" || Name == "ll" || Name == "us" ||
42177a6dacacSDimitry Andric                 Name == "ui" || Name == "ull")) {
42180b57cec5SDimitry Andric       Value *Arg0 = CI->getArgOperand(0);
42190b57cec5SDimitry Andric       Value *Arg1 = CI->getArgOperand(1);
42207a6dacacSDimitry Andric       Value *Cmp = Name.starts_with("u")
42210b57cec5SDimitry Andric                        ? Builder.CreateICmpULE(Arg0, Arg1, "min.cond")
42220b57cec5SDimitry Andric                        : Builder.CreateICmpSLE(Arg0, Arg1, "min.cond");
42230b57cec5SDimitry Andric       Rep = Builder.CreateSelect(Cmp, Arg0, Arg1, "min");
42240b57cec5SDimitry Andric     } else if (IsNVVM && Name == "clz.ll") {
42257a6dacacSDimitry Andric       // llvm.nvvm.clz.ll returns an i32, but llvm.ctlz.i64 returns an i64.
42260b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
42270b57cec5SDimitry Andric       Value *Ctlz = Builder.CreateCall(
42280b57cec5SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctlz,
42290b57cec5SDimitry Andric                                     {Arg->getType()}),
42300b57cec5SDimitry Andric           {Arg, Builder.getFalse()}, "ctlz");
42310b57cec5SDimitry Andric       Rep = Builder.CreateTrunc(Ctlz, Builder.getInt32Ty(), "ctlz.trunc");
42320b57cec5SDimitry Andric     } else if (IsNVVM && Name == "popc.ll") {
42337a6dacacSDimitry Andric       // llvm.nvvm.popc.ll returns an i32, but llvm.ctpop.i64 returns an
42340b57cec5SDimitry Andric       // i64.
42350b57cec5SDimitry Andric       Value *Arg = CI->getArgOperand(0);
42360b57cec5SDimitry Andric       Value *Popc = Builder.CreateCall(
42370b57cec5SDimitry Andric           Intrinsic::getDeclaration(F->getParent(), Intrinsic::ctpop,
42380b57cec5SDimitry Andric                                     {Arg->getType()}),
42390b57cec5SDimitry Andric           Arg, "ctpop");
42400b57cec5SDimitry Andric       Rep = Builder.CreateTrunc(Popc, Builder.getInt32Ty(), "ctpop.trunc");
424106c3fb27SDimitry Andric     } else if (IsNVVM) {
424206c3fb27SDimitry Andric       if (Name == "h2f") {
424306c3fb27SDimitry Andric         Rep =
424406c3fb27SDimitry Andric             Builder.CreateCall(Intrinsic::getDeclaration(
42450b57cec5SDimitry Andric                                    F->getParent(), Intrinsic::convert_from_fp16,
42460b57cec5SDimitry Andric                                    {Builder.getFloatTy()}),
42470b57cec5SDimitry Andric                                CI->getArgOperand(0), "h2f");
424806c3fb27SDimitry Andric       } else {
42497a6dacacSDimitry Andric         Intrinsic::ID IID = shouldUpgradeNVPTXBF16Intrinsic(Name);
425006c3fb27SDimitry Andric         if (IID != Intrinsic::not_intrinsic &&
425106c3fb27SDimitry Andric             !F->getReturnType()->getScalarType()->isBFloatTy()) {
425206c3fb27SDimitry Andric           rename(F);
425306c3fb27SDimitry Andric           NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
425406c3fb27SDimitry Andric           SmallVector<Value *, 2> Args;
425506c3fb27SDimitry Andric           for (size_t I = 0; I < NewFn->arg_size(); ++I) {
425606c3fb27SDimitry Andric             Value *Arg = CI->getArgOperand(I);
425706c3fb27SDimitry Andric             Type *OldType = Arg->getType();
425806c3fb27SDimitry Andric             Type *NewType = NewFn->getArg(I)->getType();
425906c3fb27SDimitry Andric             Args.push_back((OldType->isIntegerTy() &&
426006c3fb27SDimitry Andric                             NewType->getScalarType()->isBFloatTy())
426106c3fb27SDimitry Andric                                ? Builder.CreateBitCast(Arg, NewType)
426206c3fb27SDimitry Andric                                : Arg);
426306c3fb27SDimitry Andric           }
426406c3fb27SDimitry Andric           Rep = Builder.CreateCall(NewFn, Args);
426506c3fb27SDimitry Andric           if (F->getReturnType()->isIntegerTy())
426606c3fb27SDimitry Andric             Rep = Builder.CreateBitCast(Rep, F->getReturnType());
426706c3fb27SDimitry Andric         }
426806c3fb27SDimitry Andric       }
4269*0fca6ea1SDimitry Andric     } else if (IsX86) {
4270*0fca6ea1SDimitry Andric       Rep = upgradeX86IntrinsicCall(Name, CI, F, Builder);
42710eae32dcSDimitry Andric     } else if (IsARM) {
42727a6dacacSDimitry Andric       Rep = upgradeARMIntrinsicCall(Name, CI, F, Builder);
427306c3fb27SDimitry Andric     } else if (IsAMDGCN) {
42747a6dacacSDimitry Andric       Rep = upgradeAMDGCNIntrinsicCall(Name, CI, F, Builder);
4275*0fca6ea1SDimitry Andric     } else if (IsDbg) {
4276*0fca6ea1SDimitry Andric       // We might have decided we don't want the new format after all between
4277*0fca6ea1SDimitry Andric       // first requesting the upgrade and now; skip the conversion if that is
4278*0fca6ea1SDimitry Andric       // the case, and check here to see if the intrinsic needs to be upgraded
4279*0fca6ea1SDimitry Andric       // normally.
4280*0fca6ea1SDimitry Andric       if (!CI->getModule()->IsNewDbgInfoFormat) {
4281*0fca6ea1SDimitry Andric         bool NeedsUpgrade =
4282*0fca6ea1SDimitry Andric             upgradeIntrinsicFunction1(CI->getCalledFunction(), NewFn, false);
4283*0fca6ea1SDimitry Andric         if (!NeedsUpgrade)
4284*0fca6ea1SDimitry Andric           return;
4285*0fca6ea1SDimitry Andric         FallthroughToDefaultUpgrade = true;
4286*0fca6ea1SDimitry Andric       } else {
4287*0fca6ea1SDimitry Andric         upgradeDbgIntrinsicToDbgRecord(Name, CI);
4288*0fca6ea1SDimitry Andric       }
42890b57cec5SDimitry Andric     } else {
429081ad6265SDimitry Andric       llvm_unreachable("Unknown function for CallBase upgrade.");
42910b57cec5SDimitry Andric     }
42920b57cec5SDimitry Andric 
4293*0fca6ea1SDimitry Andric     if (!FallthroughToDefaultUpgrade) {
42940b57cec5SDimitry Andric       if (Rep)
42950b57cec5SDimitry Andric         CI->replaceAllUsesWith(Rep);
42960b57cec5SDimitry Andric       CI->eraseFromParent();
42970b57cec5SDimitry Andric       return;
42980b57cec5SDimitry Andric     }
4299*0fca6ea1SDimitry Andric   }
43000b57cec5SDimitry Andric 
430181ad6265SDimitry Andric   const auto &DefaultCase = [&]() -> void {
430281ad6265SDimitry Andric     if (CI->getFunctionType() == NewFn->getFunctionType()) {
430381ad6265SDimitry Andric       // Handle generic mangling change.
43040b57cec5SDimitry Andric       assert(
43050b57cec5SDimitry Andric           (CI->getCalledFunction()->getName() != NewFn->getName()) &&
430681ad6265SDimitry Andric           "Unknown function for CallBase upgrade and isn't just a name change");
43070b57cec5SDimitry Andric       CI->setCalledFunction(NewFn);
430881ad6265SDimitry Andric       return;
430981ad6265SDimitry Andric     }
431081ad6265SDimitry Andric 
431181ad6265SDimitry Andric     // This must be an upgrade from a named to a literal struct.
4312bdd1243dSDimitry Andric     if (auto *OldST = dyn_cast<StructType>(CI->getType())) {
4313bdd1243dSDimitry Andric       assert(OldST != NewFn->getReturnType() &&
4314bdd1243dSDimitry Andric              "Return type must have changed");
431581ad6265SDimitry Andric       assert(OldST->getNumElements() ==
431681ad6265SDimitry Andric                  cast<StructType>(NewFn->getReturnType())->getNumElements() &&
431781ad6265SDimitry Andric              "Must have same number of elements");
431881ad6265SDimitry Andric 
431981ad6265SDimitry Andric       SmallVector<Value *> Args(CI->args());
432081ad6265SDimitry Andric       Value *NewCI = Builder.CreateCall(NewFn, Args);
432181ad6265SDimitry Andric       Value *Res = PoisonValue::get(OldST);
432281ad6265SDimitry Andric       for (unsigned Idx = 0; Idx < OldST->getNumElements(); ++Idx) {
432381ad6265SDimitry Andric         Value *Elem = Builder.CreateExtractValue(NewCI, Idx);
432481ad6265SDimitry Andric         Res = Builder.CreateInsertValue(Res, Elem, Idx);
432581ad6265SDimitry Andric       }
432681ad6265SDimitry Andric       CI->replaceAllUsesWith(Res);
432781ad6265SDimitry Andric       CI->eraseFromParent();
432881ad6265SDimitry Andric       return;
4329bdd1243dSDimitry Andric     }
4330bdd1243dSDimitry Andric 
4331bdd1243dSDimitry Andric     // We're probably about to produce something invalid. Let the verifier catch
4332bdd1243dSDimitry Andric     // it instead of dying here.
4333bdd1243dSDimitry Andric     CI->setCalledOperand(
4334bdd1243dSDimitry Andric         ConstantExpr::getPointerCast(NewFn, CI->getCalledOperand()->getType()));
4335bdd1243dSDimitry Andric     return;
43360b57cec5SDimitry Andric   };
43370b57cec5SDimitry Andric   CallInst *NewCall = nullptr;
43380b57cec5SDimitry Andric   switch (NewFn->getIntrinsicID()) {
43390b57cec5SDimitry Andric   default: {
43400b57cec5SDimitry Andric     DefaultCase();
43410b57cec5SDimitry Andric     return;
43420b57cec5SDimitry Andric   }
43430b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst1:
43440b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst2:
43450b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst3:
43460b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst4:
43470b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst2lane:
43480b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst3lane:
43490b57cec5SDimitry Andric   case Intrinsic::arm_neon_vst4lane: {
4350349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
43510b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
43520b57cec5SDimitry Andric     break;
43530b57cec5SDimitry Andric   }
4354bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfmlalb_lane_v2:
4355bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfmlalt_lane_v2:
4356bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_bfdot_lane_v2: {
4357bdd1243dSDimitry Andric     LLVMContext &Ctx = F->getParent()->getContext();
4358bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4359bdd1243dSDimitry Andric     Args[3] = ConstantInt::get(Type::getInt32Ty(Ctx),
4360bdd1243dSDimitry Andric                                cast<ConstantInt>(Args[3])->getZExtValue());
4361bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4362bdd1243dSDimitry Andric     break;
4363bdd1243dSDimitry Andric   }
4364bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld3_sret:
4365bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld4_sret:
4366bdd1243dSDimitry Andric   case Intrinsic::aarch64_sve_ld2_sret: {
4367bdd1243dSDimitry Andric     StringRef Name = F->getName();
4368bdd1243dSDimitry Andric     Name = Name.substr(5);
4369bdd1243dSDimitry Andric     unsigned N = StringSwitch<unsigned>(Name)
4370bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld2", 2)
4371bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld3", 3)
4372bdd1243dSDimitry Andric                      .StartsWith("aarch64.sve.ld4", 4)
4373bdd1243dSDimitry Andric                      .Default(0);
4374*0fca6ea1SDimitry Andric     auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
4375bdd1243dSDimitry Andric     unsigned MinElts = RetTy->getMinNumElements() / N;
4376bdd1243dSDimitry Andric     SmallVector<Value *, 2> Args(CI->args());
4377bdd1243dSDimitry Andric     Value *NewLdCall = Builder.CreateCall(NewFn, Args);
4378bdd1243dSDimitry Andric     Value *Ret = llvm::PoisonValue::get(RetTy);
4379bdd1243dSDimitry Andric     for (unsigned I = 0; I < N; I++) {
4380bdd1243dSDimitry Andric       Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4381bdd1243dSDimitry Andric       Value *SRet = Builder.CreateExtractValue(NewLdCall, I);
4382bdd1243dSDimitry Andric       Ret = Builder.CreateInsertVector(RetTy, Ret, SRet, Idx);
4383bdd1243dSDimitry Andric     }
4384bdd1243dSDimitry Andric     NewCall = dyn_cast<CallInst>(Ret);
4385bdd1243dSDimitry Andric     break;
4386bdd1243dSDimitry Andric   }
4387bdd1243dSDimitry Andric 
43885f757f3fSDimitry Andric   case Intrinsic::coro_end: {
43895f757f3fSDimitry Andric     SmallVector<Value *, 3> Args(CI->args());
43905f757f3fSDimitry Andric     Args.push_back(ConstantTokenNone::get(CI->getContext()));
43915f757f3fSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
43925f757f3fSDimitry Andric     break;
43935f757f3fSDimitry Andric   }
43945f757f3fSDimitry Andric 
4395bdd1243dSDimitry Andric   case Intrinsic::vector_extract: {
4396bdd1243dSDimitry Andric     StringRef Name = F->getName();
4397bdd1243dSDimitry Andric     Name = Name.substr(5); // Strip llvm
43985f757f3fSDimitry Andric     if (!Name.starts_with("aarch64.sve.tuple.get")) {
4399bdd1243dSDimitry Andric       DefaultCase();
4400bdd1243dSDimitry Andric       return;
4401bdd1243dSDimitry Andric     }
4402*0fca6ea1SDimitry Andric     auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
4403bdd1243dSDimitry Andric     unsigned MinElts = RetTy->getMinNumElements();
4404bdd1243dSDimitry Andric     unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4405bdd1243dSDimitry Andric     Value *NewIdx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4406bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0), NewIdx});
4407bdd1243dSDimitry Andric     break;
4408bdd1243dSDimitry Andric   }
4409bdd1243dSDimitry Andric 
4410bdd1243dSDimitry Andric   case Intrinsic::vector_insert: {
4411bdd1243dSDimitry Andric     StringRef Name = F->getName();
4412bdd1243dSDimitry Andric     Name = Name.substr(5);
44135f757f3fSDimitry Andric     if (!Name.starts_with("aarch64.sve.tuple")) {
4414bdd1243dSDimitry Andric       DefaultCase();
4415bdd1243dSDimitry Andric       return;
4416bdd1243dSDimitry Andric     }
44175f757f3fSDimitry Andric     if (Name.starts_with("aarch64.sve.tuple.set")) {
4418*0fca6ea1SDimitry Andric       unsigned I = cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
4419*0fca6ea1SDimitry Andric       auto *Ty = cast<ScalableVectorType>(CI->getArgOperand(2)->getType());
4420bdd1243dSDimitry Andric       Value *NewIdx =
4421bdd1243dSDimitry Andric           ConstantInt::get(Type::getInt64Ty(C), I * Ty->getMinNumElements());
4422bdd1243dSDimitry Andric       NewCall = Builder.CreateCall(
4423bdd1243dSDimitry Andric           NewFn, {CI->getArgOperand(0), CI->getArgOperand(2), NewIdx});
4424bdd1243dSDimitry Andric       break;
4425bdd1243dSDimitry Andric     }
44265f757f3fSDimitry Andric     if (Name.starts_with("aarch64.sve.tuple.create")) {
4427bdd1243dSDimitry Andric       unsigned N = StringSwitch<unsigned>(Name)
4428bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create2", 2)
4429bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create3", 3)
4430bdd1243dSDimitry Andric                        .StartsWith("aarch64.sve.tuple.create4", 4)
4431bdd1243dSDimitry Andric                        .Default(0);
4432bdd1243dSDimitry Andric       assert(N > 1 && "Create is expected to be between 2-4");
4433*0fca6ea1SDimitry Andric       auto *RetTy = cast<ScalableVectorType>(F->getReturnType());
4434bdd1243dSDimitry Andric       Value *Ret = llvm::PoisonValue::get(RetTy);
4435bdd1243dSDimitry Andric       unsigned MinElts = RetTy->getMinNumElements() / N;
4436bdd1243dSDimitry Andric       for (unsigned I = 0; I < N; I++) {
4437bdd1243dSDimitry Andric         Value *Idx = ConstantInt::get(Type::getInt64Ty(C), I * MinElts);
4438bdd1243dSDimitry Andric         Value *V = CI->getArgOperand(I);
4439bdd1243dSDimitry Andric         Ret = Builder.CreateInsertVector(RetTy, Ret, V, Idx);
4440bdd1243dSDimitry Andric       }
4441bdd1243dSDimitry Andric       NewCall = dyn_cast<CallInst>(Ret);
4442bdd1243dSDimitry Andric     }
4443bdd1243dSDimitry Andric     break;
4444bdd1243dSDimitry Andric   }
44450b57cec5SDimitry Andric 
4446e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfdot:
4447e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmmla:
4448e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmlalb:
4449e8d8bef9SDimitry Andric   case Intrinsic::arm_neon_bfmlalt:
4450e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfdot:
4451e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmmla:
4452e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmlalb:
4453e8d8bef9SDimitry Andric   case Intrinsic::aarch64_neon_bfmlalt: {
4454e8d8bef9SDimitry Andric     SmallVector<Value *, 3> Args;
4455349cc55cSDimitry Andric     assert(CI->arg_size() == 3 &&
4456e8d8bef9SDimitry Andric            "Mismatch between function args and call args");
4457e8d8bef9SDimitry Andric     size_t OperandWidth =
4458e8d8bef9SDimitry Andric         CI->getArgOperand(1)->getType()->getPrimitiveSizeInBits();
4459e8d8bef9SDimitry Andric     assert((OperandWidth == 64 || OperandWidth == 128) &&
4460e8d8bef9SDimitry Andric            "Unexpected operand width");
4461e8d8bef9SDimitry Andric     Type *NewTy = FixedVectorType::get(Type::getBFloatTy(C), OperandWidth / 16);
4462349cc55cSDimitry Andric     auto Iter = CI->args().begin();
4463e8d8bef9SDimitry Andric     Args.push_back(*Iter++);
4464e8d8bef9SDimitry Andric     Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
4465e8d8bef9SDimitry Andric     Args.push_back(Builder.CreateBitCast(*Iter++, NewTy));
4466e8d8bef9SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4467e8d8bef9SDimitry Andric     break;
4468e8d8bef9SDimitry Andric   }
4469e8d8bef9SDimitry Andric 
44700b57cec5SDimitry Andric   case Intrinsic::bitreverse:
44710b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
44720b57cec5SDimitry Andric     break;
44730b57cec5SDimitry Andric 
44740b57cec5SDimitry Andric   case Intrinsic::ctlz:
44750b57cec5SDimitry Andric   case Intrinsic::cttz:
4476349cc55cSDimitry Andric     assert(CI->arg_size() == 1 &&
44770b57cec5SDimitry Andric            "Mismatch between function args and call args");
44780b57cec5SDimitry Andric     NewCall =
44790b57cec5SDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()});
44800b57cec5SDimitry Andric     break;
44810b57cec5SDimitry Andric 
44820b57cec5SDimitry Andric   case Intrinsic::objectsize: {
4483349cc55cSDimitry Andric     Value *NullIsUnknownSize =
4484349cc55cSDimitry Andric         CI->arg_size() == 2 ? Builder.getFalse() : CI->getArgOperand(2);
44850b57cec5SDimitry Andric     Value *Dynamic =
4486349cc55cSDimitry Andric         CI->arg_size() < 4 ? Builder.getFalse() : CI->getArgOperand(3);
44870b57cec5SDimitry Andric     NewCall = Builder.CreateCall(
44880b57cec5SDimitry Andric         NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic});
44890b57cec5SDimitry Andric     break;
44900b57cec5SDimitry Andric   }
44910b57cec5SDimitry Andric 
44920b57cec5SDimitry Andric   case Intrinsic::ctpop:
44930b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
44940b57cec5SDimitry Andric     break;
44950b57cec5SDimitry Andric 
44960b57cec5SDimitry Andric   case Intrinsic::convert_from_fp16:
44970b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});
44980b57cec5SDimitry Andric     break;
44990b57cec5SDimitry Andric 
450006c3fb27SDimitry Andric   case Intrinsic::dbg_value: {
450106c3fb27SDimitry Andric     StringRef Name = F->getName();
450206c3fb27SDimitry Andric     Name = Name.substr(5); // Strip llvm.
450306c3fb27SDimitry Andric     // Upgrade `dbg.addr` to `dbg.value` with `DW_OP_deref`.
45045f757f3fSDimitry Andric     if (Name.starts_with("dbg.addr")) {
450506c3fb27SDimitry Andric       DIExpression *Expr = cast<DIExpression>(
450606c3fb27SDimitry Andric           cast<MetadataAsValue>(CI->getArgOperand(2))->getMetadata());
450706c3fb27SDimitry Andric       Expr = DIExpression::append(Expr, dwarf::DW_OP_deref);
450806c3fb27SDimitry Andric       NewCall =
450906c3fb27SDimitry Andric           Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
451006c3fb27SDimitry Andric                                      MetadataAsValue::get(C, Expr)});
451106c3fb27SDimitry Andric       break;
451206c3fb27SDimitry Andric     }
451306c3fb27SDimitry Andric 
45140b57cec5SDimitry Andric     // Upgrade from the old version that had an extra offset argument.
4515349cc55cSDimitry Andric     assert(CI->arg_size() == 4);
45160b57cec5SDimitry Andric     // Drop nonzero offsets instead of attempting to upgrade them.
45170b57cec5SDimitry Andric     if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)))
45180b57cec5SDimitry Andric       if (Offset->isZeroValue()) {
45190b57cec5SDimitry Andric         NewCall = Builder.CreateCall(
45200b57cec5SDimitry Andric             NewFn,
45210b57cec5SDimitry Andric             {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)});
45220b57cec5SDimitry Andric         break;
45230b57cec5SDimitry Andric       }
45240b57cec5SDimitry Andric     CI->eraseFromParent();
45250b57cec5SDimitry Andric     return;
452606c3fb27SDimitry Andric   }
45270b57cec5SDimitry Andric 
4528d409305fSDimitry Andric   case Intrinsic::ptr_annotation:
4529d409305fSDimitry Andric     // Upgrade from versions that lacked the annotation attribute argument.
453081ad6265SDimitry Andric     if (CI->arg_size() != 4) {
453181ad6265SDimitry Andric       DefaultCase();
453281ad6265SDimitry Andric       return;
453381ad6265SDimitry Andric     }
453481ad6265SDimitry Andric 
4535d409305fSDimitry Andric     // Create a new call with an added null annotation attribute argument.
45365f757f3fSDimitry Andric     NewCall =
45375f757f3fSDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
45385f757f3fSDimitry Andric                                    CI->getArgOperand(2), CI->getArgOperand(3),
45395f757f3fSDimitry Andric                                    Constant::getNullValue(Builder.getPtrTy())});
4540d409305fSDimitry Andric     NewCall->takeName(CI);
4541d409305fSDimitry Andric     CI->replaceAllUsesWith(NewCall);
4542d409305fSDimitry Andric     CI->eraseFromParent();
4543d409305fSDimitry Andric     return;
4544d409305fSDimitry Andric 
4545d409305fSDimitry Andric   case Intrinsic::var_annotation:
4546d409305fSDimitry Andric     // Upgrade from versions that lacked the annotation attribute argument.
4547bdd1243dSDimitry Andric     if (CI->arg_size() != 4) {
4548bdd1243dSDimitry Andric       DefaultCase();
4549bdd1243dSDimitry Andric       return;
4550bdd1243dSDimitry Andric     }
4551d409305fSDimitry Andric     // Create a new call with an added null annotation attribute argument.
45525f757f3fSDimitry Andric     NewCall =
45535f757f3fSDimitry Andric         Builder.CreateCall(NewFn, {CI->getArgOperand(0), CI->getArgOperand(1),
45545f757f3fSDimitry Andric                                    CI->getArgOperand(2), CI->getArgOperand(3),
45555f757f3fSDimitry Andric                                    Constant::getNullValue(Builder.getPtrTy())});
4556bdd1243dSDimitry Andric     NewCall->takeName(CI);
4557bdd1243dSDimitry Andric     CI->replaceAllUsesWith(NewCall);
4558d409305fSDimitry Andric     CI->eraseFromParent();
4559d409305fSDimitry Andric     return;
4560d409305fSDimitry Andric 
456106c3fb27SDimitry Andric   case Intrinsic::riscv_aes32dsi:
456206c3fb27SDimitry Andric   case Intrinsic::riscv_aes32dsmi:
456306c3fb27SDimitry Andric   case Intrinsic::riscv_aes32esi:
456406c3fb27SDimitry Andric   case Intrinsic::riscv_aes32esmi:
456506c3fb27SDimitry Andric   case Intrinsic::riscv_sm4ks:
456606c3fb27SDimitry Andric   case Intrinsic::riscv_sm4ed: {
456706c3fb27SDimitry Andric     // The last argument to these intrinsics used to be i8 and changed to i32.
456806c3fb27SDimitry Andric     // The type overload for sm4ks and sm4ed was removed.
456906c3fb27SDimitry Andric     Value *Arg2 = CI->getArgOperand(2);
457006c3fb27SDimitry Andric     if (Arg2->getType()->isIntegerTy(32) && !CI->getType()->isIntegerTy(64))
457106c3fb27SDimitry Andric       return;
457206c3fb27SDimitry Andric 
457306c3fb27SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
457406c3fb27SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
457506c3fb27SDimitry Andric     if (CI->getType()->isIntegerTy(64)) {
457606c3fb27SDimitry Andric       Arg0 = Builder.CreateTrunc(Arg0, Builder.getInt32Ty());
457706c3fb27SDimitry Andric       Arg1 = Builder.CreateTrunc(Arg1, Builder.getInt32Ty());
457806c3fb27SDimitry Andric     }
457906c3fb27SDimitry Andric 
458006c3fb27SDimitry Andric     Arg2 = ConstantInt::get(Type::getInt32Ty(C),
458106c3fb27SDimitry Andric                             cast<ConstantInt>(Arg2)->getZExtValue());
458206c3fb27SDimitry Andric 
458306c3fb27SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {Arg0, Arg1, Arg2});
458406c3fb27SDimitry Andric     Value *Res = NewCall;
458506c3fb27SDimitry Andric     if (Res->getType() != CI->getType())
458606c3fb27SDimitry Andric       Res = Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
458706c3fb27SDimitry Andric     NewCall->takeName(CI);
458806c3fb27SDimitry Andric     CI->replaceAllUsesWith(Res);
458906c3fb27SDimitry Andric     CI->eraseFromParent();
459006c3fb27SDimitry Andric     return;
459106c3fb27SDimitry Andric   }
459206c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sig0:
459306c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sig1:
459406c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sum0:
459506c3fb27SDimitry Andric   case Intrinsic::riscv_sha256sum1:
459606c3fb27SDimitry Andric   case Intrinsic::riscv_sm3p0:
459706c3fb27SDimitry Andric   case Intrinsic::riscv_sm3p1: {
459806c3fb27SDimitry Andric     // The last argument to these intrinsics used to be i8 and changed to i32.
459906c3fb27SDimitry Andric     // The type overload for sm4ks and sm4ed was removed.
460006c3fb27SDimitry Andric     if (!CI->getType()->isIntegerTy(64))
460106c3fb27SDimitry Andric       return;
460206c3fb27SDimitry Andric 
460306c3fb27SDimitry Andric     Value *Arg =
460406c3fb27SDimitry Andric         Builder.CreateTrunc(CI->getArgOperand(0), Builder.getInt32Ty());
460506c3fb27SDimitry Andric 
460606c3fb27SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Arg);
460706c3fb27SDimitry Andric     Value *Res =
460806c3fb27SDimitry Andric         Builder.CreateIntCast(NewCall, CI->getType(), /*isSigned*/ true);
460906c3fb27SDimitry Andric     NewCall->takeName(CI);
461006c3fb27SDimitry Andric     CI->replaceAllUsesWith(Res);
461106c3fb27SDimitry Andric     CI->eraseFromParent();
461206c3fb27SDimitry Andric     return;
461306c3fb27SDimitry Andric   }
461406c3fb27SDimitry Andric 
46150b57cec5SDimitry Andric   case Intrinsic::x86_xop_vfrcz_ss:
46160b57cec5SDimitry Andric   case Intrinsic::x86_xop_vfrcz_sd:
46170b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)});
46180b57cec5SDimitry Andric     break;
46190b57cec5SDimitry Andric 
46200b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2pd:
46210b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2ps:
46220b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2pd_256:
46230b57cec5SDimitry Andric   case Intrinsic::x86_xop_vpermil2ps_256: {
4624349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
46250b57cec5SDimitry Andric     VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType());
46260b57cec5SDimitry Andric     VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy);
46270b57cec5SDimitry Andric     Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy);
46280b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
46290b57cec5SDimitry Andric     break;
46300b57cec5SDimitry Andric   }
46310b57cec5SDimitry Andric 
46320b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestc:
46330b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestz:
46340b57cec5SDimitry Andric   case Intrinsic::x86_sse41_ptestnzc: {
46350b57cec5SDimitry Andric     // The arguments for these intrinsics used to be v4f32, and changed
46360b57cec5SDimitry Andric     // to v2i64. This is purely a nop, since those are bitwise intrinsics.
46370b57cec5SDimitry Andric     // So, the only thing required is a bitcast for both arguments.
46380b57cec5SDimitry Andric     // First, check the arguments have the old type.
46390b57cec5SDimitry Andric     Value *Arg0 = CI->getArgOperand(0);
46405ffd83dbSDimitry Andric     if (Arg0->getType() != FixedVectorType::get(Type::getFloatTy(C), 4))
46410b57cec5SDimitry Andric       return;
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric     // Old intrinsic, add bitcasts
46440b57cec5SDimitry Andric     Value *Arg1 = CI->getArgOperand(1);
46450b57cec5SDimitry Andric 
46465ffd83dbSDimitry Andric     auto *NewVecTy = FixedVectorType::get(Type::getInt64Ty(C), 2);
46470b57cec5SDimitry Andric 
46480b57cec5SDimitry Andric     Value *BC0 = Builder.CreateBitCast(Arg0, NewVecTy, "cast");
46490b57cec5SDimitry Andric     Value *BC1 = Builder.CreateBitCast(Arg1, NewVecTy, "cast");
46500b57cec5SDimitry Andric 
46510b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {BC0, BC1});
46520b57cec5SDimitry Andric     break;
46530b57cec5SDimitry Andric   }
46540b57cec5SDimitry Andric 
46550b57cec5SDimitry Andric   case Intrinsic::x86_rdtscp: {
46560b57cec5SDimitry Andric     // This used to take 1 arguments. If we have no arguments, it is already
46570b57cec5SDimitry Andric     // upgraded.
46580b57cec5SDimitry Andric     if (CI->getNumOperands() == 0)
46590b57cec5SDimitry Andric       return;
46600b57cec5SDimitry Andric 
46610b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn);
46620b57cec5SDimitry Andric     // Extract the second result and store it.
46630b57cec5SDimitry Andric     Value *Data = Builder.CreateExtractValue(NewCall, 1);
46640b57cec5SDimitry Andric     // Cast the pointer to the right type.
46650b57cec5SDimitry Andric     Value *Ptr = Builder.CreateBitCast(CI->getArgOperand(0),
46660b57cec5SDimitry Andric                                  llvm::PointerType::getUnqual(Data->getType()));
46675ffd83dbSDimitry Andric     Builder.CreateAlignedStore(Data, Ptr, Align(1));
46680b57cec5SDimitry Andric     // Replace the original call result with the first result of the new call.
46690b57cec5SDimitry Andric     Value *TSC = Builder.CreateExtractValue(NewCall, 0);
46700b57cec5SDimitry Andric 
4671e8d8bef9SDimitry Andric     NewCall->takeName(CI);
46720b57cec5SDimitry Andric     CI->replaceAllUsesWith(TSC);
46730b57cec5SDimitry Andric     CI->eraseFromParent();
46740b57cec5SDimitry Andric     return;
46750b57cec5SDimitry Andric   }
46760b57cec5SDimitry Andric 
46770b57cec5SDimitry Andric   case Intrinsic::x86_sse41_insertps:
46780b57cec5SDimitry Andric   case Intrinsic::x86_sse41_dppd:
46790b57cec5SDimitry Andric   case Intrinsic::x86_sse41_dpps:
46800b57cec5SDimitry Andric   case Intrinsic::x86_sse41_mpsadbw:
46810b57cec5SDimitry Andric   case Intrinsic::x86_avx_dp_ps_256:
46820b57cec5SDimitry Andric   case Intrinsic::x86_avx2_mpsadbw: {
46830b57cec5SDimitry Andric     // Need to truncate the last argument from i32 to i8 -- this argument models
46840b57cec5SDimitry Andric     // an inherently 8-bit immediate operand to these x86 instructions.
4685349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
46860b57cec5SDimitry Andric 
46870b57cec5SDimitry Andric     // Replace the last argument with a trunc.
46880b57cec5SDimitry Andric     Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
46890b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
46900b57cec5SDimitry Andric     break;
46910b57cec5SDimitry Andric   }
46920b57cec5SDimitry Andric 
4693e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_128:
4694e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_256:
4695e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_pd_512:
4696e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_128:
4697e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_256:
4698e8d8bef9SDimitry Andric   case Intrinsic::x86_avx512_mask_cmp_ps_512: {
4699349cc55cSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4700e8d8bef9SDimitry Andric     unsigned NumElts =
4701e8d8bef9SDimitry Andric         cast<FixedVectorType>(Args[0]->getType())->getNumElements();
4702e8d8bef9SDimitry Andric     Args[3] = getX86MaskVec(Builder, Args[3], NumElts);
4703e8d8bef9SDimitry Andric 
4704e8d8bef9SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
47057a6dacacSDimitry Andric     Value *Res = applyX86MaskOn1BitsVec(Builder, NewCall, nullptr);
4706e8d8bef9SDimitry Andric 
4707e8d8bef9SDimitry Andric     NewCall->takeName(CI);
4708e8d8bef9SDimitry Andric     CI->replaceAllUsesWith(Res);
4709e8d8bef9SDimitry Andric     CI->eraseFromParent();
4710e8d8bef9SDimitry Andric     return;
4711e8d8bef9SDimitry Andric   }
4712e8d8bef9SDimitry Andric 
4713bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_128:
4714bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_256:
4715bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtne2ps2bf16_512:
4716bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128:
4717bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtneps2bf16_256:
4718bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_cvtneps2bf16_512: {
4719bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4720bdd1243dSDimitry Andric     unsigned NumElts = cast<FixedVectorType>(CI->getType())->getNumElements();
4721bdd1243dSDimitry Andric     if (NewFn->getIntrinsicID() ==
4722bdd1243dSDimitry Andric         Intrinsic::x86_avx512bf16_mask_cvtneps2bf16_128)
4723bdd1243dSDimitry Andric       Args[1] = Builder.CreateBitCast(
4724bdd1243dSDimitry Andric           Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4725bdd1243dSDimitry Andric 
4726bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4727bdd1243dSDimitry Andric     Value *Res = Builder.CreateBitCast(
4728bdd1243dSDimitry Andric         NewCall, FixedVectorType::get(Builder.getInt16Ty(), NumElts));
4729bdd1243dSDimitry Andric 
4730bdd1243dSDimitry Andric     NewCall->takeName(CI);
4731bdd1243dSDimitry Andric     CI->replaceAllUsesWith(Res);
4732bdd1243dSDimitry Andric     CI->eraseFromParent();
4733bdd1243dSDimitry Andric     return;
4734bdd1243dSDimitry Andric   }
4735bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_128:
4736bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_256:
4737bdd1243dSDimitry Andric   case Intrinsic::x86_avx512bf16_dpbf16ps_512:{
4738bdd1243dSDimitry Andric     SmallVector<Value *, 4> Args(CI->args());
4739bdd1243dSDimitry Andric     unsigned NumElts =
4740bdd1243dSDimitry Andric         cast<FixedVectorType>(CI->getType())->getNumElements() * 2;
4741bdd1243dSDimitry Andric     Args[1] = Builder.CreateBitCast(
4742bdd1243dSDimitry Andric         Args[1], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4743bdd1243dSDimitry Andric     Args[2] = Builder.CreateBitCast(
4744bdd1243dSDimitry Andric         Args[2], FixedVectorType::get(Builder.getBFloatTy(), NumElts));
4745bdd1243dSDimitry Andric 
4746bdd1243dSDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
4747bdd1243dSDimitry Andric     break;
4748bdd1243dSDimitry Andric   }
4749bdd1243dSDimitry Andric 
47500b57cec5SDimitry Andric   case Intrinsic::thread_pointer: {
47510b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, {});
47520b57cec5SDimitry Andric     break;
47530b57cec5SDimitry Andric   }
47540b57cec5SDimitry Andric 
47550b57cec5SDimitry Andric   case Intrinsic::memcpy:
47560b57cec5SDimitry Andric   case Intrinsic::memmove:
47570b57cec5SDimitry Andric   case Intrinsic::memset: {
47580b57cec5SDimitry Andric     // We have to make sure that the call signature is what we're expecting.
47590b57cec5SDimitry Andric     // We only want to change the old signatures by removing the alignment arg:
47600b57cec5SDimitry Andric     //  @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i32, i1)
47610b57cec5SDimitry Andric     //    -> @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i1)
47620b57cec5SDimitry Andric     //  @llvm.memset...(i8*, i8, i[32|64], i32, i1)
47630b57cec5SDimitry Andric     //    -> @llvm.memset...(i8*, i8, i[32|64], i1)
47640b57cec5SDimitry Andric     // Note: i8*'s in the above can be any pointer type
4765349cc55cSDimitry Andric     if (CI->arg_size() != 5) {
47660b57cec5SDimitry Andric       DefaultCase();
47670b57cec5SDimitry Andric       return;
47680b57cec5SDimitry Andric     }
47690b57cec5SDimitry Andric     // Remove alignment argument (3), and add alignment attributes to the
47700b57cec5SDimitry Andric     // dest/src pointers.
47710b57cec5SDimitry Andric     Value *Args[4] = {CI->getArgOperand(0), CI->getArgOperand(1),
47720b57cec5SDimitry Andric                       CI->getArgOperand(2), CI->getArgOperand(4)};
47730b57cec5SDimitry Andric     NewCall = Builder.CreateCall(NewFn, Args);
477481ad6265SDimitry Andric     AttributeList OldAttrs = CI->getAttributes();
477581ad6265SDimitry Andric     AttributeList NewAttrs = AttributeList::get(
477681ad6265SDimitry Andric         C, OldAttrs.getFnAttrs(), OldAttrs.getRetAttrs(),
477781ad6265SDimitry Andric         {OldAttrs.getParamAttrs(0), OldAttrs.getParamAttrs(1),
477881ad6265SDimitry Andric          OldAttrs.getParamAttrs(2), OldAttrs.getParamAttrs(4)});
477981ad6265SDimitry Andric     NewCall->setAttributes(NewAttrs);
47800b57cec5SDimitry Andric     auto *MemCI = cast<MemIntrinsic>(NewCall);
47810b57cec5SDimitry Andric     // All mem intrinsics support dest alignment.
47820b57cec5SDimitry Andric     const ConstantInt *Align = cast<ConstantInt>(CI->getArgOperand(3));
47835ffd83dbSDimitry Andric     MemCI->setDestAlignment(Align->getMaybeAlignValue());
47840b57cec5SDimitry Andric     // Memcpy/Memmove also support source alignment.
47850b57cec5SDimitry Andric     if (auto *MTI = dyn_cast<MemTransferInst>(MemCI))
47865ffd83dbSDimitry Andric       MTI->setSourceAlignment(Align->getMaybeAlignValue());
47870b57cec5SDimitry Andric     break;
47880b57cec5SDimitry Andric   }
47890b57cec5SDimitry Andric   }
47900b57cec5SDimitry Andric   assert(NewCall && "Should have either set this variable or returned through "
47910b57cec5SDimitry Andric                     "the default case");
4792e8d8bef9SDimitry Andric   NewCall->takeName(CI);
47930b57cec5SDimitry Andric   CI->replaceAllUsesWith(NewCall);
47940b57cec5SDimitry Andric   CI->eraseFromParent();
47950b57cec5SDimitry Andric }
47960b57cec5SDimitry Andric 
47970b57cec5SDimitry Andric void llvm::UpgradeCallsToIntrinsic(Function *F) {
47980b57cec5SDimitry Andric   assert(F && "Illegal attempt to upgrade a non-existent intrinsic.");
47990b57cec5SDimitry Andric 
48000b57cec5SDimitry Andric   // Check if this function should be upgraded and get the replacement function
48010b57cec5SDimitry Andric   // if there is one.
48020b57cec5SDimitry Andric   Function *NewFn;
48030b57cec5SDimitry Andric   if (UpgradeIntrinsicFunction(F, NewFn)) {
48040b57cec5SDimitry Andric     // Replace all users of the old function with the new function or new
48050b57cec5SDimitry Andric     // instructions. This is not a range loop because the call is deleted.
4806e8d8bef9SDimitry Andric     for (User *U : make_early_inc_range(F->users()))
480781ad6265SDimitry Andric       if (CallBase *CB = dyn_cast<CallBase>(U))
480881ad6265SDimitry Andric         UpgradeIntrinsicCall(CB, NewFn);
48090b57cec5SDimitry Andric 
48100b57cec5SDimitry Andric     // Remove old function, no longer used, from the module.
48110b57cec5SDimitry Andric     F->eraseFromParent();
48120b57cec5SDimitry Andric   }
48130b57cec5SDimitry Andric }
48140b57cec5SDimitry Andric 
48150b57cec5SDimitry Andric MDNode *llvm::UpgradeTBAANode(MDNode &MD) {
481606c3fb27SDimitry Andric   const unsigned NumOperands = MD.getNumOperands();
481706c3fb27SDimitry Andric   if (NumOperands == 0)
481806c3fb27SDimitry Andric     return &MD; // Invalid, punt to a verifier error.
481906c3fb27SDimitry Andric 
48200b57cec5SDimitry Andric   // Check if the tag uses struct-path aware TBAA format.
482106c3fb27SDimitry Andric   if (isa<MDNode>(MD.getOperand(0)) && NumOperands >= 3)
48220b57cec5SDimitry Andric     return &MD;
48230b57cec5SDimitry Andric 
48240b57cec5SDimitry Andric   auto &Context = MD.getContext();
482506c3fb27SDimitry Andric   if (NumOperands == 3) {
48260b57cec5SDimitry Andric     Metadata *Elts[] = {MD.getOperand(0), MD.getOperand(1)};
48270b57cec5SDimitry Andric     MDNode *ScalarType = MDNode::get(Context, Elts);
48280b57cec5SDimitry Andric     // Create a MDNode <ScalarType, ScalarType, offset 0, const>
48290b57cec5SDimitry Andric     Metadata *Elts2[] = {ScalarType, ScalarType,
48300b57cec5SDimitry Andric                          ConstantAsMetadata::get(
48310b57cec5SDimitry Andric                              Constant::getNullValue(Type::getInt64Ty(Context))),
48320b57cec5SDimitry Andric                          MD.getOperand(2)};
48330b57cec5SDimitry Andric     return MDNode::get(Context, Elts2);
48340b57cec5SDimitry Andric   }
48350b57cec5SDimitry Andric   // Create a MDNode <MD, MD, offset 0>
48360b57cec5SDimitry Andric   Metadata *Elts[] = {&MD, &MD, ConstantAsMetadata::get(Constant::getNullValue(
48370b57cec5SDimitry Andric                                     Type::getInt64Ty(Context)))};
48380b57cec5SDimitry Andric   return MDNode::get(Context, Elts);
48390b57cec5SDimitry Andric }
48400b57cec5SDimitry Andric 
48410b57cec5SDimitry Andric Instruction *llvm::UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,
48420b57cec5SDimitry Andric                                       Instruction *&Temp) {
48430b57cec5SDimitry Andric   if (Opc != Instruction::BitCast)
48440b57cec5SDimitry Andric     return nullptr;
48450b57cec5SDimitry Andric 
48460b57cec5SDimitry Andric   Temp = nullptr;
48470b57cec5SDimitry Andric   Type *SrcTy = V->getType();
48480b57cec5SDimitry Andric   if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
48490b57cec5SDimitry Andric       SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
48500b57cec5SDimitry Andric     LLVMContext &Context = V->getContext();
48510b57cec5SDimitry Andric 
48520b57cec5SDimitry Andric     // We have no information about target data layout, so we assume that
48530b57cec5SDimitry Andric     // the maximum pointer size is 64bit.
48540b57cec5SDimitry Andric     Type *MidTy = Type::getInt64Ty(Context);
48550b57cec5SDimitry Andric     Temp = CastInst::Create(Instruction::PtrToInt, V, MidTy);
48560b57cec5SDimitry Andric 
48570b57cec5SDimitry Andric     return CastInst::Create(Instruction::IntToPtr, Temp, DestTy);
48580b57cec5SDimitry Andric   }
48590b57cec5SDimitry Andric 
48600b57cec5SDimitry Andric   return nullptr;
48610b57cec5SDimitry Andric }
48620b57cec5SDimitry Andric 
486381ad6265SDimitry Andric Constant *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {
48640b57cec5SDimitry Andric   if (Opc != Instruction::BitCast)
48650b57cec5SDimitry Andric     return nullptr;
48660b57cec5SDimitry Andric 
48670b57cec5SDimitry Andric   Type *SrcTy = C->getType();
48680b57cec5SDimitry Andric   if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
48690b57cec5SDimitry Andric       SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
48700b57cec5SDimitry Andric     LLVMContext &Context = C->getContext();
48710b57cec5SDimitry Andric 
48720b57cec5SDimitry Andric     // We have no information about target data layout, so we assume that
48730b57cec5SDimitry Andric     // the maximum pointer size is 64bit.
48740b57cec5SDimitry Andric     Type *MidTy = Type::getInt64Ty(Context);
48750b57cec5SDimitry Andric 
48760b57cec5SDimitry Andric     return ConstantExpr::getIntToPtr(ConstantExpr::getPtrToInt(C, MidTy),
48770b57cec5SDimitry Andric                                      DestTy);
48780b57cec5SDimitry Andric   }
48790b57cec5SDimitry Andric 
48800b57cec5SDimitry Andric   return nullptr;
48810b57cec5SDimitry Andric }
48820b57cec5SDimitry Andric 
48830b57cec5SDimitry Andric /// Check the debug info version number, if it is out-dated, drop the debug
48840b57cec5SDimitry Andric /// info. Return true if module is modified.
48850b57cec5SDimitry Andric bool llvm::UpgradeDebugInfo(Module &M) {
488606c3fb27SDimitry Andric   if (DisableAutoUpgradeDebugInfo)
488706c3fb27SDimitry Andric     return false;
488806c3fb27SDimitry Andric 
48890b57cec5SDimitry Andric   unsigned Version = getDebugMetadataVersionFromModule(M);
48900b57cec5SDimitry Andric   if (Version == DEBUG_METADATA_VERSION) {
48910b57cec5SDimitry Andric     bool BrokenDebugInfo = false;
48920b57cec5SDimitry Andric     if (verifyModule(M, &llvm::errs(), &BrokenDebugInfo))
48930b57cec5SDimitry Andric       report_fatal_error("Broken module found, compilation aborted!");
48940b57cec5SDimitry Andric     if (!BrokenDebugInfo)
48950b57cec5SDimitry Andric       // Everything is ok.
48960b57cec5SDimitry Andric       return false;
48970b57cec5SDimitry Andric     else {
48980b57cec5SDimitry Andric       // Diagnose malformed debug info.
48990b57cec5SDimitry Andric       DiagnosticInfoIgnoringInvalidDebugMetadata Diag(M);
49000b57cec5SDimitry Andric       M.getContext().diagnose(Diag);
49010b57cec5SDimitry Andric     }
49020b57cec5SDimitry Andric   }
49030b57cec5SDimitry Andric   bool Modified = StripDebugInfo(M);
49040b57cec5SDimitry Andric   if (Modified && Version != DEBUG_METADATA_VERSION) {
49050b57cec5SDimitry Andric     // Diagnose a version mismatch.
49060b57cec5SDimitry Andric     DiagnosticInfoDebugMetadataVersion DiagVersion(M, Version);
49070b57cec5SDimitry Andric     M.getContext().diagnose(DiagVersion);
49080b57cec5SDimitry Andric   }
49090b57cec5SDimitry Andric   return Modified;
49100b57cec5SDimitry Andric }
49110b57cec5SDimitry Andric 
49128bcb0991SDimitry Andric /// This checks for objc retain release marker which should be upgraded. It
49138bcb0991SDimitry Andric /// returns true if module is modified.
49147a6dacacSDimitry Andric static bool upgradeRetainReleaseMarker(Module &M) {
49150b57cec5SDimitry Andric   bool Changed = false;
49160b57cec5SDimitry Andric   const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";
49170b57cec5SDimitry Andric   NamedMDNode *ModRetainReleaseMarker = M.getNamedMetadata(MarkerKey);
49180b57cec5SDimitry Andric   if (ModRetainReleaseMarker) {
49190b57cec5SDimitry Andric     MDNode *Op = ModRetainReleaseMarker->getOperand(0);
49200b57cec5SDimitry Andric     if (Op) {
49210b57cec5SDimitry Andric       MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(0));
49220b57cec5SDimitry Andric       if (ID) {
49230b57cec5SDimitry Andric         SmallVector<StringRef, 4> ValueComp;
49240b57cec5SDimitry Andric         ID->getString().split(ValueComp, "#");
49250b57cec5SDimitry Andric         if (ValueComp.size() == 2) {
49260b57cec5SDimitry Andric           std::string NewValue = ValueComp[0].str() + ";" + ValueComp[1].str();
49270b57cec5SDimitry Andric           ID = MDString::get(M.getContext(), NewValue);
49280b57cec5SDimitry Andric         }
49290b57cec5SDimitry Andric         M.addModuleFlag(Module::Error, MarkerKey, ID);
49300b57cec5SDimitry Andric         M.eraseNamedMetadata(ModRetainReleaseMarker);
49310b57cec5SDimitry Andric         Changed = true;
49320b57cec5SDimitry Andric       }
49330b57cec5SDimitry Andric     }
49340b57cec5SDimitry Andric   }
49350b57cec5SDimitry Andric   return Changed;
49360b57cec5SDimitry Andric }
49370b57cec5SDimitry Andric 
49388bcb0991SDimitry Andric void llvm::UpgradeARCRuntime(Module &M) {
49398bcb0991SDimitry Andric   // This lambda converts normal function calls to ARC runtime functions to
49408bcb0991SDimitry Andric   // intrinsic calls.
49418bcb0991SDimitry Andric   auto UpgradeToIntrinsic = [&](const char *OldFunc,
49428bcb0991SDimitry Andric                                 llvm::Intrinsic::ID IntrinsicFunc) {
49438bcb0991SDimitry Andric     Function *Fn = M.getFunction(OldFunc);
49448bcb0991SDimitry Andric 
49458bcb0991SDimitry Andric     if (!Fn)
49468bcb0991SDimitry Andric       return;
49478bcb0991SDimitry Andric 
49488bcb0991SDimitry Andric     Function *NewFn = llvm::Intrinsic::getDeclaration(&M, IntrinsicFunc);
49498bcb0991SDimitry Andric 
4950e8d8bef9SDimitry Andric     for (User *U : make_early_inc_range(Fn->users())) {
4951e8d8bef9SDimitry Andric       CallInst *CI = dyn_cast<CallInst>(U);
49528bcb0991SDimitry Andric       if (!CI || CI->getCalledFunction() != Fn)
49538bcb0991SDimitry Andric         continue;
49548bcb0991SDimitry Andric 
49558bcb0991SDimitry Andric       IRBuilder<> Builder(CI->getParent(), CI->getIterator());
49568bcb0991SDimitry Andric       FunctionType *NewFuncTy = NewFn->getFunctionType();
49578bcb0991SDimitry Andric       SmallVector<Value *, 2> Args;
49588bcb0991SDimitry Andric 
4959480093f4SDimitry Andric       // Don't upgrade the intrinsic if it's not valid to bitcast the return
4960480093f4SDimitry Andric       // value to the return type of the old function.
4961480093f4SDimitry Andric       if (NewFuncTy->getReturnType() != CI->getType() &&
4962480093f4SDimitry Andric           !CastInst::castIsValid(Instruction::BitCast, CI,
4963480093f4SDimitry Andric                                  NewFuncTy->getReturnType()))
4964480093f4SDimitry Andric         continue;
4965480093f4SDimitry Andric 
4966480093f4SDimitry Andric       bool InvalidCast = false;
4967480093f4SDimitry Andric 
4968349cc55cSDimitry Andric       for (unsigned I = 0, E = CI->arg_size(); I != E; ++I) {
49698bcb0991SDimitry Andric         Value *Arg = CI->getArgOperand(I);
4970480093f4SDimitry Andric 
49718bcb0991SDimitry Andric         // Bitcast argument to the parameter type of the new function if it's
49728bcb0991SDimitry Andric         // not a variadic argument.
4973480093f4SDimitry Andric         if (I < NewFuncTy->getNumParams()) {
4974480093f4SDimitry Andric           // Don't upgrade the intrinsic if it's not valid to bitcast the argument
4975480093f4SDimitry Andric           // to the parameter type of the new function.
4976480093f4SDimitry Andric           if (!CastInst::castIsValid(Instruction::BitCast, Arg,
4977480093f4SDimitry Andric                                      NewFuncTy->getParamType(I))) {
4978480093f4SDimitry Andric             InvalidCast = true;
4979480093f4SDimitry Andric             break;
4980480093f4SDimitry Andric           }
49818bcb0991SDimitry Andric           Arg = Builder.CreateBitCast(Arg, NewFuncTy->getParamType(I));
4982480093f4SDimitry Andric         }
49838bcb0991SDimitry Andric         Args.push_back(Arg);
49848bcb0991SDimitry Andric       }
49858bcb0991SDimitry Andric 
4986480093f4SDimitry Andric       if (InvalidCast)
4987480093f4SDimitry Andric         continue;
4988480093f4SDimitry Andric 
49898bcb0991SDimitry Andric       // Create a call instruction that calls the new function.
49908bcb0991SDimitry Andric       CallInst *NewCall = Builder.CreateCall(NewFuncTy, NewFn, Args);
49918bcb0991SDimitry Andric       NewCall->setTailCallKind(cast<CallInst>(CI)->getTailCallKind());
4992e8d8bef9SDimitry Andric       NewCall->takeName(CI);
49938bcb0991SDimitry Andric 
49948bcb0991SDimitry Andric       // Bitcast the return value back to the type of the old call.
49958bcb0991SDimitry Andric       Value *NewRetVal = Builder.CreateBitCast(NewCall, CI->getType());
49968bcb0991SDimitry Andric 
49978bcb0991SDimitry Andric       if (!CI->use_empty())
49988bcb0991SDimitry Andric         CI->replaceAllUsesWith(NewRetVal);
49998bcb0991SDimitry Andric       CI->eraseFromParent();
50008bcb0991SDimitry Andric     }
50018bcb0991SDimitry Andric 
50028bcb0991SDimitry Andric     if (Fn->use_empty())
50038bcb0991SDimitry Andric       Fn->eraseFromParent();
50048bcb0991SDimitry Andric   };
50058bcb0991SDimitry Andric 
50068bcb0991SDimitry Andric   // Unconditionally convert a call to "clang.arc.use" to a call to
50078bcb0991SDimitry Andric   // "llvm.objc.clang.arc.use".
50088bcb0991SDimitry Andric   UpgradeToIntrinsic("clang.arc.use", llvm::Intrinsic::objc_clang_arc_use);
50098bcb0991SDimitry Andric 
50108bcb0991SDimitry Andric   // Upgrade the retain release marker. If there is no need to upgrade
50118bcb0991SDimitry Andric   // the marker, that means either the module is already new enough to contain
50128bcb0991SDimitry Andric   // new intrinsics or it is not ARC. There is no need to upgrade runtime call.
50137a6dacacSDimitry Andric   if (!upgradeRetainReleaseMarker(M))
50148bcb0991SDimitry Andric     return;
50158bcb0991SDimitry Andric 
50168bcb0991SDimitry Andric   std::pair<const char *, llvm::Intrinsic::ID> RuntimeFuncs[] = {
50178bcb0991SDimitry Andric       {"objc_autorelease", llvm::Intrinsic::objc_autorelease},
50188bcb0991SDimitry Andric       {"objc_autoreleasePoolPop", llvm::Intrinsic::objc_autoreleasePoolPop},
50198bcb0991SDimitry Andric       {"objc_autoreleasePoolPush", llvm::Intrinsic::objc_autoreleasePoolPush},
50208bcb0991SDimitry Andric       {"objc_autoreleaseReturnValue",
50218bcb0991SDimitry Andric        llvm::Intrinsic::objc_autoreleaseReturnValue},
50228bcb0991SDimitry Andric       {"objc_copyWeak", llvm::Intrinsic::objc_copyWeak},
50238bcb0991SDimitry Andric       {"objc_destroyWeak", llvm::Intrinsic::objc_destroyWeak},
50248bcb0991SDimitry Andric       {"objc_initWeak", llvm::Intrinsic::objc_initWeak},
50258bcb0991SDimitry Andric       {"objc_loadWeak", llvm::Intrinsic::objc_loadWeak},
50268bcb0991SDimitry Andric       {"objc_loadWeakRetained", llvm::Intrinsic::objc_loadWeakRetained},
50278bcb0991SDimitry Andric       {"objc_moveWeak", llvm::Intrinsic::objc_moveWeak},
50288bcb0991SDimitry Andric       {"objc_release", llvm::Intrinsic::objc_release},
50298bcb0991SDimitry Andric       {"objc_retain", llvm::Intrinsic::objc_retain},
50308bcb0991SDimitry Andric       {"objc_retainAutorelease", llvm::Intrinsic::objc_retainAutorelease},
50318bcb0991SDimitry Andric       {"objc_retainAutoreleaseReturnValue",
50328bcb0991SDimitry Andric        llvm::Intrinsic::objc_retainAutoreleaseReturnValue},
50338bcb0991SDimitry Andric       {"objc_retainAutoreleasedReturnValue",
50348bcb0991SDimitry Andric        llvm::Intrinsic::objc_retainAutoreleasedReturnValue},
50358bcb0991SDimitry Andric       {"objc_retainBlock", llvm::Intrinsic::objc_retainBlock},
50368bcb0991SDimitry Andric       {"objc_storeStrong", llvm::Intrinsic::objc_storeStrong},
50378bcb0991SDimitry Andric       {"objc_storeWeak", llvm::Intrinsic::objc_storeWeak},
50388bcb0991SDimitry Andric       {"objc_unsafeClaimAutoreleasedReturnValue",
50398bcb0991SDimitry Andric        llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue},
50408bcb0991SDimitry Andric       {"objc_retainedObject", llvm::Intrinsic::objc_retainedObject},
50418bcb0991SDimitry Andric       {"objc_unretainedObject", llvm::Intrinsic::objc_unretainedObject},
50428bcb0991SDimitry Andric       {"objc_unretainedPointer", llvm::Intrinsic::objc_unretainedPointer},
50438bcb0991SDimitry Andric       {"objc_retain_autorelease", llvm::Intrinsic::objc_retain_autorelease},
50448bcb0991SDimitry Andric       {"objc_sync_enter", llvm::Intrinsic::objc_sync_enter},
50458bcb0991SDimitry Andric       {"objc_sync_exit", llvm::Intrinsic::objc_sync_exit},
50468bcb0991SDimitry Andric       {"objc_arc_annotation_topdown_bbstart",
50478bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_topdown_bbstart},
50488bcb0991SDimitry Andric       {"objc_arc_annotation_topdown_bbend",
50498bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_topdown_bbend},
50508bcb0991SDimitry Andric       {"objc_arc_annotation_bottomup_bbstart",
50518bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_bottomup_bbstart},
50528bcb0991SDimitry Andric       {"objc_arc_annotation_bottomup_bbend",
50538bcb0991SDimitry Andric        llvm::Intrinsic::objc_arc_annotation_bottomup_bbend}};
50548bcb0991SDimitry Andric 
50558bcb0991SDimitry Andric   for (auto &I : RuntimeFuncs)
50568bcb0991SDimitry Andric     UpgradeToIntrinsic(I.first, I.second);
50578bcb0991SDimitry Andric }
50588bcb0991SDimitry Andric 
50590b57cec5SDimitry Andric bool llvm::UpgradeModuleFlags(Module &M) {
50600b57cec5SDimitry Andric   NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
50610b57cec5SDimitry Andric   if (!ModFlags)
50620b57cec5SDimitry Andric     return false;
50630b57cec5SDimitry Andric 
50640b57cec5SDimitry Andric   bool HasObjCFlag = false, HasClassProperties = false, Changed = false;
50655ffd83dbSDimitry Andric   bool HasSwiftVersionFlag = false;
50665ffd83dbSDimitry Andric   uint8_t SwiftMajorVersion, SwiftMinorVersion;
50675ffd83dbSDimitry Andric   uint32_t SwiftABIVersion;
50685ffd83dbSDimitry Andric   auto Int8Ty = Type::getInt8Ty(M.getContext());
50695ffd83dbSDimitry Andric   auto Int32Ty = Type::getInt32Ty(M.getContext());
50705ffd83dbSDimitry Andric 
50710b57cec5SDimitry Andric   for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) {
50720b57cec5SDimitry Andric     MDNode *Op = ModFlags->getOperand(I);
50730b57cec5SDimitry Andric     if (Op->getNumOperands() != 3)
50740b57cec5SDimitry Andric       continue;
50750b57cec5SDimitry Andric     MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1));
50760b57cec5SDimitry Andric     if (!ID)
50770b57cec5SDimitry Andric       continue;
5078bdd1243dSDimitry Andric     auto SetBehavior = [&](Module::ModFlagBehavior B) {
5079bdd1243dSDimitry Andric       Metadata *Ops[3] = {ConstantAsMetadata::get(ConstantInt::get(
5080bdd1243dSDimitry Andric                               Type::getInt32Ty(M.getContext()), B)),
50810b57cec5SDimitry Andric                           MDString::get(M.getContext(), ID->getString()),
50820b57cec5SDimitry Andric                           Op->getOperand(2)};
50830b57cec5SDimitry Andric       ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
50840b57cec5SDimitry Andric       Changed = true;
5085bdd1243dSDimitry Andric     };
5086bdd1243dSDimitry Andric 
5087bdd1243dSDimitry Andric     if (ID->getString() == "Objective-C Image Info Version")
5088bdd1243dSDimitry Andric       HasObjCFlag = true;
5089bdd1243dSDimitry Andric     if (ID->getString() == "Objective-C Class Properties")
5090bdd1243dSDimitry Andric       HasClassProperties = true;
5091bdd1243dSDimitry Andric     // Upgrade PIC from Error/Max to Min.
5092bdd1243dSDimitry Andric     if (ID->getString() == "PIC Level") {
5093bdd1243dSDimitry Andric       if (auto *Behavior =
5094bdd1243dSDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
5095bdd1243dSDimitry Andric         uint64_t V = Behavior->getLimitedValue();
5096bdd1243dSDimitry Andric         if (V == Module::Error || V == Module::Max)
5097bdd1243dSDimitry Andric           SetBehavior(Module::Min);
50980b57cec5SDimitry Andric       }
50990b57cec5SDimitry Andric     }
5100bdd1243dSDimitry Andric     // Upgrade "PIE Level" from Error to Max.
5101bdd1243dSDimitry Andric     if (ID->getString() == "PIE Level")
5102bdd1243dSDimitry Andric       if (auto *Behavior =
5103bdd1243dSDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)))
5104bdd1243dSDimitry Andric         if (Behavior->getLimitedValue() == Module::Error)
5105bdd1243dSDimitry Andric           SetBehavior(Module::Max);
510681ad6265SDimitry Andric 
510781ad6265SDimitry Andric     // Upgrade branch protection and return address signing module flags. The
510881ad6265SDimitry Andric     // module flag behavior for these fields were Error and now they are Min.
510981ad6265SDimitry Andric     if (ID->getString() == "branch-target-enforcement" ||
51105f757f3fSDimitry Andric         ID->getString().starts_with("sign-return-address")) {
511181ad6265SDimitry Andric       if (auto *Behavior =
511281ad6265SDimitry Andric               mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0))) {
511381ad6265SDimitry Andric         if (Behavior->getLimitedValue() == Module::Error) {
511481ad6265SDimitry Andric           Type *Int32Ty = Type::getInt32Ty(M.getContext());
511581ad6265SDimitry Andric           Metadata *Ops[3] = {
511681ad6265SDimitry Andric               ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Module::Min)),
511781ad6265SDimitry Andric               Op->getOperand(1), Op->getOperand(2)};
511881ad6265SDimitry Andric           ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
511981ad6265SDimitry Andric           Changed = true;
512081ad6265SDimitry Andric         }
512181ad6265SDimitry Andric       }
512281ad6265SDimitry Andric     }
512381ad6265SDimitry Andric 
51240b57cec5SDimitry Andric     // Upgrade Objective-C Image Info Section. Removed the whitespce in the
51250b57cec5SDimitry Andric     // section name so that llvm-lto will not complain about mismatching
51260b57cec5SDimitry Andric     // module flags that is functionally the same.
51270b57cec5SDimitry Andric     if (ID->getString() == "Objective-C Image Info Section") {
51280b57cec5SDimitry Andric       if (auto *Value = dyn_cast_or_null<MDString>(Op->getOperand(2))) {
51290b57cec5SDimitry Andric         SmallVector<StringRef, 4> ValueComp;
51300b57cec5SDimitry Andric         Value->getString().split(ValueComp, " ");
51310b57cec5SDimitry Andric         if (ValueComp.size() != 1) {
51320b57cec5SDimitry Andric           std::string NewValue;
51330b57cec5SDimitry Andric           for (auto &S : ValueComp)
51340b57cec5SDimitry Andric             NewValue += S.str();
51350b57cec5SDimitry Andric           Metadata *Ops[3] = {Op->getOperand(0), Op->getOperand(1),
51360b57cec5SDimitry Andric                               MDString::get(M.getContext(), NewValue)};
51370b57cec5SDimitry Andric           ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
51380b57cec5SDimitry Andric           Changed = true;
51390b57cec5SDimitry Andric         }
51400b57cec5SDimitry Andric       }
51410b57cec5SDimitry Andric     }
51425ffd83dbSDimitry Andric 
51435ffd83dbSDimitry Andric     // IRUpgrader turns a i32 type "Objective-C Garbage Collection" into i8 value.
51445ffd83dbSDimitry Andric     // If the higher bits are set, it adds new module flag for swift info.
51455ffd83dbSDimitry Andric     if (ID->getString() == "Objective-C Garbage Collection") {
51465ffd83dbSDimitry Andric       auto Md = dyn_cast<ConstantAsMetadata>(Op->getOperand(2));
51475ffd83dbSDimitry Andric       if (Md) {
51485ffd83dbSDimitry Andric         assert(Md->getValue() && "Expected non-empty metadata");
51495ffd83dbSDimitry Andric         auto Type = Md->getValue()->getType();
51505ffd83dbSDimitry Andric         if (Type == Int8Ty)
51515ffd83dbSDimitry Andric           continue;
51525ffd83dbSDimitry Andric         unsigned Val = Md->getValue()->getUniqueInteger().getZExtValue();
51535ffd83dbSDimitry Andric         if ((Val & 0xff) != Val) {
51545ffd83dbSDimitry Andric           HasSwiftVersionFlag = true;
51555ffd83dbSDimitry Andric           SwiftABIVersion = (Val & 0xff00) >> 8;
51565ffd83dbSDimitry Andric           SwiftMajorVersion = (Val & 0xff000000) >> 24;
51575ffd83dbSDimitry Andric           SwiftMinorVersion = (Val & 0xff0000) >> 16;
51585ffd83dbSDimitry Andric         }
51595ffd83dbSDimitry Andric         Metadata *Ops[3] = {
51605ffd83dbSDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Int32Ty,Module::Error)),
51615ffd83dbSDimitry Andric           Op->getOperand(1),
51625ffd83dbSDimitry Andric           ConstantAsMetadata::get(ConstantInt::get(Int8Ty,Val & 0xff))};
51635ffd83dbSDimitry Andric         ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
51645ffd83dbSDimitry Andric         Changed = true;
51655ffd83dbSDimitry Andric       }
51665ffd83dbSDimitry Andric     }
5167*0fca6ea1SDimitry Andric 
5168*0fca6ea1SDimitry Andric     if (ID->getString() == "amdgpu_code_object_version") {
5169*0fca6ea1SDimitry Andric       Metadata *Ops[3] = {
5170*0fca6ea1SDimitry Andric           Op->getOperand(0),
5171*0fca6ea1SDimitry Andric           MDString::get(M.getContext(), "amdhsa_code_object_version"),
5172*0fca6ea1SDimitry Andric           Op->getOperand(2)};
5173*0fca6ea1SDimitry Andric       ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops));
5174*0fca6ea1SDimitry Andric       Changed = true;
5175*0fca6ea1SDimitry Andric     }
51760b57cec5SDimitry Andric   }
51770b57cec5SDimitry Andric 
51780b57cec5SDimitry Andric   // "Objective-C Class Properties" is recently added for Objective-C. We
51790b57cec5SDimitry Andric   // upgrade ObjC bitcodes to contain a "Objective-C Class Properties" module
51800b57cec5SDimitry Andric   // flag of value 0, so we can correclty downgrade this flag when trying to
51810b57cec5SDimitry Andric   // link an ObjC bitcode without this module flag with an ObjC bitcode with
51820b57cec5SDimitry Andric   // this module flag.
51830b57cec5SDimitry Andric   if (HasObjCFlag && !HasClassProperties) {
51840b57cec5SDimitry Andric     M.addModuleFlag(llvm::Module::Override, "Objective-C Class Properties",
51850b57cec5SDimitry Andric                     (uint32_t)0);
51860b57cec5SDimitry Andric     Changed = true;
51870b57cec5SDimitry Andric   }
51880b57cec5SDimitry Andric 
51895ffd83dbSDimitry Andric   if (HasSwiftVersionFlag) {
51905ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift ABI Version",
51915ffd83dbSDimitry Andric                     SwiftABIVersion);
51925ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift Major Version",
51935ffd83dbSDimitry Andric                     ConstantInt::get(Int8Ty, SwiftMajorVersion));
51945ffd83dbSDimitry Andric     M.addModuleFlag(Module::Error, "Swift Minor Version",
51955ffd83dbSDimitry Andric                     ConstantInt::get(Int8Ty, SwiftMinorVersion));
51965ffd83dbSDimitry Andric     Changed = true;
51975ffd83dbSDimitry Andric   }
51985ffd83dbSDimitry Andric 
51990b57cec5SDimitry Andric   return Changed;
52000b57cec5SDimitry Andric }
52010b57cec5SDimitry Andric 
52020b57cec5SDimitry Andric void llvm::UpgradeSectionAttributes(Module &M) {
52030b57cec5SDimitry Andric   auto TrimSpaces = [](StringRef Section) -> std::string {
52040b57cec5SDimitry Andric     SmallVector<StringRef, 5> Components;
52050b57cec5SDimitry Andric     Section.split(Components, ',');
52060b57cec5SDimitry Andric 
52070b57cec5SDimitry Andric     SmallString<32> Buffer;
52080b57cec5SDimitry Andric     raw_svector_ostream OS(Buffer);
52090b57cec5SDimitry Andric 
52100b57cec5SDimitry Andric     for (auto Component : Components)
52110b57cec5SDimitry Andric       OS << ',' << Component.trim();
52120b57cec5SDimitry Andric 
52135ffd83dbSDimitry Andric     return std::string(OS.str().substr(1));
52140b57cec5SDimitry Andric   };
52150b57cec5SDimitry Andric 
52160b57cec5SDimitry Andric   for (auto &GV : M.globals()) {
52170b57cec5SDimitry Andric     if (!GV.hasSection())
52180b57cec5SDimitry Andric       continue;
52190b57cec5SDimitry Andric 
52200b57cec5SDimitry Andric     StringRef Section = GV.getSection();
52210b57cec5SDimitry Andric 
52225f757f3fSDimitry Andric     if (!Section.starts_with("__DATA, __objc_catlist"))
52230b57cec5SDimitry Andric       continue;
52240b57cec5SDimitry Andric 
52250b57cec5SDimitry Andric     // __DATA, __objc_catlist, regular, no_dead_strip
52260b57cec5SDimitry Andric     // __DATA,__objc_catlist,regular,no_dead_strip
52270b57cec5SDimitry Andric     GV.setSection(TrimSpaces(Section));
52280b57cec5SDimitry Andric   }
52290b57cec5SDimitry Andric }
52300b57cec5SDimitry Andric 
52315ffd83dbSDimitry Andric namespace {
52325ffd83dbSDimitry Andric // Prior to LLVM 10.0, the strictfp attribute could be used on individual
52335ffd83dbSDimitry Andric // callsites within a function that did not also have the strictfp attribute.
52345ffd83dbSDimitry Andric // Since 10.0, if strict FP semantics are needed within a function, the
52355ffd83dbSDimitry Andric // function must have the strictfp attribute and all calls within the function
52365ffd83dbSDimitry Andric // must also have the strictfp attribute. This latter restriction is
52375ffd83dbSDimitry Andric // necessary to prevent unwanted libcall simplification when a function is
52385ffd83dbSDimitry Andric // being cloned (such as for inlining).
52395ffd83dbSDimitry Andric //
52405ffd83dbSDimitry Andric // The "dangling" strictfp attribute usage was only used to prevent constant
52415ffd83dbSDimitry Andric // folding and other libcall simplification. The nobuiltin attribute on the
52425ffd83dbSDimitry Andric // callsite has the same effect.
52435ffd83dbSDimitry Andric struct StrictFPUpgradeVisitor : public InstVisitor<StrictFPUpgradeVisitor> {
524481ad6265SDimitry Andric   StrictFPUpgradeVisitor() = default;
52455ffd83dbSDimitry Andric 
52465ffd83dbSDimitry Andric   void visitCallBase(CallBase &Call) {
52475ffd83dbSDimitry Andric     if (!Call.isStrictFP())
52485ffd83dbSDimitry Andric       return;
52495ffd83dbSDimitry Andric     if (isa<ConstrainedFPIntrinsic>(&Call))
52505ffd83dbSDimitry Andric       return;
52515ffd83dbSDimitry Andric     // If we get here, the caller doesn't have the strictfp attribute
52525ffd83dbSDimitry Andric     // but this callsite does. Replace the strictfp attribute with nobuiltin.
5253349cc55cSDimitry Andric     Call.removeFnAttr(Attribute::StrictFP);
5254349cc55cSDimitry Andric     Call.addFnAttr(Attribute::NoBuiltin);
52555ffd83dbSDimitry Andric   }
52565ffd83dbSDimitry Andric };
52575ffd83dbSDimitry Andric } // namespace
52585ffd83dbSDimitry Andric 
52595ffd83dbSDimitry Andric void llvm::UpgradeFunctionAttributes(Function &F) {
52605ffd83dbSDimitry Andric   // If a function definition doesn't have the strictfp attribute,
52615ffd83dbSDimitry Andric   // convert any callsite strictfp attributes to nobuiltin.
52625ffd83dbSDimitry Andric   if (!F.isDeclaration() && !F.hasFnAttribute(Attribute::StrictFP)) {
52635ffd83dbSDimitry Andric     StrictFPUpgradeVisitor SFPV;
52645ffd83dbSDimitry Andric     SFPV.visit(F);
52655ffd83dbSDimitry Andric   }
5266e8d8bef9SDimitry Andric 
5267fe6060f1SDimitry Andric   // Remove all incompatibile attributes from function.
5268349cc55cSDimitry Andric   F.removeRetAttrs(AttributeFuncs::typeIncompatible(F.getReturnType()));
5269fe6060f1SDimitry Andric   for (auto &Arg : F.args())
5270fe6060f1SDimitry Andric     Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
5271*0fca6ea1SDimitry Andric 
5272*0fca6ea1SDimitry Andric   // Older versions of LLVM treated an "implicit-section-name" attribute
5273*0fca6ea1SDimitry Andric   // similarly to directly setting the section on a Function.
5274*0fca6ea1SDimitry Andric   if (Attribute A = F.getFnAttribute("implicit-section-name");
5275*0fca6ea1SDimitry Andric       A.isValid() && A.isStringAttribute()) {
5276*0fca6ea1SDimitry Andric     F.setSection(A.getValueAsString());
5277*0fca6ea1SDimitry Andric     F.removeFnAttr("implicit-section-name");
5278*0fca6ea1SDimitry Andric   }
52795ffd83dbSDimitry Andric }
52805ffd83dbSDimitry Andric 
52810b57cec5SDimitry Andric static bool isOldLoopArgument(Metadata *MD) {
52820b57cec5SDimitry Andric   auto *T = dyn_cast_or_null<MDTuple>(MD);
52830b57cec5SDimitry Andric   if (!T)
52840b57cec5SDimitry Andric     return false;
52850b57cec5SDimitry Andric   if (T->getNumOperands() < 1)
52860b57cec5SDimitry Andric     return false;
52870b57cec5SDimitry Andric   auto *S = dyn_cast_or_null<MDString>(T->getOperand(0));
52880b57cec5SDimitry Andric   if (!S)
52890b57cec5SDimitry Andric     return false;
52905f757f3fSDimitry Andric   return S->getString().starts_with("llvm.vectorizer.");
52910b57cec5SDimitry Andric }
52920b57cec5SDimitry Andric 
52930b57cec5SDimitry Andric static MDString *upgradeLoopTag(LLVMContext &C, StringRef OldTag) {
52940b57cec5SDimitry Andric   StringRef OldPrefix = "llvm.vectorizer.";
52955f757f3fSDimitry Andric   assert(OldTag.starts_with(OldPrefix) && "Expected old prefix");
52960b57cec5SDimitry Andric 
52970b57cec5SDimitry Andric   if (OldTag == "llvm.vectorizer.unroll")
52980b57cec5SDimitry Andric     return MDString::get(C, "llvm.loop.interleave.count");
52990b57cec5SDimitry Andric 
53000b57cec5SDimitry Andric   return MDString::get(
53010b57cec5SDimitry Andric       C, (Twine("llvm.loop.vectorize.") + OldTag.drop_front(OldPrefix.size()))
53020b57cec5SDimitry Andric              .str());
53030b57cec5SDimitry Andric }
53040b57cec5SDimitry Andric 
53050b57cec5SDimitry Andric static Metadata *upgradeLoopArgument(Metadata *MD) {
53060b57cec5SDimitry Andric   auto *T = dyn_cast_or_null<MDTuple>(MD);
53070b57cec5SDimitry Andric   if (!T)
53080b57cec5SDimitry Andric     return MD;
53090b57cec5SDimitry Andric   if (T->getNumOperands() < 1)
53100b57cec5SDimitry Andric     return MD;
53110b57cec5SDimitry Andric   auto *OldTag = dyn_cast_or_null<MDString>(T->getOperand(0));
53120b57cec5SDimitry Andric   if (!OldTag)
53130b57cec5SDimitry Andric     return MD;
53145f757f3fSDimitry Andric   if (!OldTag->getString().starts_with("llvm.vectorizer."))
53150b57cec5SDimitry Andric     return MD;
53160b57cec5SDimitry Andric 
53170b57cec5SDimitry Andric   // This has an old tag.  Upgrade it.
53180b57cec5SDimitry Andric   SmallVector<Metadata *, 8> Ops;
53190b57cec5SDimitry Andric   Ops.reserve(T->getNumOperands());
53200b57cec5SDimitry Andric   Ops.push_back(upgradeLoopTag(T->getContext(), OldTag->getString()));
53210b57cec5SDimitry Andric   for (unsigned I = 1, E = T->getNumOperands(); I != E; ++I)
53220b57cec5SDimitry Andric     Ops.push_back(T->getOperand(I));
53230b57cec5SDimitry Andric 
53240b57cec5SDimitry Andric   return MDTuple::get(T->getContext(), Ops);
53250b57cec5SDimitry Andric }
53260b57cec5SDimitry Andric 
53270b57cec5SDimitry Andric MDNode *llvm::upgradeInstructionLoopAttachment(MDNode &N) {
53280b57cec5SDimitry Andric   auto *T = dyn_cast<MDTuple>(&N);
53290b57cec5SDimitry Andric   if (!T)
53300b57cec5SDimitry Andric     return &N;
53310b57cec5SDimitry Andric 
53320b57cec5SDimitry Andric   if (none_of(T->operands(), isOldLoopArgument))
53330b57cec5SDimitry Andric     return &N;
53340b57cec5SDimitry Andric 
53350b57cec5SDimitry Andric   SmallVector<Metadata *, 8> Ops;
53360b57cec5SDimitry Andric   Ops.reserve(T->getNumOperands());
53370b57cec5SDimitry Andric   for (Metadata *MD : T->operands())
53380b57cec5SDimitry Andric     Ops.push_back(upgradeLoopArgument(MD));
53390b57cec5SDimitry Andric 
53400b57cec5SDimitry Andric   return MDTuple::get(T->getContext(), Ops);
53410b57cec5SDimitry Andric }
53428bcb0991SDimitry Andric 
53438bcb0991SDimitry Andric std::string llvm::UpgradeDataLayoutString(StringRef DL, StringRef TT) {
5344e8d8bef9SDimitry Andric   Triple T(TT);
5345*0fca6ea1SDimitry Andric   // The only data layout upgrades needed for pre-GCN, SPIR or SPIRV are setting
5346*0fca6ea1SDimitry Andric   // the address space of globals to 1. This does not apply to SPIRV Logical.
5347*0fca6ea1SDimitry Andric   if (((T.isAMDGPU() && !T.isAMDGCN()) ||
5348*0fca6ea1SDimitry Andric        (T.isSPIR() || (T.isSPIRV() && !T.isSPIRVLogical()))) &&
5349*0fca6ea1SDimitry Andric       !DL.contains("-G") && !DL.starts_with("G")) {
5350e8d8bef9SDimitry Andric     return DL.empty() ? std::string("G1") : (DL + "-G1").str();
5351e8d8bef9SDimitry Andric   }
53528bcb0991SDimitry Andric 
5353*0fca6ea1SDimitry Andric   if (T.isLoongArch64() || T.isRISCV64()) {
5354*0fca6ea1SDimitry Andric     // Make i32 a native type for 64-bit LoongArch and RISC-V.
5355bdd1243dSDimitry Andric     auto I = DL.find("-n64-");
5356bdd1243dSDimitry Andric     if (I != StringRef::npos)
5357bdd1243dSDimitry Andric       return (DL.take_front(I) + "-n32:64-" + DL.drop_front(I + 5)).str();
5358bdd1243dSDimitry Andric     return DL.str();
5359bdd1243dSDimitry Andric   }
5360bdd1243dSDimitry Andric 
536104eeddc0SDimitry Andric   std::string Res = DL.str();
536206c3fb27SDimitry Andric   // AMDGCN data layout upgrades.
536306c3fb27SDimitry Andric   if (T.isAMDGCN()) {
536406c3fb27SDimitry Andric     // Define address spaces for constants.
536506c3fb27SDimitry Andric     if (!DL.contains("-G") && !DL.starts_with("G"))
536606c3fb27SDimitry Andric       Res.append(Res.empty() ? "G1" : "-G1");
536706c3fb27SDimitry Andric 
536806c3fb27SDimitry Andric     // Add missing non-integral declarations.
536906c3fb27SDimitry Andric     // This goes before adding new address spaces to prevent incoherent string
537006c3fb27SDimitry Andric     // values.
53715f757f3fSDimitry Andric     if (!DL.contains("-ni") && !DL.starts_with("ni"))
53725f757f3fSDimitry Andric       Res.append("-ni:7:8:9");
53735f757f3fSDimitry Andric     // Update ni:7 to ni:7:8:9.
537406c3fb27SDimitry Andric     if (DL.ends_with("ni:7"))
53755f757f3fSDimitry Andric       Res.append(":8:9");
53765f757f3fSDimitry Andric     if (DL.ends_with("ni:7:8"))
53775f757f3fSDimitry Andric       Res.append(":9");
537806c3fb27SDimitry Andric 
537906c3fb27SDimitry Andric     // Add sizing for address spaces 7 and 8 (fat raw buffers and buffer
538006c3fb27SDimitry Andric     // resources) An empty data layout has already been upgraded to G1 by now.
53815f757f3fSDimitry Andric     if (!DL.contains("-p7") && !DL.starts_with("p7"))
538206c3fb27SDimitry Andric       Res.append("-p7:160:256:256:32");
53835f757f3fSDimitry Andric     if (!DL.contains("-p8") && !DL.starts_with("p8"))
538406c3fb27SDimitry Andric       Res.append("-p8:128:128");
53855f757f3fSDimitry Andric     if (!DL.contains("-p9") && !DL.starts_with("p9"))
53865f757f3fSDimitry Andric       Res.append("-p9:192:256:256:32");
538706c3fb27SDimitry Andric 
538806c3fb27SDimitry Andric     return Res;
538906c3fb27SDimitry Andric   }
539006c3fb27SDimitry Andric 
5391*0fca6ea1SDimitry Andric   // AArch64 data layout upgrades.
5392*0fca6ea1SDimitry Andric   if (T.isAArch64()) {
5393*0fca6ea1SDimitry Andric     // Add "-Fn32"
5394*0fca6ea1SDimitry Andric     if (!DL.empty() && !DL.contains("-Fn32"))
5395*0fca6ea1SDimitry Andric       Res.append("-Fn32");
5396*0fca6ea1SDimitry Andric     return Res;
5397*0fca6ea1SDimitry Andric   }
5398*0fca6ea1SDimitry Andric 
539904eeddc0SDimitry Andric   if (!T.isX86())
540004eeddc0SDimitry Andric     return Res;
54018bcb0991SDimitry Andric 
540204eeddc0SDimitry Andric   // If the datalayout matches the expected format, add pointer size address
540304eeddc0SDimitry Andric   // spaces to the datalayout.
540404eeddc0SDimitry Andric   std::string AddrSpaces = "-p270:32:32-p271:32:32-p272:64:64";
54055f757f3fSDimitry Andric   if (StringRef Ref = Res; !Ref.contains(AddrSpaces)) {
54068bcb0991SDimitry Andric     SmallVector<StringRef, 4> Groups;
54078bcb0991SDimitry Andric     Regex R("(e-m:[a-z](-p:32:32)?)(-[if]64:.*$)");
54085f757f3fSDimitry Andric     if (R.match(Res, &Groups))
540904eeddc0SDimitry Andric       Res = (Groups[1] + AddrSpaces + Groups[3]).str();
541004eeddc0SDimitry Andric   }
54118bcb0991SDimitry Andric 
54125f757f3fSDimitry Andric   // i128 values need to be 16-byte-aligned. LLVM already called into libgcc
54135f757f3fSDimitry Andric   // for i128 operations prior to this being reflected in the data layout, and
54145f757f3fSDimitry Andric   // clang mostly produced LLVM IR that already aligned i128 to 16 byte
54155f757f3fSDimitry Andric   // boundaries, so although this is a breaking change, the upgrade is expected
54165f757f3fSDimitry Andric   // to fix more IR than it breaks.
54175f757f3fSDimitry Andric   // Intel MCU is an exception and uses 4-byte-alignment.
54185f757f3fSDimitry Andric   if (!T.isOSIAMCU()) {
54195f757f3fSDimitry Andric     std::string I128 = "-i128:128";
54205f757f3fSDimitry Andric     if (StringRef Ref = Res; !Ref.contains(I128)) {
54215f757f3fSDimitry Andric       SmallVector<StringRef, 4> Groups;
54225f757f3fSDimitry Andric       Regex R("^(e(-[mpi][^-]*)*)((-[^mpi][^-]*)*)$");
54235f757f3fSDimitry Andric       if (R.match(Res, &Groups))
54245f757f3fSDimitry Andric         Res = (Groups[1] + I128 + Groups[3]).str();
54255f757f3fSDimitry Andric     }
54265f757f3fSDimitry Andric   }
54275f757f3fSDimitry Andric 
542804eeddc0SDimitry Andric   // For 32-bit MSVC targets, raise the alignment of f80 values to 16 bytes.
542904eeddc0SDimitry Andric   // Raising the alignment is safe because Clang did not produce f80 values in
543004eeddc0SDimitry Andric   // the MSVC environment before this upgrade was added.
543104eeddc0SDimitry Andric   if (T.isWindowsMSVCEnvironment() && !T.isArch64Bit()) {
543204eeddc0SDimitry Andric     StringRef Ref = Res;
543304eeddc0SDimitry Andric     auto I = Ref.find("-f80:32-");
543404eeddc0SDimitry Andric     if (I != StringRef::npos)
543504eeddc0SDimitry Andric       Res = (Ref.take_front(I) + "-f80:128-" + Ref.drop_front(I + 8)).str();
543604eeddc0SDimitry Andric   }
543704eeddc0SDimitry Andric 
543804eeddc0SDimitry Andric   return Res;
54398bcb0991SDimitry Andric }
5440480093f4SDimitry Andric 
54415ffd83dbSDimitry Andric void llvm::UpgradeAttributes(AttrBuilder &B) {
5442480093f4SDimitry Andric   StringRef FramePointer;
544304eeddc0SDimitry Andric   Attribute A = B.getAttribute("no-frame-pointer-elim");
544404eeddc0SDimitry Andric   if (A.isValid()) {
5445480093f4SDimitry Andric     // The value can be "true" or "false".
544604eeddc0SDimitry Andric     FramePointer = A.getValueAsString() == "true" ? "all" : "none";
5447480093f4SDimitry Andric     B.removeAttribute("no-frame-pointer-elim");
5448480093f4SDimitry Andric   }
5449480093f4SDimitry Andric   if (B.contains("no-frame-pointer-elim-non-leaf")) {
5450480093f4SDimitry Andric     // The value is ignored. "no-frame-pointer-elim"="true" takes priority.
5451480093f4SDimitry Andric     if (FramePointer != "all")
5452480093f4SDimitry Andric       FramePointer = "non-leaf";
5453480093f4SDimitry Andric     B.removeAttribute("no-frame-pointer-elim-non-leaf");
5454480093f4SDimitry Andric   }
5455480093f4SDimitry Andric   if (!FramePointer.empty())
5456480093f4SDimitry Andric     B.addAttribute("frame-pointer", FramePointer);
54575ffd83dbSDimitry Andric 
545804eeddc0SDimitry Andric   A = B.getAttribute("null-pointer-is-valid");
545904eeddc0SDimitry Andric   if (A.isValid()) {
54605ffd83dbSDimitry Andric     // The value can be "true" or "false".
546104eeddc0SDimitry Andric     bool NullPointerIsValid = A.getValueAsString() == "true";
54625ffd83dbSDimitry Andric     B.removeAttribute("null-pointer-is-valid");
54635ffd83dbSDimitry Andric     if (NullPointerIsValid)
54645ffd83dbSDimitry Andric       B.addAttribute(Attribute::NullPointerIsValid);
54655ffd83dbSDimitry Andric   }
5466480093f4SDimitry Andric }
546781ad6265SDimitry Andric 
546881ad6265SDimitry Andric void llvm::UpgradeOperandBundles(std::vector<OperandBundleDef> &Bundles) {
546981ad6265SDimitry Andric   // clang.arc.attachedcall bundles are now required to have an operand.
547081ad6265SDimitry Andric   // If they don't, it's okay to drop them entirely: when there is an operand,
547181ad6265SDimitry Andric   // the "attachedcall" is meaningful and required, but without an operand,
547281ad6265SDimitry Andric   // it's just a marker NOP.  Dropping it merely prevents an optimization.
547381ad6265SDimitry Andric   erase_if(Bundles, [&](OperandBundleDef &OBD) {
547481ad6265SDimitry Andric     return OBD.getTag() == "clang.arc.attachedcall" &&
547581ad6265SDimitry Andric            OBD.inputs().empty();
547681ad6265SDimitry Andric   });
547781ad6265SDimitry Andric }
5478