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;
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);
2661 setShadow(&
I, OutShadow);
2662 setOriginForNaryOp(
I);
2665 void visitFPToSIInst(CastInst &
I) {
2666 handleGenericVectorConvertIntrinsic(
I,
false);
2668 void visitFPToUIInst(CastInst &
I) {
2669 handleGenericVectorConvertIntrinsic(
I,
false);
2671 void visitSIToFPInst(CastInst &
I) {
2672 handleGenericVectorConvertIntrinsic(
I,
false);
2674 void visitUIToFPInst(CastInst &
I) {
2675 handleGenericVectorConvertIntrinsic(
I,
false);
2678 void visitFPExtInst(CastInst &
I) {
2679 handleGenericVectorConvertIntrinsic(
I,
false);
2681 void visitFPTruncInst(CastInst &
I) {
2682 handleGenericVectorConvertIntrinsic(
I,
false);
2703 assert(
V1->getType()->isIntOrIntVectorTy());
2714 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2718 void visitAnd(BinaryOperator &
I) {
2721 Value *V2 =
I.getOperand(1);
2723 Value *S2 = getShadow(&
I, 1);
2725 Value *OutShadow = handleBitwiseAnd(IRB,
V1, V2,
S1, S2);
2727 setShadow(&
I, OutShadow);
2728 setOriginForNaryOp(
I);
2731 void visitOr(BinaryOperator &
I) {
2744 Value *S2 = getShadow(&
I, 1);
2746 Value *V2 =
I.getOperand(1);
2750 assert(
V1->getType()->isIntOrIntVectorTy());
2770 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2774 setOriginForNaryOp(
I);
2792 template <
bool CombineShadow>
class Combiner {
2793 Value *Shadow =
nullptr;
2794 Value *Origin =
nullptr;
2796 MemorySanitizerVisitor *MSV;
2799 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2800 : IRB(IRB), MSV(MSV) {}
2804 if (CombineShadow) {
2809 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2810 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2814 if (MSV->MS.TrackOrigins) {
2821 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2822 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2832 Value *OpShadow = MSV->getShadow(V);
2833 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2834 return Add(OpShadow, OpOrigin);
2839 void Done(Instruction *
I) {
2840 if (CombineShadow) {
2842 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2843 MSV->setShadow(
I, Shadow);
2845 if (MSV->MS.TrackOrigins) {
2847 MSV->setOrigin(
I, Origin);
2853 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2854 if (MSV->MS.TrackOrigins) {
2861 using ShadowAndOriginCombiner = Combiner<true>;
2862 using OriginCombiner = Combiner<false>;
2865 void setOriginForNaryOp(Instruction &
I) {
2866 if (!MS.TrackOrigins)
2869 OriginCombiner OC(
this, IRB);
2870 for (Use &
Op :
I.operands())
2875 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2877 "Vector of pointers is not a valid shadow type");
2887 Type *srcTy =
V->getType();
2890 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2891 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2892 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2910 Type *ShadowTy = getShadowTy(V);
2911 if (
V->getType() == ShadowTy)
2913 if (
V->getType()->isPtrOrPtrVectorTy())
2920 void handleShadowOr(Instruction &
I) {
2922 ShadowAndOriginCombiner SC(
this, IRB);
2923 for (Use &
Op :
I.operands())
2950 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2951 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2956 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2962 assert(NumElems % (ReductionFactor * Shards) == 0);
2967 for (
unsigned i = 0; i < ReductionFactor; i++) {
2968 SmallVector<int, 16>
Mask;
2970 for (
unsigned j = 0;
j < Shards;
j++) {
2971 unsigned Offset = NumElems / Shards *
j;
2973 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2977 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
3002 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
3003 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3005 assert(
I.getType()->isVectorTy());
3006 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3008 [[maybe_unused]] FixedVectorType *ParamType =
3012 [[maybe_unused]] FixedVectorType *
ReturnType =
3020 Value *FirstArgShadow = getShadow(&
I, 0);
3021 Value *SecondArgShadow =
nullptr;
3022 if (
I.arg_size() == 2)
3023 SecondArgShadow = getShadow(&
I, 1);
3025 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3026 FirstArgShadow, SecondArgShadow);
3028 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3030 setShadow(&
I, OrShadow);
3031 setOriginForNaryOp(
I);
3041 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3042 int ReinterpretElemWidth) {
3043 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3045 assert(
I.getType()->isVectorTy());
3046 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3048 FixedVectorType *ParamType =
3053 [[maybe_unused]] FixedVectorType *
ReturnType =
3060 FixedVectorType *ReinterpretShadowTy =
nullptr;
3068 Value *FirstArgShadow = getShadow(&
I, 0);
3069 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3079 Value *SecondArgShadow =
nullptr;
3080 if (
I.arg_size() == 2) {
3081 SecondArgShadow = getShadow(&
I, 1);
3082 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3085 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3086 FirstArgShadow, SecondArgShadow);
3088 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3090 setShadow(&
I, OrShadow);
3091 setOriginForNaryOp(
I);
3094 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3105 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3111 Type *EltTy = VTy->getElementType();
3113 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3114 if (ConstantInt *Elt =
3116 const APInt &
V = Elt->getValue();
3117 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3118 Elements.push_back(ConstantInt::get(EltTy, V2));
3120 Elements.push_back(ConstantInt::get(EltTy, 1));
3126 const APInt &
V = Elt->getValue();
3127 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3128 ShadowMul = ConstantInt::get(Ty, V2);
3130 ShadowMul = ConstantInt::get(Ty, 1);
3136 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3137 setOrigin(&
I, getOrigin(OtherArg));
3140 void visitMul(BinaryOperator &
I) {
3143 if (constOp0 && !constOp1)
3144 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3145 else if (constOp1 && !constOp0)
3146 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3151 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3152 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3153 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3154 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3155 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3156 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3158 void handleIntegerDiv(Instruction &
I) {
3161 insertCheckShadowOf(
I.getOperand(1), &
I);
3162 setShadow(&
I, getShadow(&
I, 0));
3163 setOrigin(&
I, getOrigin(&
I, 0));
3166 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3167 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3168 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3169 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3173 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3174 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3180 void handleEqualityComparison(ICmpInst &
I) {
3184 Value *Sa = getShadow(
A);
3185 Value *Sb = getShadow(
B);
3187 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3190 setOriginForNaryOp(
I);
3198 void handleRelationalComparisonExact(ICmpInst &
I) {
3202 Value *Sa = getShadow(
A);
3203 Value *Sb = getShadow(
B);
3214 bool IsSigned =
I.isSigned();
3216 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3226 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3231 return std::make_pair(Min, Max);
3234 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3235 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3241 setOriginForNaryOp(
I);
3248 void handleSignedRelationalComparison(ICmpInst &
I) {
3253 op =
I.getOperand(0);
3254 pre =
I.getPredicate();
3256 op =
I.getOperand(1);
3257 pre =
I.getSwappedPredicate();
3270 setShadow(&
I, Shadow);
3271 setOrigin(&
I, getOrigin(
op));
3277 void visitICmpInst(ICmpInst &
I) {
3282 if (
I.isEquality()) {
3283 handleEqualityComparison(
I);
3289 handleRelationalComparisonExact(
I);
3293 handleSignedRelationalComparison(
I);
3299 handleRelationalComparisonExact(
I);
3306 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3308 void handleShift(BinaryOperator &
I) {
3313 Value *S2 = getShadow(&
I, 1);
3316 Value *V2 =
I.getOperand(1);
3318 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3319 setOriginForNaryOp(
I);
3322 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3323 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3324 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3326 void handleFunnelShift(IntrinsicInst &
I) {
3330 Value *S0 = getShadow(&
I, 0);
3332 Value *S2 = getShadow(&
I, 2);
3335 Value *V2 =
I.getOperand(2);
3338 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3339 setOriginForNaryOp(
I);
3347 void handleGenericBitManipulation(IntrinsicInst &
I) {
3349 Type *ShadowTy = getShadowTy(&
I);
3352 Value *SMask = getShadow(&
I, 1);
3357 if (Function *Func =
I.getCalledFunction())
3358 S = IRB.
CreateCall(Func, {getShadow(&
I, 0),
I.getOperand(1)});
3361 {getShadow(&I, 0), I.getOperand(1)});
3364 setOriginForNaryOp(
I);
3377 void visitMemMoveInst(MemMoveInst &
I) {
3378 getShadow(
I.getArgOperand(1));
3381 {I.getArgOperand(0), I.getArgOperand(1),
3382 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3400 void visitMemCpyInst(MemCpyInst &
I) {
3401 getShadow(
I.getArgOperand(1));
3404 {I.getArgOperand(0), I.getArgOperand(1),
3405 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3410 void visitMemSetInst(MemSetInst &
I) {
3414 {I.getArgOperand(0),
3415 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3416 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3420 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3422 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3428 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3432 Value *Addr =
I.getArgOperand(0);
3433 Value *Shadow = getShadow(&
I, 1);
3434 Value *ShadowPtr, *OriginPtr;
3438 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3443 insertCheckShadowOf(Addr, &
I);
3446 if (MS.TrackOrigins)
3455 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3459 Value *Addr =
I.getArgOperand(0);
3461 Type *ShadowTy = getShadowTy(&
I);
3462 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3463 if (PropagateShadow) {
3467 std::tie(ShadowPtr, OriginPtr) =
3468 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3472 setShadow(&
I, getCleanShadow(&
I));
3476 insertCheckShadowOf(Addr, &
I);
3478 if (MS.TrackOrigins) {
3479 if (PropagateShadow)
3480 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3482 setOrigin(&
I, getCleanOrigin());
3502 [[maybe_unused]]
bool
3503 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3504 unsigned int trailingFlags) {
3505 Type *RetTy =
I.getType();
3509 unsigned NumArgOperands =
I.arg_size();
3510 assert(NumArgOperands >= trailingFlags);
3511 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3512 Type *Ty =
I.getArgOperand(i)->getType();
3518 ShadowAndOriginCombiner SC(
this, IRB);
3519 for (
unsigned i = 0; i < NumArgOperands; ++i)
3520 SC.Add(
I.getArgOperand(i));
3537 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3538 unsigned NumArgOperands =
I.arg_size();
3539 if (NumArgOperands == 0)
3542 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3543 I.getArgOperand(1)->getType()->isVectorTy() &&
3544 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3546 return handleVectorStoreIntrinsic(
I);
3549 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3550 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3552 return handleVectorLoadIntrinsic(
I);
3555 if (
I.doesNotAccessMemory())
3556 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3564 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3565 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3567 dumpInst(
I,
"Heuristic");
3569 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3576 void handleInvariantGroup(IntrinsicInst &
I) {
3577 setShadow(&
I, getShadow(&
I, 0));
3578 setOrigin(&
I, getOrigin(&
I, 0));
3581 void handleLifetimeStart(IntrinsicInst &
I) {
3586 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3589 void handleBswap(IntrinsicInst &
I) {
3592 Type *OpType =
Op->getType();
3595 setOrigin(&
I, getOrigin(
Op));
3616 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3618 Value *Src =
I.getArgOperand(0);
3619 Value *SrcShadow = getShadow(Src);
3623 I.getType(),
I.getIntrinsicID(), {Src, False});
3625 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3628 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3630 Value *NotAllZeroShadow =
3632 Value *OutputShadow =
3633 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3639 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3642 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3644 setShadow(&
I, OutputShadow);
3645 setOriginForNaryOp(
I);
3654 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3674 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3679 Value *FullShadow = getCleanShadow(&
I);
3680 unsigned ShadowNumElems =
3682 unsigned FullShadowNumElems =
3685 assert((ShadowNumElems == FullShadowNumElems) ||
3686 (ShadowNumElems * 2 == FullShadowNumElems));
3688 if (ShadowNumElems == FullShadowNumElems) {
3689 FullShadow = Shadow;
3693 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3718 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3719 bool HasRoundingMode) {
3720 if (HasRoundingMode) {
3728 Value *Src =
I.getArgOperand(0);
3729 assert(Src->getType()->isVectorTy());
3733 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3736 Value *S0 = getShadow(&
I, 0);
3748 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3750 setShadow(&
I, FullShadow);
3751 setOriginForNaryOp(
I);
3772 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3773 bool HasRoundingMode =
false) {
3775 Value *CopyOp, *ConvertOp;
3777 assert((!HasRoundingMode ||
3779 "Invalid rounding mode");
3781 switch (
I.arg_size() - HasRoundingMode) {
3783 CopyOp =
I.getArgOperand(0);
3784 ConvertOp =
I.getArgOperand(1);
3787 ConvertOp =
I.getArgOperand(0);
3801 Value *ConvertShadow = getShadow(ConvertOp);
3802 Value *AggShadow =
nullptr;
3805 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3806 for (
int i = 1; i < NumUsedElements; ++i) {
3808 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3809 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3812 AggShadow = ConvertShadow;
3815 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3822 Value *ResultShadow = getShadow(CopyOp);
3824 for (
int i = 0; i < NumUsedElements; ++i) {
3826 ResultShadow, ConstantInt::getNullValue(EltTy),
3829 setShadow(&
I, ResultShadow);
3830 setOrigin(&
I, getOrigin(CopyOp));
3832 setShadow(&
I, getCleanShadow(&
I));
3833 setOrigin(&
I, getCleanOrigin());
3841 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3844 return CreateShadowCast(IRB, S2,
T,
true);
3852 return CreateShadowCast(IRB, S2,
T,
true);
3869 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3875 Value *S2 = getShadow(&
I, 1);
3877 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3879 Value *V2 =
I.getOperand(1);
3881 {IRB.CreateBitCast(S1, V1->getType()), V2});
3883 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3884 setOriginForNaryOp(
I);
3889 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3890 unsigned X86_MMXSizeInBits = 64) {
3891 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3892 "Illegal MMX vector element size");
3894 X86_MMXSizeInBits / EltSizeInBits);
3901 case Intrinsic::x86_sse2_packsswb_128:
3902 case Intrinsic::x86_sse2_packuswb_128:
3903 return Intrinsic::x86_sse2_packsswb_128;
3905 case Intrinsic::x86_sse2_packssdw_128:
3906 case Intrinsic::x86_sse41_packusdw:
3907 return Intrinsic::x86_sse2_packssdw_128;
3909 case Intrinsic::x86_avx2_packsswb:
3910 case Intrinsic::x86_avx2_packuswb:
3911 return Intrinsic::x86_avx2_packsswb;
3913 case Intrinsic::x86_avx2_packssdw:
3914 case Intrinsic::x86_avx2_packusdw:
3915 return Intrinsic::x86_avx2_packssdw;
3917 case Intrinsic::x86_mmx_packsswb:
3918 case Intrinsic::x86_mmx_packuswb:
3919 return Intrinsic::x86_mmx_packsswb;
3921 case Intrinsic::x86_mmx_packssdw:
3922 return Intrinsic::x86_mmx_packssdw;
3924 case Intrinsic::x86_avx512_packssdw_512:
3925 case Intrinsic::x86_avx512_packusdw_512:
3926 return Intrinsic::x86_avx512_packssdw_512;
3928 case Intrinsic::x86_avx512_packsswb_512:
3929 case Intrinsic::x86_avx512_packuswb_512:
3930 return Intrinsic::x86_avx512_packsswb_512;
3946 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3947 unsigned MMXEltSizeInBits = 0) {
3951 Value *S2 = getShadow(&
I, 1);
3952 assert(
S1->getType()->isVectorTy());
3958 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3959 if (MMXEltSizeInBits) {
3967 if (MMXEltSizeInBits) {
3973 {S1_ext, S2_ext},
nullptr,
3974 "_msprop_vector_pack");
3975 if (MMXEltSizeInBits)
3978 setOriginForNaryOp(
I);
3982 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3983 SmallVector<Constant *, 4>
R(Width);
3995 const unsigned Width =
4002 Value *DstMaskV = createDppMask(Width, DstMask);
4019 void handleDppIntrinsic(IntrinsicInst &
I) {
4022 Value *S0 = getShadow(&
I, 0);
4026 const unsigned Width =
4028 assert(Width == 2 || Width == 4 || Width == 8);
4031 const unsigned SrcMask =
Mask >> 4;
4032 const unsigned DstMask =
Mask & 0xf;
4035 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4040 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4047 setOriginForNaryOp(
I);
4051 C = CreateAppToShadowCast(IRB,
C);
4060 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4065 Value *Sc = getShadow(&
I, 2);
4066 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4071 C = convertBlendvToSelectMask(IRB,
C);
4072 Sc = convertBlendvToSelectMask(IRB, Sc);
4078 handleSelectLikeInst(
I,
C,
T,
F);
4082 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4083 const unsigned SignificantBitsPerResultElement = 16;
4085 unsigned ZeroBitsPerResultElement =
4089 auto *Shadow0 = getShadow(&
I, 0);
4090 auto *Shadow1 = getShadow(&
I, 1);
4095 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4098 setOriginForNaryOp(
I);
4122 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4123 unsigned ReductionFactor,
4125 unsigned EltSizeInBits,
4129 [[maybe_unused]] FixedVectorType *
ReturnType =
4134 Value *Va =
nullptr;
4135 Value *Vb =
nullptr;
4136 Value *Sa =
nullptr;
4137 Value *Sb =
nullptr;
4139 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4140 if (
I.arg_size() == 2) {
4143 Va =
I.getOperand(0);
4144 Vb =
I.getOperand(1);
4146 Sa = getShadow(&
I, 0);
4147 Sb = getShadow(&
I, 1);
4148 }
else if (
I.arg_size() == 3) {
4150 Va =
I.getOperand(1);
4151 Vb =
I.getOperand(2);
4153 Sa = getShadow(&
I, 1);
4154 Sb = getShadow(&
I, 2);
4171 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4173 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4183 if (
I.arg_size() == 3) {
4184 [[maybe_unused]]
auto *AccumulatorType =
4186 assert(AccumulatorType == ReturnType);
4189 FixedVectorType *ImplicitReturnType =
4192 if (EltSizeInBits) {
4194 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4206 ReturnType->getNumElements() * ReductionFactor);
4223 VaInt = CreateAppToShadowCast(IRB, Va);
4224 VbInt = CreateAppToShadowCast(IRB, Vb);
4231 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4253 ImplicitReturnType);
4258 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4261 if (
I.arg_size() == 3)
4262 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4264 setShadow(&
I, OutShadow);
4265 setOriginForNaryOp(
I);
4282 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4283 bool PredicateAsOperand) {
4284 if (PredicateAsOperand) {
4286 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4294 Type *ResTy = getShadowTy(&
I);
4295 auto *Shadow0 = getShadow(&
I, 0);
4296 auto *Shadow1 = getShadow(&
I, 1);
4301 setOriginForNaryOp(
I);
4307 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4309 auto *Shadow0 = getShadow(&
I, 0);
4310 auto *Shadow1 = getShadow(&
I, 1);
4312 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4314 setOriginForNaryOp(
I);
4323 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4328 if (AllowShadowCast)
4329 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4333 setOriginForNaryOp(
I);
4343 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4347 Value *Shadow0 = getShadow(&
I, 0);
4353 setOriginForNaryOp(
I);
4359 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4363 Value *OperandShadow = getShadow(&
I, 0);
4365 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4373 setOrigin(&
I, getOrigin(&
I, 0));
4379 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4383 Value *OperandShadow = getShadow(&
I, 0);
4384 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4392 setOrigin(&
I, getOrigin(&
I, 0));
4395 void handleStmxcsr(IntrinsicInst &
I) {
4397 Value *Addr =
I.getArgOperand(0);
4400 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4405 insertCheckShadowOf(Addr, &
I);
4408 void handleLdmxcsr(IntrinsicInst &
I) {
4413 Value *Addr =
I.getArgOperand(0);
4416 Value *ShadowPtr, *OriginPtr;
4417 std::tie(ShadowPtr, OriginPtr) =
4418 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4421 insertCheckShadowOf(Addr, &
I);
4424 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4426 insertCheckShadow(Shadow, Origin, &
I);
4429 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4431 Value *Ptr =
I.getArgOperand(0);
4432 MaybeAlign
Align =
I.getParamAlign(0);
4434 Value *PassThru =
I.getArgOperand(2);
4437 insertCheckShadowOf(Ptr, &
I);
4438 insertCheckShadowOf(Mask, &
I);
4441 if (!PropagateShadow) {
4442 setShadow(&
I, getCleanShadow(&
I));
4443 setOrigin(&
I, getCleanOrigin());
4447 Type *ShadowTy = getShadowTy(&
I);
4449 auto [ShadowPtr, OriginPtr] =
4450 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4454 getShadow(PassThru),
"_msmaskedexpload");
4456 setShadow(&
I, Shadow);
4459 setOrigin(&
I, getCleanOrigin());
4462 void handleMaskedCompressStore(IntrinsicInst &
I) {
4465 Value *Ptr =
I.getArgOperand(1);
4466 MaybeAlign
Align =
I.getParamAlign(1);
4470 insertCheckShadowOf(Ptr, &
I);
4471 insertCheckShadowOf(Mask, &
I);
4475 Type *ElementShadowTy =
4477 auto [ShadowPtr, OriginPtrs] =
4478 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4485 void handleMaskedGather(IntrinsicInst &
I) {
4487 Value *Ptrs =
I.getArgOperand(0);
4488 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4490 Value *PassThru =
I.getArgOperand(2);
4492 Type *PtrsShadowTy = getShadowTy(Ptrs);
4494 insertCheckShadowOf(Mask, &
I);
4498 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4501 if (!PropagateShadow) {
4502 setShadow(&
I, getCleanShadow(&
I));
4503 setOrigin(&
I, getCleanOrigin());
4507 Type *ShadowTy = getShadowTy(&
I);
4509 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4510 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4514 getShadow(PassThru),
"_msmaskedgather");
4516 setShadow(&
I, Shadow);
4519 setOrigin(&
I, getCleanOrigin());
4522 void handleMaskedScatter(IntrinsicInst &
I) {
4525 Value *Ptrs =
I.getArgOperand(1);
4526 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4529 Type *PtrsShadowTy = getShadowTy(Ptrs);
4531 insertCheckShadowOf(Mask, &
I);
4535 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4539 Type *ElementShadowTy =
4541 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4542 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4553 void handleMaskedStore(IntrinsicInst &
I) {
4555 Value *
V =
I.getArgOperand(0);
4556 Value *Ptr =
I.getArgOperand(1);
4557 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4559 Value *Shadow = getShadow(V);
4562 insertCheckShadowOf(Ptr, &
I);
4563 insertCheckShadowOf(Mask, &
I);
4568 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4569 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4573 if (!MS.TrackOrigins)
4576 auto &
DL =
F.getDataLayout();
4577 paintOrigin(IRB, getOrigin(V), OriginPtr,
4586 void handleMaskedLoad(IntrinsicInst &
I) {
4588 Value *Ptr =
I.getArgOperand(0);
4589 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4591 Value *PassThru =
I.getArgOperand(2);
4594 insertCheckShadowOf(Ptr, &
I);
4595 insertCheckShadowOf(Mask, &
I);
4598 if (!PropagateShadow) {
4599 setShadow(&
I, getCleanShadow(&
I));
4600 setOrigin(&
I, getCleanOrigin());
4604 Type *ShadowTy = getShadowTy(&
I);
4605 Value *ShadowPtr, *OriginPtr;
4606 std::tie(ShadowPtr, OriginPtr) =
4607 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4609 getShadow(PassThru),
"_msmaskedld"));
4611 if (!MS.TrackOrigins)
4618 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4623 setOrigin(&
I, Origin);
4639 void handleAVXMaskedStore(IntrinsicInst &
I) {
4644 Value *Dst =
I.getArgOperand(0);
4645 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4650 Value *Src =
I.getArgOperand(2);
4655 Value *SrcShadow = getShadow(Src);
4658 insertCheckShadowOf(Dst, &
I);
4659 insertCheckShadowOf(Mask, &
I);
4662 Value *DstShadowPtr;
4663 Value *DstOriginPtr;
4664 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4665 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4667 SmallVector<Value *, 2> ShadowArgs;
4668 ShadowArgs.
append(1, DstShadowPtr);
4669 ShadowArgs.
append(1, Mask);
4677 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
4680 if (!MS.TrackOrigins)
4684 auto &
DL =
F.getDataLayout();
4685 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4686 DL.getTypeStoreSize(SrcShadow->
getType()),
4705 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4710 Value *Src =
I.getArgOperand(0);
4711 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4719 insertCheckShadowOf(Mask, &
I);
4722 Type *SrcShadowTy = getShadowTy(Src);
4723 Value *SrcShadowPtr, *SrcOriginPtr;
4724 std::tie(SrcShadowPtr, SrcOriginPtr) =
4725 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4727 SmallVector<Value *, 2> ShadowArgs;
4728 ShadowArgs.
append(1, SrcShadowPtr);
4729 ShadowArgs.
append(1, Mask);
4732 I.getType(),
I.getIntrinsicID(), ShadowArgs);
4738 if (!MS.TrackOrigins)
4745 setOrigin(&
I, PtrSrcOrigin);
4754 assert(isFixedIntVector(Idx));
4755 auto IdxVectorSize =
4763 auto *IdxShadow = getShadow(Idx);
4768 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4773 void handleAVXVpermilvar(IntrinsicInst &
I) {
4775 Value *Shadow = getShadow(&
I, 0);
4776 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4780 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4782 I.getType(),
I.getIntrinsicID(), {Shadow, I.getArgOperand(1)});
4785 setOriginForNaryOp(
I);
4790 void handleAVXVpermi2var(IntrinsicInst &
I) {
4795 [[maybe_unused]]
auto ArgVectorSize =
4798 ->getNumElements() == ArgVectorSize);
4800 ->getNumElements() == ArgVectorSize);
4801 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4802 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4803 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4805 Value *AShadow = getShadow(&
I, 0);
4806 Value *Idx =
I.getArgOperand(1);
4807 Value *BShadow = getShadow(&
I, 2);
4809 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4813 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4814 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4816 I.getType(),
I.getIntrinsicID(), {AShadow, Idx, BShadow});
4818 setOriginForNaryOp(
I);
4821 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4825 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4829 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4830 return isFixedIntVectorTy(
V->getType());
4833 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4834 return isFixedFPVectorTy(
V->getType());
4856 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4861 Value *WriteThrough;
4865 WriteThrough =
I.getOperand(2);
4866 Mask =
I.getOperand(3);
4869 WriteThrough =
I.getOperand(1);
4870 Mask =
I.getOperand(2);
4875 assert(isFixedIntVector(WriteThrough));
4877 unsigned ANumElements =
4879 [[maybe_unused]]
unsigned WriteThruNumElements =
4881 assert(ANumElements == WriteThruNumElements ||
4882 ANumElements * 2 == WriteThruNumElements);
4885 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4886 assert(ANumElements == MaskNumElements ||
4887 ANumElements * 2 == MaskNumElements);
4889 assert(WriteThruNumElements == MaskNumElements);
4893 insertCheckShadowOf(Mask, &
I);
4903 Value *AShadow = getShadow(
A);
4904 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4906 if (ANumElements * 2 == MaskNumElements) {
4918 "_ms_mask_bitcast");
4928 getShadowTy(&
I),
"_ms_a_shadow");
4930 Value *WriteThroughShadow = getShadow(WriteThrough);
4932 "_ms_writethru_select");
4934 setShadow(&
I, Shadow);
4935 setOriginForNaryOp(
I);
4938 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4939 SmallVector<int, 8>
Mask;
4940 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4954 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4959 "pclmul 3rd operand must be a constant");
4962 getPclmulMask(Width, Imm & 0x01));
4964 getPclmulMask(Width, Imm & 0x10));
4965 ShadowAndOriginCombiner SOC(
this, IRB);
4966 SOC.Add(Shuf0, getOrigin(&
I, 0));
4967 SOC.Add(Shuf1, getOrigin(&
I, 1));
4972 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4977 Value *Second = getShadow(&
I, 1);
4979 SmallVector<int, 16>
Mask;
4980 Mask.push_back(Width);
4981 for (
unsigned i = 1; i < Width; i++)
4985 setShadow(&
I, Shadow);
4986 setOriginForNaryOp(
I);
4989 void handleVtestIntrinsic(IntrinsicInst &
I) {
4991 Value *Shadow0 = getShadow(&
I, 0);
4992 Value *Shadow1 = getShadow(&
I, 1);
4998 setShadow(&
I, Shadow);
4999 setOriginForNaryOp(
I);
5002 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
5007 Value *Second = getShadow(&
I, 1);
5010 SmallVector<int, 16>
Mask;
5011 Mask.push_back(Width);
5012 for (
unsigned i = 1; i < Width; i++)
5016 setShadow(&
I, Shadow);
5017 setOriginForNaryOp(
I);
5023 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5024 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5029 ShadowAndOriginCombiner SC(
this, IRB);
5030 SC.Add(
I.getArgOperand(0));
5038 void handleAbsIntrinsic(IntrinsicInst &
I) {
5040 Value *Src =
I.getArgOperand(0);
5041 Value *IsIntMinPoison =
I.getArgOperand(1);
5043 assert(
I.getType()->isIntOrIntVectorTy());
5045 assert(Src->getType() ==
I.getType());
5051 Value *SrcShadow = getShadow(Src);
5055 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5058 Value *PoisonedShadow = getPoisonedShadow(Src);
5059 Value *PoisonedIfIntMinShadow =
5062 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5064 setShadow(&
I, Shadow);
5065 setOrigin(&
I, getOrigin(&
I, 0));
5068 void handleIsFpClass(IntrinsicInst &
I) {
5070 Value *Shadow = getShadow(&
I, 0);
5071 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5072 setOrigin(&
I, getOrigin(&
I, 0));
5075 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5077 Value *Shadow0 = getShadow(&
I, 0);
5078 Value *Shadow1 = getShadow(&
I, 1);
5081 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5087 setShadow(&
I, Shadow);
5088 setOriginForNaryOp(
I);
5094 Value *Shadow = getShadow(V);
5116 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5121 Value *WriteThrough =
I.getOperand(1);
5125 assert(isFixedIntVector(WriteThrough));
5127 unsigned ANumElements =
5129 unsigned OutputNumElements =
5131 assert(ANumElements == OutputNumElements ||
5132 ANumElements * 2 == OutputNumElements);
5142 insertCheckShadowOf(Mask, &
I);
5145 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5146 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5147 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5158 if (ANumElements != OutputNumElements) {
5160 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5167 Value *AShadow = getShadow(
A);
5171 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5181 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5182 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5184 Value *WriteThroughShadow = getShadow(WriteThrough);
5187 setShadow(&
I, Shadow);
5188 setOriginForNaryOp(
I);
5222 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5223 SmallVector<unsigned, 4> DataIndices,
5224 unsigned WriteThruIndex,
5225 unsigned MaskIndex) {
5228 unsigned NumArgs =
I.arg_size();
5230 assert(WriteThruIndex < NumArgs);
5231 assert(MaskIndex < NumArgs);
5232 assert(WriteThruIndex != MaskIndex);
5233 Value *WriteThru =
I.getOperand(WriteThruIndex);
5235 unsigned OutputNumElements =
5240 bool isData[16] = {
false};
5242 for (
unsigned i : DataIndices) {
5244 assert(i != WriteThruIndex);
5251 [[maybe_unused]]
unsigned ANumElements =
5253 assert(ANumElements == OutputNumElements);
5258 assert(isFixedFPVector(WriteThru));
5260 for (
unsigned i = 0; i < NumArgs; ++i) {
5261 if (!isData[i] && i != WriteThruIndex) {
5264 assert(
I.getOperand(i)->getType()->isIntegerTy());
5265 insertCheckShadowOf(
I.getOperand(i), &
I);
5270 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5271 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5272 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5279 Value *DataShadow =
nullptr;
5280 for (
unsigned i : DataIndices) {
5283 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5285 DataShadow = getShadow(
A);
5293 Value *WriteThruShadow = getShadow(WriteThru);
5296 setShadow(&
I, Shadow);
5298 setOriginForNaryOp(
I);
5308 void handleAVX512FPClass(IntrinsicInst &
I) {
5313 Value *Input =
I.getOperand(0);
5314 assert(isFixedFPVector(Input));
5317 Value *Classifiers =
I.getOperand(1);
5321 assert(isFixedIntVectorTy(
I.getType()));
5327 Value *OutputShadow;
5332 OutputShadow = getCleanShadow(OutputType);
5338 OutputShadow = IRB.
CreateICmpNE(getShadow(Input), getCleanShadow(Input));
5340 setShadow(&
I, OutputShadow);
5342 setOriginForNaryOp(
I);
5352 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5358 Value *WriteThrough =
I.getOperand(2);
5365 insertCheckShadowOf(Mask, &
I);
5369 unsigned NumElements =
5371 assert(NumElements == 8);
5372 assert(
A->getType() ==
B->getType());
5374 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5377 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5378 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5380 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5382 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5389 Value *AShadow = getShadow(
A);
5390 Value *DstLowerShadow =
5391 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5393 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5396 setShadow(&
I, DstShadow);
5397 setOriginForNaryOp(
I);
5427 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5438 ->getScalarSizeInBits() == 8);
5440 assert(
A->getType() ==
X->getType());
5442 assert(
B->getType()->isIntegerTy());
5443 assert(
B->getType()->getScalarSizeInBits() == 8);
5445 assert(
I.getType() ==
A->getType());
5447 Value *AShadow = getShadow(
A);
5448 Value *XShadow = getShadow(
X);
5449 Value *BZeroShadow = getCleanShadow(
B);
5452 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5454 {X, AShadow, BZeroShadow});
5456 {XShadow, A, BZeroShadow});
5459 Value *BShadow = getShadow(
B);
5460 Value *BBroadcastShadow = getCleanShadow(AShadow);
5465 for (
unsigned i = 0; i < NumElements; i++)
5469 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5470 setOriginForNaryOp(
I);
5484 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5485 unsigned int numArgs =
I.arg_size();
5488 assert(
I.getType()->isStructTy());
5498 assert(4 <= numArgs && numArgs <= 6);
5512 for (
unsigned int i = 0; i < numArgs - 2; i++)
5513 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5516 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5520 insertCheckShadowOf(LaneNumber, &
I);
5523 Value *Src =
I.getArgOperand(numArgs - 1);
5524 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5526 Type *SrcShadowTy = getShadowTy(Src);
5527 auto [SrcShadowPtr, SrcOriginPtr] =
5528 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5535 getShadowTy(&
I),
I.getIntrinsicID(), ShadowArgs);
5538 if (!MS.TrackOrigins)
5542 setOrigin(&
I, PtrSrcOrigin);
5559 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5563 int numArgOperands =
I.arg_size();
5566 assert(numArgOperands >= 1);
5567 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5569 int skipTrailingOperands = 1;
5572 insertCheckShadowOf(Addr, &
I);
5576 skipTrailingOperands++;
5577 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5579 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5582 SmallVector<Value *, 8> ShadowArgs;
5584 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5586 Value *Shadow = getShadow(&
I, i);
5587 ShadowArgs.
append(1, Shadow);
5604 (numArgOperands - skipTrailingOperands));
5605 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5609 I.getArgOperand(numArgOperands - skipTrailingOperands));
5611 Value *OutputShadowPtr, *OutputOriginPtr;
5613 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5614 Addr, IRB, OutputShadowTy,
Align(1),
true);
5615 ShadowArgs.
append(1, OutputShadowPtr);
5618 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
5621 if (MS.TrackOrigins) {
5629 OriginCombiner OC(
this, IRB);
5630 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5631 OC.Add(
I.getArgOperand(i));
5633 const DataLayout &
DL =
F.getDataLayout();
5634 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5667 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5671 Value *
R =
I.getArgOperand(0);
5672 Value *
A =
I.getArgOperand(1);
5673 Value *
B =
I.getArgOperand(2);
5675 assert(
I.getType() ==
R->getType());
5700 Value *ShadowR = getShadow(&
I, 0);
5701 Value *ShadowA = getShadow(&
I, 1);
5702 Value *ShadowB = getShadow(&
I, 2);
5720 {getCleanShadow(RTy), ShadowA, ShadowB});
5746 {RZeros, ShadowA, ShadowB});
5760 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5761 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5763 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5765 setOriginForNaryOp(
I);
5805 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5807 unsigned int trailingVerbatimArgs,
5808 bool forceIntegerIntrinsic) {
5811 assert(trailingVerbatimArgs <
I.arg_size());
5813 SmallVector<Value *, 8> ShadowArgs;
5815 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5816 Value *Shadow = getShadow(&
I, i);
5818 if (forceIntegerIntrinsic)
5825 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5827 Value *Arg =
I.getArgOperand(i);
5828 if (forceIntegerIntrinsic)
5833 Value *CombinedShadow;
5834 if (forceIntegerIntrinsic) {
5844 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5847 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5848 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5851 setShadow(&
I, CombinedShadow);
5853 setOriginForNaryOp(
I);
5859 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5865 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5866 switch (
I.getIntrinsicID()) {
5867 case Intrinsic::uadd_with_overflow:
5868 case Intrinsic::sadd_with_overflow:
5869 case Intrinsic::usub_with_overflow:
5870 case Intrinsic::ssub_with_overflow:
5871 case Intrinsic::umul_with_overflow:
5872 case Intrinsic::smul_with_overflow:
5873 handleArithmeticWithOverflow(
I);
5875 case Intrinsic::abs:
5876 handleAbsIntrinsic(
I);
5878 case Intrinsic::bitreverse:
5879 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5883 case Intrinsic::is_fpclass:
5886 case Intrinsic::lifetime_start:
5887 handleLifetimeStart(
I);
5889 case Intrinsic::launder_invariant_group:
5890 case Intrinsic::strip_invariant_group:
5891 handleInvariantGroup(
I);
5893 case Intrinsic::bswap:
5896 case Intrinsic::ctlz:
5897 case Intrinsic::cttz:
5898 handleCountLeadingTrailingZeros(
I);
5900 case Intrinsic::masked_compressstore:
5901 handleMaskedCompressStore(
I);
5903 case Intrinsic::masked_expandload:
5904 handleMaskedExpandLoad(
I);
5906 case Intrinsic::masked_gather:
5907 handleMaskedGather(
I);
5909 case Intrinsic::masked_scatter:
5910 handleMaskedScatter(
I);
5912 case Intrinsic::masked_store:
5913 handleMaskedStore(
I);
5915 case Intrinsic::masked_load:
5916 handleMaskedLoad(
I);
5918 case Intrinsic::vector_reduce_and:
5919 handleVectorReduceAndIntrinsic(
I);
5921 case Intrinsic::vector_reduce_or:
5922 handleVectorReduceOrIntrinsic(
I);
5925 case Intrinsic::vector_reduce_add:
5926 case Intrinsic::vector_reduce_xor:
5927 case Intrinsic::vector_reduce_mul:
5930 case Intrinsic::vector_reduce_smax:
5931 case Intrinsic::vector_reduce_smin:
5932 case Intrinsic::vector_reduce_umax:
5933 case Intrinsic::vector_reduce_umin:
5936 case Intrinsic::vector_reduce_fmax:
5937 case Intrinsic::vector_reduce_fmin:
5938 handleVectorReduceIntrinsic(
I,
false);
5941 case Intrinsic::vector_reduce_fadd:
5942 case Intrinsic::vector_reduce_fmul:
5943 handleVectorReduceWithStarterIntrinsic(
I);
5946 case Intrinsic::scmp:
5947 case Intrinsic::ucmp: {
5952 case Intrinsic::fshl:
5953 case Intrinsic::fshr:
5954 handleFunnelShift(
I);
5957 case Intrinsic::pdep:
5958 case Intrinsic::pext:
5959 handleGenericBitManipulation(
I);
5962 case Intrinsic::is_constant:
5964 setShadow(&
I, getCleanShadow(&
I));
5965 setOrigin(&
I, getCleanOrigin());
5972 case Intrinsic::fptosi_sat:
5973 case Intrinsic::fptoui_sat:
5974 handleGenericVectorConvertIntrinsic(
I,
false);
5984 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5985 switch (
I.getIntrinsicID()) {
5986 case Intrinsic::x86_sse_stmxcsr:
5989 case Intrinsic::x86_sse_ldmxcsr:
5996 case Intrinsic::x86_avx512_vcvtsd2usi64:
5997 case Intrinsic::x86_avx512_vcvtsd2usi32:
5998 case Intrinsic::x86_avx512_vcvtss2usi64:
5999 case Intrinsic::x86_avx512_vcvtss2usi32:
6000 case Intrinsic::x86_avx512_cvttss2usi64:
6001 case Intrinsic::x86_avx512_cvttss2usi:
6002 case Intrinsic::x86_avx512_cvttsd2usi64:
6003 case Intrinsic::x86_avx512_cvttsd2usi:
6004 case Intrinsic::x86_avx512_cvtusi2ss:
6005 case Intrinsic::x86_avx512_cvtusi642sd:
6006 case Intrinsic::x86_avx512_cvtusi642ss:
6007 handleSSEVectorConvertIntrinsic(
I, 1,
true);
6009 case Intrinsic::x86_sse2_cvtsd2si64:
6010 case Intrinsic::x86_sse2_cvtsd2si:
6011 case Intrinsic::x86_sse2_cvtsd2ss:
6012 case Intrinsic::x86_sse2_cvttsd2si64:
6013 case Intrinsic::x86_sse2_cvttsd2si:
6014 case Intrinsic::x86_sse_cvtss2si64:
6015 case Intrinsic::x86_sse_cvtss2si:
6016 case Intrinsic::x86_sse_cvttss2si64:
6017 case Intrinsic::x86_sse_cvttss2si:
6018 handleSSEVectorConvertIntrinsic(
I, 1);
6020 case Intrinsic::x86_sse_cvtps2pi:
6021 case Intrinsic::x86_sse_cvttps2pi:
6022 handleSSEVectorConvertIntrinsic(
I, 2);
6030 case Intrinsic::x86_vcvtps2ph_128:
6031 case Intrinsic::x86_vcvtps2ph_256: {
6032 handleSSEVectorConvertIntrinsicByProp(
I,
true);
6041 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
6042 handleAVX512VectorConvertFPToInt(
I,
false);
6047 case Intrinsic::x86_sse2_cvtpd2ps:
6048 case Intrinsic::x86_sse2_cvtps2dq:
6049 case Intrinsic::x86_sse2_cvtpd2dq:
6050 case Intrinsic::x86_sse2_cvttps2dq:
6051 case Intrinsic::x86_sse2_cvttpd2dq:
6052 case Intrinsic::x86_avx_cvt_pd2_ps_256:
6053 case Intrinsic::x86_avx_cvt_ps2dq_256:
6054 case Intrinsic::x86_avx_cvt_pd2dq_256:
6055 case Intrinsic::x86_avx_cvtt_ps2dq_256:
6056 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
6057 handleSSEVectorConvertIntrinsicByProp(
I,
false);
6068 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
6069 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
6070 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
6071 handleAVX512VectorConvertFPToInt(
I,
true);
6075 case Intrinsic::x86_avx512_psll_w_512:
6076 case Intrinsic::x86_avx512_psll_d_512:
6077 case Intrinsic::x86_avx512_psll_q_512:
6078 case Intrinsic::x86_avx512_pslli_w_512:
6079 case Intrinsic::x86_avx512_pslli_d_512:
6080 case Intrinsic::x86_avx512_pslli_q_512:
6081 case Intrinsic::x86_avx512_psrl_w_512:
6082 case Intrinsic::x86_avx512_psrl_d_512:
6083 case Intrinsic::x86_avx512_psrl_q_512:
6084 case Intrinsic::x86_avx512_psra_w_512:
6085 case Intrinsic::x86_avx512_psra_d_512:
6086 case Intrinsic::x86_avx512_psra_q_512:
6087 case Intrinsic::x86_avx512_psrli_w_512:
6088 case Intrinsic::x86_avx512_psrli_d_512:
6089 case Intrinsic::x86_avx512_psrli_q_512:
6090 case Intrinsic::x86_avx512_psrai_w_512:
6091 case Intrinsic::x86_avx512_psrai_d_512:
6092 case Intrinsic::x86_avx512_psrai_q_512:
6093 case Intrinsic::x86_avx512_psra_q_256:
6094 case Intrinsic::x86_avx512_psra_q_128:
6095 case Intrinsic::x86_avx512_psrai_q_256:
6096 case Intrinsic::x86_avx512_psrai_q_128:
6097 case Intrinsic::x86_avx2_psll_w:
6098 case Intrinsic::x86_avx2_psll_d:
6099 case Intrinsic::x86_avx2_psll_q:
6100 case Intrinsic::x86_avx2_pslli_w:
6101 case Intrinsic::x86_avx2_pslli_d:
6102 case Intrinsic::x86_avx2_pslli_q:
6103 case Intrinsic::x86_avx2_psrl_w:
6104 case Intrinsic::x86_avx2_psrl_d:
6105 case Intrinsic::x86_avx2_psrl_q:
6106 case Intrinsic::x86_avx2_psra_w:
6107 case Intrinsic::x86_avx2_psra_d:
6108 case Intrinsic::x86_avx2_psrli_w:
6109 case Intrinsic::x86_avx2_psrli_d:
6110 case Intrinsic::x86_avx2_psrli_q:
6111 case Intrinsic::x86_avx2_psrai_w:
6112 case Intrinsic::x86_avx2_psrai_d:
6113 case Intrinsic::x86_sse2_psll_w:
6114 case Intrinsic::x86_sse2_psll_d:
6115 case Intrinsic::x86_sse2_psll_q:
6116 case Intrinsic::x86_sse2_pslli_w:
6117 case Intrinsic::x86_sse2_pslli_d:
6118 case Intrinsic::x86_sse2_pslli_q:
6119 case Intrinsic::x86_sse2_psrl_w:
6120 case Intrinsic::x86_sse2_psrl_d:
6121 case Intrinsic::x86_sse2_psrl_q:
6122 case Intrinsic::x86_sse2_psra_w:
6123 case Intrinsic::x86_sse2_psra_d:
6124 case Intrinsic::x86_sse2_psrli_w:
6125 case Intrinsic::x86_sse2_psrli_d:
6126 case Intrinsic::x86_sse2_psrli_q:
6127 case Intrinsic::x86_sse2_psrai_w:
6128 case Intrinsic::x86_sse2_psrai_d:
6129 case Intrinsic::x86_mmx_psll_w:
6130 case Intrinsic::x86_mmx_psll_d:
6131 case Intrinsic::x86_mmx_psll_q:
6132 case Intrinsic::x86_mmx_pslli_w:
6133 case Intrinsic::x86_mmx_pslli_d:
6134 case Intrinsic::x86_mmx_pslli_q:
6135 case Intrinsic::x86_mmx_psrl_w:
6136 case Intrinsic::x86_mmx_psrl_d:
6137 case Intrinsic::x86_mmx_psrl_q:
6138 case Intrinsic::x86_mmx_psra_w:
6139 case Intrinsic::x86_mmx_psra_d:
6140 case Intrinsic::x86_mmx_psrli_w:
6141 case Intrinsic::x86_mmx_psrli_d:
6142 case Intrinsic::x86_mmx_psrli_q:
6143 case Intrinsic::x86_mmx_psrai_w:
6144 case Intrinsic::x86_mmx_psrai_d:
6145 handleVectorShiftIntrinsic(
I,
false);
6147 case Intrinsic::x86_avx2_psllv_d:
6148 case Intrinsic::x86_avx2_psllv_d_256:
6149 case Intrinsic::x86_avx512_psllv_d_512:
6150 case Intrinsic::x86_avx2_psllv_q:
6151 case Intrinsic::x86_avx2_psllv_q_256:
6152 case Intrinsic::x86_avx512_psllv_q_512:
6153 case Intrinsic::x86_avx2_psrlv_d:
6154 case Intrinsic::x86_avx2_psrlv_d_256:
6155 case Intrinsic::x86_avx512_psrlv_d_512:
6156 case Intrinsic::x86_avx2_psrlv_q:
6157 case Intrinsic::x86_avx2_psrlv_q_256:
6158 case Intrinsic::x86_avx512_psrlv_q_512:
6159 case Intrinsic::x86_avx2_psrav_d:
6160 case Intrinsic::x86_avx2_psrav_d_256:
6161 case Intrinsic::x86_avx512_psrav_d_512:
6162 case Intrinsic::x86_avx512_psrav_q_128:
6163 case Intrinsic::x86_avx512_psrav_q_256:
6164 case Intrinsic::x86_avx512_psrav_q_512:
6165 handleVectorShiftIntrinsic(
I,
true);
6169 case Intrinsic::x86_sse2_packsswb_128:
6170 case Intrinsic::x86_sse2_packssdw_128:
6171 case Intrinsic::x86_sse2_packuswb_128:
6172 case Intrinsic::x86_sse41_packusdw:
6173 case Intrinsic::x86_avx2_packsswb:
6174 case Intrinsic::x86_avx2_packssdw:
6175 case Intrinsic::x86_avx2_packuswb:
6176 case Intrinsic::x86_avx2_packusdw:
6182 case Intrinsic::x86_avx512_packsswb_512:
6183 case Intrinsic::x86_avx512_packssdw_512:
6184 case Intrinsic::x86_avx512_packuswb_512:
6185 case Intrinsic::x86_avx512_packusdw_512:
6186 handleVectorPackIntrinsic(
I);
6189 case Intrinsic::x86_sse41_pblendvb:
6190 case Intrinsic::x86_sse41_blendvpd:
6191 case Intrinsic::x86_sse41_blendvps:
6192 case Intrinsic::x86_avx_blendv_pd_256:
6193 case Intrinsic::x86_avx_blendv_ps_256:
6194 case Intrinsic::x86_avx2_pblendvb:
6195 handleBlendvIntrinsic(
I);
6198 case Intrinsic::x86_avx_dp_ps_256:
6199 case Intrinsic::x86_sse41_dppd:
6200 case Intrinsic::x86_sse41_dpps:
6201 handleDppIntrinsic(
I);
6204 case Intrinsic::x86_mmx_packsswb:
6205 case Intrinsic::x86_mmx_packuswb:
6206 handleVectorPackIntrinsic(
I, 16);
6209 case Intrinsic::x86_mmx_packssdw:
6210 handleVectorPackIntrinsic(
I, 32);
6213 case Intrinsic::x86_mmx_psad_bw:
6214 handleVectorSadIntrinsic(
I,
true);
6216 case Intrinsic::x86_sse2_psad_bw:
6217 case Intrinsic::x86_avx2_psad_bw:
6218 handleVectorSadIntrinsic(
I);
6244 case Intrinsic::x86_sse2_pmadd_wd:
6245 case Intrinsic::x86_avx2_pmadd_wd:
6246 case Intrinsic::x86_avx512_pmaddw_d_512:
6247 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6248 case Intrinsic::x86_avx2_pmadd_ub_sw:
6249 case Intrinsic::x86_avx512_pmaddubs_w_512:
6250 handleVectorDotProductIntrinsic(
I, 2,
6257 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6258 handleVectorDotProductIntrinsic(
I, 2,
6265 case Intrinsic::x86_mmx_pmadd_wd:
6266 handleVectorDotProductIntrinsic(
I, 2,
6275 case Intrinsic::aarch64_neon_bfmlalt:
6276 handleVectorDotProductIntrinsic(
I, 2,
6284 case Intrinsic::aarch64_neon_bfmlalb:
6285 handleVectorDotProductIntrinsic(
I, 2,
6383 case Intrinsic::x86_avx512_vpdpbusd_128:
6384 case Intrinsic::x86_avx512_vpdpbusd_256:
6385 case Intrinsic::x86_avx512_vpdpbusd_512:
6386 case Intrinsic::x86_avx512_vpdpbusds_128:
6387 case Intrinsic::x86_avx512_vpdpbusds_256:
6388 case Intrinsic::x86_avx512_vpdpbusds_512:
6389 case Intrinsic::x86_avx2_vpdpbssd_128:
6390 case Intrinsic::x86_avx2_vpdpbssd_256:
6391 case Intrinsic::x86_avx10_vpdpbssd_512:
6392 case Intrinsic::x86_avx2_vpdpbssds_128:
6393 case Intrinsic::x86_avx2_vpdpbssds_256:
6394 case Intrinsic::x86_avx10_vpdpbssds_512:
6395 case Intrinsic::x86_avx2_vpdpbsud_128:
6396 case Intrinsic::x86_avx2_vpdpbsud_256:
6397 case Intrinsic::x86_avx10_vpdpbsud_512:
6398 case Intrinsic::x86_avx2_vpdpbsuds_128:
6399 case Intrinsic::x86_avx2_vpdpbsuds_256:
6400 case Intrinsic::x86_avx10_vpdpbsuds_512:
6401 case Intrinsic::x86_avx2_vpdpbuud_128:
6402 case Intrinsic::x86_avx2_vpdpbuud_256:
6403 case Intrinsic::x86_avx10_vpdpbuud_512:
6404 case Intrinsic::x86_avx2_vpdpbuuds_128:
6405 case Intrinsic::x86_avx2_vpdpbuuds_256:
6406 case Intrinsic::x86_avx10_vpdpbuuds_512:
6407 handleVectorDotProductIntrinsic(
I, 4,
6505 case Intrinsic::x86_avx512_vpdpwssd_128:
6506 case Intrinsic::x86_avx512_vpdpwssd_256:
6507 case Intrinsic::x86_avx512_vpdpwssd_512:
6508 case Intrinsic::x86_avx512_vpdpwssds_128:
6509 case Intrinsic::x86_avx512_vpdpwssds_256:
6510 case Intrinsic::x86_avx512_vpdpwssds_512:
6511 case Intrinsic::x86_avx2_vpdpwsud_128:
6512 case Intrinsic::x86_avx2_vpdpwsud_256:
6513 case Intrinsic::x86_avx10_vpdpwsud_512:
6514 case Intrinsic::x86_avx2_vpdpwsuds_128:
6515 case Intrinsic::x86_avx2_vpdpwsuds_256:
6516 case Intrinsic::x86_avx10_vpdpwsuds_512:
6517 case Intrinsic::x86_avx2_vpdpwusd_128:
6518 case Intrinsic::x86_avx2_vpdpwusd_256:
6519 case Intrinsic::x86_avx10_vpdpwusd_512:
6520 case Intrinsic::x86_avx2_vpdpwusds_128:
6521 case Intrinsic::x86_avx2_vpdpwusds_256:
6522 case Intrinsic::x86_avx10_vpdpwusds_512:
6523 case Intrinsic::x86_avx2_vpdpwuud_128:
6524 case Intrinsic::x86_avx2_vpdpwuud_256:
6525 case Intrinsic::x86_avx10_vpdpwuud_512:
6526 case Intrinsic::x86_avx2_vpdpwuuds_128:
6527 case Intrinsic::x86_avx2_vpdpwuuds_256:
6528 case Intrinsic::x86_avx10_vpdpwuuds_512:
6529 handleVectorDotProductIntrinsic(
I, 2,
6543 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6544 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6545 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6546 handleVectorDotProductIntrinsic(
I, 2,
6552 case Intrinsic::x86_sse_cmp_ss:
6553 case Intrinsic::x86_sse2_cmp_sd:
6554 case Intrinsic::x86_sse_comieq_ss:
6555 case Intrinsic::x86_sse_comilt_ss:
6556 case Intrinsic::x86_sse_comile_ss:
6557 case Intrinsic::x86_sse_comigt_ss:
6558 case Intrinsic::x86_sse_comige_ss:
6559 case Intrinsic::x86_sse_comineq_ss:
6560 case Intrinsic::x86_sse_ucomieq_ss:
6561 case Intrinsic::x86_sse_ucomilt_ss:
6562 case Intrinsic::x86_sse_ucomile_ss:
6563 case Intrinsic::x86_sse_ucomigt_ss:
6564 case Intrinsic::x86_sse_ucomige_ss:
6565 case Intrinsic::x86_sse_ucomineq_ss:
6566 case Intrinsic::x86_sse2_comieq_sd:
6567 case Intrinsic::x86_sse2_comilt_sd:
6568 case Intrinsic::x86_sse2_comile_sd:
6569 case Intrinsic::x86_sse2_comigt_sd:
6570 case Intrinsic::x86_sse2_comige_sd:
6571 case Intrinsic::x86_sse2_comineq_sd:
6572 case Intrinsic::x86_sse2_ucomieq_sd:
6573 case Intrinsic::x86_sse2_ucomilt_sd:
6574 case Intrinsic::x86_sse2_ucomile_sd:
6575 case Intrinsic::x86_sse2_ucomigt_sd:
6576 case Intrinsic::x86_sse2_ucomige_sd:
6577 case Intrinsic::x86_sse2_ucomineq_sd:
6578 handleVectorCompareScalarIntrinsic(
I);
6581 case Intrinsic::x86_avx_cmp_pd_256:
6582 case Intrinsic::x86_avx_cmp_ps_256:
6583 case Intrinsic::x86_sse2_cmp_pd:
6584 case Intrinsic::x86_sse_cmp_ps:
6585 handleVectorComparePackedIntrinsic(
I,
true);
6588 case Intrinsic::x86_bmi_bextr_32:
6589 case Intrinsic::x86_bmi_bextr_64:
6590 case Intrinsic::x86_bmi_bzhi_32:
6591 case Intrinsic::x86_bmi_bzhi_64:
6592 handleGenericBitManipulation(
I);
6595 case Intrinsic::x86_pclmulqdq:
6596 case Intrinsic::x86_pclmulqdq_256:
6597 case Intrinsic::x86_pclmulqdq_512:
6598 handlePclmulIntrinsic(
I);
6601 case Intrinsic::x86_avx_round_pd_256:
6602 case Intrinsic::x86_avx_round_ps_256:
6603 case Intrinsic::x86_sse41_round_pd:
6604 case Intrinsic::x86_sse41_round_ps:
6605 handleRoundPdPsIntrinsic(
I);
6608 case Intrinsic::x86_sse41_round_sd:
6609 case Intrinsic::x86_sse41_round_ss:
6610 handleUnarySdSsIntrinsic(
I);
6613 case Intrinsic::x86_sse2_max_sd:
6614 case Intrinsic::x86_sse_max_ss:
6615 case Intrinsic::x86_sse2_min_sd:
6616 case Intrinsic::x86_sse_min_ss:
6617 handleBinarySdSsIntrinsic(
I);
6620 case Intrinsic::x86_avx_vtestc_pd:
6621 case Intrinsic::x86_avx_vtestc_pd_256:
6622 case Intrinsic::x86_avx_vtestc_ps:
6623 case Intrinsic::x86_avx_vtestc_ps_256:
6624 case Intrinsic::x86_avx_vtestnzc_pd:
6625 case Intrinsic::x86_avx_vtestnzc_pd_256:
6626 case Intrinsic::x86_avx_vtestnzc_ps:
6627 case Intrinsic::x86_avx_vtestnzc_ps_256:
6628 case Intrinsic::x86_avx_vtestz_pd:
6629 case Intrinsic::x86_avx_vtestz_pd_256:
6630 case Intrinsic::x86_avx_vtestz_ps:
6631 case Intrinsic::x86_avx_vtestz_ps_256:
6632 case Intrinsic::x86_avx_ptestc_256:
6633 case Intrinsic::x86_avx_ptestnzc_256:
6634 case Intrinsic::x86_avx_ptestz_256:
6635 case Intrinsic::x86_sse41_ptestc:
6636 case Intrinsic::x86_sse41_ptestnzc:
6637 case Intrinsic::x86_sse41_ptestz:
6638 handleVtestIntrinsic(
I);
6642 case Intrinsic::x86_ssse3_phadd_w:
6643 case Intrinsic::x86_ssse3_phadd_w_128:
6644 case Intrinsic::x86_ssse3_phsub_w:
6645 case Intrinsic::x86_ssse3_phsub_w_128:
6646 handlePairwiseShadowOrIntrinsic(
I, 1,
6650 case Intrinsic::x86_avx2_phadd_w:
6651 case Intrinsic::x86_avx2_phsub_w:
6652 handlePairwiseShadowOrIntrinsic(
I, 2,
6657 case Intrinsic::x86_ssse3_phadd_d:
6658 case Intrinsic::x86_ssse3_phadd_d_128:
6659 case Intrinsic::x86_ssse3_phsub_d:
6660 case Intrinsic::x86_ssse3_phsub_d_128:
6661 handlePairwiseShadowOrIntrinsic(
I, 1,
6665 case Intrinsic::x86_avx2_phadd_d:
6666 case Intrinsic::x86_avx2_phsub_d:
6667 handlePairwiseShadowOrIntrinsic(
I, 2,
6672 case Intrinsic::x86_ssse3_phadd_sw:
6673 case Intrinsic::x86_ssse3_phadd_sw_128:
6674 case Intrinsic::x86_ssse3_phsub_sw:
6675 case Intrinsic::x86_ssse3_phsub_sw_128:
6676 handlePairwiseShadowOrIntrinsic(
I, 1,
6680 case Intrinsic::x86_avx2_phadd_sw:
6681 case Intrinsic::x86_avx2_phsub_sw:
6682 handlePairwiseShadowOrIntrinsic(
I, 2,
6687 case Intrinsic::x86_sse3_hadd_ps:
6688 case Intrinsic::x86_sse3_hadd_pd:
6689 case Intrinsic::x86_sse3_hsub_ps:
6690 case Intrinsic::x86_sse3_hsub_pd:
6691 handlePairwiseShadowOrIntrinsic(
I, 1);
6694 case Intrinsic::x86_avx_hadd_pd_256:
6695 case Intrinsic::x86_avx_hadd_ps_256:
6696 case Intrinsic::x86_avx_hsub_pd_256:
6697 case Intrinsic::x86_avx_hsub_ps_256:
6698 handlePairwiseShadowOrIntrinsic(
I, 2);
6701 case Intrinsic::x86_avx_maskstore_ps:
6702 case Intrinsic::x86_avx_maskstore_pd:
6703 case Intrinsic::x86_avx_maskstore_ps_256:
6704 case Intrinsic::x86_avx_maskstore_pd_256:
6705 case Intrinsic::x86_avx2_maskstore_d:
6706 case Intrinsic::x86_avx2_maskstore_q:
6707 case Intrinsic::x86_avx2_maskstore_d_256:
6708 case Intrinsic::x86_avx2_maskstore_q_256: {
6709 handleAVXMaskedStore(
I);
6713 case Intrinsic::x86_avx_maskload_ps:
6714 case Intrinsic::x86_avx_maskload_pd:
6715 case Intrinsic::x86_avx_maskload_ps_256:
6716 case Intrinsic::x86_avx_maskload_pd_256:
6717 case Intrinsic::x86_avx2_maskload_d:
6718 case Intrinsic::x86_avx2_maskload_q:
6719 case Intrinsic::x86_avx2_maskload_d_256:
6720 case Intrinsic::x86_avx2_maskload_q_256: {
6721 handleAVXMaskedLoad(
I);
6726 case Intrinsic::x86_avx512fp16_add_ph_512:
6727 case Intrinsic::x86_avx512fp16_sub_ph_512:
6728 case Intrinsic::x86_avx512fp16_mul_ph_512:
6729 case Intrinsic::x86_avx512fp16_div_ph_512:
6730 case Intrinsic::x86_avx512fp16_max_ph_512:
6731 case Intrinsic::x86_avx512fp16_min_ph_512:
6732 case Intrinsic::x86_avx512_min_ps_512:
6733 case Intrinsic::x86_avx512_min_pd_512:
6734 case Intrinsic::x86_avx512_max_ps_512:
6735 case Intrinsic::x86_avx512_max_pd_512: {
6740 [[maybe_unused]]
bool Success =
6741 maybeHandleSimpleNomemIntrinsic(
I, 1);
6746 case Intrinsic::x86_avx_vpermilvar_pd:
6747 case Intrinsic::x86_avx_vpermilvar_pd_256:
6748 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6749 case Intrinsic::x86_avx_vpermilvar_ps:
6750 case Intrinsic::x86_avx_vpermilvar_ps_256:
6751 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6752 handleAVXVpermilvar(
I);
6756 case Intrinsic::x86_avx512_vpermi2var_d_128:
6757 case Intrinsic::x86_avx512_vpermi2var_d_256:
6758 case Intrinsic::x86_avx512_vpermi2var_d_512:
6759 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6760 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6761 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6762 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6763 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6764 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6765 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6766 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6767 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6768 case Intrinsic::x86_avx512_vpermi2var_q_128:
6769 case Intrinsic::x86_avx512_vpermi2var_q_256:
6770 case Intrinsic::x86_avx512_vpermi2var_q_512:
6771 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6772 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6773 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6774 handleAVXVpermi2var(
I);
6788 case Intrinsic::x86_avx2_pshuf_b:
6789 case Intrinsic::x86_sse_pshuf_w:
6790 case Intrinsic::x86_ssse3_pshuf_b_128:
6791 case Intrinsic::x86_ssse3_pshuf_b:
6792 case Intrinsic::x86_avx512_pshuf_b_512:
6793 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6800 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6801 case Intrinsic::x86_avx512_mask_pmov_db_128:
6802 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6803 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6804 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6805 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6806 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6807 case Intrinsic::x86_avx512_mask_pmov_db_256:
6808 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6809 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6810 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6811 case Intrinsic::x86_avx512_mask_pmov_db_512:
6812 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6813 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6816 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6825 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6826 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6827 handleIntrinsicByApplyingToShadow(
6828 I, Intrinsic::x86_avx512_mask_pmov_dw_512,
6833 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6834 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6835 handleIntrinsicByApplyingToShadow(
6836 I, Intrinsic::x86_avx512_mask_pmov_dw_256,
6840 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6841 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6842 handleIntrinsicByApplyingToShadow(
6843 I, Intrinsic::x86_avx512_mask_pmov_dw_128,
6847 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6848 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6849 handleIntrinsicByApplyingToShadow(
6850 I, Intrinsic::x86_avx512_mask_pmov_db_512,
6855 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6856 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6857 handleIntrinsicByApplyingToShadow(
6858 I, Intrinsic::x86_avx512_mask_pmov_db_256,
6862 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6863 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6864 handleIntrinsicByApplyingToShadow(
6865 I, Intrinsic::x86_avx512_mask_pmov_db_128,
6869 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6870 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6871 handleIntrinsicByApplyingToShadow(
6872 I, Intrinsic::x86_avx512_mask_pmov_qb_512,
6877 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6878 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6879 handleIntrinsicByApplyingToShadow(
6880 I, Intrinsic::x86_avx512_mask_pmov_qb_256,
6884 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6885 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6886 handleIntrinsicByApplyingToShadow(
6887 I, Intrinsic::x86_avx512_mask_pmov_qb_128,
6891 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6892 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6893 handleIntrinsicByApplyingToShadow(
6894 I, Intrinsic::x86_avx512_mask_pmov_qw_512,
6899 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6900 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6901 handleIntrinsicByApplyingToShadow(
6902 I, Intrinsic::x86_avx512_mask_pmov_qw_256,
6906 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6907 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6908 handleIntrinsicByApplyingToShadow(
6909 I, Intrinsic::x86_avx512_mask_pmov_qw_128,
6913 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6914 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6915 handleIntrinsicByApplyingToShadow(
6916 I, Intrinsic::x86_avx512_mask_pmov_qd_128,
6920 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6921 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6922 handleIntrinsicByApplyingToShadow(
6923 I, Intrinsic::x86_avx512_mask_pmov_wb_128,
6927 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6928 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6929 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6930 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6931 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6932 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6933 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6934 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6938 handleAVX512VectorDownConvert(
I);
6949 case Intrinsic::x86_avx512_mask_compress:
6950 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6991 case Intrinsic::x86_avx512_rsqrt14_ps_512:
6992 case Intrinsic::x86_avx512_rsqrt14_ps_256:
6993 case Intrinsic::x86_avx512_rsqrt14_ps_128:
6994 case Intrinsic::x86_avx512_rsqrt14_pd_512:
6995 case Intrinsic::x86_avx512_rsqrt14_pd_256:
6996 case Intrinsic::x86_avx512_rsqrt14_pd_128:
6997 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
6998 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
6999 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
7000 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
7001 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
7002 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
7003 handleAVX512VectorGenericMaskedFP(
I, {0},
7044 case Intrinsic::x86_avx512_rcp14_ps_512:
7045 case Intrinsic::x86_avx512_rcp14_ps_256:
7046 case Intrinsic::x86_avx512_rcp14_ps_128:
7047 case Intrinsic::x86_avx512_rcp14_pd_512:
7048 case Intrinsic::x86_avx512_rcp14_pd_256:
7049 case Intrinsic::x86_avx512_rcp14_pd_128:
7050 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
7051 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
7052 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
7053 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
7054 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
7055 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
7056 handleAVX512VectorGenericMaskedFP(
I, {0},
7101 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7102 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7103 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7104 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7105 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7106 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7107 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7108 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7109 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7110 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7111 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7112 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7113 handleAVX512VectorGenericMaskedFP(
I, {0},
7149 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7150 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7151 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7152 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7153 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7154 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7155 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7156 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7157 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7161 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7181 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7182 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7183 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7184 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7185 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7186 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7187 visitGenericScalarHalfwordInst(
I);
7194 case Intrinsic::x86_avx512_fpclass_pd_512:
7195 case Intrinsic::x86_avx512_fpclass_ps_512:
7196 handleAVX512FPClass(
I);
7200 case Intrinsic::x86_vgf2p8affineqb_128:
7201 case Intrinsic::x86_vgf2p8affineqb_256:
7202 case Intrinsic::x86_vgf2p8affineqb_512:
7203 handleAVXGF2P8Affine(
I);
7213 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7214 switch (
I.getIntrinsicID()) {
7218 case Intrinsic::aarch64_neon_rshrn:
7219 case Intrinsic::aarch64_neon_sqrshl:
7220 case Intrinsic::aarch64_neon_sqrshrn:
7221 case Intrinsic::aarch64_neon_sqrshrun:
7222 case Intrinsic::aarch64_neon_sqshl:
7223 case Intrinsic::aarch64_neon_sqshlu:
7224 case Intrinsic::aarch64_neon_sqshrn:
7225 case Intrinsic::aarch64_neon_sqshrun:
7226 case Intrinsic::aarch64_neon_srshl:
7227 case Intrinsic::aarch64_neon_sshl:
7228 case Intrinsic::aarch64_neon_uqrshl:
7229 case Intrinsic::aarch64_neon_uqrshrn:
7230 case Intrinsic::aarch64_neon_uqshl:
7231 case Intrinsic::aarch64_neon_uqshrn:
7232 case Intrinsic::aarch64_neon_urshl:
7233 case Intrinsic::aarch64_neon_ushl:
7234 handleVectorShiftIntrinsic(
I,
false);
7247 case Intrinsic::aarch64_neon_vsli:
7248 case Intrinsic::aarch64_neon_vsri:
7249 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7256 case Intrinsic::aarch64_neon_fmaxp:
7257 case Intrinsic::aarch64_neon_fminp:
7259 case Intrinsic::aarch64_neon_fmaxnmp:
7260 case Intrinsic::aarch64_neon_fminnmp:
7262 case Intrinsic::aarch64_neon_smaxp:
7263 case Intrinsic::aarch64_neon_sminp:
7264 case Intrinsic::aarch64_neon_umaxp:
7265 case Intrinsic::aarch64_neon_uminp:
7267 case Intrinsic::aarch64_neon_addp:
7269 case Intrinsic::aarch64_neon_faddp:
7271 case Intrinsic::aarch64_neon_saddlp:
7272 case Intrinsic::aarch64_neon_uaddlp: {
7273 handlePairwiseShadowOrIntrinsic(
I, 1);
7278 case Intrinsic::aarch64_neon_fcvtas:
7279 case Intrinsic::aarch64_neon_fcvtau:
7281 case Intrinsic::aarch64_neon_fcvtms:
7282 case Intrinsic::aarch64_neon_fcvtmu:
7284 case Intrinsic::aarch64_neon_fcvtns:
7285 case Intrinsic::aarch64_neon_fcvtnu:
7287 case Intrinsic::aarch64_neon_fcvtps:
7288 case Intrinsic::aarch64_neon_fcvtpu:
7290 case Intrinsic::aarch64_neon_fcvtzs:
7291 case Intrinsic::aarch64_neon_fcvtzu:
7293 case Intrinsic::aarch64_neon_fcvtxn:
7294 handleGenericVectorConvertIntrinsic(
I,
false);
7298 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7299 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7300 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7301 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7302 handleGenericVectorConvertIntrinsic(
I,
true);
7311 case Intrinsic::aarch64_neon_faddv:
7312 case Intrinsic::aarch64_neon_saddv:
7313 case Intrinsic::aarch64_neon_uaddv:
7316 case Intrinsic::aarch64_neon_smaxv:
7317 case Intrinsic::aarch64_neon_sminv:
7318 case Intrinsic::aarch64_neon_umaxv:
7319 case Intrinsic::aarch64_neon_uminv:
7323 case Intrinsic::aarch64_neon_fmaxv:
7324 case Intrinsic::aarch64_neon_fminv:
7325 case Intrinsic::aarch64_neon_fmaxnmv:
7326 case Intrinsic::aarch64_neon_fminnmv:
7328 case Intrinsic::aarch64_neon_saddlv:
7329 case Intrinsic::aarch64_neon_uaddlv:
7330 handleVectorReduceIntrinsic(
I,
true);
7333 case Intrinsic::aarch64_neon_ld1x2:
7334 case Intrinsic::aarch64_neon_ld1x3:
7335 case Intrinsic::aarch64_neon_ld1x4:
7336 case Intrinsic::aarch64_neon_ld2:
7337 case Intrinsic::aarch64_neon_ld3:
7338 case Intrinsic::aarch64_neon_ld4:
7339 case Intrinsic::aarch64_neon_ld2r:
7340 case Intrinsic::aarch64_neon_ld3r:
7341 case Intrinsic::aarch64_neon_ld4r: {
7342 handleNEONVectorLoad(
I,
false);
7346 case Intrinsic::aarch64_neon_ld2lane:
7347 case Intrinsic::aarch64_neon_ld3lane:
7348 case Intrinsic::aarch64_neon_ld4lane: {
7349 handleNEONVectorLoad(
I,
true);
7354 case Intrinsic::aarch64_neon_sqxtn:
7355 case Intrinsic::aarch64_neon_sqxtun:
7356 case Intrinsic::aarch64_neon_uqxtn:
7363 case Intrinsic::aarch64_neon_st1x2:
7364 case Intrinsic::aarch64_neon_st1x3:
7365 case Intrinsic::aarch64_neon_st1x4:
7366 case Intrinsic::aarch64_neon_st2:
7367 case Intrinsic::aarch64_neon_st3:
7368 case Intrinsic::aarch64_neon_st4: {
7369 handleNEONVectorStoreIntrinsic(
I,
false);
7373 case Intrinsic::aarch64_neon_st2lane:
7374 case Intrinsic::aarch64_neon_st3lane:
7375 case Intrinsic::aarch64_neon_st4lane: {
7376 handleNEONVectorStoreIntrinsic(
I,
true);
7389 case Intrinsic::aarch64_neon_tbl1:
7390 case Intrinsic::aarch64_neon_tbl2:
7391 case Intrinsic::aarch64_neon_tbl3:
7392 case Intrinsic::aarch64_neon_tbl4:
7393 case Intrinsic::aarch64_neon_tbx1:
7394 case Intrinsic::aarch64_neon_tbx2:
7395 case Intrinsic::aarch64_neon_tbx3:
7396 case Intrinsic::aarch64_neon_tbx4: {
7398 handleIntrinsicByApplyingToShadow(
7399 I,
I.getIntrinsicID(),
7404 case Intrinsic::aarch64_neon_fmulx:
7405 case Intrinsic::aarch64_neon_pmul:
7406 case Intrinsic::aarch64_neon_pmull:
7407 case Intrinsic::aarch64_neon_smull:
7408 case Intrinsic::aarch64_neon_pmull64:
7409 case Intrinsic::aarch64_neon_umull: {
7410 handleNEONVectorMultiplyIntrinsic(
I);
7414 case Intrinsic::aarch64_neon_smmla:
7415 case Intrinsic::aarch64_neon_ummla:
7416 case Intrinsic::aarch64_neon_usmmla:
7417 case Intrinsic::aarch64_neon_bfmmla:
7418 handleNEONMatrixMultiply(
I);
7425 case Intrinsic::aarch64_neon_sdot:
7426 case Intrinsic::aarch64_neon_udot:
7427 case Intrinsic::aarch64_neon_usdot:
7428 handleVectorDotProductIntrinsic(
I, 4,
7438 case Intrinsic::aarch64_neon_bfdot:
7439 handleVectorDotProductIntrinsic(
I, 2,
7446 case Intrinsic::aarch64_neon_facge:
7447 case Intrinsic::aarch64_neon_facgt:
7448 handleVectorComparePackedIntrinsic(
I,
false);
7458 void visitIntrinsicInst(IntrinsicInst &
I) {
7459 if (maybeHandleCrossPlatformIntrinsic(
I))
7462 if (maybeHandleX86SIMDIntrinsic(
I))
7465 if (maybeHandleArmSIMDIntrinsic(
I))
7468 if (maybeHandleUnknownIntrinsic(
I))
7471 visitInstruction(
I);
7474 void visitLibAtomicLoad(CallBase &CB) {
7485 Value *NewOrdering =
7489 NextNodeIRBuilder NextIRB(&CB);
7490 Value *SrcShadowPtr, *SrcOriginPtr;
7491 std::tie(SrcShadowPtr, SrcOriginPtr) =
7492 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7494 Value *DstShadowPtr =
7495 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7499 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7500 if (MS.TrackOrigins) {
7501 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7503 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7504 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7508 void visitLibAtomicStore(CallBase &CB) {
7515 Value *NewOrdering =
7519 Value *DstShadowPtr =
7529 void visitCallBase(CallBase &CB) {
7537 visitAsmInstruction(CB);
7539 visitInstruction(CB);
7548 case LibFunc_atomic_load:
7550 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7554 visitLibAtomicLoad(CB);
7556 case LibFunc_atomic_store:
7557 visitLibAtomicStore(CB);
7573 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7577 Func->removeFnAttrs(
B);
7583 bool MayCheckCall = MS.EagerChecks;
7587 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7590 unsigned ArgOffset = 0;
7593 if (!
A->getType()->isSized()) {
7594 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7598 if (
A->getType()->isScalableTy()) {
7599 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7601 insertCheckShadowOf(
A, &CB);
7606 const DataLayout &
DL =
F.getDataLayout();
7610 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7613 insertCheckShadowOf(
A, &CB);
7614 Size =
DL.getTypeAllocSize(
A->getType());
7620 Value *ArgShadow = getShadow(
A);
7621 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7623 <<
" Shadow: " << *ArgShadow <<
"\n");
7627 assert(
A->getType()->isPointerTy() &&
7628 "ByVal argument is not a pointer!");
7633 MaybeAlign Alignment = std::nullopt;
7636 Value *AShadowPtr, *AOriginPtr;
7637 std::tie(AShadowPtr, AOriginPtr) =
7638 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7640 if (!PropagateShadow) {
7647 if (MS.TrackOrigins) {
7648 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7662 Size =
DL.getTypeAllocSize(
A->getType());
7668 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7670 getOriginPtrForArgument(IRB, ArgOffset));
7682 if (FT->isVarArg()) {
7683 VAHelper->visitCallBase(CB, IRB);
7693 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7694 setShadow(&CB, getCleanShadow(&CB));
7695 setOrigin(&CB, getCleanOrigin());
7701 Value *
Base = getShadowPtrForRetval(IRBBefore);
7702 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7714 setShadow(&CB, getCleanShadow(&CB));
7715 setOrigin(&CB, getCleanOrigin());
7722 "Could not find insertion point for retval shadow load");
7725 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7728 setShadow(&CB, RetvalShadow);
7729 if (MS.TrackOrigins)
7730 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7735 RetVal =
I->getOperand(0);
7738 return I->isMustTailCall();
7743 void visitReturnInst(ReturnInst &
I) {
7745 Value *RetVal =
I.getReturnValue();
7751 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7752 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7753 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7756 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7758 Value *Shadow = getShadow(RetVal);
7759 bool StoreOrigin =
true;
7761 insertCheckShadowOf(RetVal, &
I);
7762 Shadow = getCleanShadow(RetVal);
7763 StoreOrigin =
false;
7770 if (MS.TrackOrigins && StoreOrigin)
7771 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7775 void visitPHINode(PHINode &
I) {
7777 if (!PropagateShadow) {
7778 setShadow(&
I, getCleanShadow(&
I));
7779 setOrigin(&
I, getCleanOrigin());
7783 ShadowPHINodes.push_back(&
I);
7784 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7786 if (MS.TrackOrigins)
7788 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7791 Value *getLocalVarIdptr(AllocaInst &
I) {
7792 ConstantInt *IntConst =
7793 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7794 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7799 Value *getLocalVarDescription(AllocaInst &
I) {
7805 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7807 Value *ShadowBase, *OriginBase;
7808 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7812 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7815 if (PoisonStack && MS.TrackOrigins) {
7816 Value *Idptr = getLocalVarIdptr(
I);
7818 Value *Descr = getLocalVarDescription(
I);
7819 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7820 {&I, Len, Idptr, Descr});
7822 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7828 Value *Descr = getLocalVarDescription(
I);
7830 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7832 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7836 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7839 NextNodeIRBuilder IRB(InsPoint);
7842 if (MS.CompileKernel)
7843 poisonAllocaKmsan(
I, IRB, Len);
7845 poisonAllocaUserspace(
I, IRB, Len);
7848 void visitAllocaInst(AllocaInst &
I) {
7849 setShadow(&
I, getCleanShadow(&
I));
7850 setOrigin(&
I, getCleanOrigin());
7856 void visitSelectInst(SelectInst &
I) {
7862 handleSelectLikeInst(
I,
B,
C,
D);
7868 Value *Sb = getShadow(
B);
7869 Value *Sc = getShadow(
C);
7870 Value *Sd = getShadow(
D);
7872 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7873 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7874 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7879 if (
I.getType()->isAggregateType()) {
7883 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7884 }
else if (isScalableNonVectorType(
I.getType())) {
7892 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7900 C = CreateAppToShadowCast(IRB,
C);
7901 D = CreateAppToShadowCast(IRB,
D);
7908 if (MS.TrackOrigins) {
7911 if (
B->getType()->isVectorTy()) {
7912 B = convertToBool(
B, IRB);
7913 Sb = convertToBool(Sb, IRB);
7921 void visitLandingPadInst(LandingPadInst &
I) {
7924 setShadow(&
I, getCleanShadow(&
I));
7925 setOrigin(&
I, getCleanOrigin());
7928 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7929 setShadow(&
I, getCleanShadow(&
I));
7930 setOrigin(&
I, getCleanOrigin());
7933 void visitFuncletPadInst(FuncletPadInst &
I) {
7934 setShadow(&
I, getCleanShadow(&
I));
7935 setOrigin(&
I, getCleanOrigin());
7938 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7940 void visitExtractValueInst(ExtractValueInst &
I) {
7942 Value *Agg =
I.getAggregateOperand();
7944 Value *AggShadow = getShadow(Agg);
7948 setShadow(&
I, ResShadow);
7949 setOriginForNaryOp(
I);
7952 void visitInsertValueInst(InsertValueInst &
I) {
7955 Value *AggShadow = getShadow(
I.getAggregateOperand());
7956 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7962 setOriginForNaryOp(
I);
7965 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7972 << CI->getCalledFunction()->
getName() <<
"\n";
7974 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
7981 unsigned NumOperands =
I.getNumOperands();
7983 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
7995 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
7996 <<
I.getOpcodeName() <<
"(";
7998 for (
size_t i = 0; i < NumOperands; i++) {
8016 void visitResumeInst(ResumeInst &
I) {
8021 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
8026 void visitCatchReturnInst(CatchReturnInst &CRI) {
8031 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
8040 insertCheckShadowOf(Operand, &
I);
8047 auto Size =
DL.getTypeStoreSize(ElemTy);
8049 if (MS.CompileKernel) {
8050 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
8056 auto [ShadowPtr,
_] =
8057 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
8067 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
8068 int NumRetOutputs = 0;
8075 NumRetOutputs =
ST->getNumElements();
8080 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
8081 switch (
Info.Type) {
8089 return NumOutputs - NumRetOutputs;
8092 void visitAsmInstruction(Instruction &
I) {
8108 const DataLayout &
DL =
F.getDataLayout();
8112 int OutputArgs = getNumOutputArgs(IA, CB);
8118 for (
int i = OutputArgs; i < NumOperands; i++) {
8126 for (
int i = 0; i < OutputArgs; i++) {
8132 setShadow(&
I, getCleanShadow(&
I));
8133 setOrigin(&
I, getCleanOrigin());
8136 void visitFreezeInst(FreezeInst &
I) {
8138 setShadow(&
I, getCleanShadow(&
I));
8139 setOrigin(&
I, getCleanOrigin());
8142 void visitInstruction(Instruction &
I) {
8145 dumpInst(
I,
"Strict");
8147 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8148 Value *Operand =
I.getOperand(i);
8150 insertCheckShadowOf(Operand, &
I);
8152 setShadow(&
I, getCleanShadow(&
I));
8153 setOrigin(&
I, getCleanOrigin());
8157struct VarArgHelperBase :
public VarArgHelper {
8159 MemorySanitizer &MS;
8160 MemorySanitizerVisitor &MSV;
8162 const unsigned VAListTagSize;
8164 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
8165 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8166 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8170 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8176 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8185 return getShadowPtrForVAArgument(IRB, ArgOffset);
8194 ConstantInt::get(MS.IntptrTy, ArgOffset),
8199 unsigned BaseOffset) {
8208 TailSize,
Align(8));
8211 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8213 Value *VAListTag =
I.getArgOperand(0);
8215 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8216 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8219 VAListTagSize, Alignment,
false);
8222 void visitVAStartInst(VAStartInst &
I)
override {
8223 if (
F.getCallingConv() == CallingConv::Win64)
8226 unpoisonVAListTagForInst(
I);
8229 void visitVACopyInst(VACopyInst &
I)
override {
8230 if (
F.getCallingConv() == CallingConv::Win64)
8232 unpoisonVAListTagForInst(
I);
8237struct VarArgAMD64Helper :
public VarArgHelperBase {
8240 static const unsigned AMD64GpEndOffset = 48;
8241 static const unsigned AMD64FpEndOffsetSSE = 176;
8243 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8245 unsigned AMD64FpEndOffset;
8246 AllocaInst *VAArgTLSCopy =
nullptr;
8247 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8248 Value *VAArgOverflowSize =
nullptr;
8250 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8252 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
8253 MemorySanitizerVisitor &MSV)
8254 : VarArgHelperBase(
F, MS, MSV, 24) {
8255 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8256 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8257 if (Attr.isStringAttribute() &&
8258 (Attr.getKindAsString() ==
"target-features")) {
8259 if (Attr.getValueAsString().contains(
"-sse"))
8260 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8266 ArgKind classifyArgument(
Value *arg) {
8269 if (
T->isX86_FP80Ty())
8271 if (
T->isFPOrFPVectorTy())
8272 return AK_FloatingPoint;
8273 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8274 return AK_GeneralPurpose;
8275 if (
T->isPointerTy())
8276 return AK_GeneralPurpose;
8288 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8289 unsigned GpOffset = 0;
8290 unsigned FpOffset = AMD64GpEndOffset;
8291 unsigned OverflowOffset = AMD64FpEndOffset;
8292 const DataLayout &
DL =
F.getDataLayout();
8296 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8303 assert(
A->getType()->isPointerTy());
8305 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8306 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8307 unsigned BaseOffset = OverflowOffset;
8308 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8309 Value *OriginBase =
nullptr;
8310 if (MS.TrackOrigins)
8311 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8312 OverflowOffset += AlignedSize;
8315 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8319 Value *ShadowPtr, *OriginPtr;
8320 std::tie(ShadowPtr, OriginPtr) =
8325 if (MS.TrackOrigins)
8329 ArgKind AK = classifyArgument(
A);
8330 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8332 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8334 Value *ShadowBase, *OriginBase =
nullptr;
8336 case AK_GeneralPurpose:
8337 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8338 if (MS.TrackOrigins)
8339 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8343 case AK_FloatingPoint:
8344 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8345 if (MS.TrackOrigins)
8346 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8353 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8354 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8355 unsigned BaseOffset = OverflowOffset;
8356 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8357 if (MS.TrackOrigins) {
8358 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8360 OverflowOffset += AlignedSize;
8363 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8372 Value *Shadow = MSV.getShadow(
A);
8374 if (MS.TrackOrigins) {
8375 Value *Origin = MSV.getOrigin(
A);
8376 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8377 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8383 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8384 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8387 void finalizeInstrumentation()
override {
8388 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8389 "finalizeInstrumentation called twice");
8390 if (!VAStartInstrumentationList.
empty()) {
8397 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8398 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8404 Intrinsic::umin, CopySize,
8408 if (MS.TrackOrigins) {
8409 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8418 for (CallInst *OrigInst : VAStartInstrumentationList) {
8419 NextNodeIRBuilder IRB(OrigInst);
8420 Value *VAListTag = OrigInst->getArgOperand(0);
8422 Value *RegSaveAreaPtrPtr =
8423 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8425 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8427 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8428 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8430 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8432 if (MS.TrackOrigins)
8433 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8434 Alignment, AMD64FpEndOffset);
8435 Value *OverflowArgAreaPtrPtr =
8436 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8437 Value *OverflowArgAreaPtr =
8438 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8439 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8440 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8441 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8445 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8447 if (MS.TrackOrigins) {
8450 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8458struct VarArgAArch64Helper :
public VarArgHelperBase {
8459 static const unsigned kAArch64GrArgSize = 64;
8460 static const unsigned kAArch64VrArgSize = 128;
8462 static const unsigned AArch64GrBegOffset = 0;
8463 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8465 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8466 static const unsigned AArch64VrEndOffset =
8467 AArch64VrBegOffset + kAArch64VrArgSize;
8468 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8470 AllocaInst *VAArgTLSCopy =
nullptr;
8471 Value *VAArgOverflowSize =
nullptr;
8473 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8475 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
8476 MemorySanitizerVisitor &MSV)
8477 : VarArgHelperBase(
F, MS, MSV, 32) {}
8480 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8481 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8482 return {AK_GeneralPurpose, 1};
8483 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8484 return {AK_FloatingPoint, 1};
8486 if (
T->isArrayTy()) {
8487 auto R = classifyArgument(
T->getArrayElementType());
8488 R.second *=
T->getScalarType()->getArrayNumElements();
8493 auto R = classifyArgument(FV->getScalarType());
8494 R.second *= FV->getNumElements();
8499 return {AK_Memory, 0};
8511 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8512 unsigned GrOffset = AArch64GrBegOffset;
8513 unsigned VrOffset = AArch64VrBegOffset;
8514 unsigned OverflowOffset = AArch64VAEndOffset;
8516 const DataLayout &
DL =
F.getDataLayout();
8519 auto [AK, RegNum] = classifyArgument(
A->getType());
8520 if (AK == AK_GeneralPurpose &&
8521 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8523 if (AK == AK_FloatingPoint &&
8524 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8528 case AK_GeneralPurpose:
8529 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8530 GrOffset += 8 * RegNum;
8532 case AK_FloatingPoint:
8533 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8534 VrOffset += 16 * RegNum;
8541 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8542 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8543 unsigned BaseOffset = OverflowOffset;
8544 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8545 OverflowOffset += AlignedSize;
8548 CleanUnusedTLS(IRB,
Base, BaseOffset);
8560 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8561 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8566 Value *SaveAreaPtrPtr =
8567 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8568 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8573 Value *SaveAreaPtr =
8574 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8576 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8579 void finalizeInstrumentation()
override {
8580 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8581 "finalizeInstrumentation called twice");
8582 if (!VAStartInstrumentationList.empty()) {
8589 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8590 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8596 Intrinsic::umin, CopySize,
8602 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8603 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8607 for (CallInst *OrigInst : VAStartInstrumentationList) {
8608 NextNodeIRBuilder IRB(OrigInst);
8610 Value *VAListTag = OrigInst->getArgOperand(0);
8627 Value *StackSaveAreaPtr =
8628 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8631 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8632 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8635 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8638 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8639 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8642 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8648 Value *GrRegSaveAreaShadowPtrOff =
8649 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8651 Value *GrRegSaveAreaShadowPtr =
8652 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8658 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8664 Value *VrRegSaveAreaShadowPtrOff =
8665 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8667 Value *VrRegSaveAreaShadowPtr =
8668 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8675 VrRegSaveAreaShadowPtrOff);
8676 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8682 Value *StackSaveAreaShadowPtr =
8683 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8688 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8691 Align(16), VAArgOverflowSize);
8697struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8698 AllocaInst *VAArgTLSCopy =
nullptr;
8699 Value *VAArgSize =
nullptr;
8701 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
8702 MemorySanitizerVisitor &MSV)
8703 : VarArgHelperBase(
F, MS, MSV, 8) {}
8705 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8713 Triple TargetTriple(
F.getParent()->getTargetTriple());
8717 if (TargetTriple.isPPC64ELFv2ABI())
8721 unsigned VAArgOffset = VAArgBase;
8722 const DataLayout &
DL =
F.getDataLayout();
8725 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8727 assert(
A->getType()->isPointerTy());
8729 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8732 ArgAlign =
Align(8);
8733 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8736 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8738 Value *AShadowPtr, *AOriginPtr;
8739 std::tie(AShadowPtr, AOriginPtr) =
8740 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8750 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8752 if (
A->getType()->isArrayTy()) {
8755 Type *ElementTy =
A->getType()->getArrayElementType();
8757 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8758 }
else if (
A->getType()->isVectorTy()) {
8760 ArgAlign =
Align(ArgSize);
8763 ArgAlign =
Align(8);
8764 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8765 if (
DL.isBigEndian()) {
8769 VAArgOffset += (8 - ArgSize);
8773 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8777 VAArgOffset += ArgSize;
8781 VAArgBase = VAArgOffset;
8785 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8788 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8791 void finalizeInstrumentation()
override {
8792 assert(!VAArgSize && !VAArgTLSCopy &&
8793 "finalizeInstrumentation called twice");
8796 Value *CopySize = VAArgSize;
8798 if (!VAStartInstrumentationList.empty()) {
8802 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8808 Intrinsic::umin, CopySize,
8816 for (CallInst *OrigInst : VAStartInstrumentationList) {
8817 NextNodeIRBuilder IRB(OrigInst);
8818 Value *VAListTag = OrigInst->getArgOperand(0);
8821 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8824 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8825 const DataLayout &
DL =
F.getDataLayout();
8826 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8828 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8829 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8831 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8838struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8839 AllocaInst *VAArgTLSCopy =
nullptr;
8840 Value *VAArgSize =
nullptr;
8842 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
8843 MemorySanitizerVisitor &MSV)
8844 : VarArgHelperBase(
F, MS, MSV, 12) {}
8846 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8850 unsigned VAArgOffset = VAArgBase;
8851 const DataLayout &
DL =
F.getDataLayout();
8852 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8855 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8857 assert(
A->getType()->isPointerTy());
8859 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8861 if (ArgAlign < IntptrSize)
8862 ArgAlign =
Align(IntptrSize);
8863 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8866 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8868 Value *AShadowPtr, *AOriginPtr;
8869 std::tie(AShadowPtr, AOriginPtr) =
8870 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8880 Type *ArgTy =
A->getType();
8886 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8893 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8896 ArgAlign =
Align(ArgSize);
8898 if (ArgAlign < IntptrSize)
8899 ArgAlign =
Align(IntptrSize);
8900 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8901 if (
DL.isBigEndian()) {
8904 if (ArgSize < IntptrSize)
8905 VAArgOffset += (IntptrSize - ArgSize);
8908 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8914 VAArgOffset += ArgSize;
8921 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8924 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8927 void finalizeInstrumentation()
override {
8928 assert(!VAArgSize && !VAArgTLSCopy &&
8929 "finalizeInstrumentation called twice");
8931 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8932 Value *CopySize = VAArgSize;
8934 if (!VAStartInstrumentationList.empty()) {
8938 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8944 Intrinsic::umin, CopySize,
8952 for (CallInst *OrigInst : VAStartInstrumentationList) {
8953 NextNodeIRBuilder IRB(OrigInst);
8954 Value *VAListTag = OrigInst->getArgOperand(0);
8956 Value *RegSaveAreaSize = CopySize;
8960 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8964 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8966 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8969 const DataLayout &
DL =
F.getDataLayout();
8970 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8974 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8975 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8976 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8978 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
8979 Alignment, RegSaveAreaSize);
8981 RegSaveAreaShadowPtr =
8984 ConstantInt::get(MS.IntptrTy, 32));
8989 ConstantInt::get(MS.IntptrTy, 32), Alignment);
8994 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
8997 OverflowAreaPtrPtr =
8998 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
8999 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
9001 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
9003 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
9004 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
9005 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
9008 Value *OverflowVAArgTLSCopyPtr =
9010 OverflowVAArgTLSCopyPtr =
9011 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
9013 OverflowVAArgTLSCopyPtr =
9016 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
9023struct VarArgSystemZHelper :
public VarArgHelperBase {
9024 static const unsigned SystemZGpOffset = 16;
9025 static const unsigned SystemZGpEndOffset = 56;
9026 static const unsigned SystemZFpOffset = 128;
9027 static const unsigned SystemZFpEndOffset = 160;
9028 static const unsigned SystemZMaxVrArgs = 8;
9029 static const unsigned SystemZRegSaveAreaSize = 160;
9030 static const unsigned SystemZOverflowOffset = 160;
9031 static const unsigned SystemZVAListTagSize = 32;
9032 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
9033 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
9035 bool IsSoftFloatABI;
9036 AllocaInst *VAArgTLSCopy =
nullptr;
9037 AllocaInst *VAArgTLSOriginCopy =
nullptr;
9038 Value *VAArgOverflowSize =
nullptr;
9040 enum class ArgKind {
9048 enum class ShadowExtension {
None,
Zero, Sign };
9050 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
9051 MemorySanitizerVisitor &MSV)
9052 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
9053 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
9055 ArgKind classifyArgument(
Type *
T) {
9062 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
9063 return ArgKind::Indirect;
9064 if (
T->isFloatingPointTy())
9065 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
9066 if (
T->isIntegerTy() ||
T->isPointerTy())
9067 return ArgKind::GeneralPurpose;
9068 if (
T->isVectorTy())
9069 return ArgKind::Vector;
9070 return ArgKind::Memory;
9073 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
9083 return ShadowExtension::Zero;
9087 return ShadowExtension::Sign;
9089 return ShadowExtension::None;
9092 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9093 unsigned GpOffset = SystemZGpOffset;
9094 unsigned FpOffset = SystemZFpOffset;
9095 unsigned VrIndex = 0;
9096 unsigned OverflowOffset = SystemZOverflowOffset;
9097 const DataLayout &
DL =
F.getDataLayout();
9103 ArgKind AK = classifyArgument(
T);
9104 if (AK == ArgKind::Indirect) {
9106 AK = ArgKind::GeneralPurpose;
9108 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9109 AK = ArgKind::Memory;
9110 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9111 AK = ArgKind::Memory;
9112 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9113 AK = ArgKind::Memory;
9114 Value *ShadowBase =
nullptr;
9115 Value *OriginBase =
nullptr;
9116 ShadowExtension SE = ShadowExtension::None;
9118 case ArgKind::GeneralPurpose: {
9120 uint64_t ArgSize = 8;
9123 SE = getShadowExtension(CB, ArgNo);
9124 uint64_t GapSize = 0;
9125 if (SE == ShadowExtension::None) {
9126 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9127 assert(ArgAllocSize <= ArgSize);
9128 GapSize = ArgSize - ArgAllocSize;
9130 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9131 if (MS.TrackOrigins)
9132 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9134 GpOffset += ArgSize;
9140 case ArgKind::FloatingPoint: {
9142 uint64_t ArgSize = 8;
9149 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9150 if (MS.TrackOrigins)
9151 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9153 FpOffset += ArgSize;
9159 case ArgKind::Vector: {
9166 case ArgKind::Memory: {
9171 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9172 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
9174 SE = getShadowExtension(CB, ArgNo);
9176 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9178 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9179 if (MS.TrackOrigins)
9181 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9182 OverflowOffset += ArgSize;
9189 case ArgKind::Indirect:
9192 if (ShadowBase ==
nullptr)
9194 Value *Shadow = MSV.getShadow(
A);
9195 if (SE != ShadowExtension::None)
9196 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9197 SE == ShadowExtension::Sign);
9198 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9200 if (MS.TrackOrigins) {
9201 Value *Origin = MSV.getOrigin(
A);
9202 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9203 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9207 Constant *OverflowSize = ConstantInt::get(
9208 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9209 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9216 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9219 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9221 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9222 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9227 unsigned RegSaveAreaSize =
9228 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9229 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9231 if (MS.TrackOrigins)
9232 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9233 Alignment, RegSaveAreaSize);
9242 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9244 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9245 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9247 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9248 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9251 SystemZOverflowOffset);
9252 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9254 if (MS.TrackOrigins) {
9256 SystemZOverflowOffset);
9257 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9262 void finalizeInstrumentation()
override {
9263 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9264 "finalizeInstrumentation called twice");
9265 if (!VAStartInstrumentationList.empty()) {
9272 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9274 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9280 Intrinsic::umin, CopySize,
9284 if (MS.TrackOrigins) {
9285 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9294 for (CallInst *OrigInst : VAStartInstrumentationList) {
9295 NextNodeIRBuilder IRB(OrigInst);
9296 Value *VAListTag = OrigInst->getArgOperand(0);
9297 copyRegSaveArea(IRB, VAListTag);
9298 copyOverflowArea(IRB, VAListTag);
9304struct VarArgI386Helper :
public VarArgHelperBase {
9305 AllocaInst *VAArgTLSCopy =
nullptr;
9306 Value *VAArgSize =
nullptr;
9308 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
9309 MemorySanitizerVisitor &MSV)
9310 : VarArgHelperBase(
F, MS, MSV, 4) {}
9312 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9313 const DataLayout &
DL =
F.getDataLayout();
9314 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9315 unsigned VAArgOffset = 0;
9318 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
9320 assert(
A->getType()->isPointerTy());
9322 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9324 if (ArgAlign < IntptrSize)
9325 ArgAlign =
Align(IntptrSize);
9326 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9328 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9330 Value *AShadowPtr, *AOriginPtr;
9331 std::tie(AShadowPtr, AOriginPtr) =
9332 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9342 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9344 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9345 if (
DL.isBigEndian()) {
9348 if (ArgSize < IntptrSize)
9349 VAArgOffset += (IntptrSize - ArgSize);
9352 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9355 VAArgOffset += ArgSize;
9361 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9364 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9367 void finalizeInstrumentation()
override {
9368 assert(!VAArgSize && !VAArgTLSCopy &&
9369 "finalizeInstrumentation called twice");
9371 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9372 Value *CopySize = VAArgSize;
9374 if (!VAStartInstrumentationList.empty()) {
9377 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9383 Intrinsic::umin, CopySize,
9391 for (CallInst *OrigInst : VAStartInstrumentationList) {
9392 NextNodeIRBuilder IRB(OrigInst);
9393 Value *VAListTag = OrigInst->getArgOperand(0);
9394 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9395 Value *RegSaveAreaPtrPtr =
9397 PointerType::get(*MS.C, 0));
9398 Value *RegSaveAreaPtr =
9399 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9400 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9401 const DataLayout &
DL =
F.getDataLayout();
9402 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9404 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9405 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9407 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9415struct VarArgGenericHelper :
public VarArgHelperBase {
9416 AllocaInst *VAArgTLSCopy =
nullptr;
9417 Value *VAArgSize =
nullptr;
9419 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
9420 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9421 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9423 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9424 unsigned VAArgOffset = 0;
9425 const DataLayout &
DL =
F.getDataLayout();
9426 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9431 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9432 if (
DL.isBigEndian()) {
9435 if (ArgSize < IntptrSize)
9436 VAArgOffset += (IntptrSize - ArgSize);
9438 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9439 VAArgOffset += ArgSize;
9440 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9446 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9449 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9452 void finalizeInstrumentation()
override {
9453 assert(!VAArgSize && !VAArgTLSCopy &&
9454 "finalizeInstrumentation called twice");
9456 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9457 Value *CopySize = VAArgSize;
9459 if (!VAStartInstrumentationList.empty()) {
9462 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9468 Intrinsic::umin, CopySize,
9476 for (CallInst *OrigInst : VAStartInstrumentationList) {
9477 NextNodeIRBuilder IRB(OrigInst);
9478 Value *VAListTag = OrigInst->getArgOperand(0);
9479 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9480 Value *RegSaveAreaPtrPtr =
9482 PointerType::get(*MS.C, 0));
9483 Value *RegSaveAreaPtr =
9484 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9485 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9486 const DataLayout &
DL =
F.getDataLayout();
9487 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9489 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9490 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9492 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9500using VarArgARM32Helper = VarArgGenericHelper;
9501using VarArgRISCVHelper = VarArgGenericHelper;
9502using VarArgMIPSHelper = VarArgGenericHelper;
9503using VarArgLoongArch64Helper = VarArgGenericHelper;
9504using VarArgHexagonHelper = VarArgGenericHelper;
9507struct VarArgNoOpHelper :
public VarArgHelper {
9508 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
9509 MemorySanitizerVisitor &MSV) {}
9511 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9513 void visitVAStartInst(VAStartInst &
I)
override {}
9515 void visitVACopyInst(VACopyInst &
I)
override {}
9517 void finalizeInstrumentation()
override {}
9523 MemorySanitizerVisitor &Visitor) {
9526 Triple TargetTriple(Func.getParent()->getTargetTriple());
9529 return new VarArgI386Helper(Func, Msan, Visitor);
9532 return new VarArgAMD64Helper(Func, Msan, Visitor);
9534 if (TargetTriple.
isARM())
9535 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9538 return new VarArgAArch64Helper(Func, Msan, Visitor);
9541 return new VarArgSystemZHelper(Func, Msan, Visitor);
9546 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9549 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9552 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9555 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9558 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9561 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9564 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9568 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9570 return new VarArgNoOpHelper(Func, Msan, Visitor);
9577 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9580 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9587 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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...
static bool insertModuleCtor(Module &M)
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.
@ 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.