184#include "llvm/IR/IntrinsicsAArch64.h"
185#include "llvm/IR/IntrinsicsX86.h"
216#define DEBUG_TYPE "msan"
219 "Controls which checks to insert");
222 "Controls which instruction to instrument");
241 "msan-track-origins",
246 cl::desc(
"keep going after reporting a UMR"),
255 "msan-poison-stack-with-call",
260 "msan-poison-stack-pattern",
261 cl::desc(
"poison uninitialized stack variables with the given pattern"),
266 cl::desc(
"Print name of local stack variable"),
271 cl::desc(
"Poison fully undef temporary values. "
272 "Partially undefined constant vectors "
273 "are unaffected by this flag (see "
274 "-msan-poison-undef-vectors)."),
278 "msan-poison-undef-vectors",
279 cl::desc(
"Precisely poison partially undefined constant vectors. "
280 "If false (legacy behavior), the entire vector is "
281 "considered fully initialized, which may lead to false "
282 "negatives. Fully undefined constant vectors are "
283 "unaffected by this flag (see -msan-poison-undef)."),
287 "msan-precise-disjoint-or",
288 cl::desc(
"Precisely poison disjoint OR. If false (legacy behavior), "
289 "disjointedness is ignored (i.e., 1|1 is initialized)."),
294 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
299 cl::desc(
"exact handling of relational integer ICmp"),
303 "msan-switch-precision",
304 cl::desc(
"Controls the number of cases considered by MSan for LLVM switch "
305 "instructions. 0 means no UUMs detected. Higher values lead to "
306 "fewer false negatives but may impact compiler and/or "
307 "application performance. N.B. LLVM switch instructions do not "
308 "correspond exactly to C++ switch statements."),
312 "msan-handle-lifetime-intrinsics",
314 "when possible, poison scoped variables at the beginning of the scope "
315 "(slower, but more precise)"),
326 "msan-handle-asm-conservative",
337 "msan-check-access-address",
338 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
343 cl::desc(
"check arguments and return values at function call boundaries"),
347 "msan-dump-strict-instructions",
348 cl::desc(
"print out instructions with default strict semantics i.e.,"
349 "check that all the inputs are fully initialized, and mark "
350 "the output as fully initialized. These semantics are applied "
351 "to instructions that could not be handled explicitly nor "
360 "msan-dump-heuristic-instructions",
361 cl::desc(
"Prints 'unknown' instructions that were handled heuristically. "
362 "Use -msan-dump-strict-instructions to print instructions that "
363 "could not be handled explicitly nor heuristically."),
367 "msan-instrumentation-with-call-threshold",
369 "If the function being instrumented requires more than "
370 "this number of checks and origin stores, use callbacks instead of "
371 "inline checks (-1 means never use callbacks)."),
376 cl::desc(
"Enable KernelMemorySanitizer instrumentation"),
386 cl::desc(
"Insert checks for constant shadow values"),
393 cl::desc(
"Place MSan constructors in comdat sections"),
399 cl::desc(
"Define custom MSan AndMask"),
403 cl::desc(
"Define custom MSan XorMask"),
407 cl::desc(
"Define custom MSan ShadowBase"),
411 cl::desc(
"Define custom MSan OriginBase"),
416 cl::desc(
"Define threshold for number of checks per "
417 "debug location to force origin update."),
429struct MemoryMapParams {
436struct PlatformMemoryMapParams {
437 const MemoryMapParams *bits32;
438 const MemoryMapParams *bits64;
615class MemorySanitizer {
624 MemorySanitizer(MemorySanitizer &&) =
delete;
625 MemorySanitizer &operator=(MemorySanitizer &&) =
delete;
626 MemorySanitizer(
const MemorySanitizer &) =
delete;
627 MemorySanitizer &operator=(
const MemorySanitizer &) =
delete;
629 bool sanitizeFunction(Function &
F, TargetLibraryInfo &TLI);
632 friend struct MemorySanitizerVisitor;
633 friend struct VarArgHelperBase;
634 friend struct VarArgAMD64Helper;
635 friend struct VarArgAArch64Helper;
636 friend struct VarArgPowerPC64Helper;
637 friend struct VarArgPowerPC32Helper;
638 friend struct VarArgSystemZHelper;
639 friend struct VarArgI386Helper;
640 friend struct VarArgGenericHelper;
642 void initializeModule(
Module &M);
643 void initializeCallbacks(
Module &M,
const TargetLibraryInfo &TLI);
644 void createKernelApi(
Module &M,
const TargetLibraryInfo &TLI);
645 void createUserspaceApi(
Module &M,
const TargetLibraryInfo &TLI);
647 template <
typename... ArgsTy>
648 FunctionCallee getOrInsertMsanMetadataFunction(
Module &M, StringRef Name,
674 Value *ParamOriginTLS;
680 Value *RetvalOriginTLS;
686 Value *VAArgOriginTLS;
689 Value *VAArgOverflowSizeTLS;
692 bool CallbacksInitialized =
false;
695 FunctionCallee WarningFn;
699 FunctionCallee MaybeWarningVarSizeFn;
704 FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
706 FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
709 FunctionCallee MsanPoisonStackFn;
713 FunctionCallee MsanChainOriginFn;
716 FunctionCallee MsanSetOriginFn;
719 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
722 StructType *MsanContextStateTy;
723 FunctionCallee MsanGetContextStateFn;
726 FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
732 FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
733 FunctionCallee MsanMetadataPtrForLoad_1_8[4];
734 FunctionCallee MsanMetadataPtrForStore_1_8[4];
735 FunctionCallee MsanInstrumentAsmStoreFn;
738 Value *MsanMetadataAlloca;
741 FunctionCallee getKmsanShadowOriginAccessFn(
bool isStore,
int size);
744 const MemoryMapParams *MapParams;
748 MemoryMapParams CustomMapParams;
750 MDNode *ColdCallWeights;
753 MDNode *OriginStoreWeights;
756void insertModuleCtor(
Module &M) {
793 if (!Options.Kernel) {
802 MemorySanitizer Msan(*
F.getParent(), Options);
821 OS, MapClassName2PassName);
827 if (Options.EagerChecks)
828 OS <<
"eager-checks;";
829 OS <<
"track-origins=" << Options.TrackOrigins;
845template <
typename... ArgsTy>
847MemorySanitizer::getOrInsertMsanMetadataFunction(
Module &M,
StringRef Name,
852 std::forward<ArgsTy>(Args)...);
855 return M.getOrInsertFunction(Name, MsanMetadata,
856 std::forward<ArgsTy>(Args)...);
865 RetvalOriginTLS =
nullptr;
867 ParamOriginTLS =
nullptr;
869 VAArgOriginTLS =
nullptr;
870 VAArgOverflowSizeTLS =
nullptr;
872 WarningFn =
M.getOrInsertFunction(
"__msan_warning",
874 IRB.getVoidTy(), IRB.getInt32Ty());
885 MsanGetContextStateFn =
886 M.getOrInsertFunction(
"__msan_get_context_state", PtrTy);
890 for (
int ind = 0,
size = 1; ind < 4; ind++,
size <<= 1) {
891 std::string name_load =
892 "__msan_metadata_ptr_for_load_" + std::to_string(
size);
893 std::string name_store =
894 "__msan_metadata_ptr_for_store_" + std::to_string(
size);
895 MsanMetadataPtrForLoad_1_8[ind] =
896 getOrInsertMsanMetadataFunction(M, name_load, PtrTy);
897 MsanMetadataPtrForStore_1_8[ind] =
898 getOrInsertMsanMetadataFunction(M, name_store, PtrTy);
901 MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
902 M,
"__msan_metadata_ptr_for_load_n", PtrTy, IntptrTy);
903 MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
904 M,
"__msan_metadata_ptr_for_store_n", PtrTy, IntptrTy);
907 MsanPoisonAllocaFn =
M.getOrInsertFunction(
908 "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
909 MsanUnpoisonAllocaFn =
M.getOrInsertFunction(
910 "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
914 return M.getOrInsertGlobal(Name, Ty, [&] {
916 nullptr, Name,
nullptr,
922void MemorySanitizer::createUserspaceApi(
Module &M,
930 StringRef WarningFnName = Recover ?
"__msan_warning_with_origin"
931 :
"__msan_warning_with_origin_noreturn";
932 WarningFn =
M.getOrInsertFunction(WarningFnName,
934 IRB.getVoidTy(), IRB.getInt32Ty());
937 Recover ?
"__msan_warning" :
"__msan_warning_noreturn";
938 WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
965 IRB.getIntPtrTy(
M.getDataLayout()));
969 unsigned AccessSize = 1 << AccessSizeIndex;
970 std::string FunctionName =
"__msan_maybe_warning_" +
itostr(AccessSize);
971 MaybeWarningFn[AccessSizeIndex] =
M.getOrInsertFunction(
973 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
974 MaybeWarningVarSizeFn =
M.getOrInsertFunction(
975 "__msan_maybe_warning_N", TLI.
getAttrList(
C, {},
false),
976 IRB.getVoidTy(), PtrTy, IRB.getInt64Ty(), IRB.getInt32Ty());
977 FunctionName =
"__msan_maybe_store_origin_" +
itostr(AccessSize);
978 MaybeStoreOriginFn[AccessSizeIndex] =
M.getOrInsertFunction(
980 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
984 MsanSetAllocaOriginWithDescriptionFn =
985 M.getOrInsertFunction(
"__msan_set_alloca_origin_with_descr",
986 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
987 MsanSetAllocaOriginNoDescriptionFn =
988 M.getOrInsertFunction(
"__msan_set_alloca_origin_no_descr",
989 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
990 MsanPoisonStackFn =
M.getOrInsertFunction(
"__msan_poison_stack",
991 IRB.getVoidTy(), PtrTy, IntptrTy);
995void MemorySanitizer::initializeCallbacks(
Module &M,
998 if (CallbacksInitialized)
1004 MsanChainOriginFn =
M.getOrInsertFunction(
1005 "__msan_chain_origin",
1006 TLI.
getAttrList(
C, {0},
false,
true), IRB.getInt32Ty(),
1008 MsanSetOriginFn =
M.getOrInsertFunction(
1010 IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
1012 M.getOrInsertFunction(
"__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1014 M.getOrInsertFunction(
"__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1015 MemsetFn =
M.getOrInsertFunction(
"__msan_memset",
1017 PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1019 MsanInstrumentAsmStoreFn =
M.getOrInsertFunction(
1020 "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
1022 if (CompileKernel) {
1023 createKernelApi(M, TLI);
1025 createUserspaceApi(M, TLI);
1027 CallbacksInitialized =
true;
1033 isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
1051void MemorySanitizer::initializeModule(
Module &M) {
1052 auto &
DL =
M.getDataLayout();
1054 TargetTriple =
M.getTargetTriple();
1056 bool ShadowPassed =
ClShadowBase.getNumOccurrences() > 0;
1057 bool OriginPassed =
ClOriginBase.getNumOccurrences() > 0;
1059 if (ShadowPassed || OriginPassed) {
1064 MapParams = &CustomMapParams;
1066 switch (TargetTriple.getOS()) {
1068 switch (TargetTriple.getArch()) {
1083 switch (TargetTriple.getArch()) {
1092 switch (TargetTriple.getArch()) {
1129 C = &(
M.getContext());
1131 IntptrTy = IRB.getIntPtrTy(
DL);
1132 OriginTy = IRB.getInt32Ty();
1133 PtrTy = IRB.getPtrTy();
1138 if (!CompileKernel) {
1140 M.getOrInsertGlobal(
"__msan_track_origins", IRB.getInt32Ty(), [&] {
1141 return new GlobalVariable(
1142 M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1143 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
1147 M.getOrInsertGlobal(
"__msan_keep_going", IRB.getInt32Ty(), [&] {
1148 return new GlobalVariable(M, IRB.getInt32Ty(), true,
1149 GlobalValue::WeakODRLinkage,
1150 IRB.getInt32(Recover),
"__msan_keep_going");
1165struct VarArgHelper {
1166 virtual ~VarArgHelper() =
default;
1169 virtual void visitCallBase(CallBase &CB,
IRBuilder<> &IRB) = 0;
1172 virtual void visitVAStartInst(VAStartInst &
I) = 0;
1175 virtual void visitVACopyInst(VACopyInst &
I) = 0;
1181 virtual void finalizeInstrumentation() = 0;
1184struct MemorySanitizerVisitor;
1189 MemorySanitizerVisitor &Visitor);
1196 if (TypeSizeFixed <= 8)
1205class NextNodeIRBuilder :
public IRBuilder<> {
1218struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
1220 MemorySanitizer &MS;
1222 ValueMap<Value *, Value *> ShadowMap, OriginMap;
1223 std::unique_ptr<VarArgHelper> VAHelper;
1224 const TargetLibraryInfo *TLI;
1231 bool PropagateShadow;
1234 bool PoisonUndefVectors;
1236 struct ShadowOriginAndInsertPoint {
1241 ShadowOriginAndInsertPoint(
Value *S,
Value *O, Instruction *
I)
1242 : Shadow(S), Origin(
O), OrigIns(
I) {}
1245 DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
1246 SmallSetVector<AllocaInst *, 16> AllocaSet;
1249 int64_t SplittableBlocksCount = 0;
1251 MemorySanitizerVisitor(Function &
F, MemorySanitizer &MS,
1252 const TargetLibraryInfo &TLI)
1254 bool SanitizeFunction =
1256 InsertChecks = SanitizeFunction;
1257 PropagateShadow = SanitizeFunction;
1268 MS.initializeCallbacks(*
F.getParent(), TLI);
1270 IRBuilder<>(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt())
1271 .CreateIntrinsicWithoutFolding(Intrinsic::donothing, {});
1273 if (MS.CompileKernel) {
1275 insertKmsanPrologue(IRB);
1279 <<
"MemorySanitizer is not inserting checks into '"
1280 <<
F.getName() <<
"'\n");
1283 bool instrumentWithCalls(
Value *V) {
1287 ++SplittableBlocksCount;
1292 bool isInPrologue(Instruction &
I) {
1293 return I.getParent() == FnPrologueEnd->
getParent() &&
1302 if (MS.TrackOrigins <= 1)
1304 return IRB.
CreateCall(MS.MsanChainOriginFn, V);
1308 const DataLayout &
DL =
F.getDataLayout();
1309 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1319 TypeSize TS, Align Alignment) {
1320 const DataLayout &
DL =
F.getDataLayout();
1321 const Align IntptrAlignment =
DL.getABITypeAlign(MS.IntptrTy);
1322 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1334 auto [InsertPt,
Index] =
1346 Align CurrentAlignment = Alignment;
1347 if (Alignment >= IntptrAlignment && IntptrSize >
kOriginSize) {
1348 Value *IntptrOrigin = originToIntptr(IRB, Origin);
1350 for (
unsigned i = 0; i <
Size / IntptrSize; ++i) {
1355 CurrentAlignment = IntptrAlignment;
1368 Value *OriginPtr, Align Alignment) {
1369 const DataLayout &
DL =
F.getDataLayout();
1371 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
1373 Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
1382 paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize,
1389 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1391 if (instrumentWithCalls(ConvertedShadow) &&
1393 FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex];
1394 Value *ConvertedShadow2 =
1396 CallBase *CB = IRB.
CreateCall(Fn, {ConvertedShadow2, Addr, Origin});
1400 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1404 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize,
1409 void materializeStores() {
1410 for (StoreInst *SI : StoreList) {
1412 Value *Val =
SI->getValueOperand();
1413 Value *Addr =
SI->getPointerOperand();
1414 Value *Shadow =
SI->isAtomic() ? getCleanShadow(Val) : getShadow(Val);
1415 Value *ShadowPtr, *OriginPtr;
1417 const Align Alignment =
SI->getAlign();
1419 std::tie(ShadowPtr, OriginPtr) =
1420 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
true);
1422 [[maybe_unused]] StoreInst *NewSI =
1429 if (MS.TrackOrigins && !
SI->isAtomic())
1430 storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,
1437 if (MS.TrackOrigins < 2)
1440 if (LazyWarningDebugLocationCount.
empty())
1441 for (
const auto &
I : InstrumentationList)
1442 ++LazyWarningDebugLocationCount[
I.OrigIns->getDebugLoc()];
1458 auto NewDebugLoc = OI->getDebugLoc();
1465 IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);
1466 Origin = updateOrigin(Origin, IRBOrigin);
1471 if (MS.CompileKernel || MS.TrackOrigins)
1482 const DataLayout &
DL =
F.getDataLayout();
1483 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1485 if (instrumentWithCalls(ConvertedShadow) && !MS.CompileKernel) {
1487 ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
1488 Value *ConvertedShadow2 =
1492 FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1496 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1500 FunctionCallee Fn = MS.MaybeWarningVarSizeFn;
1503 unsigned ShadowSize =
DL.getTypeAllocSize(ConvertedShadow2->
getType());
1506 {ShadowAlloca, ConstantInt::get(IRB.
getInt64Ty(), ShadowSize),
1507 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1512 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1515 !MS.Recover, MS.ColdCallWeights);
1518 insertWarningFn(IRB, Origin);
1523 void materializeInstructionChecks(
1525 const DataLayout &
DL =
F.getDataLayout();
1528 bool Combine = !MS.TrackOrigins;
1530 Value *Shadow =
nullptr;
1531 for (
const auto &ShadowData : InstructionChecks) {
1532 assert(ShadowData.OrigIns == Instruction);
1535 Value *ConvertedShadow = ShadowData.Shadow;
1544 insertWarningFn(IRB, ShadowData.Origin);
1554 materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);
1559 Shadow = ConvertedShadow;
1563 Shadow = convertToBool(Shadow, IRB,
"_mscmp");
1564 ConvertedShadow = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1565 Shadow = IRB.
CreateOr(Shadow, ConvertedShadow,
"_msor");
1571 materializeOneCheck(IRB, Shadow,
nullptr);
1575 static bool isAArch64SVCount(
Type *Ty) {
1577 return TTy->
getName() ==
"aarch64.svcount";
1583 static bool isScalableNonVectorType(
Type *Ty) {
1584 if (!isAArch64SVCount(Ty))
1585 LLVM_DEBUG(
dbgs() <<
"isScalableNonVectorType: Unexpected type " << *Ty
1591 void materializeChecks() {
1594 SmallPtrSet<Instruction *, 16>
Done;
1597 for (
auto I = InstrumentationList.begin();
1598 I != InstrumentationList.end();) {
1599 auto OrigIns =
I->OrigIns;
1603 auto J = std::find_if(
I + 1, InstrumentationList.end(),
1604 [OrigIns](
const ShadowOriginAndInsertPoint &R) {
1605 return OrigIns != R.OrigIns;
1619 MS.ParamTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1620 {Zero, IRB.getInt32(0)},
"param_shadow");
1621 MS.RetvalTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1622 {Zero, IRB.getInt32(1)},
"retval_shadow");
1623 MS.VAArgTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1624 {Zero, IRB.getInt32(2)},
"va_arg_shadow");
1625 MS.VAArgOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1626 {Zero, IRB.getInt32(3)},
"va_arg_origin");
1627 MS.VAArgOverflowSizeTLS =
1628 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1629 {Zero, IRB.getInt32(4)},
"va_arg_overflow_size");
1630 MS.ParamOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1631 {Zero, IRB.getInt32(5)},
"param_origin");
1632 MS.RetvalOriginTLS =
1633 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1634 {Zero, IRB.getInt32(6)},
"retval_origin");
1636 MS.MsanMetadataAlloca = IRB.
CreateAlloca(MS.MsanMetadata, 0u);
1649 for (Instruction *
I : Instructions)
1653 for (PHINode *PN : ShadowPHINodes) {
1655 PHINode *PNO = MS.TrackOrigins ?
cast<PHINode>(getOrigin(PN)) : nullptr;
1656 size_t NumValues = PN->getNumIncomingValues();
1657 for (
size_t v = 0;
v < NumValues;
v++) {
1658 PNS->
addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));
1660 PNO->
addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));
1664 VAHelper->finalizeInstrumentation();
1669 for (
auto Item : LifetimeStartList) {
1670 instrumentAlloca(*Item.second, Item.first);
1671 AllocaSet.
remove(Item.second);
1676 for (AllocaInst *AI : AllocaSet)
1677 instrumentAlloca(*AI);
1680 materializeChecks();
1684 materializeStores();
1690 Type *getShadowTy(
Value *V) {
return getShadowTy(
V->getType()); }
1701 const DataLayout &
DL =
F.getDataLayout();
1703 uint32_t EltSize =
DL.getTypeSizeInBits(VT->getElementType());
1705 VT->getElementCount());
1708 return ArrayType::get(getShadowTy(AT->getElementType()),
1709 AT->getNumElements());
1713 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
1714 Elements.push_back(getShadowTy(
ST->getElementType(i)));
1716 LLVM_DEBUG(
dbgs() <<
"getShadowTy: " << *ST <<
" ===> " << *Res <<
"\n");
1719 if (isScalableNonVectorType(OrigTy)) {
1720 LLVM_DEBUG(
dbgs() <<
"getShadowTy: Scalable non-vector type: " << *OrigTy
1725 uint32_t TypeSize =
DL.getTypeSizeInBits(OrigTy);
1730 Value *collapseStructShadow(StructType *Struct,
Value *Shadow,
1735 for (
unsigned Idx = 0; Idx <
Struct->getNumElements(); Idx++) {
1738 Value *ShadowBool = convertToBool(ShadowItem, IRB);
1740 if (Aggregator != FalseVal)
1741 Aggregator = IRB.
CreateOr(Aggregator, ShadowBool);
1743 Aggregator = ShadowBool;
1750 Value *collapseArrayShadow(ArrayType *Array,
Value *Shadow,
1752 if (!
Array->getNumElements())
1756 Value *Aggregator = convertShadowToScalar(FirstItem, IRB);
1758 for (
unsigned Idx = 1; Idx <
Array->getNumElements(); Idx++) {
1760 Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
1761 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1771 return collapseStructShadow(Struct, V, IRB);
1773 return collapseArrayShadow(Array, V, IRB);
1778 V->getType()->getPrimitiveSizeInBits().getFixedValue();
1786 Type *VTy =
V->getType();
1788 return convertToBool(convertShadowToScalar(V, IRB), IRB,
name);
1795 Type *ptrToIntPtrType(
Type *PtrTy)
const {
1797 return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),
1798 VectTy->getElementCount());
1806 return VectorType::get(
1807 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1808 VectTy->getElementCount());
1817 VectTy->getElementCount(),
1818 constToIntPtr(VectTy->getElementType(),
C));
1823 return ConstantInt::get(MS.IntptrTy,
C,
false,
1837 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1840 if (uint64_t AndMask = MS.MapParams->AndMask)
1841 OffsetLong = IRB.
CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));
1843 if (uint64_t XorMask = MS.MapParams->XorMask)
1844 OffsetLong = IRB.
CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));
1856 std::pair<Value *, Value *>
1858 MaybeAlign Alignment) {
1863 assert(VectTy->getElementType()->isPointerTy());
1865 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1866 Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);
1867 Value *ShadowLong = ShadowOffset;
1868 if (uint64_t ShadowBase = MS.MapParams->ShadowBase) {
1870 IRB.
CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));
1873 ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));
1875 Value *OriginPtr =
nullptr;
1876 if (MS.TrackOrigins) {
1877 Value *OriginLong = ShadowOffset;
1878 uint64_t OriginBase = MS.MapParams->OriginBase;
1879 if (OriginBase != 0)
1881 IRB.
CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));
1884 OriginLong = IRB.
CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));
1887 OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));
1889 return std::make_pair(ShadowPtr, OriginPtr);
1892 template <
typename... ArgsTy>
1897 {MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});
1898 return IRB.
CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);
1901 return IRB.
CreateCall(Callee, {std::forward<ArgsTy>(Args)...});
1904 std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(
Value *Addr,
1908 Value *ShadowOriginPtrs;
1909 const DataLayout &
DL =
F.getDataLayout();
1910 TypeSize
Size =
DL.getTypeStoreSize(ShadowTy);
1912 FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(
isStore,
Size);
1915 ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);
1917 Value *SizeVal = ConstantInt::get(MS.IntptrTy,
Size);
1918 ShadowOriginPtrs = createMetadataCall(
1920 isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,
1927 return std::make_pair(ShadowPtr, OriginPtr);
1933 std::pair<Value *, Value *> getShadowOriginPtrKernel(
Value *Addr,
1940 return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy,
isStore);
1945 Value *ShadowPtrs = ConstantInt::getNullValue(
1947 Value *OriginPtrs =
nullptr;
1948 if (MS.TrackOrigins)
1949 OriginPtrs = ConstantInt::getNullValue(
1951 for (
unsigned i = 0; i < NumElements; ++i) {
1954 auto [ShadowPtr, OriginPtr] =
1955 getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy,
isStore);
1958 ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1959 if (MS.TrackOrigins)
1961 OriginPtrs, OriginPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1963 return {ShadowPtrs, OriginPtrs};
1966 std::pair<Value *, Value *> getShadowOriginPtr(
Value *Addr,
IRBuilder<> &IRB,
1968 MaybeAlign Alignment,
1970 if (MS.CompileKernel)
1971 return getShadowOriginPtrKernel(Addr, IRB, ShadowTy,
isStore);
1972 return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);
1980 ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg");
1985 if (!MS.TrackOrigins)
1988 ConstantInt::get(MS.IntptrTy, ArgOffset),
1998 Value *getOriginPtrForRetval() {
2000 return MS.RetvalOriginTLS;
2005 assert(!ShadowMap.
count(V) &&
"Values may only have one shadow");
2006 ShadowMap[
V] = PropagateShadow ? SV : getCleanShadow(V);
2011 if (!MS.TrackOrigins)
2013 assert(!OriginMap.
count(V) &&
"Values may only have one origin");
2014 LLVM_DEBUG(
dbgs() <<
"ORIGIN: " << *V <<
" ==> " << *Origin <<
"\n");
2015 OriginMap[
V] = Origin;
2019 Type *ShadowTy = getShadowTy(OrigTy);
2029 Constant *getCleanShadow(
Value *V) {
return getCleanShadow(
V->getType()); }
2037 SmallVector<Constant *, 4> Vals(AT->getNumElements(),
2038 getPoisonedShadow(AT->getElementType()));
2042 SmallVector<Constant *, 4> Vals;
2043 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
2044 Vals.
push_back(getPoisonedShadow(
ST->getElementType(i)));
2052 Type *ShadowTy = getShadowTy(V);
2055 return getPoisonedShadow(ShadowTy);
2067 if (!PropagateShadow ||
I->getMetadata(LLVMContext::MD_nosanitize))
2068 return getCleanShadow(V);
2070 Value *Shadow = ShadowMap[
V];
2072 LLVM_DEBUG(
dbgs() <<
"No shadow: " << *V <<
"\n" << *(
I->getParent()));
2073 assert(Shadow &&
"No shadow for a value");
2080 Value *
AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
2081 : getCleanShadow(V);
2087 Value *&ShadowPtr = ShadowMap[
V];
2092 unsigned ArgOffset = 0;
2093 const DataLayout &
DL =
F->getDataLayout();
2094 for (
auto &FArg :
F->args()) {
2095 if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
2097 ?
"vscale not fully supported\n"
2098 :
"Arg is not sized\n"));
2100 ShadowPtr = getCleanShadow(V);
2101 setOrigin(
A, getCleanOrigin());
2107 unsigned Size = FArg.hasByValAttr()
2108 ?
DL.getTypeAllocSize(FArg.getParamByValType())
2109 :
DL.getTypeAllocSize(FArg.getType());
2113 if (FArg.hasByValAttr()) {
2117 const Align ArgAlign =
DL.getValueOrABITypeAlignment(
2118 FArg.getParamAlign(), FArg.getParamByValType());
2119 Value *CpShadowPtr, *CpOriginPtr;
2120 std::tie(CpShadowPtr, CpOriginPtr) =
2121 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
2123 if (!PropagateShadow || Overflow) {
2125 EntryIRB.CreateMemSet(
2129 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2131 [[maybe_unused]]
Value *Cpy = EntryIRB.CreateMemCpy(
2132 CpShadowPtr, CopyAlign,
Base, CopyAlign,
Size);
2135 if (MS.TrackOrigins) {
2136 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2140 EntryIRB.CreateMemCpy(
2149 if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
2150 (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
2151 ShadowPtr = getCleanShadow(V);
2152 setOrigin(
A, getCleanOrigin());
2155 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2156 ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg),
Base,
2158 if (MS.TrackOrigins) {
2159 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2160 setOrigin(
A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));
2164 <<
" ARG: " << FArg <<
" ==> " << *ShadowPtr <<
"\n");
2170 assert(ShadowPtr &&
"Could not find shadow for an argument");
2177 cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
2178 PoisonUndefVectors) {
2181 for (
unsigned i = 0; i != NumElems; ++i) {
2184 : getCleanShadow(Elem);
2188 LLVM_DEBUG(
dbgs() <<
"Partial undef constant vector: " << *V <<
" ==> "
2189 << *ShadowConstant <<
"\n");
2191 return ShadowConstant;
2197 return getCleanShadow(V);
2201 Value *getShadow(Instruction *
I,
int i) {
2202 return getShadow(
I->getOperand(i));
2207 if (!MS.TrackOrigins)
2210 return getCleanOrigin();
2212 "Unexpected value type in getOrigin()");
2214 if (
I->getMetadata(LLVMContext::MD_nosanitize))
2215 return getCleanOrigin();
2217 Value *Origin = OriginMap[
V];
2218 assert(Origin &&
"Missing origin");
2223 Value *getOrigin(Instruction *
I,
int i) {
2224 return getOrigin(
I->getOperand(i));
2231 void insertCheckShadow(
Value *Shadow,
Value *Origin, Instruction *OrigIns) {
2237 LLVM_DEBUG(
dbgs() <<
"Skipping check of " << *Shadow <<
" before "
2238 << *OrigIns <<
"\n");
2243 if (isScalableNonVectorType(ShadowTy)) {
2244 LLVM_DEBUG(
dbgs() <<
"Skipping check of scalable non-vector " << *Shadow
2245 <<
" before " << *OrigIns <<
"\n");
2251 "Can only insert checks for integer, vector, and aggregate shadow "
2254 InstrumentationList.push_back(
2255 ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
2263 void insertCheckShadowOf(
Value *Val, Instruction *OrigIns) {
2265 Value *Shadow, *Origin;
2267 Shadow = getShadow(Val);
2270 Origin = getOrigin(Val);
2277 insertCheckShadow(Shadow, Origin, OrigIns);
2282 case AtomicOrdering::NotAtomic:
2283 return AtomicOrdering::NotAtomic;
2284 case AtomicOrdering::Unordered:
2285 case AtomicOrdering::Monotonic:
2286 case AtomicOrdering::Release:
2287 return AtomicOrdering::Release;
2288 case AtomicOrdering::Acquire:
2289 case AtomicOrdering::AcquireRelease:
2290 return AtomicOrdering::AcquireRelease;
2291 case AtomicOrdering::SequentiallyConsistent:
2292 return AtomicOrdering::SequentiallyConsistent;
2298 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2299 uint32_t OrderingTable[NumOrderings] = {};
2301 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2302 OrderingTable[(
int)AtomicOrderingCABI::release] =
2303 (int)AtomicOrderingCABI::release;
2304 OrderingTable[(int)AtomicOrderingCABI::consume] =
2305 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2306 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2307 (
int)AtomicOrderingCABI::acq_rel;
2308 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2309 (
int)AtomicOrderingCABI::seq_cst;
2316 case AtomicOrdering::NotAtomic:
2317 return AtomicOrdering::NotAtomic;
2318 case AtomicOrdering::Unordered:
2319 case AtomicOrdering::Monotonic:
2320 case AtomicOrdering::Acquire:
2321 return AtomicOrdering::Acquire;
2322 case AtomicOrdering::Release:
2323 case AtomicOrdering::AcquireRelease:
2324 return AtomicOrdering::AcquireRelease;
2325 case AtomicOrdering::SequentiallyConsistent:
2326 return AtomicOrdering::SequentiallyConsistent;
2332 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2333 uint32_t OrderingTable[NumOrderings] = {};
2335 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2336 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2337 OrderingTable[(int)AtomicOrderingCABI::consume] =
2338 (
int)AtomicOrderingCABI::acquire;
2339 OrderingTable[(int)AtomicOrderingCABI::release] =
2340 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
2341 (int)AtomicOrderingCABI::acq_rel;
2342 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2343 (
int)AtomicOrderingCABI::seq_cst;
2349 using InstVisitor<MemorySanitizerVisitor>
::visit;
2350 void visit(Instruction &
I) {
2351 if (
I.getMetadata(LLVMContext::MD_nosanitize))
2354 if (isInPrologue(
I))
2359 setShadow(&
I, getCleanShadow(&
I));
2360 setOrigin(&
I, getCleanOrigin());
2371 void visitLoadInst(LoadInst &
I) {
2372 assert(
I.getType()->isSized() &&
"Load type must have size");
2373 assert(!
I.getMetadata(LLVMContext::MD_nosanitize));
2374 NextNodeIRBuilder IRB(&
I);
2375 Type *ShadowTy = getShadowTy(&
I);
2376 Value *Addr =
I.getPointerOperand();
2377 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
2378 const Align Alignment =
I.getAlign();
2379 if (PropagateShadow) {
2380 std::tie(ShadowPtr, OriginPtr) =
2381 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
2385 setShadow(&
I, getCleanShadow(&
I));
2389 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2394 if (MS.TrackOrigins) {
2395 if (PropagateShadow) {
2400 setOrigin(&
I, getCleanOrigin());
2409 void visitStoreInst(StoreInst &
I) {
2410 StoreList.push_back(&
I);
2412 insertCheckShadowOf(
I.getPointerOperand(), &
I);
2415 void handleCASOrRMW(Instruction &
I) {
2419 Value *Addr =
I.getOperand(0);
2420 Value *Val =
I.getOperand(1);
2421 Value *ShadowPtr = getShadowOriginPtr(Addr, IRB, getShadowTy(Val),
Align(1),
2426 insertCheckShadowOf(Addr, &
I);
2432 insertCheckShadowOf(Val, &
I);
2436 setShadow(&
I, getCleanShadow(&
I));
2437 setOrigin(&
I, getCleanOrigin());
2440 void visitAtomicRMWInst(AtomicRMWInst &
I) {
2445 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2507 void visitSwitchInst(SwitchInst &SI) {
2510 Value *Val =
SI.getCondition();
2511 Value *ShadowVal = getShadow(Val);
2523 Value *ShadowCases =
nullptr;
2524 for (
auto Case :
SI.cases()) {
2525 if (casesToConsider <= 0)
2528 Value *Comparator = Case.getCaseValue();
2531 Value *ComparisonShadow = propagateEqualityComparison(
2532 IRB, Val, Comparator, ShadowVal, getShadow(Comparator));
2535 ShadowCases = IRB.
CreateOr(ShadowCases, ComparisonShadow);
2537 ShadowCases = ComparisonShadow;
2543 insertCheckShadow(ShadowCases, getOrigin(Val), &SI);
2547 void visitExtractElementInst(ExtractElementInst &
I) {
2548 insertCheckShadowOf(
I.getOperand(1), &
I);
2552 setOrigin(&
I, getOrigin(&
I, 0));
2555 void visitInsertElementInst(InsertElementInst &
I) {
2556 insertCheckShadowOf(
I.getOperand(2), &
I);
2558 auto *Shadow0 = getShadow(&
I, 0);
2559 auto *Shadow1 = getShadow(&
I, 1);
2562 setOriginForNaryOp(
I);
2565 void visitShuffleVectorInst(ShuffleVectorInst &
I) {
2567 auto *Shadow0 = getShadow(&
I, 0);
2568 auto *Shadow1 = getShadow(&
I, 1);
2571 setOriginForNaryOp(
I);
2575 void visitSExtInst(SExtInst &
I) {
2577 setShadow(&
I, IRB.
CreateSExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2578 setOrigin(&
I, getOrigin(&
I, 0));
2581 void visitZExtInst(ZExtInst &
I) {
2583 setShadow(&
I, IRB.
CreateZExt(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2584 setOrigin(&
I, getOrigin(&
I, 0));
2587 void visitTruncInst(TruncInst &
I) {
2589 setShadow(&
I, IRB.
CreateTrunc(getShadow(&
I, 0),
I.getType(),
"_msprop"));
2590 setOrigin(&
I, getOrigin(&
I, 0));
2593 void visitBitCastInst(BitCastInst &
I) {
2598 if (CI->isMustTailCall())
2602 setOrigin(&
I, getOrigin(&
I, 0));
2605 void visitPtrToIntInst(PtrToIntInst &
I) {
2608 "_msprop_ptrtoint"));
2609 setOrigin(&
I, getOrigin(&
I, 0));
2612 void visitIntToPtrInst(IntToPtrInst &
I) {
2615 "_msprop_inttoptr"));
2616 setOrigin(&
I, getOrigin(&
I, 0));
2637 void handleGenericVectorConvertIntrinsic(Instruction &
I,
bool FixedPoint) {
2638 [[maybe_unused]]
unsigned NumArgs =
I.getNumOperands();
2640 NumArgs = CI->arg_size();
2644 Value *Precision =
I.getOperand(1);
2645 insertCheckShadowOf(Precision, &
I);
2651 Value *S0 = getShadow(&
I, 0);
2660 setShadow(&
I, OutShadow);
2661 setOriginForNaryOp(
I);
2664 void visitFPToSIInst(CastInst &
I) {
2665 handleGenericVectorConvertIntrinsic(
I,
false);
2667 void visitFPToUIInst(CastInst &
I) {
2668 handleGenericVectorConvertIntrinsic(
I,
false);
2670 void visitSIToFPInst(CastInst &
I) {
2671 handleGenericVectorConvertIntrinsic(
I,
false);
2673 void visitUIToFPInst(CastInst &
I) {
2674 handleGenericVectorConvertIntrinsic(
I,
false);
2676 void visitFPExtInst(CastInst &
I) { handleShadowOr(
I); }
2677 void visitFPTruncInst(CastInst &
I) { handleShadowOr(
I); }
2697 assert(
V1->getType()->isIntOrIntVectorTy());
2708 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2712 void visitAnd(BinaryOperator &
I) {
2715 Value *V2 =
I.getOperand(1);
2717 Value *S2 = getShadow(&
I, 1);
2719 Value *OutShadow = handleBitwiseAnd(IRB,
V1, V2,
S1, S2);
2721 setShadow(&
I, OutShadow);
2722 setOriginForNaryOp(
I);
2725 void visitOr(BinaryOperator &
I) {
2738 Value *S2 = getShadow(&
I, 1);
2740 Value *V2 =
I.getOperand(1);
2744 assert(
V1->getType()->isIntOrIntVectorTy());
2764 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2768 setOriginForNaryOp(
I);
2786 template <
bool CombineShadow>
class Combiner {
2787 Value *Shadow =
nullptr;
2788 Value *Origin =
nullptr;
2790 MemorySanitizerVisitor *MSV;
2793 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2794 : IRB(IRB), MSV(MSV) {}
2798 if (CombineShadow) {
2803 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2804 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2808 if (MSV->MS.TrackOrigins) {
2815 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2816 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2826 Value *OpShadow = MSV->getShadow(V);
2827 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2828 return Add(OpShadow, OpOrigin);
2833 void Done(Instruction *
I) {
2834 if (CombineShadow) {
2836 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2837 MSV->setShadow(
I, Shadow);
2839 if (MSV->MS.TrackOrigins) {
2841 MSV->setOrigin(
I, Origin);
2847 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2848 if (MSV->MS.TrackOrigins) {
2855 using ShadowAndOriginCombiner = Combiner<true>;
2856 using OriginCombiner = Combiner<false>;
2859 void setOriginForNaryOp(Instruction &
I) {
2860 if (!MS.TrackOrigins)
2863 OriginCombiner OC(
this, IRB);
2864 for (Use &
Op :
I.operands())
2869 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2871 "Vector of pointers is not a valid shadow type");
2881 Type *srcTy =
V->getType();
2884 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2885 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2886 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2904 Type *ShadowTy = getShadowTy(V);
2905 if (
V->getType() == ShadowTy)
2907 if (
V->getType()->isPtrOrPtrVectorTy())
2914 void handleShadowOr(Instruction &
I) {
2916 ShadowAndOriginCombiner SC(
this, IRB);
2917 for (Use &
Op :
I.operands())
2944 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2945 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2950 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2956 assert(NumElems % (ReductionFactor * Shards) == 0);
2961 for (
unsigned i = 0; i < ReductionFactor; i++) {
2962 SmallVector<int, 16>
Mask;
2964 for (
unsigned j = 0;
j < Shards;
j++) {
2965 unsigned Offset = NumElems / Shards *
j;
2967 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2971 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2996 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
2997 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2999 assert(
I.getType()->isVectorTy());
3000 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3002 [[maybe_unused]] FixedVectorType *ParamType =
3006 [[maybe_unused]] FixedVectorType *
ReturnType =
3014 Value *FirstArgShadow = getShadow(&
I, 0);
3015 Value *SecondArgShadow =
nullptr;
3016 if (
I.arg_size() == 2)
3017 SecondArgShadow = getShadow(&
I, 1);
3019 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3020 FirstArgShadow, SecondArgShadow);
3022 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3024 setShadow(&
I, OrShadow);
3025 setOriginForNaryOp(
I);
3035 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3036 int ReinterpretElemWidth) {
3037 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3039 assert(
I.getType()->isVectorTy());
3040 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3042 FixedVectorType *ParamType =
3047 [[maybe_unused]] FixedVectorType *
ReturnType =
3054 FixedVectorType *ReinterpretShadowTy =
nullptr;
3062 Value *FirstArgShadow = getShadow(&
I, 0);
3063 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3073 Value *SecondArgShadow =
nullptr;
3074 if (
I.arg_size() == 2) {
3075 SecondArgShadow = getShadow(&
I, 1);
3076 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3079 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3080 FirstArgShadow, SecondArgShadow);
3082 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3084 setShadow(&
I, OrShadow);
3085 setOriginForNaryOp(
I);
3088 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3099 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3105 Type *EltTy = VTy->getElementType();
3107 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3108 if (ConstantInt *Elt =
3110 const APInt &
V = Elt->getValue();
3111 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3112 Elements.push_back(ConstantInt::get(EltTy, V2));
3114 Elements.push_back(ConstantInt::get(EltTy, 1));
3120 const APInt &
V = Elt->getValue();
3121 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3122 ShadowMul = ConstantInt::get(Ty, V2);
3124 ShadowMul = ConstantInt::get(Ty, 1);
3130 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3131 setOrigin(&
I, getOrigin(OtherArg));
3134 void visitMul(BinaryOperator &
I) {
3137 if (constOp0 && !constOp1)
3138 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3139 else if (constOp1 && !constOp0)
3140 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3145 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3146 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3147 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3148 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3149 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3150 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3152 void handleIntegerDiv(Instruction &
I) {
3155 insertCheckShadowOf(
I.getOperand(1), &
I);
3156 setShadow(&
I, getShadow(&
I, 0));
3157 setOrigin(&
I, getOrigin(&
I, 0));
3160 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3161 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3162 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3163 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3167 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3168 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3174 void handleEqualityComparison(ICmpInst &
I) {
3178 Value *Sa = getShadow(
A);
3179 Value *Sb = getShadow(
B);
3181 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3184 setOriginForNaryOp(
I);
3192 void handleRelationalComparisonExact(ICmpInst &
I) {
3196 Value *Sa = getShadow(
A);
3197 Value *Sb = getShadow(
B);
3208 bool IsSigned =
I.isSigned();
3210 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3220 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3225 return std::make_pair(Min, Max);
3228 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3229 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3235 setOriginForNaryOp(
I);
3242 void handleSignedRelationalComparison(ICmpInst &
I) {
3247 op =
I.getOperand(0);
3248 pre =
I.getPredicate();
3250 op =
I.getOperand(1);
3251 pre =
I.getSwappedPredicate();
3264 setShadow(&
I, Shadow);
3265 setOrigin(&
I, getOrigin(
op));
3271 void visitICmpInst(ICmpInst &
I) {
3276 if (
I.isEquality()) {
3277 handleEqualityComparison(
I);
3283 handleRelationalComparisonExact(
I);
3287 handleSignedRelationalComparison(
I);
3293 handleRelationalComparisonExact(
I);
3300 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3302 void handleShift(BinaryOperator &
I) {
3307 Value *S2 = getShadow(&
I, 1);
3310 Value *V2 =
I.getOperand(1);
3312 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3313 setOriginForNaryOp(
I);
3316 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3317 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3318 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3320 void handleFunnelShift(IntrinsicInst &
I) {
3324 Value *S0 = getShadow(&
I, 0);
3326 Value *S2 = getShadow(&
I, 2);
3329 Value *V2 =
I.getOperand(2);
3332 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3333 setOriginForNaryOp(
I);
3341 void handleGenericBitManipulation(IntrinsicInst &
I) {
3343 Type *ShadowTy = getShadowTy(&
I);
3346 Value *SMask = getShadow(&
I, 1);
3351 if (Function *Func =
I.getCalledFunction())
3352 S = IRB.
CreateCall(Func, {getShadow(&
I, 0),
I.getOperand(1)});
3355 {getShadow(&I, 0), I.getOperand(1)});
3358 setOriginForNaryOp(
I);
3371 void visitMemMoveInst(MemMoveInst &
I) {
3372 getShadow(
I.getArgOperand(1));
3375 {I.getArgOperand(0), I.getArgOperand(1),
3376 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3394 void visitMemCpyInst(MemCpyInst &
I) {
3395 getShadow(
I.getArgOperand(1));
3398 {I.getArgOperand(0), I.getArgOperand(1),
3399 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3404 void visitMemSetInst(MemSetInst &
I) {
3408 {I.getArgOperand(0),
3409 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3410 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3414 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3416 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3422 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3426 Value *Addr =
I.getArgOperand(0);
3427 Value *Shadow = getShadow(&
I, 1);
3428 Value *ShadowPtr, *OriginPtr;
3432 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3437 insertCheckShadowOf(Addr, &
I);
3440 if (MS.TrackOrigins)
3449 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3453 Value *Addr =
I.getArgOperand(0);
3455 Type *ShadowTy = getShadowTy(&
I);
3456 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3457 if (PropagateShadow) {
3461 std::tie(ShadowPtr, OriginPtr) =
3462 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3466 setShadow(&
I, getCleanShadow(&
I));
3470 insertCheckShadowOf(Addr, &
I);
3472 if (MS.TrackOrigins) {
3473 if (PropagateShadow)
3474 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3476 setOrigin(&
I, getCleanOrigin());
3496 [[maybe_unused]]
bool
3497 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3498 unsigned int trailingFlags) {
3499 Type *RetTy =
I.getType();
3503 unsigned NumArgOperands =
I.arg_size();
3504 assert(NumArgOperands >= trailingFlags);
3505 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3506 Type *Ty =
I.getArgOperand(i)->getType();
3512 ShadowAndOriginCombiner SC(
this, IRB);
3513 for (
unsigned i = 0; i < NumArgOperands; ++i)
3514 SC.Add(
I.getArgOperand(i));
3531 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3532 unsigned NumArgOperands =
I.arg_size();
3533 if (NumArgOperands == 0)
3536 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3537 I.getArgOperand(1)->getType()->isVectorTy() &&
3538 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3540 return handleVectorStoreIntrinsic(
I);
3543 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3544 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3546 return handleVectorLoadIntrinsic(
I);
3549 if (
I.doesNotAccessMemory())
3550 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3558 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3559 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3561 dumpInst(
I,
"Heuristic");
3563 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3570 void handleInvariantGroup(IntrinsicInst &
I) {
3571 setShadow(&
I, getShadow(&
I, 0));
3572 setOrigin(&
I, getOrigin(&
I, 0));
3575 void handleLifetimeStart(IntrinsicInst &
I) {
3580 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3583 void handleBswap(IntrinsicInst &
I) {
3586 Type *OpType =
Op->getType();
3589 setOrigin(&
I, getOrigin(
Op));
3610 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3612 Value *Src =
I.getArgOperand(0);
3613 Value *SrcShadow = getShadow(Src);
3617 I.getType(),
I.getIntrinsicID(), {Src, False});
3619 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3622 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3624 Value *NotAllZeroShadow =
3626 Value *OutputShadow =
3627 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3633 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3636 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3638 setShadow(&
I, OutputShadow);
3639 setOriginForNaryOp(
I);
3648 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3668 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3673 Value *FullShadow = getCleanShadow(&
I);
3674 unsigned ShadowNumElems =
3676 unsigned FullShadowNumElems =
3679 assert((ShadowNumElems == FullShadowNumElems) ||
3680 (ShadowNumElems * 2 == FullShadowNumElems));
3682 if (ShadowNumElems == FullShadowNumElems) {
3683 FullShadow = Shadow;
3687 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3712 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3713 bool HasRoundingMode) {
3714 if (HasRoundingMode) {
3722 Value *Src =
I.getArgOperand(0);
3723 assert(Src->getType()->isVectorTy());
3727 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3730 Value *S0 = getShadow(&
I, 0);
3742 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3744 setShadow(&
I, FullShadow);
3745 setOriginForNaryOp(
I);
3766 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3767 bool HasRoundingMode =
false) {
3769 Value *CopyOp, *ConvertOp;
3771 assert((!HasRoundingMode ||
3773 "Invalid rounding mode");
3775 switch (
I.arg_size() - HasRoundingMode) {
3777 CopyOp =
I.getArgOperand(0);
3778 ConvertOp =
I.getArgOperand(1);
3781 ConvertOp =
I.getArgOperand(0);
3795 Value *ConvertShadow = getShadow(ConvertOp);
3796 Value *AggShadow =
nullptr;
3799 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3800 for (
int i = 1; i < NumUsedElements; ++i) {
3802 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3803 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3806 AggShadow = ConvertShadow;
3809 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3816 Value *ResultShadow = getShadow(CopyOp);
3818 for (
int i = 0; i < NumUsedElements; ++i) {
3820 ResultShadow, ConstantInt::getNullValue(EltTy),
3823 setShadow(&
I, ResultShadow);
3824 setOrigin(&
I, getOrigin(CopyOp));
3826 setShadow(&
I, getCleanShadow(&
I));
3827 setOrigin(&
I, getCleanOrigin());
3835 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3838 return CreateShadowCast(IRB, S2,
T,
true);
3846 return CreateShadowCast(IRB, S2,
T,
true);
3863 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3869 Value *S2 = getShadow(&
I, 1);
3871 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3873 Value *V2 =
I.getOperand(1);
3875 {IRB.CreateBitCast(S1, V1->getType()), V2});
3877 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3878 setOriginForNaryOp(
I);
3883 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3884 unsigned X86_MMXSizeInBits = 64) {
3885 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3886 "Illegal MMX vector element size");
3888 X86_MMXSizeInBits / EltSizeInBits);
3895 case Intrinsic::x86_sse2_packsswb_128:
3896 case Intrinsic::x86_sse2_packuswb_128:
3897 return Intrinsic::x86_sse2_packsswb_128;
3899 case Intrinsic::x86_sse2_packssdw_128:
3900 case Intrinsic::x86_sse41_packusdw:
3901 return Intrinsic::x86_sse2_packssdw_128;
3903 case Intrinsic::x86_avx2_packsswb:
3904 case Intrinsic::x86_avx2_packuswb:
3905 return Intrinsic::x86_avx2_packsswb;
3907 case Intrinsic::x86_avx2_packssdw:
3908 case Intrinsic::x86_avx2_packusdw:
3909 return Intrinsic::x86_avx2_packssdw;
3911 case Intrinsic::x86_mmx_packsswb:
3912 case Intrinsic::x86_mmx_packuswb:
3913 return Intrinsic::x86_mmx_packsswb;
3915 case Intrinsic::x86_mmx_packssdw:
3916 return Intrinsic::x86_mmx_packssdw;
3918 case Intrinsic::x86_avx512_packssdw_512:
3919 case Intrinsic::x86_avx512_packusdw_512:
3920 return Intrinsic::x86_avx512_packssdw_512;
3922 case Intrinsic::x86_avx512_packsswb_512:
3923 case Intrinsic::x86_avx512_packuswb_512:
3924 return Intrinsic::x86_avx512_packsswb_512;
3940 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3941 unsigned MMXEltSizeInBits = 0) {
3945 Value *S2 = getShadow(&
I, 1);
3946 assert(
S1->getType()->isVectorTy());
3952 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3953 if (MMXEltSizeInBits) {
3961 if (MMXEltSizeInBits) {
3967 {S1_ext, S2_ext},
nullptr,
3968 "_msprop_vector_pack");
3969 if (MMXEltSizeInBits)
3972 setOriginForNaryOp(
I);
3976 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3977 SmallVector<Constant *, 4>
R(Width);
3989 const unsigned Width =
3996 Value *DstMaskV = createDppMask(Width, DstMask);
4013 void handleDppIntrinsic(IntrinsicInst &
I) {
4016 Value *S0 = getShadow(&
I, 0);
4020 const unsigned Width =
4022 assert(Width == 2 || Width == 4 || Width == 8);
4025 const unsigned SrcMask =
Mask >> 4;
4026 const unsigned DstMask =
Mask & 0xf;
4029 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4034 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4041 setOriginForNaryOp(
I);
4045 C = CreateAppToShadowCast(IRB,
C);
4054 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4059 Value *Sc = getShadow(&
I, 2);
4060 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4065 C = convertBlendvToSelectMask(IRB,
C);
4066 Sc = convertBlendvToSelectMask(IRB, Sc);
4072 handleSelectLikeInst(
I,
C,
T,
F);
4076 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4077 const unsigned SignificantBitsPerResultElement = 16;
4079 unsigned ZeroBitsPerResultElement =
4083 auto *Shadow0 = getShadow(&
I, 0);
4084 auto *Shadow1 = getShadow(&
I, 1);
4089 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4092 setOriginForNaryOp(
I);
4116 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4117 unsigned ReductionFactor,
4119 unsigned EltSizeInBits,
4123 [[maybe_unused]] FixedVectorType *
ReturnType =
4128 Value *Va =
nullptr;
4129 Value *Vb =
nullptr;
4130 Value *Sa =
nullptr;
4131 Value *Sb =
nullptr;
4133 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4134 if (
I.arg_size() == 2) {
4137 Va =
I.getOperand(0);
4138 Vb =
I.getOperand(1);
4140 Sa = getShadow(&
I, 0);
4141 Sb = getShadow(&
I, 1);
4142 }
else if (
I.arg_size() == 3) {
4144 Va =
I.getOperand(1);
4145 Vb =
I.getOperand(2);
4147 Sa = getShadow(&
I, 1);
4148 Sb = getShadow(&
I, 2);
4165 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4167 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4177 if (
I.arg_size() == 3) {
4178 [[maybe_unused]]
auto *AccumulatorType =
4180 assert(AccumulatorType == ReturnType);
4183 FixedVectorType *ImplicitReturnType =
4186 if (EltSizeInBits) {
4188 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4200 ReturnType->getNumElements() * ReductionFactor);
4217 VaInt = CreateAppToShadowCast(IRB, Va);
4218 VbInt = CreateAppToShadowCast(IRB, Vb);
4225 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4247 ImplicitReturnType);
4252 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4255 if (
I.arg_size() == 3)
4256 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4258 setShadow(&
I, OutShadow);
4259 setOriginForNaryOp(
I);
4276 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4277 bool PredicateAsOperand) {
4278 if (PredicateAsOperand) {
4280 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4288 Type *ResTy = getShadowTy(&
I);
4289 auto *Shadow0 = getShadow(&
I, 0);
4290 auto *Shadow1 = getShadow(&
I, 1);
4295 setOriginForNaryOp(
I);
4301 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4303 auto *Shadow0 = getShadow(&
I, 0);
4304 auto *Shadow1 = getShadow(&
I, 1);
4306 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4308 setOriginForNaryOp(
I);
4317 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4322 if (AllowShadowCast)
4323 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4327 setOriginForNaryOp(
I);
4337 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4341 Value *Shadow0 = getShadow(&
I, 0);
4347 setOriginForNaryOp(
I);
4353 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4357 Value *OperandShadow = getShadow(&
I, 0);
4359 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4367 setOrigin(&
I, getOrigin(&
I, 0));
4373 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4377 Value *OperandShadow = getShadow(&
I, 0);
4378 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4386 setOrigin(&
I, getOrigin(&
I, 0));
4389 void handleStmxcsr(IntrinsicInst &
I) {
4391 Value *Addr =
I.getArgOperand(0);
4394 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4399 insertCheckShadowOf(Addr, &
I);
4402 void handleLdmxcsr(IntrinsicInst &
I) {
4407 Value *Addr =
I.getArgOperand(0);
4410 Value *ShadowPtr, *OriginPtr;
4411 std::tie(ShadowPtr, OriginPtr) =
4412 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4415 insertCheckShadowOf(Addr, &
I);
4418 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4420 insertCheckShadow(Shadow, Origin, &
I);
4423 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4425 Value *Ptr =
I.getArgOperand(0);
4426 MaybeAlign
Align =
I.getParamAlign(0);
4428 Value *PassThru =
I.getArgOperand(2);
4431 insertCheckShadowOf(Ptr, &
I);
4432 insertCheckShadowOf(Mask, &
I);
4435 if (!PropagateShadow) {
4436 setShadow(&
I, getCleanShadow(&
I));
4437 setOrigin(&
I, getCleanOrigin());
4441 Type *ShadowTy = getShadowTy(&
I);
4443 auto [ShadowPtr, OriginPtr] =
4444 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4448 getShadow(PassThru),
"_msmaskedexpload");
4450 setShadow(&
I, Shadow);
4453 setOrigin(&
I, getCleanOrigin());
4456 void handleMaskedCompressStore(IntrinsicInst &
I) {
4459 Value *Ptr =
I.getArgOperand(1);
4460 MaybeAlign
Align =
I.getParamAlign(1);
4464 insertCheckShadowOf(Ptr, &
I);
4465 insertCheckShadowOf(Mask, &
I);
4469 Type *ElementShadowTy =
4471 auto [ShadowPtr, OriginPtrs] =
4472 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4479 void handleMaskedGather(IntrinsicInst &
I) {
4481 Value *Ptrs =
I.getArgOperand(0);
4482 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4484 Value *PassThru =
I.getArgOperand(2);
4486 Type *PtrsShadowTy = getShadowTy(Ptrs);
4488 insertCheckShadowOf(Mask, &
I);
4492 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4495 if (!PropagateShadow) {
4496 setShadow(&
I, getCleanShadow(&
I));
4497 setOrigin(&
I, getCleanOrigin());
4501 Type *ShadowTy = getShadowTy(&
I);
4503 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4504 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4508 getShadow(PassThru),
"_msmaskedgather");
4510 setShadow(&
I, Shadow);
4513 setOrigin(&
I, getCleanOrigin());
4516 void handleMaskedScatter(IntrinsicInst &
I) {
4519 Value *Ptrs =
I.getArgOperand(1);
4520 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4523 Type *PtrsShadowTy = getShadowTy(Ptrs);
4525 insertCheckShadowOf(Mask, &
I);
4529 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4533 Type *ElementShadowTy =
4535 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4536 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4547 void handleMaskedStore(IntrinsicInst &
I) {
4549 Value *
V =
I.getArgOperand(0);
4550 Value *Ptr =
I.getArgOperand(1);
4551 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4553 Value *Shadow = getShadow(V);
4556 insertCheckShadowOf(Ptr, &
I);
4557 insertCheckShadowOf(Mask, &
I);
4562 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4563 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4567 if (!MS.TrackOrigins)
4570 auto &
DL =
F.getDataLayout();
4571 paintOrigin(IRB, getOrigin(V), OriginPtr,
4580 void handleMaskedLoad(IntrinsicInst &
I) {
4582 Value *Ptr =
I.getArgOperand(0);
4583 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4585 Value *PassThru =
I.getArgOperand(2);
4588 insertCheckShadowOf(Ptr, &
I);
4589 insertCheckShadowOf(Mask, &
I);
4592 if (!PropagateShadow) {
4593 setShadow(&
I, getCleanShadow(&
I));
4594 setOrigin(&
I, getCleanOrigin());
4598 Type *ShadowTy = getShadowTy(&
I);
4599 Value *ShadowPtr, *OriginPtr;
4600 std::tie(ShadowPtr, OriginPtr) =
4601 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4603 getShadow(PassThru),
"_msmaskedld"));
4605 if (!MS.TrackOrigins)
4612 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4617 setOrigin(&
I, Origin);
4633 void handleAVXMaskedStore(IntrinsicInst &
I) {
4638 Value *Dst =
I.getArgOperand(0);
4639 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4644 Value *Src =
I.getArgOperand(2);
4649 Value *SrcShadow = getShadow(Src);
4652 insertCheckShadowOf(Dst, &
I);
4653 insertCheckShadowOf(Mask, &
I);
4656 Value *DstShadowPtr;
4657 Value *DstOriginPtr;
4658 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4659 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4661 SmallVector<Value *, 2> ShadowArgs;
4662 ShadowArgs.
append(1, DstShadowPtr);
4663 ShadowArgs.
append(1, Mask);
4671 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
4674 if (!MS.TrackOrigins)
4678 auto &
DL =
F.getDataLayout();
4679 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4680 DL.getTypeStoreSize(SrcShadow->
getType()),
4699 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4704 Value *Src =
I.getArgOperand(0);
4705 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4713 insertCheckShadowOf(Mask, &
I);
4716 Type *SrcShadowTy = getShadowTy(Src);
4717 Value *SrcShadowPtr, *SrcOriginPtr;
4718 std::tie(SrcShadowPtr, SrcOriginPtr) =
4719 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4721 SmallVector<Value *, 2> ShadowArgs;
4722 ShadowArgs.
append(1, SrcShadowPtr);
4723 ShadowArgs.
append(1, Mask);
4726 I.getType(),
I.getIntrinsicID(), ShadowArgs);
4732 if (!MS.TrackOrigins)
4739 setOrigin(&
I, PtrSrcOrigin);
4748 assert(isFixedIntVector(Idx));
4749 auto IdxVectorSize =
4757 auto *IdxShadow = getShadow(Idx);
4762 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4767 void handleAVXVpermilvar(IntrinsicInst &
I) {
4769 Value *Shadow = getShadow(&
I, 0);
4770 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4774 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4776 I.getType(),
I.getIntrinsicID(), {Shadow, I.getArgOperand(1)});
4779 setOriginForNaryOp(
I);
4784 void handleAVXVpermi2var(IntrinsicInst &
I) {
4789 [[maybe_unused]]
auto ArgVectorSize =
4792 ->getNumElements() == ArgVectorSize);
4794 ->getNumElements() == ArgVectorSize);
4795 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4796 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4797 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4799 Value *AShadow = getShadow(&
I, 0);
4800 Value *Idx =
I.getArgOperand(1);
4801 Value *BShadow = getShadow(&
I, 2);
4803 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4807 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4808 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4810 I.getType(),
I.getIntrinsicID(), {AShadow, Idx, BShadow});
4812 setOriginForNaryOp(
I);
4815 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4819 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4823 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4824 return isFixedIntVectorTy(
V->getType());
4827 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4828 return isFixedFPVectorTy(
V->getType());
4850 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4855 Value *WriteThrough;
4859 WriteThrough =
I.getOperand(2);
4860 Mask =
I.getOperand(3);
4863 WriteThrough =
I.getOperand(1);
4864 Mask =
I.getOperand(2);
4869 assert(isFixedIntVector(WriteThrough));
4871 unsigned ANumElements =
4873 [[maybe_unused]]
unsigned WriteThruNumElements =
4875 assert(ANumElements == WriteThruNumElements ||
4876 ANumElements * 2 == WriteThruNumElements);
4879 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4880 assert(ANumElements == MaskNumElements ||
4881 ANumElements * 2 == MaskNumElements);
4883 assert(WriteThruNumElements == MaskNumElements);
4887 insertCheckShadowOf(Mask, &
I);
4897 Value *AShadow = getShadow(
A);
4898 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4900 if (ANumElements * 2 == MaskNumElements) {
4912 "_ms_mask_bitcast");
4922 getShadowTy(&
I),
"_ms_a_shadow");
4924 Value *WriteThroughShadow = getShadow(WriteThrough);
4926 "_ms_writethru_select");
4928 setShadow(&
I, Shadow);
4929 setOriginForNaryOp(
I);
4932 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4933 SmallVector<int, 8>
Mask;
4934 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4948 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4953 "pclmul 3rd operand must be a constant");
4956 getPclmulMask(Width, Imm & 0x01));
4958 getPclmulMask(Width, Imm & 0x10));
4959 ShadowAndOriginCombiner SOC(
this, IRB);
4960 SOC.Add(Shuf0, getOrigin(&
I, 0));
4961 SOC.Add(Shuf1, getOrigin(&
I, 1));
4966 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4971 Value *Second = getShadow(&
I, 1);
4973 SmallVector<int, 16>
Mask;
4974 Mask.push_back(Width);
4975 for (
unsigned i = 1; i < Width; i++)
4979 setShadow(&
I, Shadow);
4980 setOriginForNaryOp(
I);
4983 void handleVtestIntrinsic(IntrinsicInst &
I) {
4985 Value *Shadow0 = getShadow(&
I, 0);
4986 Value *Shadow1 = getShadow(&
I, 1);
4992 setShadow(&
I, Shadow);
4993 setOriginForNaryOp(
I);
4996 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
5001 Value *Second = getShadow(&
I, 1);
5004 SmallVector<int, 16>
Mask;
5005 Mask.push_back(Width);
5006 for (
unsigned i = 1; i < Width; i++)
5010 setShadow(&
I, Shadow);
5011 setOriginForNaryOp(
I);
5017 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5018 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5023 ShadowAndOriginCombiner SC(
this, IRB);
5024 SC.Add(
I.getArgOperand(0));
5032 void handleAbsIntrinsic(IntrinsicInst &
I) {
5034 Value *Src =
I.getArgOperand(0);
5035 Value *IsIntMinPoison =
I.getArgOperand(1);
5037 assert(
I.getType()->isIntOrIntVectorTy());
5039 assert(Src->getType() ==
I.getType());
5045 Value *SrcShadow = getShadow(Src);
5049 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5052 Value *PoisonedShadow = getPoisonedShadow(Src);
5053 Value *PoisonedIfIntMinShadow =
5056 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5058 setShadow(&
I, Shadow);
5059 setOrigin(&
I, getOrigin(&
I, 0));
5062 void handleIsFpClass(IntrinsicInst &
I) {
5064 Value *Shadow = getShadow(&
I, 0);
5065 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5066 setOrigin(&
I, getOrigin(&
I, 0));
5069 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5071 Value *Shadow0 = getShadow(&
I, 0);
5072 Value *Shadow1 = getShadow(&
I, 1);
5075 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5081 setShadow(&
I, Shadow);
5082 setOriginForNaryOp(
I);
5088 Value *Shadow = getShadow(V);
5110 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5115 Value *WriteThrough =
I.getOperand(1);
5119 assert(isFixedIntVector(WriteThrough));
5121 unsigned ANumElements =
5123 unsigned OutputNumElements =
5125 assert(ANumElements == OutputNumElements ||
5126 ANumElements * 2 == OutputNumElements);
5136 insertCheckShadowOf(Mask, &
I);
5139 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5140 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5141 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5152 if (ANumElements != OutputNumElements) {
5154 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5161 Value *AShadow = getShadow(
A);
5165 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5175 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5176 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5178 Value *WriteThroughShadow = getShadow(WriteThrough);
5181 setShadow(&
I, Shadow);
5182 setOriginForNaryOp(
I);
5216 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5217 SmallVector<unsigned, 4> DataIndices,
5218 unsigned WriteThruIndex,
5219 unsigned MaskIndex) {
5222 unsigned NumArgs =
I.arg_size();
5224 assert(WriteThruIndex < NumArgs);
5225 assert(MaskIndex < NumArgs);
5226 assert(WriteThruIndex != MaskIndex);
5227 Value *WriteThru =
I.getOperand(WriteThruIndex);
5229 unsigned OutputNumElements =
5234 bool isData[16] = {
false};
5236 for (
unsigned i : DataIndices) {
5238 assert(i != WriteThruIndex);
5245 [[maybe_unused]]
unsigned ANumElements =
5247 assert(ANumElements == OutputNumElements);
5252 assert(isFixedFPVector(WriteThru));
5254 for (
unsigned i = 0; i < NumArgs; ++i) {
5255 if (!isData[i] && i != WriteThruIndex) {
5258 assert(
I.getOperand(i)->getType()->isIntegerTy());
5259 insertCheckShadowOf(
I.getOperand(i), &
I);
5264 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5265 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5266 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5273 Value *DataShadow =
nullptr;
5274 for (
unsigned i : DataIndices) {
5277 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5279 DataShadow = getShadow(
A);
5287 Value *WriteThruShadow = getShadow(WriteThru);
5290 setShadow(&
I, Shadow);
5292 setOriginForNaryOp(
I);
5302 void handleAVX512FPClass(IntrinsicInst &
I) {
5307 Value *Input =
I.getOperand(0);
5308 assert(isFixedFPVector(Input));
5311 Value *Classifiers =
I.getOperand(1);
5315 assert(isFixedIntVectorTy(
I.getType()));
5321 Value *OutputShadow;
5326 OutputShadow = getCleanShadow(OutputType);
5332 OutputShadow = IRB.
CreateICmpNE(getShadow(Input), getCleanShadow(Input));
5334 setShadow(&
I, OutputShadow);
5336 setOriginForNaryOp(
I);
5346 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5352 Value *WriteThrough =
I.getOperand(2);
5359 insertCheckShadowOf(Mask, &
I);
5363 unsigned NumElements =
5365 assert(NumElements == 8);
5366 assert(
A->getType() ==
B->getType());
5368 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5371 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5372 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5374 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5376 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5383 Value *AShadow = getShadow(
A);
5384 Value *DstLowerShadow =
5385 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5387 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5390 setShadow(&
I, DstShadow);
5391 setOriginForNaryOp(
I);
5421 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5432 ->getScalarSizeInBits() == 8);
5434 assert(
A->getType() ==
X->getType());
5436 assert(
B->getType()->isIntegerTy());
5437 assert(
B->getType()->getScalarSizeInBits() == 8);
5439 assert(
I.getType() ==
A->getType());
5441 Value *AShadow = getShadow(
A);
5442 Value *XShadow = getShadow(
X);
5443 Value *BZeroShadow = getCleanShadow(
B);
5446 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5448 {X, AShadow, BZeroShadow});
5450 {XShadow, A, BZeroShadow});
5453 Value *BShadow = getShadow(
B);
5454 Value *BBroadcastShadow = getCleanShadow(AShadow);
5459 for (
unsigned i = 0; i < NumElements; i++)
5463 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5464 setOriginForNaryOp(
I);
5478 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5479 unsigned int numArgs =
I.arg_size();
5482 assert(
I.getType()->isStructTy());
5492 assert(4 <= numArgs && numArgs <= 6);
5506 for (
unsigned int i = 0; i < numArgs - 2; i++)
5507 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5510 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5514 insertCheckShadowOf(LaneNumber, &
I);
5517 Value *Src =
I.getArgOperand(numArgs - 1);
5518 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5520 Type *SrcShadowTy = getShadowTy(Src);
5521 auto [SrcShadowPtr, SrcOriginPtr] =
5522 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5529 getShadowTy(&
I),
I.getIntrinsicID(), ShadowArgs);
5532 if (!MS.TrackOrigins)
5536 setOrigin(&
I, PtrSrcOrigin);
5553 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5557 int numArgOperands =
I.arg_size();
5560 assert(numArgOperands >= 1);
5561 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5563 int skipTrailingOperands = 1;
5566 insertCheckShadowOf(Addr, &
I);
5570 skipTrailingOperands++;
5571 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5573 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5576 SmallVector<Value *, 8> ShadowArgs;
5578 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5580 Value *Shadow = getShadow(&
I, i);
5581 ShadowArgs.
append(1, Shadow);
5598 (numArgOperands - skipTrailingOperands));
5599 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5603 I.getArgOperand(numArgOperands - skipTrailingOperands));
5605 Value *OutputShadowPtr, *OutputOriginPtr;
5607 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5608 Addr, IRB, OutputShadowTy,
Align(1),
true);
5609 ShadowArgs.
append(1, OutputShadowPtr);
5612 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
5615 if (MS.TrackOrigins) {
5623 OriginCombiner OC(
this, IRB);
5624 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5625 OC.Add(
I.getArgOperand(i));
5627 const DataLayout &
DL =
F.getDataLayout();
5628 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5661 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5665 Value *
R =
I.getArgOperand(0);
5666 Value *
A =
I.getArgOperand(1);
5667 Value *
B =
I.getArgOperand(2);
5669 assert(
I.getType() ==
R->getType());
5694 Value *ShadowR = getShadow(&
I, 0);
5695 Value *ShadowA = getShadow(&
I, 1);
5696 Value *ShadowB = getShadow(&
I, 2);
5714 {getCleanShadow(RTy), ShadowA, ShadowB});
5740 {RZeros, ShadowA, ShadowB});
5754 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5755 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5757 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5759 setOriginForNaryOp(
I);
5799 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5801 unsigned int trailingVerbatimArgs,
5802 bool forceIntegerIntrinsic) {
5805 assert(trailingVerbatimArgs <
I.arg_size());
5807 SmallVector<Value *, 8> ShadowArgs;
5809 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5810 Value *Shadow = getShadow(&
I, i);
5812 if (forceIntegerIntrinsic)
5819 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5821 Value *Arg =
I.getArgOperand(i);
5822 if (forceIntegerIntrinsic)
5827 Value *CombinedShadow;
5828 if (forceIntegerIntrinsic) {
5838 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5841 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5842 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5845 setShadow(&
I, CombinedShadow);
5847 setOriginForNaryOp(
I);
5853 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5859 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5860 switch (
I.getIntrinsicID()) {
5861 case Intrinsic::uadd_with_overflow:
5862 case Intrinsic::sadd_with_overflow:
5863 case Intrinsic::usub_with_overflow:
5864 case Intrinsic::ssub_with_overflow:
5865 case Intrinsic::umul_with_overflow:
5866 case Intrinsic::smul_with_overflow:
5867 handleArithmeticWithOverflow(
I);
5869 case Intrinsic::abs:
5870 handleAbsIntrinsic(
I);
5872 case Intrinsic::bitreverse:
5873 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5877 case Intrinsic::is_fpclass:
5880 case Intrinsic::lifetime_start:
5881 handleLifetimeStart(
I);
5883 case Intrinsic::launder_invariant_group:
5884 case Intrinsic::strip_invariant_group:
5885 handleInvariantGroup(
I);
5887 case Intrinsic::bswap:
5890 case Intrinsic::ctlz:
5891 case Intrinsic::cttz:
5892 handleCountLeadingTrailingZeros(
I);
5894 case Intrinsic::masked_compressstore:
5895 handleMaskedCompressStore(
I);
5897 case Intrinsic::masked_expandload:
5898 handleMaskedExpandLoad(
I);
5900 case Intrinsic::masked_gather:
5901 handleMaskedGather(
I);
5903 case Intrinsic::masked_scatter:
5904 handleMaskedScatter(
I);
5906 case Intrinsic::masked_store:
5907 handleMaskedStore(
I);
5909 case Intrinsic::masked_load:
5910 handleMaskedLoad(
I);
5912 case Intrinsic::vector_reduce_and:
5913 handleVectorReduceAndIntrinsic(
I);
5915 case Intrinsic::vector_reduce_or:
5916 handleVectorReduceOrIntrinsic(
I);
5919 case Intrinsic::vector_reduce_add:
5920 case Intrinsic::vector_reduce_xor:
5921 case Intrinsic::vector_reduce_mul:
5924 case Intrinsic::vector_reduce_smax:
5925 case Intrinsic::vector_reduce_smin:
5926 case Intrinsic::vector_reduce_umax:
5927 case Intrinsic::vector_reduce_umin:
5930 case Intrinsic::vector_reduce_fmax:
5931 case Intrinsic::vector_reduce_fmin:
5932 handleVectorReduceIntrinsic(
I,
false);
5935 case Intrinsic::vector_reduce_fadd:
5936 case Intrinsic::vector_reduce_fmul:
5937 handleVectorReduceWithStarterIntrinsic(
I);
5940 case Intrinsic::scmp:
5941 case Intrinsic::ucmp: {
5946 case Intrinsic::fshl:
5947 case Intrinsic::fshr:
5948 handleFunnelShift(
I);
5951 case Intrinsic::pdep:
5952 case Intrinsic::pext:
5953 handleGenericBitManipulation(
I);
5956 case Intrinsic::is_constant:
5958 setShadow(&
I, getCleanShadow(&
I));
5959 setOrigin(&
I, getCleanOrigin());
5966 case Intrinsic::fptosi_sat:
5967 case Intrinsic::fptoui_sat:
5968 handleGenericVectorConvertIntrinsic(
I,
false);
5978 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5979 switch (
I.getIntrinsicID()) {
5980 case Intrinsic::x86_sse_stmxcsr:
5983 case Intrinsic::x86_sse_ldmxcsr:
5990 case Intrinsic::x86_avx512_vcvtsd2usi64:
5991 case Intrinsic::x86_avx512_vcvtsd2usi32:
5992 case Intrinsic::x86_avx512_vcvtss2usi64:
5993 case Intrinsic::x86_avx512_vcvtss2usi32:
5994 case Intrinsic::x86_avx512_cvttss2usi64:
5995 case Intrinsic::x86_avx512_cvttss2usi:
5996 case Intrinsic::x86_avx512_cvttsd2usi64:
5997 case Intrinsic::x86_avx512_cvttsd2usi:
5998 case Intrinsic::x86_avx512_cvtusi2ss:
5999 case Intrinsic::x86_avx512_cvtusi642sd:
6000 case Intrinsic::x86_avx512_cvtusi642ss:
6001 handleSSEVectorConvertIntrinsic(
I, 1,
true);
6003 case Intrinsic::x86_sse2_cvtsd2si64:
6004 case Intrinsic::x86_sse2_cvtsd2si:
6005 case Intrinsic::x86_sse2_cvtsd2ss:
6006 case Intrinsic::x86_sse2_cvttsd2si64:
6007 case Intrinsic::x86_sse2_cvttsd2si:
6008 case Intrinsic::x86_sse_cvtss2si64:
6009 case Intrinsic::x86_sse_cvtss2si:
6010 case Intrinsic::x86_sse_cvttss2si64:
6011 case Intrinsic::x86_sse_cvttss2si:
6012 handleSSEVectorConvertIntrinsic(
I, 1);
6014 case Intrinsic::x86_sse_cvtps2pi:
6015 case Intrinsic::x86_sse_cvttps2pi:
6016 handleSSEVectorConvertIntrinsic(
I, 2);
6024 case Intrinsic::x86_vcvtps2ph_128:
6025 case Intrinsic::x86_vcvtps2ph_256: {
6026 handleSSEVectorConvertIntrinsicByProp(
I,
true);
6035 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
6036 handleAVX512VectorConvertFPToInt(
I,
false);
6041 case Intrinsic::x86_sse2_cvtpd2ps:
6042 case Intrinsic::x86_sse2_cvtps2dq:
6043 case Intrinsic::x86_sse2_cvtpd2dq:
6044 case Intrinsic::x86_sse2_cvttps2dq:
6045 case Intrinsic::x86_sse2_cvttpd2dq:
6046 case Intrinsic::x86_avx_cvt_pd2_ps_256:
6047 case Intrinsic::x86_avx_cvt_ps2dq_256:
6048 case Intrinsic::x86_avx_cvt_pd2dq_256:
6049 case Intrinsic::x86_avx_cvtt_ps2dq_256:
6050 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
6051 handleSSEVectorConvertIntrinsicByProp(
I,
false);
6062 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
6063 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
6064 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
6065 handleAVX512VectorConvertFPToInt(
I,
true);
6069 case Intrinsic::x86_avx512_psll_w_512:
6070 case Intrinsic::x86_avx512_psll_d_512:
6071 case Intrinsic::x86_avx512_psll_q_512:
6072 case Intrinsic::x86_avx512_pslli_w_512:
6073 case Intrinsic::x86_avx512_pslli_d_512:
6074 case Intrinsic::x86_avx512_pslli_q_512:
6075 case Intrinsic::x86_avx512_psrl_w_512:
6076 case Intrinsic::x86_avx512_psrl_d_512:
6077 case Intrinsic::x86_avx512_psrl_q_512:
6078 case Intrinsic::x86_avx512_psra_w_512:
6079 case Intrinsic::x86_avx512_psra_d_512:
6080 case Intrinsic::x86_avx512_psra_q_512:
6081 case Intrinsic::x86_avx512_psrli_w_512:
6082 case Intrinsic::x86_avx512_psrli_d_512:
6083 case Intrinsic::x86_avx512_psrli_q_512:
6084 case Intrinsic::x86_avx512_psrai_w_512:
6085 case Intrinsic::x86_avx512_psrai_d_512:
6086 case Intrinsic::x86_avx512_psrai_q_512:
6087 case Intrinsic::x86_avx512_psra_q_256:
6088 case Intrinsic::x86_avx512_psra_q_128:
6089 case Intrinsic::x86_avx512_psrai_q_256:
6090 case Intrinsic::x86_avx512_psrai_q_128:
6091 case Intrinsic::x86_avx2_psll_w:
6092 case Intrinsic::x86_avx2_psll_d:
6093 case Intrinsic::x86_avx2_psll_q:
6094 case Intrinsic::x86_avx2_pslli_w:
6095 case Intrinsic::x86_avx2_pslli_d:
6096 case Intrinsic::x86_avx2_pslli_q:
6097 case Intrinsic::x86_avx2_psrl_w:
6098 case Intrinsic::x86_avx2_psrl_d:
6099 case Intrinsic::x86_avx2_psrl_q:
6100 case Intrinsic::x86_avx2_psra_w:
6101 case Intrinsic::x86_avx2_psra_d:
6102 case Intrinsic::x86_avx2_psrli_w:
6103 case Intrinsic::x86_avx2_psrli_d:
6104 case Intrinsic::x86_avx2_psrli_q:
6105 case Intrinsic::x86_avx2_psrai_w:
6106 case Intrinsic::x86_avx2_psrai_d:
6107 case Intrinsic::x86_sse2_psll_w:
6108 case Intrinsic::x86_sse2_psll_d:
6109 case Intrinsic::x86_sse2_psll_q:
6110 case Intrinsic::x86_sse2_pslli_w:
6111 case Intrinsic::x86_sse2_pslli_d:
6112 case Intrinsic::x86_sse2_pslli_q:
6113 case Intrinsic::x86_sse2_psrl_w:
6114 case Intrinsic::x86_sse2_psrl_d:
6115 case Intrinsic::x86_sse2_psrl_q:
6116 case Intrinsic::x86_sse2_psra_w:
6117 case Intrinsic::x86_sse2_psra_d:
6118 case Intrinsic::x86_sse2_psrli_w:
6119 case Intrinsic::x86_sse2_psrli_d:
6120 case Intrinsic::x86_sse2_psrli_q:
6121 case Intrinsic::x86_sse2_psrai_w:
6122 case Intrinsic::x86_sse2_psrai_d:
6123 case Intrinsic::x86_mmx_psll_w:
6124 case Intrinsic::x86_mmx_psll_d:
6125 case Intrinsic::x86_mmx_psll_q:
6126 case Intrinsic::x86_mmx_pslli_w:
6127 case Intrinsic::x86_mmx_pslli_d:
6128 case Intrinsic::x86_mmx_pslli_q:
6129 case Intrinsic::x86_mmx_psrl_w:
6130 case Intrinsic::x86_mmx_psrl_d:
6131 case Intrinsic::x86_mmx_psrl_q:
6132 case Intrinsic::x86_mmx_psra_w:
6133 case Intrinsic::x86_mmx_psra_d:
6134 case Intrinsic::x86_mmx_psrli_w:
6135 case Intrinsic::x86_mmx_psrli_d:
6136 case Intrinsic::x86_mmx_psrli_q:
6137 case Intrinsic::x86_mmx_psrai_w:
6138 case Intrinsic::x86_mmx_psrai_d:
6139 handleVectorShiftIntrinsic(
I,
false);
6141 case Intrinsic::x86_avx2_psllv_d:
6142 case Intrinsic::x86_avx2_psllv_d_256:
6143 case Intrinsic::x86_avx512_psllv_d_512:
6144 case Intrinsic::x86_avx2_psllv_q:
6145 case Intrinsic::x86_avx2_psllv_q_256:
6146 case Intrinsic::x86_avx512_psllv_q_512:
6147 case Intrinsic::x86_avx2_psrlv_d:
6148 case Intrinsic::x86_avx2_psrlv_d_256:
6149 case Intrinsic::x86_avx512_psrlv_d_512:
6150 case Intrinsic::x86_avx2_psrlv_q:
6151 case Intrinsic::x86_avx2_psrlv_q_256:
6152 case Intrinsic::x86_avx512_psrlv_q_512:
6153 case Intrinsic::x86_avx2_psrav_d:
6154 case Intrinsic::x86_avx2_psrav_d_256:
6155 case Intrinsic::x86_avx512_psrav_d_512:
6156 case Intrinsic::x86_avx512_psrav_q_128:
6157 case Intrinsic::x86_avx512_psrav_q_256:
6158 case Intrinsic::x86_avx512_psrav_q_512:
6159 handleVectorShiftIntrinsic(
I,
true);
6163 case Intrinsic::x86_sse2_packsswb_128:
6164 case Intrinsic::x86_sse2_packssdw_128:
6165 case Intrinsic::x86_sse2_packuswb_128:
6166 case Intrinsic::x86_sse41_packusdw:
6167 case Intrinsic::x86_avx2_packsswb:
6168 case Intrinsic::x86_avx2_packssdw:
6169 case Intrinsic::x86_avx2_packuswb:
6170 case Intrinsic::x86_avx2_packusdw:
6176 case Intrinsic::x86_avx512_packsswb_512:
6177 case Intrinsic::x86_avx512_packssdw_512:
6178 case Intrinsic::x86_avx512_packuswb_512:
6179 case Intrinsic::x86_avx512_packusdw_512:
6180 handleVectorPackIntrinsic(
I);
6183 case Intrinsic::x86_sse41_pblendvb:
6184 case Intrinsic::x86_sse41_blendvpd:
6185 case Intrinsic::x86_sse41_blendvps:
6186 case Intrinsic::x86_avx_blendv_pd_256:
6187 case Intrinsic::x86_avx_blendv_ps_256:
6188 case Intrinsic::x86_avx2_pblendvb:
6189 handleBlendvIntrinsic(
I);
6192 case Intrinsic::x86_avx_dp_ps_256:
6193 case Intrinsic::x86_sse41_dppd:
6194 case Intrinsic::x86_sse41_dpps:
6195 handleDppIntrinsic(
I);
6198 case Intrinsic::x86_mmx_packsswb:
6199 case Intrinsic::x86_mmx_packuswb:
6200 handleVectorPackIntrinsic(
I, 16);
6203 case Intrinsic::x86_mmx_packssdw:
6204 handleVectorPackIntrinsic(
I, 32);
6207 case Intrinsic::x86_mmx_psad_bw:
6208 handleVectorSadIntrinsic(
I,
true);
6210 case Intrinsic::x86_sse2_psad_bw:
6211 case Intrinsic::x86_avx2_psad_bw:
6212 handleVectorSadIntrinsic(
I);
6238 case Intrinsic::x86_sse2_pmadd_wd:
6239 case Intrinsic::x86_avx2_pmadd_wd:
6240 case Intrinsic::x86_avx512_pmaddw_d_512:
6241 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6242 case Intrinsic::x86_avx2_pmadd_ub_sw:
6243 case Intrinsic::x86_avx512_pmaddubs_w_512:
6244 handleVectorDotProductIntrinsic(
I, 2,
6251 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6252 handleVectorDotProductIntrinsic(
I, 2,
6259 case Intrinsic::x86_mmx_pmadd_wd:
6260 handleVectorDotProductIntrinsic(
I, 2,
6269 case Intrinsic::aarch64_neon_bfmlalt:
6270 handleVectorDotProductIntrinsic(
I, 2,
6278 case Intrinsic::aarch64_neon_bfmlalb:
6279 handleVectorDotProductIntrinsic(
I, 2,
6377 case Intrinsic::x86_avx512_vpdpbusd_128:
6378 case Intrinsic::x86_avx512_vpdpbusd_256:
6379 case Intrinsic::x86_avx512_vpdpbusd_512:
6380 case Intrinsic::x86_avx512_vpdpbusds_128:
6381 case Intrinsic::x86_avx512_vpdpbusds_256:
6382 case Intrinsic::x86_avx512_vpdpbusds_512:
6383 case Intrinsic::x86_avx2_vpdpbssd_128:
6384 case Intrinsic::x86_avx2_vpdpbssd_256:
6385 case Intrinsic::x86_avx10_vpdpbssd_512:
6386 case Intrinsic::x86_avx2_vpdpbssds_128:
6387 case Intrinsic::x86_avx2_vpdpbssds_256:
6388 case Intrinsic::x86_avx10_vpdpbssds_512:
6389 case Intrinsic::x86_avx2_vpdpbsud_128:
6390 case Intrinsic::x86_avx2_vpdpbsud_256:
6391 case Intrinsic::x86_avx10_vpdpbsud_512:
6392 case Intrinsic::x86_avx2_vpdpbsuds_128:
6393 case Intrinsic::x86_avx2_vpdpbsuds_256:
6394 case Intrinsic::x86_avx10_vpdpbsuds_512:
6395 case Intrinsic::x86_avx2_vpdpbuud_128:
6396 case Intrinsic::x86_avx2_vpdpbuud_256:
6397 case Intrinsic::x86_avx10_vpdpbuud_512:
6398 case Intrinsic::x86_avx2_vpdpbuuds_128:
6399 case Intrinsic::x86_avx2_vpdpbuuds_256:
6400 case Intrinsic::x86_avx10_vpdpbuuds_512:
6401 handleVectorDotProductIntrinsic(
I, 4,
6499 case Intrinsic::x86_avx512_vpdpwssd_128:
6500 case Intrinsic::x86_avx512_vpdpwssd_256:
6501 case Intrinsic::x86_avx512_vpdpwssd_512:
6502 case Intrinsic::x86_avx512_vpdpwssds_128:
6503 case Intrinsic::x86_avx512_vpdpwssds_256:
6504 case Intrinsic::x86_avx512_vpdpwssds_512:
6505 case Intrinsic::x86_avx2_vpdpwsud_128:
6506 case Intrinsic::x86_avx2_vpdpwsud_256:
6507 case Intrinsic::x86_avx10_vpdpwsud_512:
6508 case Intrinsic::x86_avx2_vpdpwsuds_128:
6509 case Intrinsic::x86_avx2_vpdpwsuds_256:
6510 case Intrinsic::x86_avx10_vpdpwsuds_512:
6511 case Intrinsic::x86_avx2_vpdpwusd_128:
6512 case Intrinsic::x86_avx2_vpdpwusd_256:
6513 case Intrinsic::x86_avx10_vpdpwusd_512:
6514 case Intrinsic::x86_avx2_vpdpwusds_128:
6515 case Intrinsic::x86_avx2_vpdpwusds_256:
6516 case Intrinsic::x86_avx10_vpdpwusds_512:
6517 case Intrinsic::x86_avx2_vpdpwuud_128:
6518 case Intrinsic::x86_avx2_vpdpwuud_256:
6519 case Intrinsic::x86_avx10_vpdpwuud_512:
6520 case Intrinsic::x86_avx2_vpdpwuuds_128:
6521 case Intrinsic::x86_avx2_vpdpwuuds_256:
6522 case Intrinsic::x86_avx10_vpdpwuuds_512:
6523 handleVectorDotProductIntrinsic(
I, 2,
6537 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6538 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6539 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6540 handleVectorDotProductIntrinsic(
I, 2,
6546 case Intrinsic::x86_sse_cmp_ss:
6547 case Intrinsic::x86_sse2_cmp_sd:
6548 case Intrinsic::x86_sse_comieq_ss:
6549 case Intrinsic::x86_sse_comilt_ss:
6550 case Intrinsic::x86_sse_comile_ss:
6551 case Intrinsic::x86_sse_comigt_ss:
6552 case Intrinsic::x86_sse_comige_ss:
6553 case Intrinsic::x86_sse_comineq_ss:
6554 case Intrinsic::x86_sse_ucomieq_ss:
6555 case Intrinsic::x86_sse_ucomilt_ss:
6556 case Intrinsic::x86_sse_ucomile_ss:
6557 case Intrinsic::x86_sse_ucomigt_ss:
6558 case Intrinsic::x86_sse_ucomige_ss:
6559 case Intrinsic::x86_sse_ucomineq_ss:
6560 case Intrinsic::x86_sse2_comieq_sd:
6561 case Intrinsic::x86_sse2_comilt_sd:
6562 case Intrinsic::x86_sse2_comile_sd:
6563 case Intrinsic::x86_sse2_comigt_sd:
6564 case Intrinsic::x86_sse2_comige_sd:
6565 case Intrinsic::x86_sse2_comineq_sd:
6566 case Intrinsic::x86_sse2_ucomieq_sd:
6567 case Intrinsic::x86_sse2_ucomilt_sd:
6568 case Intrinsic::x86_sse2_ucomile_sd:
6569 case Intrinsic::x86_sse2_ucomigt_sd:
6570 case Intrinsic::x86_sse2_ucomige_sd:
6571 case Intrinsic::x86_sse2_ucomineq_sd:
6572 handleVectorCompareScalarIntrinsic(
I);
6575 case Intrinsic::x86_avx_cmp_pd_256:
6576 case Intrinsic::x86_avx_cmp_ps_256:
6577 case Intrinsic::x86_sse2_cmp_pd:
6578 case Intrinsic::x86_sse_cmp_ps:
6579 handleVectorComparePackedIntrinsic(
I,
true);
6582 case Intrinsic::x86_bmi_bextr_32:
6583 case Intrinsic::x86_bmi_bextr_64:
6584 case Intrinsic::x86_bmi_bzhi_32:
6585 case Intrinsic::x86_bmi_bzhi_64:
6586 handleGenericBitManipulation(
I);
6589 case Intrinsic::x86_pclmulqdq:
6590 case Intrinsic::x86_pclmulqdq_256:
6591 case Intrinsic::x86_pclmulqdq_512:
6592 handlePclmulIntrinsic(
I);
6595 case Intrinsic::x86_avx_round_pd_256:
6596 case Intrinsic::x86_avx_round_ps_256:
6597 case Intrinsic::x86_sse41_round_pd:
6598 case Intrinsic::x86_sse41_round_ps:
6599 handleRoundPdPsIntrinsic(
I);
6602 case Intrinsic::x86_sse41_round_sd:
6603 case Intrinsic::x86_sse41_round_ss:
6604 handleUnarySdSsIntrinsic(
I);
6607 case Intrinsic::x86_sse2_max_sd:
6608 case Intrinsic::x86_sse_max_ss:
6609 case Intrinsic::x86_sse2_min_sd:
6610 case Intrinsic::x86_sse_min_ss:
6611 handleBinarySdSsIntrinsic(
I);
6614 case Intrinsic::x86_avx_vtestc_pd:
6615 case Intrinsic::x86_avx_vtestc_pd_256:
6616 case Intrinsic::x86_avx_vtestc_ps:
6617 case Intrinsic::x86_avx_vtestc_ps_256:
6618 case Intrinsic::x86_avx_vtestnzc_pd:
6619 case Intrinsic::x86_avx_vtestnzc_pd_256:
6620 case Intrinsic::x86_avx_vtestnzc_ps:
6621 case Intrinsic::x86_avx_vtestnzc_ps_256:
6622 case Intrinsic::x86_avx_vtestz_pd:
6623 case Intrinsic::x86_avx_vtestz_pd_256:
6624 case Intrinsic::x86_avx_vtestz_ps:
6625 case Intrinsic::x86_avx_vtestz_ps_256:
6626 case Intrinsic::x86_avx_ptestc_256:
6627 case Intrinsic::x86_avx_ptestnzc_256:
6628 case Intrinsic::x86_avx_ptestz_256:
6629 case Intrinsic::x86_sse41_ptestc:
6630 case Intrinsic::x86_sse41_ptestnzc:
6631 case Intrinsic::x86_sse41_ptestz:
6632 handleVtestIntrinsic(
I);
6636 case Intrinsic::x86_ssse3_phadd_w:
6637 case Intrinsic::x86_ssse3_phadd_w_128:
6638 case Intrinsic::x86_ssse3_phsub_w:
6639 case Intrinsic::x86_ssse3_phsub_w_128:
6640 handlePairwiseShadowOrIntrinsic(
I, 1,
6644 case Intrinsic::x86_avx2_phadd_w:
6645 case Intrinsic::x86_avx2_phsub_w:
6646 handlePairwiseShadowOrIntrinsic(
I, 2,
6651 case Intrinsic::x86_ssse3_phadd_d:
6652 case Intrinsic::x86_ssse3_phadd_d_128:
6653 case Intrinsic::x86_ssse3_phsub_d:
6654 case Intrinsic::x86_ssse3_phsub_d_128:
6655 handlePairwiseShadowOrIntrinsic(
I, 1,
6659 case Intrinsic::x86_avx2_phadd_d:
6660 case Intrinsic::x86_avx2_phsub_d:
6661 handlePairwiseShadowOrIntrinsic(
I, 2,
6666 case Intrinsic::x86_ssse3_phadd_sw:
6667 case Intrinsic::x86_ssse3_phadd_sw_128:
6668 case Intrinsic::x86_ssse3_phsub_sw:
6669 case Intrinsic::x86_ssse3_phsub_sw_128:
6670 handlePairwiseShadowOrIntrinsic(
I, 1,
6674 case Intrinsic::x86_avx2_phadd_sw:
6675 case Intrinsic::x86_avx2_phsub_sw:
6676 handlePairwiseShadowOrIntrinsic(
I, 2,
6681 case Intrinsic::x86_sse3_hadd_ps:
6682 case Intrinsic::x86_sse3_hadd_pd:
6683 case Intrinsic::x86_sse3_hsub_ps:
6684 case Intrinsic::x86_sse3_hsub_pd:
6685 handlePairwiseShadowOrIntrinsic(
I, 1);
6688 case Intrinsic::x86_avx_hadd_pd_256:
6689 case Intrinsic::x86_avx_hadd_ps_256:
6690 case Intrinsic::x86_avx_hsub_pd_256:
6691 case Intrinsic::x86_avx_hsub_ps_256:
6692 handlePairwiseShadowOrIntrinsic(
I, 2);
6695 case Intrinsic::x86_avx_maskstore_ps:
6696 case Intrinsic::x86_avx_maskstore_pd:
6697 case Intrinsic::x86_avx_maskstore_ps_256:
6698 case Intrinsic::x86_avx_maskstore_pd_256:
6699 case Intrinsic::x86_avx2_maskstore_d:
6700 case Intrinsic::x86_avx2_maskstore_q:
6701 case Intrinsic::x86_avx2_maskstore_d_256:
6702 case Intrinsic::x86_avx2_maskstore_q_256: {
6703 handleAVXMaskedStore(
I);
6707 case Intrinsic::x86_avx_maskload_ps:
6708 case Intrinsic::x86_avx_maskload_pd:
6709 case Intrinsic::x86_avx_maskload_ps_256:
6710 case Intrinsic::x86_avx_maskload_pd_256:
6711 case Intrinsic::x86_avx2_maskload_d:
6712 case Intrinsic::x86_avx2_maskload_q:
6713 case Intrinsic::x86_avx2_maskload_d_256:
6714 case Intrinsic::x86_avx2_maskload_q_256: {
6715 handleAVXMaskedLoad(
I);
6720 case Intrinsic::x86_avx512fp16_add_ph_512:
6721 case Intrinsic::x86_avx512fp16_sub_ph_512:
6722 case Intrinsic::x86_avx512fp16_mul_ph_512:
6723 case Intrinsic::x86_avx512fp16_div_ph_512:
6724 case Intrinsic::x86_avx512fp16_max_ph_512:
6725 case Intrinsic::x86_avx512fp16_min_ph_512:
6726 case Intrinsic::x86_avx512_min_ps_512:
6727 case Intrinsic::x86_avx512_min_pd_512:
6728 case Intrinsic::x86_avx512_max_ps_512:
6729 case Intrinsic::x86_avx512_max_pd_512: {
6734 [[maybe_unused]]
bool Success =
6735 maybeHandleSimpleNomemIntrinsic(
I, 1);
6740 case Intrinsic::x86_avx_vpermilvar_pd:
6741 case Intrinsic::x86_avx_vpermilvar_pd_256:
6742 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6743 case Intrinsic::x86_avx_vpermilvar_ps:
6744 case Intrinsic::x86_avx_vpermilvar_ps_256:
6745 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6746 handleAVXVpermilvar(
I);
6750 case Intrinsic::x86_avx512_vpermi2var_d_128:
6751 case Intrinsic::x86_avx512_vpermi2var_d_256:
6752 case Intrinsic::x86_avx512_vpermi2var_d_512:
6753 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6754 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6755 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6756 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6757 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6758 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6759 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6760 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6761 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6762 case Intrinsic::x86_avx512_vpermi2var_q_128:
6763 case Intrinsic::x86_avx512_vpermi2var_q_256:
6764 case Intrinsic::x86_avx512_vpermi2var_q_512:
6765 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6766 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6767 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6768 handleAVXVpermi2var(
I);
6782 case Intrinsic::x86_avx2_pshuf_b:
6783 case Intrinsic::x86_sse_pshuf_w:
6784 case Intrinsic::x86_ssse3_pshuf_b_128:
6785 case Intrinsic::x86_ssse3_pshuf_b:
6786 case Intrinsic::x86_avx512_pshuf_b_512:
6787 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6794 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6795 case Intrinsic::x86_avx512_mask_pmov_db_128:
6796 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6797 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6798 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6799 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6800 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6801 case Intrinsic::x86_avx512_mask_pmov_db_256:
6802 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6803 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6804 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6805 case Intrinsic::x86_avx512_mask_pmov_db_512:
6806 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6807 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6810 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6819 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6820 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6821 handleIntrinsicByApplyingToShadow(
6822 I, Intrinsic::x86_avx512_mask_pmov_dw_512,
6827 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6828 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6829 handleIntrinsicByApplyingToShadow(
6830 I, Intrinsic::x86_avx512_mask_pmov_dw_256,
6834 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6835 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6836 handleIntrinsicByApplyingToShadow(
6837 I, Intrinsic::x86_avx512_mask_pmov_dw_128,
6841 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6842 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6843 handleIntrinsicByApplyingToShadow(
6844 I, Intrinsic::x86_avx512_mask_pmov_db_512,
6849 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6850 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6851 handleIntrinsicByApplyingToShadow(
6852 I, Intrinsic::x86_avx512_mask_pmov_db_256,
6856 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6857 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6858 handleIntrinsicByApplyingToShadow(
6859 I, Intrinsic::x86_avx512_mask_pmov_db_128,
6863 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6864 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6865 handleIntrinsicByApplyingToShadow(
6866 I, Intrinsic::x86_avx512_mask_pmov_qb_512,
6871 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6872 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6873 handleIntrinsicByApplyingToShadow(
6874 I, Intrinsic::x86_avx512_mask_pmov_qb_256,
6878 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6879 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6880 handleIntrinsicByApplyingToShadow(
6881 I, Intrinsic::x86_avx512_mask_pmov_qb_128,
6885 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6886 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6887 handleIntrinsicByApplyingToShadow(
6888 I, Intrinsic::x86_avx512_mask_pmov_qw_512,
6893 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6894 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6895 handleIntrinsicByApplyingToShadow(
6896 I, Intrinsic::x86_avx512_mask_pmov_qw_256,
6900 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6901 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6902 handleIntrinsicByApplyingToShadow(
6903 I, Intrinsic::x86_avx512_mask_pmov_qw_128,
6907 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6908 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6909 handleIntrinsicByApplyingToShadow(
6910 I, Intrinsic::x86_avx512_mask_pmov_qd_128,
6914 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6915 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6916 handleIntrinsicByApplyingToShadow(
6917 I, Intrinsic::x86_avx512_mask_pmov_wb_128,
6921 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6922 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6923 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6924 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6925 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6926 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6927 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6928 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6932 handleAVX512VectorDownConvert(
I);
6943 case Intrinsic::x86_avx512_mask_compress:
6944 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6985 case Intrinsic::x86_avx512_rsqrt14_ps_512:
6986 case Intrinsic::x86_avx512_rsqrt14_ps_256:
6987 case Intrinsic::x86_avx512_rsqrt14_ps_128:
6988 case Intrinsic::x86_avx512_rsqrt14_pd_512:
6989 case Intrinsic::x86_avx512_rsqrt14_pd_256:
6990 case Intrinsic::x86_avx512_rsqrt14_pd_128:
6991 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
6992 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
6993 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
6994 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
6995 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
6996 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
6997 handleAVX512VectorGenericMaskedFP(
I, {0},
7038 case Intrinsic::x86_avx512_rcp14_ps_512:
7039 case Intrinsic::x86_avx512_rcp14_ps_256:
7040 case Intrinsic::x86_avx512_rcp14_ps_128:
7041 case Intrinsic::x86_avx512_rcp14_pd_512:
7042 case Intrinsic::x86_avx512_rcp14_pd_256:
7043 case Intrinsic::x86_avx512_rcp14_pd_128:
7044 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
7045 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
7046 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
7047 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
7048 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
7049 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
7050 handleAVX512VectorGenericMaskedFP(
I, {0},
7095 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7096 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7097 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7098 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7099 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7100 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7101 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7102 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7103 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7104 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7105 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7106 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7107 handleAVX512VectorGenericMaskedFP(
I, {0},
7143 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7144 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7145 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7146 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7147 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7148 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7149 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7150 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7151 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7155 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7175 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7176 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7177 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7178 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7179 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7180 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7181 visitGenericScalarHalfwordInst(
I);
7188 case Intrinsic::x86_avx512_fpclass_pd_512:
7189 case Intrinsic::x86_avx512_fpclass_ps_512:
7190 handleAVX512FPClass(
I);
7194 case Intrinsic::x86_vgf2p8affineqb_128:
7195 case Intrinsic::x86_vgf2p8affineqb_256:
7196 case Intrinsic::x86_vgf2p8affineqb_512:
7197 handleAVXGF2P8Affine(
I);
7207 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7208 switch (
I.getIntrinsicID()) {
7212 case Intrinsic::aarch64_neon_rshrn:
7213 case Intrinsic::aarch64_neon_sqrshl:
7214 case Intrinsic::aarch64_neon_sqrshrn:
7215 case Intrinsic::aarch64_neon_sqrshrun:
7216 case Intrinsic::aarch64_neon_sqshl:
7217 case Intrinsic::aarch64_neon_sqshlu:
7218 case Intrinsic::aarch64_neon_sqshrn:
7219 case Intrinsic::aarch64_neon_sqshrun:
7220 case Intrinsic::aarch64_neon_srshl:
7221 case Intrinsic::aarch64_neon_sshl:
7222 case Intrinsic::aarch64_neon_uqrshl:
7223 case Intrinsic::aarch64_neon_uqrshrn:
7224 case Intrinsic::aarch64_neon_uqshl:
7225 case Intrinsic::aarch64_neon_uqshrn:
7226 case Intrinsic::aarch64_neon_urshl:
7227 case Intrinsic::aarch64_neon_ushl:
7228 handleVectorShiftIntrinsic(
I,
false);
7241 case Intrinsic::aarch64_neon_vsli:
7242 case Intrinsic::aarch64_neon_vsri:
7243 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7250 case Intrinsic::aarch64_neon_fmaxp:
7251 case Intrinsic::aarch64_neon_fminp:
7253 case Intrinsic::aarch64_neon_fmaxnmp:
7254 case Intrinsic::aarch64_neon_fminnmp:
7256 case Intrinsic::aarch64_neon_smaxp:
7257 case Intrinsic::aarch64_neon_sminp:
7258 case Intrinsic::aarch64_neon_umaxp:
7259 case Intrinsic::aarch64_neon_uminp:
7261 case Intrinsic::aarch64_neon_addp:
7263 case Intrinsic::aarch64_neon_faddp:
7265 case Intrinsic::aarch64_neon_saddlp:
7266 case Intrinsic::aarch64_neon_uaddlp: {
7267 handlePairwiseShadowOrIntrinsic(
I, 1);
7272 case Intrinsic::aarch64_neon_fcvtas:
7273 case Intrinsic::aarch64_neon_fcvtau:
7275 case Intrinsic::aarch64_neon_fcvtms:
7276 case Intrinsic::aarch64_neon_fcvtmu:
7278 case Intrinsic::aarch64_neon_fcvtns:
7279 case Intrinsic::aarch64_neon_fcvtnu:
7281 case Intrinsic::aarch64_neon_fcvtps:
7282 case Intrinsic::aarch64_neon_fcvtpu:
7284 case Intrinsic::aarch64_neon_fcvtzs:
7285 case Intrinsic::aarch64_neon_fcvtzu:
7287 case Intrinsic::aarch64_neon_fcvtxn:
7288 handleGenericVectorConvertIntrinsic(
I,
false);
7292 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7293 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7294 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7295 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7296 handleGenericVectorConvertIntrinsic(
I,
true);
7305 case Intrinsic::aarch64_neon_faddv:
7306 case Intrinsic::aarch64_neon_saddv:
7307 case Intrinsic::aarch64_neon_uaddv:
7310 case Intrinsic::aarch64_neon_smaxv:
7311 case Intrinsic::aarch64_neon_sminv:
7312 case Intrinsic::aarch64_neon_umaxv:
7313 case Intrinsic::aarch64_neon_uminv:
7317 case Intrinsic::aarch64_neon_fmaxv:
7318 case Intrinsic::aarch64_neon_fminv:
7319 case Intrinsic::aarch64_neon_fmaxnmv:
7320 case Intrinsic::aarch64_neon_fminnmv:
7322 case Intrinsic::aarch64_neon_saddlv:
7323 case Intrinsic::aarch64_neon_uaddlv:
7324 handleVectorReduceIntrinsic(
I,
true);
7327 case Intrinsic::aarch64_neon_ld1x2:
7328 case Intrinsic::aarch64_neon_ld1x3:
7329 case Intrinsic::aarch64_neon_ld1x4:
7330 case Intrinsic::aarch64_neon_ld2:
7331 case Intrinsic::aarch64_neon_ld3:
7332 case Intrinsic::aarch64_neon_ld4:
7333 case Intrinsic::aarch64_neon_ld2r:
7334 case Intrinsic::aarch64_neon_ld3r:
7335 case Intrinsic::aarch64_neon_ld4r: {
7336 handleNEONVectorLoad(
I,
false);
7340 case Intrinsic::aarch64_neon_ld2lane:
7341 case Intrinsic::aarch64_neon_ld3lane:
7342 case Intrinsic::aarch64_neon_ld4lane: {
7343 handleNEONVectorLoad(
I,
true);
7348 case Intrinsic::aarch64_neon_sqxtn:
7349 case Intrinsic::aarch64_neon_sqxtun:
7350 case Intrinsic::aarch64_neon_uqxtn:
7357 case Intrinsic::aarch64_neon_st1x2:
7358 case Intrinsic::aarch64_neon_st1x3:
7359 case Intrinsic::aarch64_neon_st1x4:
7360 case Intrinsic::aarch64_neon_st2:
7361 case Intrinsic::aarch64_neon_st3:
7362 case Intrinsic::aarch64_neon_st4: {
7363 handleNEONVectorStoreIntrinsic(
I,
false);
7367 case Intrinsic::aarch64_neon_st2lane:
7368 case Intrinsic::aarch64_neon_st3lane:
7369 case Intrinsic::aarch64_neon_st4lane: {
7370 handleNEONVectorStoreIntrinsic(
I,
true);
7383 case Intrinsic::aarch64_neon_tbl1:
7384 case Intrinsic::aarch64_neon_tbl2:
7385 case Intrinsic::aarch64_neon_tbl3:
7386 case Intrinsic::aarch64_neon_tbl4:
7387 case Intrinsic::aarch64_neon_tbx1:
7388 case Intrinsic::aarch64_neon_tbx2:
7389 case Intrinsic::aarch64_neon_tbx3:
7390 case Intrinsic::aarch64_neon_tbx4: {
7392 handleIntrinsicByApplyingToShadow(
7393 I,
I.getIntrinsicID(),
7398 case Intrinsic::aarch64_neon_fmulx:
7399 case Intrinsic::aarch64_neon_pmul:
7400 case Intrinsic::aarch64_neon_pmull:
7401 case Intrinsic::aarch64_neon_smull:
7402 case Intrinsic::aarch64_neon_pmull64:
7403 case Intrinsic::aarch64_neon_umull: {
7404 handleNEONVectorMultiplyIntrinsic(
I);
7408 case Intrinsic::aarch64_neon_smmla:
7409 case Intrinsic::aarch64_neon_ummla:
7410 case Intrinsic::aarch64_neon_usmmla:
7411 case Intrinsic::aarch64_neon_bfmmla:
7412 handleNEONMatrixMultiply(
I);
7419 case Intrinsic::aarch64_neon_sdot:
7420 case Intrinsic::aarch64_neon_udot:
7421 case Intrinsic::aarch64_neon_usdot:
7422 handleVectorDotProductIntrinsic(
I, 4,
7432 case Intrinsic::aarch64_neon_bfdot:
7433 handleVectorDotProductIntrinsic(
I, 2,
7440 case Intrinsic::aarch64_neon_facge:
7441 case Intrinsic::aarch64_neon_facgt:
7442 handleVectorComparePackedIntrinsic(
I,
false);
7452 void visitIntrinsicInst(IntrinsicInst &
I) {
7453 if (maybeHandleCrossPlatformIntrinsic(
I))
7456 if (maybeHandleX86SIMDIntrinsic(
I))
7459 if (maybeHandleArmSIMDIntrinsic(
I))
7462 if (maybeHandleUnknownIntrinsic(
I))
7465 visitInstruction(
I);
7468 void visitLibAtomicLoad(CallBase &CB) {
7479 Value *NewOrdering =
7483 NextNodeIRBuilder NextIRB(&CB);
7484 Value *SrcShadowPtr, *SrcOriginPtr;
7485 std::tie(SrcShadowPtr, SrcOriginPtr) =
7486 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7488 Value *DstShadowPtr =
7489 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7493 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7494 if (MS.TrackOrigins) {
7495 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7497 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7498 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7502 void visitLibAtomicStore(CallBase &CB) {
7509 Value *NewOrdering =
7513 Value *DstShadowPtr =
7523 void visitCallBase(CallBase &CB) {
7531 visitAsmInstruction(CB);
7533 visitInstruction(CB);
7542 case LibFunc_atomic_load:
7544 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7548 visitLibAtomicLoad(CB);
7550 case LibFunc_atomic_store:
7551 visitLibAtomicStore(CB);
7567 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7571 Func->removeFnAttrs(
B);
7577 bool MayCheckCall = MS.EagerChecks;
7581 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7584 unsigned ArgOffset = 0;
7587 if (!
A->getType()->isSized()) {
7588 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7592 if (
A->getType()->isScalableTy()) {
7593 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7595 insertCheckShadowOf(
A, &CB);
7600 const DataLayout &
DL =
F.getDataLayout();
7604 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7607 insertCheckShadowOf(
A, &CB);
7608 Size =
DL.getTypeAllocSize(
A->getType());
7614 Value *ArgShadow = getShadow(
A);
7615 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7617 <<
" Shadow: " << *ArgShadow <<
"\n");
7621 assert(
A->getType()->isPointerTy() &&
7622 "ByVal argument is not a pointer!");
7627 MaybeAlign Alignment = std::nullopt;
7630 Value *AShadowPtr, *AOriginPtr;
7631 std::tie(AShadowPtr, AOriginPtr) =
7632 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7634 if (!PropagateShadow) {
7641 if (MS.TrackOrigins) {
7642 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7656 Size =
DL.getTypeAllocSize(
A->getType());
7662 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7664 getOriginPtrForArgument(IRB, ArgOffset));
7676 if (FT->isVarArg()) {
7677 VAHelper->visitCallBase(CB, IRB);
7687 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7688 setShadow(&CB, getCleanShadow(&CB));
7689 setOrigin(&CB, getCleanOrigin());
7695 Value *
Base = getShadowPtrForRetval(IRBBefore);
7696 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7708 setShadow(&CB, getCleanShadow(&CB));
7709 setOrigin(&CB, getCleanOrigin());
7716 "Could not find insertion point for retval shadow load");
7719 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7722 setShadow(&CB, RetvalShadow);
7723 if (MS.TrackOrigins)
7724 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7729 RetVal =
I->getOperand(0);
7732 return I->isMustTailCall();
7737 void visitReturnInst(ReturnInst &
I) {
7739 Value *RetVal =
I.getReturnValue();
7745 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7746 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7747 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7750 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7752 Value *Shadow = getShadow(RetVal);
7753 bool StoreOrigin =
true;
7755 insertCheckShadowOf(RetVal, &
I);
7756 Shadow = getCleanShadow(RetVal);
7757 StoreOrigin =
false;
7764 if (MS.TrackOrigins && StoreOrigin)
7765 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7769 void visitPHINode(PHINode &
I) {
7771 if (!PropagateShadow) {
7772 setShadow(&
I, getCleanShadow(&
I));
7773 setOrigin(&
I, getCleanOrigin());
7777 ShadowPHINodes.push_back(&
I);
7778 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7780 if (MS.TrackOrigins)
7782 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7785 Value *getLocalVarIdptr(AllocaInst &
I) {
7786 ConstantInt *IntConst =
7787 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7788 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7793 Value *getLocalVarDescription(AllocaInst &
I) {
7799 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7801 Value *ShadowBase, *OriginBase;
7802 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7806 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7809 if (PoisonStack && MS.TrackOrigins) {
7810 Value *Idptr = getLocalVarIdptr(
I);
7812 Value *Descr = getLocalVarDescription(
I);
7813 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7814 {&I, Len, Idptr, Descr});
7816 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7822 Value *Descr = getLocalVarDescription(
I);
7824 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7826 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7830 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7833 NextNodeIRBuilder IRB(InsPoint);
7836 if (MS.CompileKernel)
7837 poisonAllocaKmsan(
I, IRB, Len);
7839 poisonAllocaUserspace(
I, IRB, Len);
7842 void visitAllocaInst(AllocaInst &
I) {
7843 setShadow(&
I, getCleanShadow(&
I));
7844 setOrigin(&
I, getCleanOrigin());
7850 void visitSelectInst(SelectInst &
I) {
7856 handleSelectLikeInst(
I,
B,
C,
D);
7862 Value *Sb = getShadow(
B);
7863 Value *Sc = getShadow(
C);
7864 Value *Sd = getShadow(
D);
7866 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7867 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7868 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7873 if (
I.getType()->isAggregateType()) {
7877 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7878 }
else if (isScalableNonVectorType(
I.getType())) {
7886 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7894 C = CreateAppToShadowCast(IRB,
C);
7895 D = CreateAppToShadowCast(IRB,
D);
7902 if (MS.TrackOrigins) {
7905 if (
B->getType()->isVectorTy()) {
7906 B = convertToBool(
B, IRB);
7907 Sb = convertToBool(Sb, IRB);
7915 void visitLandingPadInst(LandingPadInst &
I) {
7918 setShadow(&
I, getCleanShadow(&
I));
7919 setOrigin(&
I, getCleanOrigin());
7922 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7923 setShadow(&
I, getCleanShadow(&
I));
7924 setOrigin(&
I, getCleanOrigin());
7927 void visitFuncletPadInst(FuncletPadInst &
I) {
7928 setShadow(&
I, getCleanShadow(&
I));
7929 setOrigin(&
I, getCleanOrigin());
7932 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7934 void visitExtractValueInst(ExtractValueInst &
I) {
7936 Value *Agg =
I.getAggregateOperand();
7938 Value *AggShadow = getShadow(Agg);
7942 setShadow(&
I, ResShadow);
7943 setOriginForNaryOp(
I);
7946 void visitInsertValueInst(InsertValueInst &
I) {
7949 Value *AggShadow = getShadow(
I.getAggregateOperand());
7950 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7956 setOriginForNaryOp(
I);
7959 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7966 << CI->getCalledFunction()->
getName() <<
"\n";
7968 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
7975 unsigned NumOperands =
I.getNumOperands();
7977 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
7989 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
7990 <<
I.getOpcodeName() <<
"(";
7992 for (
size_t i = 0; i < NumOperands; i++) {
8010 void visitResumeInst(ResumeInst &
I) {
8015 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
8020 void visitCatchReturnInst(CatchReturnInst &CRI) {
8025 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
8034 insertCheckShadowOf(Operand, &
I);
8041 auto Size =
DL.getTypeStoreSize(ElemTy);
8043 if (MS.CompileKernel) {
8044 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
8050 auto [ShadowPtr,
_] =
8051 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
8061 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
8062 int NumRetOutputs = 0;
8069 NumRetOutputs =
ST->getNumElements();
8074 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
8075 switch (
Info.Type) {
8083 return NumOutputs - NumRetOutputs;
8086 void visitAsmInstruction(Instruction &
I) {
8102 const DataLayout &
DL =
F.getDataLayout();
8106 int OutputArgs = getNumOutputArgs(IA, CB);
8112 for (
int i = OutputArgs; i < NumOperands; i++) {
8120 for (
int i = 0; i < OutputArgs; i++) {
8126 setShadow(&
I, getCleanShadow(&
I));
8127 setOrigin(&
I, getCleanOrigin());
8130 void visitFreezeInst(FreezeInst &
I) {
8132 setShadow(&
I, getCleanShadow(&
I));
8133 setOrigin(&
I, getCleanOrigin());
8136 void visitInstruction(Instruction &
I) {
8139 dumpInst(
I,
"Strict");
8141 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8142 Value *Operand =
I.getOperand(i);
8144 insertCheckShadowOf(Operand, &
I);
8146 setShadow(&
I, getCleanShadow(&
I));
8147 setOrigin(&
I, getCleanOrigin());
8151struct VarArgHelperBase :
public VarArgHelper {
8153 MemorySanitizer &MS;
8154 MemorySanitizerVisitor &MSV;
8156 const unsigned VAListTagSize;
8158 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
8159 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8160 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8164 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8170 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8179 return getShadowPtrForVAArgument(IRB, ArgOffset);
8188 ConstantInt::get(MS.IntptrTy, ArgOffset),
8193 unsigned BaseOffset) {
8202 TailSize,
Align(8));
8205 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8207 Value *VAListTag =
I.getArgOperand(0);
8209 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8210 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8213 VAListTagSize, Alignment,
false);
8216 void visitVAStartInst(VAStartInst &
I)
override {
8217 if (
F.getCallingConv() == CallingConv::Win64)
8220 unpoisonVAListTagForInst(
I);
8223 void visitVACopyInst(VACopyInst &
I)
override {
8224 if (
F.getCallingConv() == CallingConv::Win64)
8226 unpoisonVAListTagForInst(
I);
8231struct VarArgAMD64Helper :
public VarArgHelperBase {
8234 static const unsigned AMD64GpEndOffset = 48;
8235 static const unsigned AMD64FpEndOffsetSSE = 176;
8237 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8239 unsigned AMD64FpEndOffset;
8240 AllocaInst *VAArgTLSCopy =
nullptr;
8241 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8242 Value *VAArgOverflowSize =
nullptr;
8244 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8246 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
8247 MemorySanitizerVisitor &MSV)
8248 : VarArgHelperBase(
F, MS, MSV, 24) {
8249 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8250 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8251 if (Attr.isStringAttribute() &&
8252 (Attr.getKindAsString() ==
"target-features")) {
8253 if (Attr.getValueAsString().contains(
"-sse"))
8254 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8260 ArgKind classifyArgument(
Value *arg) {
8263 if (
T->isX86_FP80Ty())
8265 if (
T->isFPOrFPVectorTy())
8266 return AK_FloatingPoint;
8267 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8268 return AK_GeneralPurpose;
8269 if (
T->isPointerTy())
8270 return AK_GeneralPurpose;
8282 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8283 unsigned GpOffset = 0;
8284 unsigned FpOffset = AMD64GpEndOffset;
8285 unsigned OverflowOffset = AMD64FpEndOffset;
8286 const DataLayout &
DL =
F.getDataLayout();
8290 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8297 assert(
A->getType()->isPointerTy());
8299 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8300 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8301 unsigned BaseOffset = OverflowOffset;
8302 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8303 Value *OriginBase =
nullptr;
8304 if (MS.TrackOrigins)
8305 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8306 OverflowOffset += AlignedSize;
8309 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8313 Value *ShadowPtr, *OriginPtr;
8314 std::tie(ShadowPtr, OriginPtr) =
8319 if (MS.TrackOrigins)
8323 ArgKind AK = classifyArgument(
A);
8324 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8326 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8328 Value *ShadowBase, *OriginBase =
nullptr;
8330 case AK_GeneralPurpose:
8331 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8332 if (MS.TrackOrigins)
8333 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8337 case AK_FloatingPoint:
8338 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8339 if (MS.TrackOrigins)
8340 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8347 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8348 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8349 unsigned BaseOffset = OverflowOffset;
8350 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8351 if (MS.TrackOrigins) {
8352 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8354 OverflowOffset += AlignedSize;
8357 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8366 Value *Shadow = MSV.getShadow(
A);
8368 if (MS.TrackOrigins) {
8369 Value *Origin = MSV.getOrigin(
A);
8370 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8371 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8377 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8378 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8381 void finalizeInstrumentation()
override {
8382 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8383 "finalizeInstrumentation called twice");
8384 if (!VAStartInstrumentationList.
empty()) {
8391 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8392 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8398 Intrinsic::umin, CopySize,
8402 if (MS.TrackOrigins) {
8403 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8412 for (CallInst *OrigInst : VAStartInstrumentationList) {
8413 NextNodeIRBuilder IRB(OrigInst);
8414 Value *VAListTag = OrigInst->getArgOperand(0);
8416 Value *RegSaveAreaPtrPtr =
8417 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8419 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8421 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8422 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8424 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8426 if (MS.TrackOrigins)
8427 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8428 Alignment, AMD64FpEndOffset);
8429 Value *OverflowArgAreaPtrPtr =
8430 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8431 Value *OverflowArgAreaPtr =
8432 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8433 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8434 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8435 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8439 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8441 if (MS.TrackOrigins) {
8444 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8452struct VarArgAArch64Helper :
public VarArgHelperBase {
8453 static const unsigned kAArch64GrArgSize = 64;
8454 static const unsigned kAArch64VrArgSize = 128;
8456 static const unsigned AArch64GrBegOffset = 0;
8457 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8459 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8460 static const unsigned AArch64VrEndOffset =
8461 AArch64VrBegOffset + kAArch64VrArgSize;
8462 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8464 AllocaInst *VAArgTLSCopy =
nullptr;
8465 Value *VAArgOverflowSize =
nullptr;
8467 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8469 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
8470 MemorySanitizerVisitor &MSV)
8471 : VarArgHelperBase(
F, MS, MSV, 32) {}
8474 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8475 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8476 return {AK_GeneralPurpose, 1};
8477 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8478 return {AK_FloatingPoint, 1};
8480 if (
T->isArrayTy()) {
8481 auto R = classifyArgument(
T->getArrayElementType());
8482 R.second *=
T->getScalarType()->getArrayNumElements();
8487 auto R = classifyArgument(FV->getScalarType());
8488 R.second *= FV->getNumElements();
8493 return {AK_Memory, 0};
8505 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8506 unsigned GrOffset = AArch64GrBegOffset;
8507 unsigned VrOffset = AArch64VrBegOffset;
8508 unsigned OverflowOffset = AArch64VAEndOffset;
8510 const DataLayout &
DL =
F.getDataLayout();
8513 auto [AK, RegNum] = classifyArgument(
A->getType());
8514 if (AK == AK_GeneralPurpose &&
8515 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8517 if (AK == AK_FloatingPoint &&
8518 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8522 case AK_GeneralPurpose:
8523 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8524 GrOffset += 8 * RegNum;
8526 case AK_FloatingPoint:
8527 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8528 VrOffset += 16 * RegNum;
8535 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8536 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8537 unsigned BaseOffset = OverflowOffset;
8538 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8539 OverflowOffset += AlignedSize;
8542 CleanUnusedTLS(IRB,
Base, BaseOffset);
8554 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8555 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8560 Value *SaveAreaPtrPtr =
8561 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8562 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8567 Value *SaveAreaPtr =
8568 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8570 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8573 void finalizeInstrumentation()
override {
8574 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8575 "finalizeInstrumentation called twice");
8576 if (!VAStartInstrumentationList.empty()) {
8583 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8584 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8590 Intrinsic::umin, CopySize,
8596 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8597 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8601 for (CallInst *OrigInst : VAStartInstrumentationList) {
8602 NextNodeIRBuilder IRB(OrigInst);
8604 Value *VAListTag = OrigInst->getArgOperand(0);
8621 Value *StackSaveAreaPtr =
8622 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8625 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8626 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8629 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8632 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8633 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8636 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8642 Value *GrRegSaveAreaShadowPtrOff =
8643 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8645 Value *GrRegSaveAreaShadowPtr =
8646 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8652 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8658 Value *VrRegSaveAreaShadowPtrOff =
8659 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8661 Value *VrRegSaveAreaShadowPtr =
8662 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8669 VrRegSaveAreaShadowPtrOff);
8670 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8676 Value *StackSaveAreaShadowPtr =
8677 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8682 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8685 Align(16), VAArgOverflowSize);
8691struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8692 AllocaInst *VAArgTLSCopy =
nullptr;
8693 Value *VAArgSize =
nullptr;
8695 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
8696 MemorySanitizerVisitor &MSV)
8697 : VarArgHelperBase(
F, MS, MSV, 8) {}
8699 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8707 Triple TargetTriple(
F.getParent()->getTargetTriple());
8711 if (TargetTriple.isPPC64ELFv2ABI())
8715 unsigned VAArgOffset = VAArgBase;
8716 const DataLayout &
DL =
F.getDataLayout();
8719 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8721 assert(
A->getType()->isPointerTy());
8723 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8726 ArgAlign =
Align(8);
8727 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8730 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8732 Value *AShadowPtr, *AOriginPtr;
8733 std::tie(AShadowPtr, AOriginPtr) =
8734 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8744 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8746 if (
A->getType()->isArrayTy()) {
8749 Type *ElementTy =
A->getType()->getArrayElementType();
8751 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8752 }
else if (
A->getType()->isVectorTy()) {
8754 ArgAlign =
Align(ArgSize);
8757 ArgAlign =
Align(8);
8758 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8759 if (
DL.isBigEndian()) {
8763 VAArgOffset += (8 - ArgSize);
8767 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8771 VAArgOffset += ArgSize;
8775 VAArgBase = VAArgOffset;
8779 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8782 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8785 void finalizeInstrumentation()
override {
8786 assert(!VAArgSize && !VAArgTLSCopy &&
8787 "finalizeInstrumentation called twice");
8790 Value *CopySize = VAArgSize;
8792 if (!VAStartInstrumentationList.empty()) {
8796 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8802 Intrinsic::umin, CopySize,
8810 for (CallInst *OrigInst : VAStartInstrumentationList) {
8811 NextNodeIRBuilder IRB(OrigInst);
8812 Value *VAListTag = OrigInst->getArgOperand(0);
8815 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8818 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8819 const DataLayout &
DL =
F.getDataLayout();
8820 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8822 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8823 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8825 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8832struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8833 AllocaInst *VAArgTLSCopy =
nullptr;
8834 Value *VAArgSize =
nullptr;
8836 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
8837 MemorySanitizerVisitor &MSV)
8838 : VarArgHelperBase(
F, MS, MSV, 12) {}
8840 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8844 unsigned VAArgOffset = VAArgBase;
8845 const DataLayout &
DL =
F.getDataLayout();
8846 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8849 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8851 assert(
A->getType()->isPointerTy());
8853 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8855 if (ArgAlign < IntptrSize)
8856 ArgAlign =
Align(IntptrSize);
8857 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8860 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8862 Value *AShadowPtr, *AOriginPtr;
8863 std::tie(AShadowPtr, AOriginPtr) =
8864 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8874 Type *ArgTy =
A->getType();
8880 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8887 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8890 ArgAlign =
Align(ArgSize);
8892 if (ArgAlign < IntptrSize)
8893 ArgAlign =
Align(IntptrSize);
8894 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8895 if (
DL.isBigEndian()) {
8898 if (ArgSize < IntptrSize)
8899 VAArgOffset += (IntptrSize - ArgSize);
8902 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8908 VAArgOffset += ArgSize;
8915 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8918 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8921 void finalizeInstrumentation()
override {
8922 assert(!VAArgSize && !VAArgTLSCopy &&
8923 "finalizeInstrumentation called twice");
8925 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8926 Value *CopySize = VAArgSize;
8928 if (!VAStartInstrumentationList.empty()) {
8932 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8938 Intrinsic::umin, CopySize,
8946 for (CallInst *OrigInst : VAStartInstrumentationList) {
8947 NextNodeIRBuilder IRB(OrigInst);
8948 Value *VAListTag = OrigInst->getArgOperand(0);
8950 Value *RegSaveAreaSize = CopySize;
8954 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8958 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8960 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8963 const DataLayout &
DL =
F.getDataLayout();
8964 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8968 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8969 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8970 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8972 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
8973 Alignment, RegSaveAreaSize);
8975 RegSaveAreaShadowPtr =
8978 ConstantInt::get(MS.IntptrTy, 32));
8983 ConstantInt::get(MS.IntptrTy, 32), Alignment);
8988 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
8991 OverflowAreaPtrPtr =
8992 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
8993 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
8995 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
8997 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
8998 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
8999 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
9002 Value *OverflowVAArgTLSCopyPtr =
9004 OverflowVAArgTLSCopyPtr =
9005 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
9007 OverflowVAArgTLSCopyPtr =
9010 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
9017struct VarArgSystemZHelper :
public VarArgHelperBase {
9018 static const unsigned SystemZGpOffset = 16;
9019 static const unsigned SystemZGpEndOffset = 56;
9020 static const unsigned SystemZFpOffset = 128;
9021 static const unsigned SystemZFpEndOffset = 160;
9022 static const unsigned SystemZMaxVrArgs = 8;
9023 static const unsigned SystemZRegSaveAreaSize = 160;
9024 static const unsigned SystemZOverflowOffset = 160;
9025 static const unsigned SystemZVAListTagSize = 32;
9026 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
9027 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
9029 bool IsSoftFloatABI;
9030 AllocaInst *VAArgTLSCopy =
nullptr;
9031 AllocaInst *VAArgTLSOriginCopy =
nullptr;
9032 Value *VAArgOverflowSize =
nullptr;
9034 enum class ArgKind {
9042 enum class ShadowExtension {
None,
Zero, Sign };
9044 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
9045 MemorySanitizerVisitor &MSV)
9046 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
9047 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
9049 ArgKind classifyArgument(
Type *
T) {
9056 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
9057 return ArgKind::Indirect;
9058 if (
T->isFloatingPointTy())
9059 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
9060 if (
T->isIntegerTy() ||
T->isPointerTy())
9061 return ArgKind::GeneralPurpose;
9062 if (
T->isVectorTy())
9063 return ArgKind::Vector;
9064 return ArgKind::Memory;
9067 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
9077 return ShadowExtension::Zero;
9081 return ShadowExtension::Sign;
9083 return ShadowExtension::None;
9086 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9087 unsigned GpOffset = SystemZGpOffset;
9088 unsigned FpOffset = SystemZFpOffset;
9089 unsigned VrIndex = 0;
9090 unsigned OverflowOffset = SystemZOverflowOffset;
9091 const DataLayout &
DL =
F.getDataLayout();
9097 ArgKind AK = classifyArgument(
T);
9098 if (AK == ArgKind::Indirect) {
9100 AK = ArgKind::GeneralPurpose;
9102 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9103 AK = ArgKind::Memory;
9104 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9105 AK = ArgKind::Memory;
9106 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9107 AK = ArgKind::Memory;
9108 Value *ShadowBase =
nullptr;
9109 Value *OriginBase =
nullptr;
9110 ShadowExtension SE = ShadowExtension::None;
9112 case ArgKind::GeneralPurpose: {
9114 uint64_t ArgSize = 8;
9117 SE = getShadowExtension(CB, ArgNo);
9118 uint64_t GapSize = 0;
9119 if (SE == ShadowExtension::None) {
9120 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9121 assert(ArgAllocSize <= ArgSize);
9122 GapSize = ArgSize - ArgAllocSize;
9124 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9125 if (MS.TrackOrigins)
9126 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9128 GpOffset += ArgSize;
9134 case ArgKind::FloatingPoint: {
9136 uint64_t ArgSize = 8;
9143 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9144 if (MS.TrackOrigins)
9145 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9147 FpOffset += ArgSize;
9153 case ArgKind::Vector: {
9160 case ArgKind::Memory: {
9165 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9166 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
9168 SE = getShadowExtension(CB, ArgNo);
9170 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9172 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9173 if (MS.TrackOrigins)
9175 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9176 OverflowOffset += ArgSize;
9183 case ArgKind::Indirect:
9186 if (ShadowBase ==
nullptr)
9188 Value *Shadow = MSV.getShadow(
A);
9189 if (SE != ShadowExtension::None)
9190 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9191 SE == ShadowExtension::Sign);
9192 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9194 if (MS.TrackOrigins) {
9195 Value *Origin = MSV.getOrigin(
A);
9196 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9197 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9201 Constant *OverflowSize = ConstantInt::get(
9202 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9203 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9210 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9213 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9215 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9216 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9221 unsigned RegSaveAreaSize =
9222 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9223 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9225 if (MS.TrackOrigins)
9226 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9227 Alignment, RegSaveAreaSize);
9236 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9238 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9239 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9241 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9242 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9245 SystemZOverflowOffset);
9246 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9248 if (MS.TrackOrigins) {
9250 SystemZOverflowOffset);
9251 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9256 void finalizeInstrumentation()
override {
9257 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9258 "finalizeInstrumentation called twice");
9259 if (!VAStartInstrumentationList.empty()) {
9266 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9268 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9274 Intrinsic::umin, CopySize,
9278 if (MS.TrackOrigins) {
9279 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9288 for (CallInst *OrigInst : VAStartInstrumentationList) {
9289 NextNodeIRBuilder IRB(OrigInst);
9290 Value *VAListTag = OrigInst->getArgOperand(0);
9291 copyRegSaveArea(IRB, VAListTag);
9292 copyOverflowArea(IRB, VAListTag);
9298struct VarArgI386Helper :
public VarArgHelperBase {
9299 AllocaInst *VAArgTLSCopy =
nullptr;
9300 Value *VAArgSize =
nullptr;
9302 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
9303 MemorySanitizerVisitor &MSV)
9304 : VarArgHelperBase(
F, MS, MSV, 4) {}
9306 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9307 const DataLayout &
DL =
F.getDataLayout();
9308 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9309 unsigned VAArgOffset = 0;
9312 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
9314 assert(
A->getType()->isPointerTy());
9316 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9318 if (ArgAlign < IntptrSize)
9319 ArgAlign =
Align(IntptrSize);
9320 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9322 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9324 Value *AShadowPtr, *AOriginPtr;
9325 std::tie(AShadowPtr, AOriginPtr) =
9326 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9336 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9338 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9339 if (
DL.isBigEndian()) {
9342 if (ArgSize < IntptrSize)
9343 VAArgOffset += (IntptrSize - ArgSize);
9346 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9349 VAArgOffset += ArgSize;
9355 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9358 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9361 void finalizeInstrumentation()
override {
9362 assert(!VAArgSize && !VAArgTLSCopy &&
9363 "finalizeInstrumentation called twice");
9365 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9366 Value *CopySize = VAArgSize;
9368 if (!VAStartInstrumentationList.empty()) {
9371 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9377 Intrinsic::umin, CopySize,
9385 for (CallInst *OrigInst : VAStartInstrumentationList) {
9386 NextNodeIRBuilder IRB(OrigInst);
9387 Value *VAListTag = OrigInst->getArgOperand(0);
9388 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9389 Value *RegSaveAreaPtrPtr =
9391 PointerType::get(*MS.C, 0));
9392 Value *RegSaveAreaPtr =
9393 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9394 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9395 const DataLayout &
DL =
F.getDataLayout();
9396 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9398 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9399 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9401 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9409struct VarArgGenericHelper :
public VarArgHelperBase {
9410 AllocaInst *VAArgTLSCopy =
nullptr;
9411 Value *VAArgSize =
nullptr;
9413 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
9414 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9415 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9417 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9418 unsigned VAArgOffset = 0;
9419 const DataLayout &
DL =
F.getDataLayout();
9420 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9425 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9426 if (
DL.isBigEndian()) {
9429 if (ArgSize < IntptrSize)
9430 VAArgOffset += (IntptrSize - ArgSize);
9432 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9433 VAArgOffset += ArgSize;
9434 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9440 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9443 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9446 void finalizeInstrumentation()
override {
9447 assert(!VAArgSize && !VAArgTLSCopy &&
9448 "finalizeInstrumentation called twice");
9450 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9451 Value *CopySize = VAArgSize;
9453 if (!VAStartInstrumentationList.empty()) {
9456 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9462 Intrinsic::umin, CopySize,
9470 for (CallInst *OrigInst : VAStartInstrumentationList) {
9471 NextNodeIRBuilder IRB(OrigInst);
9472 Value *VAListTag = OrigInst->getArgOperand(0);
9473 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9474 Value *RegSaveAreaPtrPtr =
9476 PointerType::get(*MS.C, 0));
9477 Value *RegSaveAreaPtr =
9478 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9479 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9480 const DataLayout &
DL =
F.getDataLayout();
9481 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9483 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9484 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9486 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9494using VarArgARM32Helper = VarArgGenericHelper;
9495using VarArgRISCVHelper = VarArgGenericHelper;
9496using VarArgMIPSHelper = VarArgGenericHelper;
9497using VarArgLoongArch64Helper = VarArgGenericHelper;
9498using VarArgHexagonHelper = VarArgGenericHelper;
9501struct VarArgNoOpHelper :
public VarArgHelper {
9502 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
9503 MemorySanitizerVisitor &MSV) {}
9505 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9507 void visitVAStartInst(VAStartInst &
I)
override {}
9509 void visitVACopyInst(VACopyInst &
I)
override {}
9511 void finalizeInstrumentation()
override {}
9517 MemorySanitizerVisitor &Visitor) {
9520 Triple TargetTriple(Func.getParent()->getTargetTriple());
9523 return new VarArgI386Helper(Func, Msan, Visitor);
9526 return new VarArgAMD64Helper(Func, Msan, Visitor);
9528 if (TargetTriple.
isARM())
9529 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9532 return new VarArgAArch64Helper(Func, Msan, Visitor);
9535 return new VarArgSystemZHelper(Func, Msan, Visitor);
9540 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9543 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9546 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9549 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9552 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9555 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9558 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9562 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9564 return new VarArgNoOpHelper(Func, Msan, Visitor);
9571 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9574 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9581 return Visitor.runOnFunction();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isStore(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
VarLocInsertPt getNextNode(const DbgRecord *DVR)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static bool isAMustTailRetVal(Value *RetVal)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
Module.h This file contains the declarations for the Module class.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Machine Check Debug Module
static const PlatformMemoryMapParams Linux_S390_MemoryMapParams
static const Align kMinOriginAlignment
static cl::opt< uint64_t > ClShadowBase("msan-shadow-base", cl::desc("Define custom MSan ShadowBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClPoisonUndef("msan-poison-undef", cl::desc("Poison fully undef temporary values. " "Partially undefined constant vectors " "are unaffected by this flag (see " "-msan-poison-undef-vectors)."), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_X86_MemoryMapParams
static cl::opt< uint64_t > ClOriginBase("msan-origin-base", cl::desc("Define custom MSan OriginBase"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClCheckConstantShadow("msan-check-constant-shadow", cl::desc("Insert checks for constant shadow values"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_LoongArch_MemoryMapParams
static const MemoryMapParams NetBSD_X86_64_MemoryMapParams
static const PlatformMemoryMapParams Linux_MIPS_MemoryMapParams
static const unsigned kOriginSize
static cl::opt< bool > ClWithComdat("msan-with-comdat", cl::desc("Place MSan constructors in comdat sections"), cl::Hidden, cl::init(false))
static cl::opt< int > ClTrackOrigins("msan-track-origins", cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden, cl::init(0))
Track origins of uninitialized values.
static cl::opt< int > ClInstrumentationWithCallThreshold("msan-instrumentation-with-call-threshold", cl::desc("If the function being instrumented requires more than " "this number of checks and origin stores, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500))
static cl::opt< int > ClPoisonStackPattern("msan-poison-stack-pattern", cl::desc("poison uninitialized stack variables with the given pattern"), cl::Hidden, cl::init(0xff))
static const Align kShadowTLSAlignment
static cl::opt< bool > ClHandleICmpExact("msan-handle-icmp-exact", cl::desc("exact handling of relational integer ICmp"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams Linux_ARM_MemoryMapParams
static cl::opt< bool > ClDumpStrictInstructions("msan-dump-strict-instructions", cl::desc("print out instructions with default strict semantics i.e.," "check that all the inputs are fully initialized, and mark " "the output as fully initialized. These semantics are applied " "to instructions that could not be handled explicitly nor " "heuristically."), cl::Hidden, cl::init(false))
static Constant * getOrInsertGlobal(Module &M, StringRef Name, Type *Ty)
static cl::opt< bool > ClPreciseDisjointOr("msan-precise-disjoint-or", cl::desc("Precisely poison disjoint OR. If false (legacy behavior), " "disjointedness is ignored (i.e., 1|1 is initialized)."), cl::Hidden, cl::init(false))
static const PlatformMemoryMapParams Linux_Hexagon_MemoryMapParams_P
static cl::opt< bool > ClPoisonStack("msan-poison-stack", cl::desc("poison uninitialized stack variables"), cl::Hidden, cl::init(true))
static const MemoryMapParams Linux_I386_MemoryMapParams
const char kMsanInitName[]
static cl::opt< bool > ClPoisonUndefVectors("msan-poison-undef-vectors", cl::desc("Precisely poison partially undefined constant vectors. " "If false (legacy behavior), the entire vector is " "considered fully initialized, which may lead to false " "negatives. Fully undefined constant vectors are " "unaffected by this flag (see -msan-poison-undef)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClPrintStackNames("msan-print-stack-names", cl::desc("Print name of local stack variable"), cl::Hidden, cl::init(true))
static cl::opt< uint64_t > ClAndMask("msan-and-mask", cl::desc("Define custom MSan AndMask"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClHandleLifetimeIntrinsics("msan-handle-lifetime-intrinsics", cl::desc("when possible, poison scoped variables at the beginning of the scope " "(slower, but more precise)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKeepGoing("msan-keep-going", cl::desc("keep going after reporting a UMR"), cl::Hidden, cl::init(false))
static const MemoryMapParams FreeBSD_X86_64_MemoryMapParams
static GlobalVariable * createPrivateConstGlobalForString(Module &M, StringRef Str)
Create a non-const global initialized with the given string.
static const PlatformMemoryMapParams Linux_PowerPC_MemoryMapParams
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClEagerChecks("msan-eager-checks", cl::desc("check arguments and return values at function call boundaries"), cl::Hidden, cl::init(false))
static cl::opt< int > ClDisambiguateWarning("msan-disambiguate-warning-threshold", cl::desc("Define threshold for number of checks per " "debug location to force origin update."), cl::Hidden, cl::init(3))
static VarArgHelper * CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, MemorySanitizerVisitor &Visitor)
static const MemoryMapParams Linux_MIPS64_MemoryMapParams
static const MemoryMapParams Linux_PowerPC64_MemoryMapParams
static cl::opt< int > ClSwitchPrecision("msan-switch-precision", cl::desc("Controls the number of cases considered by MSan for LLVM switch " "instructions. 0 means no UUMs detected. Higher values lead to " "fewer false negatives but may impact compiler and/or " "application performance. N.B. LLVM switch instructions do not " "correspond exactly to C++ switch statements."), cl::Hidden, cl::init(99))
static cl::opt< uint64_t > ClXorMask("msan-xor-mask", cl::desc("Define custom MSan XorMask"), cl::Hidden, cl::init(0))
static const MemoryMapParams Linux_Hexagon_MemoryMapParams
static cl::opt< bool > ClHandleAsmConservative("msan-handle-asm-conservative", cl::desc("conservative handling of inline assembly"), cl::Hidden, cl::init(true))
static const PlatformMemoryMapParams FreeBSD_X86_MemoryMapParams
static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams
static const unsigned kParamTLSSize
static cl::opt< bool > ClHandleICmp("msan-handle-icmp", cl::desc("propagate shadow through ICmpEQ and ICmpNE"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClEnableKmsan("msan-kernel", cl::desc("Enable KernelMemorySanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClPoisonStackWithCall("msan-poison-stack-with-call", cl::desc("poison uninitialized stack variables with a call"), cl::Hidden, cl::init(false))
static const PlatformMemoryMapParams NetBSD_X86_MemoryMapParams
static cl::opt< bool > ClDumpHeuristicInstructions("msan-dump-heuristic-instructions", cl::desc("Prints 'unknown' instructions that were handled heuristically. " "Use -msan-dump-strict-instructions to print instructions that " "could not be handled explicitly nor heuristically."), cl::Hidden, cl::init(false))
static const unsigned kRetvalTLSSize
static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams
const char kMsanModuleCtorName[]
static const MemoryMapParams FreeBSD_I386_MemoryMapParams
static cl::opt< bool > ClCheckAccessAddress("msan-check-access-address", cl::desc("report accesses through a pointer which has poisoned shadow"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClDisableChecks("msan-disable-checks", cl::desc("Apply no_sanitize to the whole file"), cl::Hidden, cl::init(false))
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
void setAlignment(Align Align)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
const T & front() const
Get the first element.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
void removeFnAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the function.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getCalledOperand() const
Type * getParamElementType(unsigned ArgNo) const
Extract the elementtype type for a parameter.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
LLVM_ABI bool isAllOnesValue() const
Return true if this is the value that would be returned by getAllOnesValue.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
static bool shouldExecute(CounterInfo &Counter)
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
static FixedVectorType * getHalfElementsVectorType(FixedVectorType *VTy)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
LLVM_ABI void setComdat(Comdat *C)
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ ExternalLinkage
Externally visible function.
Analysis pass providing a never-invalidated alias analysis result.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI Value * CreateAndReduce(Value *Src)
Create a vector int AND reduction intrinsic of the source vector.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
LLVM_ABI CallInst * CreateMaskedCompressStore(Value *Val, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr)
Create a call to Masked Compress Store intrinsic.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateAllocationSize(Type *DestTy, AllocaInst *AI)
Get allocation size of an alloca as a runtime Value* (handles both static and dynamic allocas and vsc...
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memcpy between the specified pointers.
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
LLVM_ABI Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 2 operands which is mangled on the first type.
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI DebugLoc getCurrentDebugLocation() const
Get location information used by debugging information.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended from a 64-bit value.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedExpandLoad(Type *Ty, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Expand Load intrinsic.
Value * CreateInBoundsPtrAdd(Value *Ptr, Value *Offset, const Twine &Name="")
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI CallInst * CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment, Value *Mask=nullptr)
Create a call to Masked Scatter intrinsic.
LLVM_ABI CallInst * CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Gather intrinsic.
Value * CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
std::vector< ConstraintInfo > ConstraintInfoVector
void visit(Iterator Start, Iterator End)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
bool remove(const value_type &X)
Remove an item from the set vector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
bool isRISCV32() const
Tests whether the target is 32-bit RISC-V.
bool isPPC32() const
Tests whether the target is 32-bit PowerPC (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isPPC64() const
Tests whether the target is 64-bit PowerPC (little and big endian).
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isSystemZ() const
Tests whether the target is SystemZ.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isPPC_FP128Ty() const
Return true if this is powerpc long double.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
int getNumOccurrences() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
initializer< Ty > init(const Ty &Val)
Function * Kernel
Summary of a kernel (=entry point for target offloading).
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
RelativeUniformCounterPtr Values
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI std::pair< Instruction *, Value * > SplitBlockAndInsertSimpleForLoop(Value *End, BasicBlock::iterator SplitBefore)
Insert a for (int i = 0; i < End; i++) loop structure (with the exception that End is assumed > 0,...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
RoundingMode
Rounding mode.
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr unsigned BitWidth
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A CRTP mix-in to automatically provide informational APIs needed for passes.