184#include "llvm/IR/IntrinsicsAArch64.h"
185#include "llvm/IR/IntrinsicsX86.h"
216#define DEBUG_TYPE "msan"
219 "Controls which checks to insert");
222 "Controls which instruction to instrument");
241 "msan-track-origins",
246 cl::desc(
"keep going after reporting a UMR"),
255 "msan-poison-stack-with-call",
260 "msan-poison-stack-pattern",
261 cl::desc(
"poison uninitialized stack variables with the given pattern"),
266 cl::desc(
"Print name of local stack variable"),
271 cl::desc(
"Poison fully undef temporary values. "
272 "Partially undefined constant vectors "
273 "are unaffected by this flag (see "
274 "-msan-poison-undef-vectors)."),
278 "msan-poison-undef-vectors",
279 cl::desc(
"Precisely poison partially undefined constant vectors. "
280 "If false (legacy behavior), the entire vector is "
281 "considered fully initialized, which may lead to false "
282 "negatives. Fully undefined constant vectors are "
283 "unaffected by this flag (see -msan-poison-undef)."),
287 "msan-precise-disjoint-or",
288 cl::desc(
"Precisely poison disjoint OR. If false (legacy behavior), "
289 "disjointedness is ignored (i.e., 1|1 is initialized)."),
294 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
299 cl::desc(
"exact handling of relational integer ICmp"),
303 "msan-switch-precision",
304 cl::desc(
"Controls the number of cases considered by MSan for LLVM switch "
305 "instructions. 0 means no UUMs detected. Higher values lead to "
306 "fewer false negatives but may impact compiler and/or "
307 "application performance. N.B. LLVM switch instructions do not "
308 "correspond exactly to C++ switch statements."),
312 "msan-handle-lifetime-intrinsics",
314 "when possible, poison scoped variables at the beginning of the scope "
315 "(slower, but more precise)"),
326 "msan-handle-asm-conservative",
337 "msan-check-access-address",
338 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
343 cl::desc(
"check arguments and return values at function call boundaries"),
347 "msan-dump-strict-instructions",
348 cl::desc(
"print out instructions with default strict semantics i.e.,"
349 "check that all the inputs are fully initialized, and mark "
350 "the output as fully initialized. These semantics are applied "
351 "to instructions that could not be handled explicitly nor "
360 "msan-dump-heuristic-instructions",
361 cl::desc(
"Prints 'unknown' instructions that were handled heuristically. "
362 "Use -msan-dump-strict-instructions to print instructions that "
363 "could not be handled explicitly nor heuristically."),
367 "msan-instrumentation-with-call-threshold",
369 "If the function being instrumented requires more than "
370 "this number of checks and origin stores, use callbacks instead of "
371 "inline checks (-1 means never use callbacks)."),
376 cl::desc(
"Enable KernelMemorySanitizer instrumentation"),
386 cl::desc(
"Insert checks for constant shadow values"),
393 cl::desc(
"Place MSan constructors in comdat sections"),
399 cl::desc(
"Define custom MSan AndMask"),
403 cl::desc(
"Define custom MSan XorMask"),
407 cl::desc(
"Define custom MSan ShadowBase"),
411 cl::desc(
"Define custom MSan OriginBase"),
416 cl::desc(
"Define threshold for number of checks per "
417 "debug location to force origin update."),
429struct MemoryMapParams {
436struct PlatformMemoryMapParams {
437 const MemoryMapParams *bits32;
438 const MemoryMapParams *bits64;
615class MemorySanitizer {
624 MemorySanitizer(MemorySanitizer &&) =
delete;
625 MemorySanitizer &operator=(MemorySanitizer &&) =
delete;
626 MemorySanitizer(
const MemorySanitizer &) =
delete;
627 MemorySanitizer &operator=(
const MemorySanitizer &) =
delete;
629 bool sanitizeFunction(Function &
F, TargetLibraryInfo &TLI);
632 friend struct MemorySanitizerVisitor;
633 friend struct VarArgHelperBase;
634 friend struct VarArgAMD64Helper;
635 friend struct VarArgAArch64Helper;
636 friend struct VarArgPowerPC64Helper;
637 friend struct VarArgPowerPC32Helper;
638 friend struct VarArgSystemZHelper;
639 friend struct VarArgI386Helper;
640 friend struct VarArgGenericHelper;
642 void initializeModule(
Module &M);
643 void initializeCallbacks(
Module &M,
const TargetLibraryInfo &TLI);
644 void createKernelApi(
Module &M,
const TargetLibraryInfo &TLI);
645 void createUserspaceApi(
Module &M,
const TargetLibraryInfo &TLI);
647 template <
typename... ArgsTy>
648 FunctionCallee getOrInsertMsanMetadataFunction(
Module &M, StringRef Name,
674 Value *ParamOriginTLS;
680 Value *RetvalOriginTLS;
686 Value *VAArgOriginTLS;
689 Value *VAArgOverflowSizeTLS;
692 bool CallbacksInitialized =
false;
695 FunctionCallee WarningFn;
699 FunctionCallee MaybeWarningVarSizeFn;
704 FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
706 FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
709 FunctionCallee MsanPoisonStackFn;
713 FunctionCallee MsanChainOriginFn;
716 FunctionCallee MsanSetOriginFn;
719 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
722 StructType *MsanContextStateTy;
723 FunctionCallee MsanGetContextStateFn;
726 FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
732 FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
733 FunctionCallee MsanMetadataPtrForLoad_1_8[4];
734 FunctionCallee MsanMetadataPtrForStore_1_8[4];
735 FunctionCallee MsanInstrumentAsmStoreFn;
738 Value *MsanMetadataAlloca;
741 FunctionCallee getKmsanShadowOriginAccessFn(
bool isStore,
int size);
744 const MemoryMapParams *MapParams;
748 MemoryMapParams CustomMapParams;
750 MDNode *ColdCallWeights;
753 MDNode *OriginStoreWeights;
756void insertModuleCtor(
Module &M) {
793 if (!Options.Kernel) {
802 MemorySanitizer Msan(*
F.getParent(), Options);
821 OS, MapClassName2PassName);
827 if (Options.EagerChecks)
828 OS <<
"eager-checks;";
829 OS <<
"track-origins=" << Options.TrackOrigins;
845template <
typename... ArgsTy>
847MemorySanitizer::getOrInsertMsanMetadataFunction(
Module &M,
StringRef Name,
852 std::forward<ArgsTy>(Args)...);
855 return M.getOrInsertFunction(Name, MsanMetadata,
856 std::forward<ArgsTy>(Args)...);
865 RetvalOriginTLS =
nullptr;
867 ParamOriginTLS =
nullptr;
869 VAArgOriginTLS =
nullptr;
870 VAArgOverflowSizeTLS =
nullptr;
872 WarningFn =
M.getOrInsertFunction(
"__msan_warning",
874 IRB.getVoidTy(), IRB.getInt32Ty());
885 MsanGetContextStateFn =
886 M.getOrInsertFunction(
"__msan_get_context_state", PtrTy);
890 for (
int ind = 0,
size = 1; ind < 4; ind++,
size <<= 1) {
891 std::string name_load =
892 "__msan_metadata_ptr_for_load_" + std::to_string(
size);
893 std::string name_store =
894 "__msan_metadata_ptr_for_store_" + std::to_string(
size);
895 MsanMetadataPtrForLoad_1_8[ind] =
896 getOrInsertMsanMetadataFunction(M, name_load, PtrTy);
897 MsanMetadataPtrForStore_1_8[ind] =
898 getOrInsertMsanMetadataFunction(M, name_store, PtrTy);
901 MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
902 M,
"__msan_metadata_ptr_for_load_n", PtrTy, IntptrTy);
903 MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
904 M,
"__msan_metadata_ptr_for_store_n", PtrTy, IntptrTy);
907 MsanPoisonAllocaFn =
M.getOrInsertFunction(
908 "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
909 MsanUnpoisonAllocaFn =
M.getOrInsertFunction(
910 "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
914 return M.getOrInsertGlobal(Name, Ty, [&] {
916 nullptr, Name,
nullptr,
922void MemorySanitizer::createUserspaceApi(
Module &M,
930 StringRef WarningFnName = Recover ?
"__msan_warning_with_origin"
931 :
"__msan_warning_with_origin_noreturn";
932 WarningFn =
M.getOrInsertFunction(WarningFnName,
934 IRB.getVoidTy(), IRB.getInt32Ty());
937 Recover ?
"__msan_warning" :
"__msan_warning_noreturn";
938 WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
965 IRB.getIntPtrTy(
M.getDataLayout()));
969 unsigned AccessSize = 1 << AccessSizeIndex;
970 std::string FunctionName =
"__msan_maybe_warning_" +
itostr(AccessSize);
971 MaybeWarningFn[AccessSizeIndex] =
M.getOrInsertFunction(
973 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
974 MaybeWarningVarSizeFn =
M.getOrInsertFunction(
975 "__msan_maybe_warning_N", TLI.
getAttrList(
C, {},
false),
976 IRB.getVoidTy(), PtrTy, IRB.getInt64Ty(), IRB.getInt32Ty());
977 FunctionName =
"__msan_maybe_store_origin_" +
itostr(AccessSize);
978 MaybeStoreOriginFn[AccessSizeIndex] =
M.getOrInsertFunction(
980 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
984 MsanSetAllocaOriginWithDescriptionFn =
985 M.getOrInsertFunction(
"__msan_set_alloca_origin_with_descr",
986 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
987 MsanSetAllocaOriginNoDescriptionFn =
988 M.getOrInsertFunction(
"__msan_set_alloca_origin_no_descr",
989 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
990 MsanPoisonStackFn =
M.getOrInsertFunction(
"__msan_poison_stack",
991 IRB.getVoidTy(), PtrTy, IntptrTy);
995void MemorySanitizer::initializeCallbacks(
Module &M,
998 if (CallbacksInitialized)
1004 MsanChainOriginFn =
M.getOrInsertFunction(
1005 "__msan_chain_origin",
1006 TLI.
getAttrList(
C, {0},
false,
true), IRB.getInt32Ty(),
1008 MsanSetOriginFn =
M.getOrInsertFunction(
1010 IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
1012 M.getOrInsertFunction(
"__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1014 M.getOrInsertFunction(
"__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1015 MemsetFn =
M.getOrInsertFunction(
"__msan_memset",
1017 PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1019 MsanInstrumentAsmStoreFn =
M.getOrInsertFunction(
1020 "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
1022 if (CompileKernel) {
1023 createKernelApi(M, TLI);
1025 createUserspaceApi(M, TLI);
1027 CallbacksInitialized =
true;
1033 isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
1051void MemorySanitizer::initializeModule(
Module &M) {
1052 auto &
DL =
M.getDataLayout();
1054 TargetTriple =
M.getTargetTriple();
1056 bool ShadowPassed =
ClShadowBase.getNumOccurrences() > 0;
1057 bool OriginPassed =
ClOriginBase.getNumOccurrences() > 0;
1059 if (ShadowPassed || OriginPassed) {
1064 MapParams = &CustomMapParams;
1066 switch (TargetTriple.getOS()) {
1068 switch (TargetTriple.getArch()) {
1083 switch (TargetTriple.getArch()) {
1092 switch (TargetTriple.getArch()) {
1129 C = &(
M.getContext());
1131 IntptrTy = IRB.getIntPtrTy(
DL);
1132 OriginTy = IRB.getInt32Ty();
1133 PtrTy = IRB.getPtrTy();
1138 if (!CompileKernel) {
1140 M.getOrInsertGlobal(
"__msan_track_origins", IRB.getInt32Ty(), [&] {
1141 return new GlobalVariable(
1142 M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1143 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
1147 M.getOrInsertGlobal(
"__msan_keep_going", IRB.getInt32Ty(), [&] {
1148 return new GlobalVariable(M, IRB.getInt32Ty(), true,
1149 GlobalValue::WeakODRLinkage,
1150 IRB.getInt32(Recover),
"__msan_keep_going");
1165struct VarArgHelper {
1166 virtual ~VarArgHelper() =
default;
1169 virtual void visitCallBase(CallBase &CB,
IRBuilder<> &IRB) = 0;
1172 virtual void visitVAStartInst(VAStartInst &
I) = 0;
1175 virtual void visitVACopyInst(VACopyInst &
I) = 0;
1181 virtual void finalizeInstrumentation() = 0;
1184struct MemorySanitizerVisitor;
1189 MemorySanitizerVisitor &Visitor);
1196 if (TypeSizeFixed <= 8)
1205class NextNodeIRBuilder :
public IRBuilder<> {
1218struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
1220 MemorySanitizer &MS;
1222 ValueMap<Value *, Value *> ShadowMap, OriginMap;
1223 std::unique_ptr<VarArgHelper> VAHelper;
1224 const TargetLibraryInfo *TLI;
1231 bool PropagateShadow;
1234 bool PoisonUndefVectors;
1236 struct ShadowOriginAndInsertPoint {
1241 ShadowOriginAndInsertPoint(
Value *S,
Value *O, Instruction *
I)
1242 : Shadow(S), Origin(
O), OrigIns(
I) {}
1245 DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
1246 SmallSetVector<AllocaInst *, 16> AllocaSet;
1249 int64_t SplittableBlocksCount = 0;
1251 MemorySanitizerVisitor(Function &
F, MemorySanitizer &MS,
1252 const TargetLibraryInfo &TLI)
1254 bool SanitizeFunction =
1256 InsertChecks = SanitizeFunction;
1257 PropagateShadow = SanitizeFunction;
1268 MS.initializeCallbacks(*
F.getParent(), TLI);
1270 IRBuilder<>(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt())
1271 .CreateIntrinsic(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());
1804 Type *getPtrToShadowPtrType(
Type *IntPtrTy,
Type *ShadowTy)
const {
1806 return VectorType::get(
1807 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1808 VectTy->getElementCount());
1810 assert(IntPtrTy == MS.IntptrTy);
1817 VectTy->getElementCount(),
1818 constToIntPtr(VectTy->getElementType(),
C));
1820 assert(IntPtrTy == MS.IntptrTy);
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));
2619 void visitFPToSIInst(CastInst &
I) { handleShadowOr(
I); }
2620 void visitFPToUIInst(CastInst &
I) { handleShadowOr(
I); }
2621 void visitSIToFPInst(CastInst &
I) { handleShadowOr(
I); }
2622 void visitUIToFPInst(CastInst &
I) { handleShadowOr(
I); }
2623 void visitFPExtInst(CastInst &
I) { handleShadowOr(
I); }
2624 void visitFPTruncInst(CastInst &
I) { handleShadowOr(
I); }
2655 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2659 void visitAnd(BinaryOperator &
I) {
2661 Value *V1 =
I.getOperand(0);
2662 Value *V2 =
I.getOperand(1);
2664 Value *S2 = getShadow(&
I, 1);
2666 Value *OutShadow = handleBitwiseAnd(IRB, V1, V2,
S1, S2);
2668 setShadow(&
I, OutShadow);
2669 setOriginForNaryOp(
I);
2672 void visitOr(BinaryOperator &
I) {
2685 Value *S2 = getShadow(&
I, 1);
2686 Value *V1 =
I.getOperand(0);
2687 Value *V2 =
I.getOperand(1);
2711 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2715 setOriginForNaryOp(
I);
2733 template <
bool CombineShadow>
class Combiner {
2734 Value *Shadow =
nullptr;
2735 Value *Origin =
nullptr;
2737 MemorySanitizerVisitor *MSV;
2740 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2741 : IRB(IRB), MSV(MSV) {}
2745 if (CombineShadow) {
2750 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2751 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2755 if (MSV->MS.TrackOrigins) {
2762 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2763 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2773 Value *OpShadow = MSV->getShadow(V);
2774 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2775 return Add(OpShadow, OpOrigin);
2780 void Done(Instruction *
I) {
2781 if (CombineShadow) {
2783 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2784 MSV->setShadow(
I, Shadow);
2786 if (MSV->MS.TrackOrigins) {
2788 MSV->setOrigin(
I, Origin);
2794 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2795 if (MSV->MS.TrackOrigins) {
2802 using ShadowAndOriginCombiner = Combiner<true>;
2803 using OriginCombiner = Combiner<false>;
2806 void setOriginForNaryOp(Instruction &
I) {
2807 if (!MS.TrackOrigins)
2810 OriginCombiner OC(
this, IRB);
2811 for (Use &
Op :
I.operands())
2816 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2818 "Vector of pointers is not a valid shadow type");
2828 Type *srcTy =
V->getType();
2831 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2832 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2833 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2851 Type *ShadowTy = getShadowTy(V);
2852 if (
V->getType() == ShadowTy)
2854 if (
V->getType()->isPtrOrPtrVectorTy())
2861 void handleShadowOr(Instruction &
I) {
2863 ShadowAndOriginCombiner SC(
this, IRB);
2864 for (Use &
Op :
I.operands())
2891 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2892 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2897 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2903 assert(NumElems % (ReductionFactor * Shards) == 0);
2908 for (
unsigned i = 0; i < ReductionFactor; i++) {
2909 SmallVector<int, 16>
Mask;
2911 for (
unsigned j = 0;
j < Shards;
j++) {
2912 unsigned Offset = NumElems / Shards *
j;
2914 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2918 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2943 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
2944 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2946 assert(
I.getType()->isVectorTy());
2947 assert(
I.getArgOperand(0)->getType()->isVectorTy());
2949 [[maybe_unused]] FixedVectorType *ParamType =
2953 [[maybe_unused]] FixedVectorType *
ReturnType =
2961 Value *FirstArgShadow = getShadow(&
I, 0);
2962 Value *SecondArgShadow =
nullptr;
2963 if (
I.arg_size() == 2)
2964 SecondArgShadow = getShadow(&
I, 1);
2966 Value *OrShadow = horizontalReduce(
I, 2, Shards,
2967 FirstArgShadow, SecondArgShadow);
2969 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
2971 setShadow(&
I, OrShadow);
2972 setOriginForNaryOp(
I);
2982 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
2983 int ReinterpretElemWidth) {
2984 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2986 assert(
I.getType()->isVectorTy());
2987 assert(
I.getArgOperand(0)->getType()->isVectorTy());
2989 FixedVectorType *ParamType =
2994 [[maybe_unused]] FixedVectorType *
ReturnType =
3001 FixedVectorType *ReinterpretShadowTy =
nullptr;
3009 Value *FirstArgShadow = getShadow(&
I, 0);
3010 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3020 Value *SecondArgShadow =
nullptr;
3021 if (
I.arg_size() == 2) {
3022 SecondArgShadow = getShadow(&
I, 1);
3023 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3026 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3027 FirstArgShadow, SecondArgShadow);
3029 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3031 setShadow(&
I, OrShadow);
3032 setOriginForNaryOp(
I);
3035 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3046 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3052 Type *EltTy = VTy->getElementType();
3054 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3055 if (ConstantInt *Elt =
3057 const APInt &
V = Elt->getValue();
3058 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3059 Elements.push_back(ConstantInt::get(EltTy, V2));
3061 Elements.push_back(ConstantInt::get(EltTy, 1));
3067 const APInt &
V = Elt->getValue();
3068 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3069 ShadowMul = ConstantInt::get(Ty, V2);
3071 ShadowMul = ConstantInt::get(Ty, 1);
3077 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3078 setOrigin(&
I, getOrigin(OtherArg));
3081 void visitMul(BinaryOperator &
I) {
3084 if (constOp0 && !constOp1)
3085 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3086 else if (constOp1 && !constOp0)
3087 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3092 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3093 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3094 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3095 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3096 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3097 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3099 void handleIntegerDiv(Instruction &
I) {
3102 insertCheckShadowOf(
I.getOperand(1), &
I);
3103 setShadow(&
I, getShadow(&
I, 0));
3104 setOrigin(&
I, getOrigin(&
I, 0));
3107 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3108 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3109 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3110 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3114 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3115 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3121 void handleEqualityComparison(ICmpInst &
I) {
3125 Value *Sa = getShadow(
A);
3126 Value *Sb = getShadow(
B);
3128 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3131 setOriginForNaryOp(
I);
3139 void handleRelationalComparisonExact(ICmpInst &
I) {
3143 Value *Sa = getShadow(
A);
3144 Value *Sb = getShadow(
B);
3155 bool IsSigned =
I.isSigned();
3157 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3167 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3172 return std::make_pair(Min, Max);
3175 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3176 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3182 setOriginForNaryOp(
I);
3189 void handleSignedRelationalComparison(ICmpInst &
I) {
3194 op =
I.getOperand(0);
3195 pre =
I.getPredicate();
3197 op =
I.getOperand(1);
3198 pre =
I.getSwappedPredicate();
3211 setShadow(&
I, Shadow);
3212 setOrigin(&
I, getOrigin(
op));
3218 void visitICmpInst(ICmpInst &
I) {
3223 if (
I.isEquality()) {
3224 handleEqualityComparison(
I);
3230 handleRelationalComparisonExact(
I);
3234 handleSignedRelationalComparison(
I);
3240 handleRelationalComparisonExact(
I);
3247 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3249 void handleShift(BinaryOperator &
I) {
3254 Value *S2 = getShadow(&
I, 1);
3257 Value *V2 =
I.getOperand(1);
3259 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3260 setOriginForNaryOp(
I);
3263 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3264 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3265 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3267 void handleFunnelShift(IntrinsicInst &
I) {
3271 Value *S0 = getShadow(&
I, 0);
3273 Value *S2 = getShadow(&
I, 2);
3276 Value *V2 =
I.getOperand(2);
3279 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3280 setOriginForNaryOp(
I);
3293 void visitMemMoveInst(MemMoveInst &
I) {
3294 getShadow(
I.getArgOperand(1));
3297 {I.getArgOperand(0), I.getArgOperand(1),
3298 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3316 void visitMemCpyInst(MemCpyInst &
I) {
3317 getShadow(
I.getArgOperand(1));
3320 {I.getArgOperand(0), I.getArgOperand(1),
3321 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3326 void visitMemSetInst(MemSetInst &
I) {
3330 {I.getArgOperand(0),
3331 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3332 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3336 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3338 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3344 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3348 Value *Addr =
I.getArgOperand(0);
3349 Value *Shadow = getShadow(&
I, 1);
3350 Value *ShadowPtr, *OriginPtr;
3354 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3359 insertCheckShadowOf(Addr, &
I);
3362 if (MS.TrackOrigins)
3371 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3375 Value *Addr =
I.getArgOperand(0);
3377 Type *ShadowTy = getShadowTy(&
I);
3378 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3379 if (PropagateShadow) {
3383 std::tie(ShadowPtr, OriginPtr) =
3384 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3388 setShadow(&
I, getCleanShadow(&
I));
3392 insertCheckShadowOf(Addr, &
I);
3394 if (MS.TrackOrigins) {
3395 if (PropagateShadow)
3396 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3398 setOrigin(&
I, getCleanOrigin());
3418 [[maybe_unused]]
bool
3419 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3420 unsigned int trailingFlags) {
3421 Type *RetTy =
I.getType();
3425 unsigned NumArgOperands =
I.arg_size();
3426 assert(NumArgOperands >= trailingFlags);
3427 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3428 Type *Ty =
I.getArgOperand(i)->getType();
3434 ShadowAndOriginCombiner SC(
this, IRB);
3435 for (
unsigned i = 0; i < NumArgOperands; ++i)
3436 SC.Add(
I.getArgOperand(i));
3453 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3454 unsigned NumArgOperands =
I.arg_size();
3455 if (NumArgOperands == 0)
3458 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3459 I.getArgOperand(1)->getType()->isVectorTy() &&
3460 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3462 return handleVectorStoreIntrinsic(
I);
3465 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3466 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3468 return handleVectorLoadIntrinsic(
I);
3471 if (
I.doesNotAccessMemory())
3472 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3480 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3481 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3483 dumpInst(
I,
"Heuristic");
3485 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3492 void handleInvariantGroup(IntrinsicInst &
I) {
3493 setShadow(&
I, getShadow(&
I, 0));
3494 setOrigin(&
I, getOrigin(&
I, 0));
3497 void handleLifetimeStart(IntrinsicInst &
I) {
3502 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3505 void handleBswap(IntrinsicInst &
I) {
3508 Type *OpType =
Op->getType();
3511 setOrigin(&
I, getOrigin(
Op));
3532 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3534 Value *Src =
I.getArgOperand(0);
3535 Value *SrcShadow = getShadow(Src);
3539 I.getType(),
I.getIntrinsicID(), {Src, False});
3541 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3544 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3546 Value *NotAllZeroShadow =
3548 Value *OutputShadow =
3549 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3555 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3558 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3560 setShadow(&
I, OutputShadow);
3561 setOriginForNaryOp(
I);
3576 void handleNEONVectorConvertIntrinsic(IntrinsicInst &
I,
bool FixedPoint) {
3583 Value *S0 = getShadow(&
I, 0);
3586 Value *Precision =
I.getOperand(1);
3587 insertCheckShadowOf(Precision, &
I);
3597 setShadow(&
I, OutShadow);
3598 setOriginForNaryOp(
I);
3607 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3627 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3632 Value *FullShadow = getCleanShadow(&
I);
3633 unsigned ShadowNumElems =
3635 unsigned FullShadowNumElems =
3638 assert((ShadowNumElems == FullShadowNumElems) ||
3639 (ShadowNumElems * 2 == FullShadowNumElems));
3641 if (ShadowNumElems == FullShadowNumElems) {
3642 FullShadow = Shadow;
3646 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3671 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3672 bool HasRoundingMode) {
3673 if (HasRoundingMode) {
3681 Value *Src =
I.getArgOperand(0);
3682 assert(Src->getType()->isVectorTy());
3686 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3689 Value *S0 = getShadow(&
I, 0);
3701 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3703 setShadow(&
I, FullShadow);
3704 setOriginForNaryOp(
I);
3725 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3726 bool HasRoundingMode =
false) {
3728 Value *CopyOp, *ConvertOp;
3730 assert((!HasRoundingMode ||
3732 "Invalid rounding mode");
3734 switch (
I.arg_size() - HasRoundingMode) {
3736 CopyOp =
I.getArgOperand(0);
3737 ConvertOp =
I.getArgOperand(1);
3740 ConvertOp =
I.getArgOperand(0);
3754 Value *ConvertShadow = getShadow(ConvertOp);
3755 Value *AggShadow =
nullptr;
3758 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3759 for (
int i = 1; i < NumUsedElements; ++i) {
3761 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3762 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3765 AggShadow = ConvertShadow;
3768 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3775 Value *ResultShadow = getShadow(CopyOp);
3777 for (
int i = 0; i < NumUsedElements; ++i) {
3779 ResultShadow, ConstantInt::getNullValue(EltTy),
3782 setShadow(&
I, ResultShadow);
3783 setOrigin(&
I, getOrigin(CopyOp));
3785 setShadow(&
I, getCleanShadow(&
I));
3786 setOrigin(&
I, getCleanOrigin());
3794 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3797 return CreateShadowCast(IRB, S2,
T,
true);
3805 return CreateShadowCast(IRB, S2,
T,
true);
3822 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3828 Value *S2 = getShadow(&
I, 1);
3830 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3831 Value *V1 =
I.getOperand(0);
3832 Value *V2 =
I.getOperand(1);
3834 {IRB.CreateBitCast(S1, V1->getType()), V2});
3836 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3837 setOriginForNaryOp(
I);
3842 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3843 unsigned X86_MMXSizeInBits = 64) {
3844 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3845 "Illegal MMX vector element size");
3847 X86_MMXSizeInBits / EltSizeInBits);
3854 case Intrinsic::x86_sse2_packsswb_128:
3855 case Intrinsic::x86_sse2_packuswb_128:
3856 return Intrinsic::x86_sse2_packsswb_128;
3858 case Intrinsic::x86_sse2_packssdw_128:
3859 case Intrinsic::x86_sse41_packusdw:
3860 return Intrinsic::x86_sse2_packssdw_128;
3862 case Intrinsic::x86_avx2_packsswb:
3863 case Intrinsic::x86_avx2_packuswb:
3864 return Intrinsic::x86_avx2_packsswb;
3866 case Intrinsic::x86_avx2_packssdw:
3867 case Intrinsic::x86_avx2_packusdw:
3868 return Intrinsic::x86_avx2_packssdw;
3870 case Intrinsic::x86_mmx_packsswb:
3871 case Intrinsic::x86_mmx_packuswb:
3872 return Intrinsic::x86_mmx_packsswb;
3874 case Intrinsic::x86_mmx_packssdw:
3875 return Intrinsic::x86_mmx_packssdw;
3877 case Intrinsic::x86_avx512_packssdw_512:
3878 case Intrinsic::x86_avx512_packusdw_512:
3879 return Intrinsic::x86_avx512_packssdw_512;
3881 case Intrinsic::x86_avx512_packsswb_512:
3882 case Intrinsic::x86_avx512_packuswb_512:
3883 return Intrinsic::x86_avx512_packsswb_512;
3899 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3900 unsigned MMXEltSizeInBits = 0) {
3904 Value *S2 = getShadow(&
I, 1);
3905 assert(
S1->getType()->isVectorTy());
3911 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3912 if (MMXEltSizeInBits) {
3920 if (MMXEltSizeInBits) {
3926 {S1_ext, S2_ext},
nullptr,
3927 "_msprop_vector_pack");
3928 if (MMXEltSizeInBits)
3931 setOriginForNaryOp(
I);
3935 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3936 SmallVector<Constant *, 4>
R(Width);
3948 const unsigned Width =
3955 Value *DstMaskV = createDppMask(Width, DstMask);
3972 void handleDppIntrinsic(IntrinsicInst &
I) {
3975 Value *S0 = getShadow(&
I, 0);
3979 const unsigned Width =
3981 assert(Width == 2 || Width == 4 || Width == 8);
3984 const unsigned SrcMask =
Mask >> 4;
3985 const unsigned DstMask =
Mask & 0xf;
3988 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
3993 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4000 setOriginForNaryOp(
I);
4004 C = CreateAppToShadowCast(IRB,
C);
4013 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4018 Value *Sc = getShadow(&
I, 2);
4019 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4024 C = convertBlendvToSelectMask(IRB,
C);
4025 Sc = convertBlendvToSelectMask(IRB, Sc);
4031 handleSelectLikeInst(
I,
C,
T,
F);
4035 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4036 const unsigned SignificantBitsPerResultElement = 16;
4038 unsigned ZeroBitsPerResultElement =
4042 auto *Shadow0 = getShadow(&
I, 0);
4043 auto *Shadow1 = getShadow(&
I, 1);
4048 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4051 setOriginForNaryOp(
I);
4075 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4076 unsigned ReductionFactor,
4078 unsigned EltSizeInBits,
4082 [[maybe_unused]] FixedVectorType *
ReturnType =
4087 Value *Va =
nullptr;
4088 Value *Vb =
nullptr;
4089 Value *Sa =
nullptr;
4090 Value *Sb =
nullptr;
4092 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4093 if (
I.arg_size() == 2) {
4096 Va =
I.getOperand(0);
4097 Vb =
I.getOperand(1);
4099 Sa = getShadow(&
I, 0);
4100 Sb = getShadow(&
I, 1);
4101 }
else if (
I.arg_size() == 3) {
4103 Va =
I.getOperand(1);
4104 Vb =
I.getOperand(2);
4106 Sa = getShadow(&
I, 1);
4107 Sb = getShadow(&
I, 2);
4124 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4126 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4136 if (
I.arg_size() == 3) {
4137 [[maybe_unused]]
auto *AccumulatorType =
4139 assert(AccumulatorType == ReturnType);
4142 FixedVectorType *ImplicitReturnType =
4145 if (EltSizeInBits) {
4147 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4159 ReturnType->getNumElements() * ReductionFactor);
4176 VaInt = CreateAppToShadowCast(IRB, Va);
4177 VbInt = CreateAppToShadowCast(IRB, Vb);
4184 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4206 ImplicitReturnType);
4211 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4214 if (
I.arg_size() == 3)
4215 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4217 setShadow(&
I, OutShadow);
4218 setOriginForNaryOp(
I);
4235 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4236 bool PredicateAsOperand) {
4237 if (PredicateAsOperand) {
4239 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4247 Type *ResTy = getShadowTy(&
I);
4248 auto *Shadow0 = getShadow(&
I, 0);
4249 auto *Shadow1 = getShadow(&
I, 1);
4254 setOriginForNaryOp(
I);
4260 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4262 auto *Shadow0 = getShadow(&
I, 0);
4263 auto *Shadow1 = getShadow(&
I, 1);
4265 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4267 setOriginForNaryOp(
I);
4276 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4281 if (AllowShadowCast)
4282 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4286 setOriginForNaryOp(
I);
4296 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4300 Value *Shadow0 = getShadow(&
I, 0);
4306 setOriginForNaryOp(
I);
4312 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4316 Value *OperandShadow = getShadow(&
I, 0);
4318 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4326 setOrigin(&
I, getOrigin(&
I, 0));
4332 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4336 Value *OperandShadow = getShadow(&
I, 0);
4337 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4345 setOrigin(&
I, getOrigin(&
I, 0));
4348 void handleStmxcsr(IntrinsicInst &
I) {
4350 Value *Addr =
I.getArgOperand(0);
4353 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4358 insertCheckShadowOf(Addr, &
I);
4361 void handleLdmxcsr(IntrinsicInst &
I) {
4366 Value *Addr =
I.getArgOperand(0);
4369 Value *ShadowPtr, *OriginPtr;
4370 std::tie(ShadowPtr, OriginPtr) =
4371 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4374 insertCheckShadowOf(Addr, &
I);
4377 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4379 insertCheckShadow(Shadow, Origin, &
I);
4382 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4384 Value *Ptr =
I.getArgOperand(0);
4385 MaybeAlign
Align =
I.getParamAlign(0);
4387 Value *PassThru =
I.getArgOperand(2);
4390 insertCheckShadowOf(Ptr, &
I);
4391 insertCheckShadowOf(Mask, &
I);
4394 if (!PropagateShadow) {
4395 setShadow(&
I, getCleanShadow(&
I));
4396 setOrigin(&
I, getCleanOrigin());
4400 Type *ShadowTy = getShadowTy(&
I);
4402 auto [ShadowPtr, OriginPtr] =
4403 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4407 getShadow(PassThru),
"_msmaskedexpload");
4409 setShadow(&
I, Shadow);
4412 setOrigin(&
I, getCleanOrigin());
4415 void handleMaskedCompressStore(IntrinsicInst &
I) {
4417 Value *Values =
I.getArgOperand(0);
4418 Value *Ptr =
I.getArgOperand(1);
4419 MaybeAlign
Align =
I.getParamAlign(1);
4423 insertCheckShadowOf(Ptr, &
I);
4424 insertCheckShadowOf(Mask, &
I);
4427 Value *Shadow = getShadow(Values);
4428 Type *ElementShadowTy =
4430 auto [ShadowPtr, OriginPtrs] =
4431 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4438 void handleMaskedGather(IntrinsicInst &
I) {
4440 Value *Ptrs =
I.getArgOperand(0);
4441 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4443 Value *PassThru =
I.getArgOperand(2);
4445 Type *PtrsShadowTy = getShadowTy(Ptrs);
4447 insertCheckShadowOf(Mask, &
I);
4451 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4454 if (!PropagateShadow) {
4455 setShadow(&
I, getCleanShadow(&
I));
4456 setOrigin(&
I, getCleanOrigin());
4460 Type *ShadowTy = getShadowTy(&
I);
4462 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4463 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4467 getShadow(PassThru),
"_msmaskedgather");
4469 setShadow(&
I, Shadow);
4472 setOrigin(&
I, getCleanOrigin());
4475 void handleMaskedScatter(IntrinsicInst &
I) {
4477 Value *Values =
I.getArgOperand(0);
4478 Value *Ptrs =
I.getArgOperand(1);
4479 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4482 Type *PtrsShadowTy = getShadowTy(Ptrs);
4484 insertCheckShadowOf(Mask, &
I);
4488 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4491 Value *Shadow = getShadow(Values);
4492 Type *ElementShadowTy =
4494 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4495 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4506 void handleMaskedStore(IntrinsicInst &
I) {
4508 Value *
V =
I.getArgOperand(0);
4509 Value *Ptr =
I.getArgOperand(1);
4510 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4512 Value *Shadow = getShadow(V);
4515 insertCheckShadowOf(Ptr, &
I);
4516 insertCheckShadowOf(Mask, &
I);
4521 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4522 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4526 if (!MS.TrackOrigins)
4529 auto &
DL =
F.getDataLayout();
4530 paintOrigin(IRB, getOrigin(V), OriginPtr,
4539 void handleMaskedLoad(IntrinsicInst &
I) {
4541 Value *Ptr =
I.getArgOperand(0);
4542 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4544 Value *PassThru =
I.getArgOperand(2);
4547 insertCheckShadowOf(Ptr, &
I);
4548 insertCheckShadowOf(Mask, &
I);
4551 if (!PropagateShadow) {
4552 setShadow(&
I, getCleanShadow(&
I));
4553 setOrigin(&
I, getCleanOrigin());
4557 Type *ShadowTy = getShadowTy(&
I);
4558 Value *ShadowPtr, *OriginPtr;
4559 std::tie(ShadowPtr, OriginPtr) =
4560 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4562 getShadow(PassThru),
"_msmaskedld"));
4564 if (!MS.TrackOrigins)
4571 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4576 setOrigin(&
I, Origin);
4592 void handleAVXMaskedStore(IntrinsicInst &
I) {
4597 Value *Dst =
I.getArgOperand(0);
4598 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4603 Value *Src =
I.getArgOperand(2);
4608 Value *SrcShadow = getShadow(Src);
4611 insertCheckShadowOf(Dst, &
I);
4612 insertCheckShadowOf(Mask, &
I);
4615 Value *DstShadowPtr;
4616 Value *DstOriginPtr;
4617 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4618 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4620 SmallVector<Value *, 2> ShadowArgs;
4621 ShadowArgs.
append(1, DstShadowPtr);
4622 ShadowArgs.
append(1, Mask);
4633 if (!MS.TrackOrigins)
4637 auto &
DL =
F.getDataLayout();
4638 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4639 DL.getTypeStoreSize(SrcShadow->
getType()),
4658 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4663 Value *Src =
I.getArgOperand(0);
4664 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4672 insertCheckShadowOf(Mask, &
I);
4675 Type *SrcShadowTy = getShadowTy(Src);
4676 Value *SrcShadowPtr, *SrcOriginPtr;
4677 std::tie(SrcShadowPtr, SrcOriginPtr) =
4678 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4680 SmallVector<Value *, 2> ShadowArgs;
4681 ShadowArgs.
append(1, SrcShadowPtr);
4682 ShadowArgs.
append(1, Mask);
4691 if (!MS.TrackOrigins)
4698 setOrigin(&
I, PtrSrcOrigin);
4707 assert(isFixedIntVector(Idx));
4708 auto IdxVectorSize =
4716 auto *IdxShadow = getShadow(Idx);
4721 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4726 void handleAVXVpermilvar(IntrinsicInst &
I) {
4728 Value *Shadow = getShadow(&
I, 0);
4729 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4733 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4735 {Shadow, I.getArgOperand(1)});
4738 setOriginForNaryOp(
I);
4743 void handleAVXVpermi2var(IntrinsicInst &
I) {
4748 [[maybe_unused]]
auto ArgVectorSize =
4751 ->getNumElements() == ArgVectorSize);
4753 ->getNumElements() == ArgVectorSize);
4754 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4755 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4756 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4758 Value *AShadow = getShadow(&
I, 0);
4759 Value *Idx =
I.getArgOperand(1);
4760 Value *BShadow = getShadow(&
I, 2);
4762 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4766 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4767 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4769 {AShadow, Idx, BShadow});
4771 setOriginForNaryOp(
I);
4774 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4778 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4782 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4783 return isFixedIntVectorTy(
V->getType());
4786 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4787 return isFixedFPVectorTy(
V->getType());
4809 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4814 Value *WriteThrough;
4818 WriteThrough =
I.getOperand(2);
4819 Mask =
I.getOperand(3);
4822 WriteThrough =
I.getOperand(1);
4823 Mask =
I.getOperand(2);
4828 assert(isFixedIntVector(WriteThrough));
4830 unsigned ANumElements =
4832 [[maybe_unused]]
unsigned WriteThruNumElements =
4834 assert(ANumElements == WriteThruNumElements ||
4835 ANumElements * 2 == WriteThruNumElements);
4838 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4839 assert(ANumElements == MaskNumElements ||
4840 ANumElements * 2 == MaskNumElements);
4842 assert(WriteThruNumElements == MaskNumElements);
4846 insertCheckShadowOf(Mask, &
I);
4856 Value *AShadow = getShadow(
A);
4857 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4859 if (ANumElements * 2 == MaskNumElements) {
4871 "_ms_mask_bitcast");
4881 getShadowTy(&
I),
"_ms_a_shadow");
4883 Value *WriteThroughShadow = getShadow(WriteThrough);
4885 "_ms_writethru_select");
4887 setShadow(&
I, Shadow);
4888 setOriginForNaryOp(
I);
4896 void handleBmiIntrinsic(IntrinsicInst &
I) {
4898 Type *ShadowTy = getShadowTy(&
I);
4901 Value *SMask = getShadow(&
I, 1);
4906 {getShadow(&I, 0), I.getOperand(1)});
4909 setOriginForNaryOp(
I);
4912 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4913 SmallVector<int, 8>
Mask;
4914 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4928 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4933 "pclmul 3rd operand must be a constant");
4936 getPclmulMask(Width, Imm & 0x01));
4938 getPclmulMask(Width, Imm & 0x10));
4939 ShadowAndOriginCombiner SOC(
this, IRB);
4940 SOC.Add(Shuf0, getOrigin(&
I, 0));
4941 SOC.Add(Shuf1, getOrigin(&
I, 1));
4946 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4951 Value *Second = getShadow(&
I, 1);
4953 SmallVector<int, 16>
Mask;
4954 Mask.push_back(Width);
4955 for (
unsigned i = 1; i < Width; i++)
4959 setShadow(&
I, Shadow);
4960 setOriginForNaryOp(
I);
4963 void handleVtestIntrinsic(IntrinsicInst &
I) {
4965 Value *Shadow0 = getShadow(&
I, 0);
4966 Value *Shadow1 = getShadow(&
I, 1);
4972 setShadow(&
I, Shadow);
4973 setOriginForNaryOp(
I);
4976 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
4981 Value *Second = getShadow(&
I, 1);
4984 SmallVector<int, 16>
Mask;
4985 Mask.push_back(Width);
4986 for (
unsigned i = 1; i < Width; i++)
4990 setShadow(&
I, Shadow);
4991 setOriginForNaryOp(
I);
4997 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
4998 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5003 ShadowAndOriginCombiner SC(
this, IRB);
5004 SC.Add(
I.getArgOperand(0));
5012 void handleAbsIntrinsic(IntrinsicInst &
I) {
5014 Value *Src =
I.getArgOperand(0);
5015 Value *IsIntMinPoison =
I.getArgOperand(1);
5017 assert(
I.getType()->isIntOrIntVectorTy());
5019 assert(Src->getType() ==
I.getType());
5025 Value *SrcShadow = getShadow(Src);
5029 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5032 Value *PoisonedShadow = getPoisonedShadow(Src);
5033 Value *PoisonedIfIntMinShadow =
5036 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5038 setShadow(&
I, Shadow);
5039 setOrigin(&
I, getOrigin(&
I, 0));
5042 void handleIsFpClass(IntrinsicInst &
I) {
5044 Value *Shadow = getShadow(&
I, 0);
5045 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5046 setOrigin(&
I, getOrigin(&
I, 0));
5049 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5051 Value *Shadow0 = getShadow(&
I, 0);
5052 Value *Shadow1 = getShadow(&
I, 1);
5055 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5061 setShadow(&
I, Shadow);
5062 setOriginForNaryOp(
I);
5068 Value *Shadow = getShadow(V);
5090 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5095 Value *WriteThrough =
I.getOperand(1);
5099 assert(isFixedIntVector(WriteThrough));
5101 unsigned ANumElements =
5103 unsigned OutputNumElements =
5105 assert(ANumElements == OutputNumElements ||
5106 ANumElements * 2 == OutputNumElements);
5116 insertCheckShadowOf(Mask, &
I);
5119 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5120 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5121 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5132 if (ANumElements != OutputNumElements) {
5134 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5141 Value *AShadow = getShadow(
A);
5145 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5155 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5156 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5158 Value *WriteThroughShadow = getShadow(WriteThrough);
5161 setShadow(&
I, Shadow);
5162 setOriginForNaryOp(
I);
5196 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5197 SmallVector<unsigned, 4> DataIndices,
5198 unsigned WriteThruIndex,
5199 unsigned MaskIndex) {
5202 unsigned NumArgs =
I.arg_size();
5204 assert(WriteThruIndex < NumArgs);
5205 assert(MaskIndex < NumArgs);
5206 assert(WriteThruIndex != MaskIndex);
5207 Value *WriteThru =
I.getOperand(WriteThruIndex);
5209 unsigned OutputNumElements =
5214 bool isData[16] = {
false};
5216 for (
unsigned i : DataIndices) {
5218 assert(i != WriteThruIndex);
5225 [[maybe_unused]]
unsigned ANumElements =
5227 assert(ANumElements == OutputNumElements);
5232 assert(isFixedFPVector(WriteThru));
5234 for (
unsigned i = 0; i < NumArgs; ++i) {
5235 if (!isData[i] && i != WriteThruIndex) {
5238 assert(
I.getOperand(i)->getType()->isIntegerTy());
5239 insertCheckShadowOf(
I.getOperand(i), &
I);
5244 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5245 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5246 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5253 Value *DataShadow =
nullptr;
5254 for (
unsigned i : DataIndices) {
5257 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5259 DataShadow = getShadow(
A);
5267 Value *WriteThruShadow = getShadow(WriteThru);
5270 setShadow(&
I, Shadow);
5272 setOriginForNaryOp(
I);
5282 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5288 Value *WriteThrough =
I.getOperand(2);
5295 insertCheckShadowOf(Mask, &
I);
5299 unsigned NumElements =
5301 assert(NumElements == 8);
5302 assert(
A->getType() ==
B->getType());
5304 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5307 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5308 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5310 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5312 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5319 Value *AShadow = getShadow(
A);
5320 Value *DstLowerShadow =
5321 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5323 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5326 setShadow(&
I, DstShadow);
5327 setOriginForNaryOp(
I);
5357 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5368 ->getScalarSizeInBits() == 8);
5370 assert(
A->getType() ==
X->getType());
5372 assert(
B->getType()->isIntegerTy());
5373 assert(
B->getType()->getScalarSizeInBits() == 8);
5375 assert(
I.getType() ==
A->getType());
5377 Value *AShadow = getShadow(
A);
5378 Value *XShadow = getShadow(
X);
5379 Value *BZeroShadow = getCleanShadow(
B);
5382 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5384 {X, AShadow, BZeroShadow});
5386 {XShadow, A, BZeroShadow});
5389 Value *BShadow = getShadow(
B);
5390 Value *BBroadcastShadow = getCleanShadow(AShadow);
5395 for (
unsigned i = 0; i < NumElements; i++)
5399 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5400 setOriginForNaryOp(
I);
5414 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5415 unsigned int numArgs =
I.arg_size();
5418 assert(
I.getType()->isStructTy());
5428 assert(4 <= numArgs && numArgs <= 6);
5442 for (
unsigned int i = 0; i < numArgs - 2; i++)
5443 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5446 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5450 insertCheckShadowOf(LaneNumber, &
I);
5453 Value *Src =
I.getArgOperand(numArgs - 1);
5454 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5456 Type *SrcShadowTy = getShadowTy(Src);
5457 auto [SrcShadowPtr, SrcOriginPtr] =
5458 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5468 if (!MS.TrackOrigins)
5472 setOrigin(&
I, PtrSrcOrigin);
5489 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5493 int numArgOperands =
I.arg_size();
5496 assert(numArgOperands >= 1);
5497 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5499 int skipTrailingOperands = 1;
5502 insertCheckShadowOf(Addr, &
I);
5506 skipTrailingOperands++;
5507 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5509 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5512 SmallVector<Value *, 8> ShadowArgs;
5514 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5516 Value *Shadow = getShadow(&
I, i);
5517 ShadowArgs.
append(1, Shadow);
5534 (numArgOperands - skipTrailingOperands));
5535 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5539 I.getArgOperand(numArgOperands - skipTrailingOperands));
5541 Value *OutputShadowPtr, *OutputOriginPtr;
5543 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5544 Addr, IRB, OutputShadowTy,
Align(1),
true);
5545 ShadowArgs.
append(1, OutputShadowPtr);
5551 if (MS.TrackOrigins) {
5559 OriginCombiner OC(
this, IRB);
5560 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5561 OC.Add(
I.getArgOperand(i));
5563 const DataLayout &
DL =
F.getDataLayout();
5564 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5597 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5601 Value *
R =
I.getArgOperand(0);
5602 Value *
A =
I.getArgOperand(1);
5603 Value *
B =
I.getArgOperand(2);
5605 assert(
I.getType() ==
R->getType());
5630 Value *ShadowR = getShadow(&
I, 0);
5631 Value *ShadowA = getShadow(&
I, 1);
5632 Value *ShadowB = getShadow(&
I, 2);
5650 {getCleanShadow(RTy), ShadowA, ShadowB});
5676 {RZeros, ShadowA, ShadowB});
5690 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5691 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5693 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5695 setOriginForNaryOp(
I);
5720 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5722 unsigned int trailingVerbatimArgs) {
5725 assert(trailingVerbatimArgs <
I.arg_size());
5727 SmallVector<Value *, 8> ShadowArgs;
5729 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5730 Value *Shadow = getShadow(&
I, i);
5738 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5740 Value *Arg =
I.getArgOperand(i);
5746 Value *CombinedShadow = CI;
5749 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5752 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5753 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5758 setOriginForNaryOp(
I);
5764 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5770 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5771 switch (
I.getIntrinsicID()) {
5772 case Intrinsic::uadd_with_overflow:
5773 case Intrinsic::sadd_with_overflow:
5774 case Intrinsic::usub_with_overflow:
5775 case Intrinsic::ssub_with_overflow:
5776 case Intrinsic::umul_with_overflow:
5777 case Intrinsic::smul_with_overflow:
5778 handleArithmeticWithOverflow(
I);
5780 case Intrinsic::abs:
5781 handleAbsIntrinsic(
I);
5783 case Intrinsic::bitreverse:
5784 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5787 case Intrinsic::is_fpclass:
5790 case Intrinsic::lifetime_start:
5791 handleLifetimeStart(
I);
5793 case Intrinsic::launder_invariant_group:
5794 case Intrinsic::strip_invariant_group:
5795 handleInvariantGroup(
I);
5797 case Intrinsic::bswap:
5800 case Intrinsic::ctlz:
5801 case Intrinsic::cttz:
5802 handleCountLeadingTrailingZeros(
I);
5804 case Intrinsic::masked_compressstore:
5805 handleMaskedCompressStore(
I);
5807 case Intrinsic::masked_expandload:
5808 handleMaskedExpandLoad(
I);
5810 case Intrinsic::masked_gather:
5811 handleMaskedGather(
I);
5813 case Intrinsic::masked_scatter:
5814 handleMaskedScatter(
I);
5816 case Intrinsic::masked_store:
5817 handleMaskedStore(
I);
5819 case Intrinsic::masked_load:
5820 handleMaskedLoad(
I);
5822 case Intrinsic::vector_reduce_and:
5823 handleVectorReduceAndIntrinsic(
I);
5825 case Intrinsic::vector_reduce_or:
5826 handleVectorReduceOrIntrinsic(
I);
5829 case Intrinsic::vector_reduce_add:
5830 case Intrinsic::vector_reduce_xor:
5831 case Intrinsic::vector_reduce_mul:
5834 case Intrinsic::vector_reduce_smax:
5835 case Intrinsic::vector_reduce_smin:
5836 case Intrinsic::vector_reduce_umax:
5837 case Intrinsic::vector_reduce_umin:
5840 case Intrinsic::vector_reduce_fmax:
5841 case Intrinsic::vector_reduce_fmin:
5842 handleVectorReduceIntrinsic(
I,
false);
5845 case Intrinsic::vector_reduce_fadd:
5846 case Intrinsic::vector_reduce_fmul:
5847 handleVectorReduceWithStarterIntrinsic(
I);
5850 case Intrinsic::scmp:
5851 case Intrinsic::ucmp: {
5856 case Intrinsic::fshl:
5857 case Intrinsic::fshr:
5858 handleFunnelShift(
I);
5861 case Intrinsic::is_constant:
5863 setShadow(&
I, getCleanShadow(&
I));
5864 setOrigin(&
I, getCleanOrigin());
5874 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5875 switch (
I.getIntrinsicID()) {
5876 case Intrinsic::x86_sse_stmxcsr:
5879 case Intrinsic::x86_sse_ldmxcsr:
5886 case Intrinsic::x86_avx512_vcvtsd2usi64:
5887 case Intrinsic::x86_avx512_vcvtsd2usi32:
5888 case Intrinsic::x86_avx512_vcvtss2usi64:
5889 case Intrinsic::x86_avx512_vcvtss2usi32:
5890 case Intrinsic::x86_avx512_cvttss2usi64:
5891 case Intrinsic::x86_avx512_cvttss2usi:
5892 case Intrinsic::x86_avx512_cvttsd2usi64:
5893 case Intrinsic::x86_avx512_cvttsd2usi:
5894 case Intrinsic::x86_avx512_cvtusi2ss:
5895 case Intrinsic::x86_avx512_cvtusi642sd:
5896 case Intrinsic::x86_avx512_cvtusi642ss:
5897 handleSSEVectorConvertIntrinsic(
I, 1,
true);
5899 case Intrinsic::x86_sse2_cvtsd2si64:
5900 case Intrinsic::x86_sse2_cvtsd2si:
5901 case Intrinsic::x86_sse2_cvtsd2ss:
5902 case Intrinsic::x86_sse2_cvttsd2si64:
5903 case Intrinsic::x86_sse2_cvttsd2si:
5904 case Intrinsic::x86_sse_cvtss2si64:
5905 case Intrinsic::x86_sse_cvtss2si:
5906 case Intrinsic::x86_sse_cvttss2si64:
5907 case Intrinsic::x86_sse_cvttss2si:
5908 handleSSEVectorConvertIntrinsic(
I, 1);
5910 case Intrinsic::x86_sse_cvtps2pi:
5911 case Intrinsic::x86_sse_cvttps2pi:
5912 handleSSEVectorConvertIntrinsic(
I, 2);
5920 case Intrinsic::x86_vcvtps2ph_128:
5921 case Intrinsic::x86_vcvtps2ph_256: {
5922 handleSSEVectorConvertIntrinsicByProp(
I,
true);
5931 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
5932 handleAVX512VectorConvertFPToInt(
I,
false);
5937 case Intrinsic::x86_sse2_cvtpd2ps:
5938 case Intrinsic::x86_sse2_cvtps2dq:
5939 case Intrinsic::x86_sse2_cvtpd2dq:
5940 case Intrinsic::x86_sse2_cvttps2dq:
5941 case Intrinsic::x86_sse2_cvttpd2dq:
5942 case Intrinsic::x86_avx_cvt_pd2_ps_256:
5943 case Intrinsic::x86_avx_cvt_ps2dq_256:
5944 case Intrinsic::x86_avx_cvt_pd2dq_256:
5945 case Intrinsic::x86_avx_cvtt_ps2dq_256:
5946 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
5947 handleSSEVectorConvertIntrinsicByProp(
I,
false);
5958 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
5959 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
5960 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
5961 handleAVX512VectorConvertFPToInt(
I,
true);
5965 case Intrinsic::x86_avx512_psll_w_512:
5966 case Intrinsic::x86_avx512_psll_d_512:
5967 case Intrinsic::x86_avx512_psll_q_512:
5968 case Intrinsic::x86_avx512_pslli_w_512:
5969 case Intrinsic::x86_avx512_pslli_d_512:
5970 case Intrinsic::x86_avx512_pslli_q_512:
5971 case Intrinsic::x86_avx512_psrl_w_512:
5972 case Intrinsic::x86_avx512_psrl_d_512:
5973 case Intrinsic::x86_avx512_psrl_q_512:
5974 case Intrinsic::x86_avx512_psra_w_512:
5975 case Intrinsic::x86_avx512_psra_d_512:
5976 case Intrinsic::x86_avx512_psra_q_512:
5977 case Intrinsic::x86_avx512_psrli_w_512:
5978 case Intrinsic::x86_avx512_psrli_d_512:
5979 case Intrinsic::x86_avx512_psrli_q_512:
5980 case Intrinsic::x86_avx512_psrai_w_512:
5981 case Intrinsic::x86_avx512_psrai_d_512:
5982 case Intrinsic::x86_avx512_psrai_q_512:
5983 case Intrinsic::x86_avx512_psra_q_256:
5984 case Intrinsic::x86_avx512_psra_q_128:
5985 case Intrinsic::x86_avx512_psrai_q_256:
5986 case Intrinsic::x86_avx512_psrai_q_128:
5987 case Intrinsic::x86_avx2_psll_w:
5988 case Intrinsic::x86_avx2_psll_d:
5989 case Intrinsic::x86_avx2_psll_q:
5990 case Intrinsic::x86_avx2_pslli_w:
5991 case Intrinsic::x86_avx2_pslli_d:
5992 case Intrinsic::x86_avx2_pslli_q:
5993 case Intrinsic::x86_avx2_psrl_w:
5994 case Intrinsic::x86_avx2_psrl_d:
5995 case Intrinsic::x86_avx2_psrl_q:
5996 case Intrinsic::x86_avx2_psra_w:
5997 case Intrinsic::x86_avx2_psra_d:
5998 case Intrinsic::x86_avx2_psrli_w:
5999 case Intrinsic::x86_avx2_psrli_d:
6000 case Intrinsic::x86_avx2_psrli_q:
6001 case Intrinsic::x86_avx2_psrai_w:
6002 case Intrinsic::x86_avx2_psrai_d:
6003 case Intrinsic::x86_sse2_psll_w:
6004 case Intrinsic::x86_sse2_psll_d:
6005 case Intrinsic::x86_sse2_psll_q:
6006 case Intrinsic::x86_sse2_pslli_w:
6007 case Intrinsic::x86_sse2_pslli_d:
6008 case Intrinsic::x86_sse2_pslli_q:
6009 case Intrinsic::x86_sse2_psrl_w:
6010 case Intrinsic::x86_sse2_psrl_d:
6011 case Intrinsic::x86_sse2_psrl_q:
6012 case Intrinsic::x86_sse2_psra_w:
6013 case Intrinsic::x86_sse2_psra_d:
6014 case Intrinsic::x86_sse2_psrli_w:
6015 case Intrinsic::x86_sse2_psrli_d:
6016 case Intrinsic::x86_sse2_psrli_q:
6017 case Intrinsic::x86_sse2_psrai_w:
6018 case Intrinsic::x86_sse2_psrai_d:
6019 case Intrinsic::x86_mmx_psll_w:
6020 case Intrinsic::x86_mmx_psll_d:
6021 case Intrinsic::x86_mmx_psll_q:
6022 case Intrinsic::x86_mmx_pslli_w:
6023 case Intrinsic::x86_mmx_pslli_d:
6024 case Intrinsic::x86_mmx_pslli_q:
6025 case Intrinsic::x86_mmx_psrl_w:
6026 case Intrinsic::x86_mmx_psrl_d:
6027 case Intrinsic::x86_mmx_psrl_q:
6028 case Intrinsic::x86_mmx_psra_w:
6029 case Intrinsic::x86_mmx_psra_d:
6030 case Intrinsic::x86_mmx_psrli_w:
6031 case Intrinsic::x86_mmx_psrli_d:
6032 case Intrinsic::x86_mmx_psrli_q:
6033 case Intrinsic::x86_mmx_psrai_w:
6034 case Intrinsic::x86_mmx_psrai_d:
6035 handleVectorShiftIntrinsic(
I,
false);
6037 case Intrinsic::x86_avx2_psllv_d:
6038 case Intrinsic::x86_avx2_psllv_d_256:
6039 case Intrinsic::x86_avx512_psllv_d_512:
6040 case Intrinsic::x86_avx2_psllv_q:
6041 case Intrinsic::x86_avx2_psllv_q_256:
6042 case Intrinsic::x86_avx512_psllv_q_512:
6043 case Intrinsic::x86_avx2_psrlv_d:
6044 case Intrinsic::x86_avx2_psrlv_d_256:
6045 case Intrinsic::x86_avx512_psrlv_d_512:
6046 case Intrinsic::x86_avx2_psrlv_q:
6047 case Intrinsic::x86_avx2_psrlv_q_256:
6048 case Intrinsic::x86_avx512_psrlv_q_512:
6049 case Intrinsic::x86_avx2_psrav_d:
6050 case Intrinsic::x86_avx2_psrav_d_256:
6051 case Intrinsic::x86_avx512_psrav_d_512:
6052 case Intrinsic::x86_avx512_psrav_q_128:
6053 case Intrinsic::x86_avx512_psrav_q_256:
6054 case Intrinsic::x86_avx512_psrav_q_512:
6055 handleVectorShiftIntrinsic(
I,
true);
6059 case Intrinsic::x86_sse2_packsswb_128:
6060 case Intrinsic::x86_sse2_packssdw_128:
6061 case Intrinsic::x86_sse2_packuswb_128:
6062 case Intrinsic::x86_sse41_packusdw:
6063 case Intrinsic::x86_avx2_packsswb:
6064 case Intrinsic::x86_avx2_packssdw:
6065 case Intrinsic::x86_avx2_packuswb:
6066 case Intrinsic::x86_avx2_packusdw:
6072 case Intrinsic::x86_avx512_packsswb_512:
6073 case Intrinsic::x86_avx512_packssdw_512:
6074 case Intrinsic::x86_avx512_packuswb_512:
6075 case Intrinsic::x86_avx512_packusdw_512:
6076 handleVectorPackIntrinsic(
I);
6079 case Intrinsic::x86_sse41_pblendvb:
6080 case Intrinsic::x86_sse41_blendvpd:
6081 case Intrinsic::x86_sse41_blendvps:
6082 case Intrinsic::x86_avx_blendv_pd_256:
6083 case Intrinsic::x86_avx_blendv_ps_256:
6084 case Intrinsic::x86_avx2_pblendvb:
6085 handleBlendvIntrinsic(
I);
6088 case Intrinsic::x86_avx_dp_ps_256:
6089 case Intrinsic::x86_sse41_dppd:
6090 case Intrinsic::x86_sse41_dpps:
6091 handleDppIntrinsic(
I);
6094 case Intrinsic::x86_mmx_packsswb:
6095 case Intrinsic::x86_mmx_packuswb:
6096 handleVectorPackIntrinsic(
I, 16);
6099 case Intrinsic::x86_mmx_packssdw:
6100 handleVectorPackIntrinsic(
I, 32);
6103 case Intrinsic::x86_mmx_psad_bw:
6104 handleVectorSadIntrinsic(
I,
true);
6106 case Intrinsic::x86_sse2_psad_bw:
6107 case Intrinsic::x86_avx2_psad_bw:
6108 handleVectorSadIntrinsic(
I);
6134 case Intrinsic::x86_sse2_pmadd_wd:
6135 case Intrinsic::x86_avx2_pmadd_wd:
6136 case Intrinsic::x86_avx512_pmaddw_d_512:
6137 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6138 case Intrinsic::x86_avx2_pmadd_ub_sw:
6139 case Intrinsic::x86_avx512_pmaddubs_w_512:
6140 handleVectorDotProductIntrinsic(
I, 2,
6147 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6148 handleVectorDotProductIntrinsic(
I, 2,
6155 case Intrinsic::x86_mmx_pmadd_wd:
6156 handleVectorDotProductIntrinsic(
I, 2,
6165 case Intrinsic::aarch64_neon_bfmlalt:
6166 handleVectorDotProductIntrinsic(
I, 2,
6174 case Intrinsic::aarch64_neon_bfmlalb:
6175 handleVectorDotProductIntrinsic(
I, 2,
6273 case Intrinsic::x86_avx512_vpdpbusd_128:
6274 case Intrinsic::x86_avx512_vpdpbusd_256:
6275 case Intrinsic::x86_avx512_vpdpbusd_512:
6276 case Intrinsic::x86_avx512_vpdpbusds_128:
6277 case Intrinsic::x86_avx512_vpdpbusds_256:
6278 case Intrinsic::x86_avx512_vpdpbusds_512:
6279 case Intrinsic::x86_avx2_vpdpbssd_128:
6280 case Intrinsic::x86_avx2_vpdpbssd_256:
6281 case Intrinsic::x86_avx10_vpdpbssd_512:
6282 case Intrinsic::x86_avx2_vpdpbssds_128:
6283 case Intrinsic::x86_avx2_vpdpbssds_256:
6284 case Intrinsic::x86_avx10_vpdpbssds_512:
6285 case Intrinsic::x86_avx2_vpdpbsud_128:
6286 case Intrinsic::x86_avx2_vpdpbsud_256:
6287 case Intrinsic::x86_avx10_vpdpbsud_512:
6288 case Intrinsic::x86_avx2_vpdpbsuds_128:
6289 case Intrinsic::x86_avx2_vpdpbsuds_256:
6290 case Intrinsic::x86_avx10_vpdpbsuds_512:
6291 case Intrinsic::x86_avx2_vpdpbuud_128:
6292 case Intrinsic::x86_avx2_vpdpbuud_256:
6293 case Intrinsic::x86_avx10_vpdpbuud_512:
6294 case Intrinsic::x86_avx2_vpdpbuuds_128:
6295 case Intrinsic::x86_avx2_vpdpbuuds_256:
6296 case Intrinsic::x86_avx10_vpdpbuuds_512:
6297 handleVectorDotProductIntrinsic(
I, 4,
6395 case Intrinsic::x86_avx512_vpdpwssd_128:
6396 case Intrinsic::x86_avx512_vpdpwssd_256:
6397 case Intrinsic::x86_avx512_vpdpwssd_512:
6398 case Intrinsic::x86_avx512_vpdpwssds_128:
6399 case Intrinsic::x86_avx512_vpdpwssds_256:
6400 case Intrinsic::x86_avx512_vpdpwssds_512:
6401 case Intrinsic::x86_avx2_vpdpwsud_128:
6402 case Intrinsic::x86_avx2_vpdpwsud_256:
6403 case Intrinsic::x86_avx10_vpdpwsud_512:
6404 case Intrinsic::x86_avx2_vpdpwsuds_128:
6405 case Intrinsic::x86_avx2_vpdpwsuds_256:
6406 case Intrinsic::x86_avx10_vpdpwsuds_512:
6407 case Intrinsic::x86_avx2_vpdpwusd_128:
6408 case Intrinsic::x86_avx2_vpdpwusd_256:
6409 case Intrinsic::x86_avx10_vpdpwusd_512:
6410 case Intrinsic::x86_avx2_vpdpwusds_128:
6411 case Intrinsic::x86_avx2_vpdpwusds_256:
6412 case Intrinsic::x86_avx10_vpdpwusds_512:
6413 case Intrinsic::x86_avx2_vpdpwuud_128:
6414 case Intrinsic::x86_avx2_vpdpwuud_256:
6415 case Intrinsic::x86_avx10_vpdpwuud_512:
6416 case Intrinsic::x86_avx2_vpdpwuuds_128:
6417 case Intrinsic::x86_avx2_vpdpwuuds_256:
6418 case Intrinsic::x86_avx10_vpdpwuuds_512:
6419 handleVectorDotProductIntrinsic(
I, 2,
6433 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6434 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6435 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6436 handleVectorDotProductIntrinsic(
I, 2,
6442 case Intrinsic::x86_sse_cmp_ss:
6443 case Intrinsic::x86_sse2_cmp_sd:
6444 case Intrinsic::x86_sse_comieq_ss:
6445 case Intrinsic::x86_sse_comilt_ss:
6446 case Intrinsic::x86_sse_comile_ss:
6447 case Intrinsic::x86_sse_comigt_ss:
6448 case Intrinsic::x86_sse_comige_ss:
6449 case Intrinsic::x86_sse_comineq_ss:
6450 case Intrinsic::x86_sse_ucomieq_ss:
6451 case Intrinsic::x86_sse_ucomilt_ss:
6452 case Intrinsic::x86_sse_ucomile_ss:
6453 case Intrinsic::x86_sse_ucomigt_ss:
6454 case Intrinsic::x86_sse_ucomige_ss:
6455 case Intrinsic::x86_sse_ucomineq_ss:
6456 case Intrinsic::x86_sse2_comieq_sd:
6457 case Intrinsic::x86_sse2_comilt_sd:
6458 case Intrinsic::x86_sse2_comile_sd:
6459 case Intrinsic::x86_sse2_comigt_sd:
6460 case Intrinsic::x86_sse2_comige_sd:
6461 case Intrinsic::x86_sse2_comineq_sd:
6462 case Intrinsic::x86_sse2_ucomieq_sd:
6463 case Intrinsic::x86_sse2_ucomilt_sd:
6464 case Intrinsic::x86_sse2_ucomile_sd:
6465 case Intrinsic::x86_sse2_ucomigt_sd:
6466 case Intrinsic::x86_sse2_ucomige_sd:
6467 case Intrinsic::x86_sse2_ucomineq_sd:
6468 handleVectorCompareScalarIntrinsic(
I);
6471 case Intrinsic::x86_avx_cmp_pd_256:
6472 case Intrinsic::x86_avx_cmp_ps_256:
6473 case Intrinsic::x86_sse2_cmp_pd:
6474 case Intrinsic::x86_sse_cmp_ps:
6475 handleVectorComparePackedIntrinsic(
I,
true);
6478 case Intrinsic::x86_bmi_bextr_32:
6479 case Intrinsic::x86_bmi_bextr_64:
6480 case Intrinsic::x86_bmi_bzhi_32:
6481 case Intrinsic::x86_bmi_bzhi_64:
6482 case Intrinsic::x86_bmi_pdep_32:
6483 case Intrinsic::x86_bmi_pdep_64:
6484 case Intrinsic::x86_bmi_pext_32:
6485 case Intrinsic::x86_bmi_pext_64:
6486 handleBmiIntrinsic(
I);
6489 case Intrinsic::x86_pclmulqdq:
6490 case Intrinsic::x86_pclmulqdq_256:
6491 case Intrinsic::x86_pclmulqdq_512:
6492 handlePclmulIntrinsic(
I);
6495 case Intrinsic::x86_avx_round_pd_256:
6496 case Intrinsic::x86_avx_round_ps_256:
6497 case Intrinsic::x86_sse41_round_pd:
6498 case Intrinsic::x86_sse41_round_ps:
6499 handleRoundPdPsIntrinsic(
I);
6502 case Intrinsic::x86_sse41_round_sd:
6503 case Intrinsic::x86_sse41_round_ss:
6504 handleUnarySdSsIntrinsic(
I);
6507 case Intrinsic::x86_sse2_max_sd:
6508 case Intrinsic::x86_sse_max_ss:
6509 case Intrinsic::x86_sse2_min_sd:
6510 case Intrinsic::x86_sse_min_ss:
6511 handleBinarySdSsIntrinsic(
I);
6514 case Intrinsic::x86_avx_vtestc_pd:
6515 case Intrinsic::x86_avx_vtestc_pd_256:
6516 case Intrinsic::x86_avx_vtestc_ps:
6517 case Intrinsic::x86_avx_vtestc_ps_256:
6518 case Intrinsic::x86_avx_vtestnzc_pd:
6519 case Intrinsic::x86_avx_vtestnzc_pd_256:
6520 case Intrinsic::x86_avx_vtestnzc_ps:
6521 case Intrinsic::x86_avx_vtestnzc_ps_256:
6522 case Intrinsic::x86_avx_vtestz_pd:
6523 case Intrinsic::x86_avx_vtestz_pd_256:
6524 case Intrinsic::x86_avx_vtestz_ps:
6525 case Intrinsic::x86_avx_vtestz_ps_256:
6526 case Intrinsic::x86_avx_ptestc_256:
6527 case Intrinsic::x86_avx_ptestnzc_256:
6528 case Intrinsic::x86_avx_ptestz_256:
6529 case Intrinsic::x86_sse41_ptestc:
6530 case Intrinsic::x86_sse41_ptestnzc:
6531 case Intrinsic::x86_sse41_ptestz:
6532 handleVtestIntrinsic(
I);
6536 case Intrinsic::x86_ssse3_phadd_w:
6537 case Intrinsic::x86_ssse3_phadd_w_128:
6538 case Intrinsic::x86_ssse3_phsub_w:
6539 case Intrinsic::x86_ssse3_phsub_w_128:
6540 handlePairwiseShadowOrIntrinsic(
I, 1,
6544 case Intrinsic::x86_avx2_phadd_w:
6545 case Intrinsic::x86_avx2_phsub_w:
6546 handlePairwiseShadowOrIntrinsic(
I, 2,
6551 case Intrinsic::x86_ssse3_phadd_d:
6552 case Intrinsic::x86_ssse3_phadd_d_128:
6553 case Intrinsic::x86_ssse3_phsub_d:
6554 case Intrinsic::x86_ssse3_phsub_d_128:
6555 handlePairwiseShadowOrIntrinsic(
I, 1,
6559 case Intrinsic::x86_avx2_phadd_d:
6560 case Intrinsic::x86_avx2_phsub_d:
6561 handlePairwiseShadowOrIntrinsic(
I, 2,
6566 case Intrinsic::x86_ssse3_phadd_sw:
6567 case Intrinsic::x86_ssse3_phadd_sw_128:
6568 case Intrinsic::x86_ssse3_phsub_sw:
6569 case Intrinsic::x86_ssse3_phsub_sw_128:
6570 handlePairwiseShadowOrIntrinsic(
I, 1,
6574 case Intrinsic::x86_avx2_phadd_sw:
6575 case Intrinsic::x86_avx2_phsub_sw:
6576 handlePairwiseShadowOrIntrinsic(
I, 2,
6581 case Intrinsic::x86_sse3_hadd_ps:
6582 case Intrinsic::x86_sse3_hadd_pd:
6583 case Intrinsic::x86_sse3_hsub_ps:
6584 case Intrinsic::x86_sse3_hsub_pd:
6585 handlePairwiseShadowOrIntrinsic(
I, 1);
6588 case Intrinsic::x86_avx_hadd_pd_256:
6589 case Intrinsic::x86_avx_hadd_ps_256:
6590 case Intrinsic::x86_avx_hsub_pd_256:
6591 case Intrinsic::x86_avx_hsub_ps_256:
6592 handlePairwiseShadowOrIntrinsic(
I, 2);
6595 case Intrinsic::x86_avx_maskstore_ps:
6596 case Intrinsic::x86_avx_maskstore_pd:
6597 case Intrinsic::x86_avx_maskstore_ps_256:
6598 case Intrinsic::x86_avx_maskstore_pd_256:
6599 case Intrinsic::x86_avx2_maskstore_d:
6600 case Intrinsic::x86_avx2_maskstore_q:
6601 case Intrinsic::x86_avx2_maskstore_d_256:
6602 case Intrinsic::x86_avx2_maskstore_q_256: {
6603 handleAVXMaskedStore(
I);
6607 case Intrinsic::x86_avx_maskload_ps:
6608 case Intrinsic::x86_avx_maskload_pd:
6609 case Intrinsic::x86_avx_maskload_ps_256:
6610 case Intrinsic::x86_avx_maskload_pd_256:
6611 case Intrinsic::x86_avx2_maskload_d:
6612 case Intrinsic::x86_avx2_maskload_q:
6613 case Intrinsic::x86_avx2_maskload_d_256:
6614 case Intrinsic::x86_avx2_maskload_q_256: {
6615 handleAVXMaskedLoad(
I);
6620 case Intrinsic::x86_avx512fp16_add_ph_512:
6621 case Intrinsic::x86_avx512fp16_sub_ph_512:
6622 case Intrinsic::x86_avx512fp16_mul_ph_512:
6623 case Intrinsic::x86_avx512fp16_div_ph_512:
6624 case Intrinsic::x86_avx512fp16_max_ph_512:
6625 case Intrinsic::x86_avx512fp16_min_ph_512:
6626 case Intrinsic::x86_avx512_min_ps_512:
6627 case Intrinsic::x86_avx512_min_pd_512:
6628 case Intrinsic::x86_avx512_max_ps_512:
6629 case Intrinsic::x86_avx512_max_pd_512: {
6634 [[maybe_unused]]
bool Success =
6635 maybeHandleSimpleNomemIntrinsic(
I, 1);
6640 case Intrinsic::x86_avx_vpermilvar_pd:
6641 case Intrinsic::x86_avx_vpermilvar_pd_256:
6642 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6643 case Intrinsic::x86_avx_vpermilvar_ps:
6644 case Intrinsic::x86_avx_vpermilvar_ps_256:
6645 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6646 handleAVXVpermilvar(
I);
6650 case Intrinsic::x86_avx512_vpermi2var_d_128:
6651 case Intrinsic::x86_avx512_vpermi2var_d_256:
6652 case Intrinsic::x86_avx512_vpermi2var_d_512:
6653 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6654 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6655 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6656 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6657 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6658 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6659 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6660 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6661 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6662 case Intrinsic::x86_avx512_vpermi2var_q_128:
6663 case Intrinsic::x86_avx512_vpermi2var_q_256:
6664 case Intrinsic::x86_avx512_vpermi2var_q_512:
6665 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6666 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6667 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6668 handleAVXVpermi2var(
I);
6682 case Intrinsic::x86_avx2_pshuf_b:
6683 case Intrinsic::x86_sse_pshuf_w:
6684 case Intrinsic::x86_ssse3_pshuf_b_128:
6685 case Intrinsic::x86_ssse3_pshuf_b:
6686 case Intrinsic::x86_avx512_pshuf_b_512:
6687 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6693 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6694 case Intrinsic::x86_avx512_mask_pmov_db_128:
6695 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6696 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6697 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6698 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6699 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6700 case Intrinsic::x86_avx512_mask_pmov_db_256:
6701 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6702 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6703 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6704 case Intrinsic::x86_avx512_mask_pmov_db_512:
6705 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6706 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6709 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6717 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6718 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6719 handleIntrinsicByApplyingToShadow(
I,
6720 Intrinsic::x86_avx512_mask_pmov_dw_512,
6725 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6726 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6727 handleIntrinsicByApplyingToShadow(
I,
6728 Intrinsic::x86_avx512_mask_pmov_dw_256,
6732 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6733 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6734 handleIntrinsicByApplyingToShadow(
I,
6735 Intrinsic::x86_avx512_mask_pmov_dw_128,
6739 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6740 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6741 handleIntrinsicByApplyingToShadow(
I,
6742 Intrinsic::x86_avx512_mask_pmov_db_512,
6747 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6748 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6749 handleIntrinsicByApplyingToShadow(
I,
6750 Intrinsic::x86_avx512_mask_pmov_db_256,
6754 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6755 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6756 handleIntrinsicByApplyingToShadow(
I,
6757 Intrinsic::x86_avx512_mask_pmov_db_128,
6761 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6762 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6763 handleIntrinsicByApplyingToShadow(
I,
6764 Intrinsic::x86_avx512_mask_pmov_qb_512,
6769 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6770 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6771 handleIntrinsicByApplyingToShadow(
I,
6772 Intrinsic::x86_avx512_mask_pmov_qb_256,
6776 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6777 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6778 handleIntrinsicByApplyingToShadow(
I,
6779 Intrinsic::x86_avx512_mask_pmov_qb_128,
6783 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6784 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6785 handleIntrinsicByApplyingToShadow(
I,
6786 Intrinsic::x86_avx512_mask_pmov_qw_512,
6791 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6792 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6793 handleIntrinsicByApplyingToShadow(
I,
6794 Intrinsic::x86_avx512_mask_pmov_qw_256,
6798 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6799 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6800 handleIntrinsicByApplyingToShadow(
I,
6801 Intrinsic::x86_avx512_mask_pmov_qw_128,
6805 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6806 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6807 handleIntrinsicByApplyingToShadow(
I,
6808 Intrinsic::x86_avx512_mask_pmov_qd_128,
6812 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6813 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6814 handleIntrinsicByApplyingToShadow(
I,
6815 Intrinsic::x86_avx512_mask_pmov_wb_128,
6819 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6820 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6821 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6822 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6823 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6824 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6825 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6826 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6830 handleAVX512VectorDownConvert(
I);
6870 case Intrinsic::x86_avx512_rsqrt14_ps_512:
6871 case Intrinsic::x86_avx512_rsqrt14_ps_256:
6872 case Intrinsic::x86_avx512_rsqrt14_ps_128:
6873 case Intrinsic::x86_avx512_rsqrt14_pd_512:
6874 case Intrinsic::x86_avx512_rsqrt14_pd_256:
6875 case Intrinsic::x86_avx512_rsqrt14_pd_128:
6876 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
6877 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
6878 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
6879 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
6880 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
6881 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
6882 handleAVX512VectorGenericMaskedFP(
I, {0},
6923 case Intrinsic::x86_avx512_rcp14_ps_512:
6924 case Intrinsic::x86_avx512_rcp14_ps_256:
6925 case Intrinsic::x86_avx512_rcp14_ps_128:
6926 case Intrinsic::x86_avx512_rcp14_pd_512:
6927 case Intrinsic::x86_avx512_rcp14_pd_256:
6928 case Intrinsic::x86_avx512_rcp14_pd_128:
6929 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
6930 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
6931 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
6932 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
6933 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
6934 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
6935 handleAVX512VectorGenericMaskedFP(
I, {0},
6980 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
6981 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
6982 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
6983 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
6984 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
6985 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
6986 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
6987 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
6988 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
6989 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
6990 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
6991 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
6992 handleAVX512VectorGenericMaskedFP(
I, {0},
7028 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7029 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7030 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7031 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7032 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7033 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7034 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7035 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7036 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7040 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7060 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7061 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7062 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7063 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7064 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7065 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7066 visitGenericScalarHalfwordInst(
I);
7071 case Intrinsic::x86_vgf2p8affineqb_128:
7072 case Intrinsic::x86_vgf2p8affineqb_256:
7073 case Intrinsic::x86_vgf2p8affineqb_512:
7074 handleAVXGF2P8Affine(
I);
7084 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7085 switch (
I.getIntrinsicID()) {
7089 case Intrinsic::aarch64_neon_rshrn:
7090 case Intrinsic::aarch64_neon_sqrshl:
7091 case Intrinsic::aarch64_neon_sqrshrn:
7092 case Intrinsic::aarch64_neon_sqrshrun:
7093 case Intrinsic::aarch64_neon_sqshl:
7094 case Intrinsic::aarch64_neon_sqshlu:
7095 case Intrinsic::aarch64_neon_sqshrn:
7096 case Intrinsic::aarch64_neon_sqshrun:
7097 case Intrinsic::aarch64_neon_srshl:
7098 case Intrinsic::aarch64_neon_sshl:
7099 case Intrinsic::aarch64_neon_uqrshl:
7100 case Intrinsic::aarch64_neon_uqrshrn:
7101 case Intrinsic::aarch64_neon_uqshl:
7102 case Intrinsic::aarch64_neon_uqshrn:
7103 case Intrinsic::aarch64_neon_urshl:
7104 case Intrinsic::aarch64_neon_ushl:
7105 handleVectorShiftIntrinsic(
I,
false);
7118 case Intrinsic::aarch64_neon_vsli:
7119 case Intrinsic::aarch64_neon_vsri:
7120 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7126 case Intrinsic::aarch64_neon_fmaxp:
7127 case Intrinsic::aarch64_neon_fminp:
7129 case Intrinsic::aarch64_neon_fmaxnmp:
7130 case Intrinsic::aarch64_neon_fminnmp:
7132 case Intrinsic::aarch64_neon_smaxp:
7133 case Intrinsic::aarch64_neon_sminp:
7134 case Intrinsic::aarch64_neon_umaxp:
7135 case Intrinsic::aarch64_neon_uminp:
7137 case Intrinsic::aarch64_neon_addp:
7139 case Intrinsic::aarch64_neon_faddp:
7141 case Intrinsic::aarch64_neon_saddlp:
7142 case Intrinsic::aarch64_neon_uaddlp: {
7143 handlePairwiseShadowOrIntrinsic(
I, 1);
7148 case Intrinsic::aarch64_neon_fcvtas:
7149 case Intrinsic::aarch64_neon_fcvtau:
7151 case Intrinsic::aarch64_neon_fcvtms:
7152 case Intrinsic::aarch64_neon_fcvtmu:
7154 case Intrinsic::aarch64_neon_fcvtns:
7155 case Intrinsic::aarch64_neon_fcvtnu:
7157 case Intrinsic::aarch64_neon_fcvtps:
7158 case Intrinsic::aarch64_neon_fcvtpu:
7160 case Intrinsic::aarch64_neon_fcvtzs:
7161 case Intrinsic::aarch64_neon_fcvtzu:
7163 case Intrinsic::aarch64_neon_fcvtxn:
7165 case Intrinsic::aarch64_neon_vcvthf2fp:
7166 case Intrinsic::aarch64_neon_vcvtfp2hf:
7167 handleNEONVectorConvertIntrinsic(
I,
false);
7171 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7172 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7173 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7174 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7175 handleNEONVectorConvertIntrinsic(
I,
true);
7184 case Intrinsic::aarch64_neon_faddv:
7185 case Intrinsic::aarch64_neon_saddv:
7186 case Intrinsic::aarch64_neon_uaddv:
7189 case Intrinsic::aarch64_neon_smaxv:
7190 case Intrinsic::aarch64_neon_sminv:
7191 case Intrinsic::aarch64_neon_umaxv:
7192 case Intrinsic::aarch64_neon_uminv:
7196 case Intrinsic::aarch64_neon_fmaxv:
7197 case Intrinsic::aarch64_neon_fminv:
7198 case Intrinsic::aarch64_neon_fmaxnmv:
7199 case Intrinsic::aarch64_neon_fminnmv:
7201 case Intrinsic::aarch64_neon_saddlv:
7202 case Intrinsic::aarch64_neon_uaddlv:
7203 handleVectorReduceIntrinsic(
I,
true);
7206 case Intrinsic::aarch64_neon_ld1x2:
7207 case Intrinsic::aarch64_neon_ld1x3:
7208 case Intrinsic::aarch64_neon_ld1x4:
7209 case Intrinsic::aarch64_neon_ld2:
7210 case Intrinsic::aarch64_neon_ld3:
7211 case Intrinsic::aarch64_neon_ld4:
7212 case Intrinsic::aarch64_neon_ld2r:
7213 case Intrinsic::aarch64_neon_ld3r:
7214 case Intrinsic::aarch64_neon_ld4r: {
7215 handleNEONVectorLoad(
I,
false);
7219 case Intrinsic::aarch64_neon_ld2lane:
7220 case Intrinsic::aarch64_neon_ld3lane:
7221 case Intrinsic::aarch64_neon_ld4lane: {
7222 handleNEONVectorLoad(
I,
true);
7227 case Intrinsic::aarch64_neon_sqxtn:
7228 case Intrinsic::aarch64_neon_sqxtun:
7229 case Intrinsic::aarch64_neon_uqxtn:
7236 case Intrinsic::aarch64_neon_st1x2:
7237 case Intrinsic::aarch64_neon_st1x3:
7238 case Intrinsic::aarch64_neon_st1x4:
7239 case Intrinsic::aarch64_neon_st2:
7240 case Intrinsic::aarch64_neon_st3:
7241 case Intrinsic::aarch64_neon_st4: {
7242 handleNEONVectorStoreIntrinsic(
I,
false);
7246 case Intrinsic::aarch64_neon_st2lane:
7247 case Intrinsic::aarch64_neon_st3lane:
7248 case Intrinsic::aarch64_neon_st4lane: {
7249 handleNEONVectorStoreIntrinsic(
I,
true);
7262 case Intrinsic::aarch64_neon_tbl1:
7263 case Intrinsic::aarch64_neon_tbl2:
7264 case Intrinsic::aarch64_neon_tbl3:
7265 case Intrinsic::aarch64_neon_tbl4:
7266 case Intrinsic::aarch64_neon_tbx1:
7267 case Intrinsic::aarch64_neon_tbx2:
7268 case Intrinsic::aarch64_neon_tbx3:
7269 case Intrinsic::aarch64_neon_tbx4: {
7271 handleIntrinsicByApplyingToShadow(
7272 I,
I.getIntrinsicID(),
7277 case Intrinsic::aarch64_neon_fmulx:
7278 case Intrinsic::aarch64_neon_pmul:
7279 case Intrinsic::aarch64_neon_pmull:
7280 case Intrinsic::aarch64_neon_smull:
7281 case Intrinsic::aarch64_neon_pmull64:
7282 case Intrinsic::aarch64_neon_umull: {
7283 handleNEONVectorMultiplyIntrinsic(
I);
7287 case Intrinsic::aarch64_neon_smmla:
7288 case Intrinsic::aarch64_neon_ummla:
7289 case Intrinsic::aarch64_neon_usmmla:
7290 case Intrinsic::aarch64_neon_bfmmla:
7291 handleNEONMatrixMultiply(
I);
7298 case Intrinsic::aarch64_neon_sdot:
7299 case Intrinsic::aarch64_neon_udot:
7300 case Intrinsic::aarch64_neon_usdot:
7301 handleVectorDotProductIntrinsic(
I, 4,
7311 case Intrinsic::aarch64_neon_bfdot:
7312 handleVectorDotProductIntrinsic(
I, 2,
7319 case Intrinsic::aarch64_neon_facge:
7320 case Intrinsic::aarch64_neon_facgt:
7321 handleVectorComparePackedIntrinsic(
I,
false);
7331 void visitIntrinsicInst(IntrinsicInst &
I) {
7332 if (maybeHandleCrossPlatformIntrinsic(
I))
7335 if (maybeHandleX86SIMDIntrinsic(
I))
7338 if (maybeHandleArmSIMDIntrinsic(
I))
7341 if (maybeHandleUnknownIntrinsic(
I))
7344 visitInstruction(
I);
7347 void visitLibAtomicLoad(CallBase &CB) {
7358 Value *NewOrdering =
7362 NextNodeIRBuilder NextIRB(&CB);
7363 Value *SrcShadowPtr, *SrcOriginPtr;
7364 std::tie(SrcShadowPtr, SrcOriginPtr) =
7365 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7367 Value *DstShadowPtr =
7368 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7372 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7373 if (MS.TrackOrigins) {
7374 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7376 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7377 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7381 void visitLibAtomicStore(CallBase &CB) {
7388 Value *NewOrdering =
7392 Value *DstShadowPtr =
7402 void visitCallBase(CallBase &CB) {
7410 visitAsmInstruction(CB);
7412 visitInstruction(CB);
7421 case LibFunc_atomic_load:
7423 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7427 visitLibAtomicLoad(CB);
7429 case LibFunc_atomic_store:
7430 visitLibAtomicStore(CB);
7446 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7450 Func->removeFnAttrs(
B);
7456 bool MayCheckCall = MS.EagerChecks;
7460 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7463 unsigned ArgOffset = 0;
7466 if (!
A->getType()->isSized()) {
7467 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7471 if (
A->getType()->isScalableTy()) {
7472 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7474 insertCheckShadowOf(
A, &CB);
7479 const DataLayout &
DL =
F.getDataLayout();
7483 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7486 insertCheckShadowOf(
A, &CB);
7487 Size =
DL.getTypeAllocSize(
A->getType());
7493 Value *ArgShadow = getShadow(
A);
7494 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7496 <<
" Shadow: " << *ArgShadow <<
"\n");
7500 assert(
A->getType()->isPointerTy() &&
7501 "ByVal argument is not a pointer!");
7506 MaybeAlign Alignment = std::nullopt;
7509 Value *AShadowPtr, *AOriginPtr;
7510 std::tie(AShadowPtr, AOriginPtr) =
7511 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7513 if (!PropagateShadow) {
7520 if (MS.TrackOrigins) {
7521 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7535 Size =
DL.getTypeAllocSize(
A->getType());
7541 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7543 getOriginPtrForArgument(IRB, ArgOffset));
7546 assert(Store !=
nullptr);
7555 if (FT->isVarArg()) {
7556 VAHelper->visitCallBase(CB, IRB);
7566 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7567 setShadow(&CB, getCleanShadow(&CB));
7568 setOrigin(&CB, getCleanOrigin());
7574 Value *
Base = getShadowPtrForRetval(IRBBefore);
7575 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7587 setShadow(&CB, getCleanShadow(&CB));
7588 setOrigin(&CB, getCleanOrigin());
7595 "Could not find insertion point for retval shadow load");
7598 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7601 setShadow(&CB, RetvalShadow);
7602 if (MS.TrackOrigins)
7603 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7608 RetVal =
I->getOperand(0);
7611 return I->isMustTailCall();
7616 void visitReturnInst(ReturnInst &
I) {
7618 Value *RetVal =
I.getReturnValue();
7624 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7625 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7626 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7629 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7631 Value *Shadow = getShadow(RetVal);
7632 bool StoreOrigin =
true;
7634 insertCheckShadowOf(RetVal, &
I);
7635 Shadow = getCleanShadow(RetVal);
7636 StoreOrigin =
false;
7643 if (MS.TrackOrigins && StoreOrigin)
7644 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7648 void visitPHINode(PHINode &
I) {
7650 if (!PropagateShadow) {
7651 setShadow(&
I, getCleanShadow(&
I));
7652 setOrigin(&
I, getCleanOrigin());
7656 ShadowPHINodes.push_back(&
I);
7657 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7659 if (MS.TrackOrigins)
7661 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7664 Value *getLocalVarIdptr(AllocaInst &
I) {
7665 ConstantInt *IntConst =
7666 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7667 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7672 Value *getLocalVarDescription(AllocaInst &
I) {
7678 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7680 Value *ShadowBase, *OriginBase;
7681 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7685 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7688 if (PoisonStack && MS.TrackOrigins) {
7689 Value *Idptr = getLocalVarIdptr(
I);
7691 Value *Descr = getLocalVarDescription(
I);
7692 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7693 {&I, Len, Idptr, Descr});
7695 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7701 Value *Descr = getLocalVarDescription(
I);
7703 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7705 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7709 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7712 NextNodeIRBuilder IRB(InsPoint);
7715 if (MS.CompileKernel)
7716 poisonAllocaKmsan(
I, IRB, Len);
7718 poisonAllocaUserspace(
I, IRB, Len);
7721 void visitAllocaInst(AllocaInst &
I) {
7722 setShadow(&
I, getCleanShadow(&
I));
7723 setOrigin(&
I, getCleanOrigin());
7729 void visitSelectInst(SelectInst &
I) {
7735 handleSelectLikeInst(
I,
B,
C,
D);
7741 Value *Sb = getShadow(
B);
7742 Value *Sc = getShadow(
C);
7743 Value *Sd = getShadow(
D);
7745 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7746 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7747 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7752 if (
I.getType()->isAggregateType()) {
7756 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7757 }
else if (isScalableNonVectorType(
I.getType())) {
7765 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7773 C = CreateAppToShadowCast(IRB,
C);
7774 D = CreateAppToShadowCast(IRB,
D);
7781 if (MS.TrackOrigins) {
7784 if (
B->getType()->isVectorTy()) {
7785 B = convertToBool(
B, IRB);
7786 Sb = convertToBool(Sb, IRB);
7794 void visitLandingPadInst(LandingPadInst &
I) {
7797 setShadow(&
I, getCleanShadow(&
I));
7798 setOrigin(&
I, getCleanOrigin());
7801 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7802 setShadow(&
I, getCleanShadow(&
I));
7803 setOrigin(&
I, getCleanOrigin());
7806 void visitFuncletPadInst(FuncletPadInst &
I) {
7807 setShadow(&
I, getCleanShadow(&
I));
7808 setOrigin(&
I, getCleanOrigin());
7811 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7813 void visitExtractValueInst(ExtractValueInst &
I) {
7815 Value *Agg =
I.getAggregateOperand();
7817 Value *AggShadow = getShadow(Agg);
7821 setShadow(&
I, ResShadow);
7822 setOriginForNaryOp(
I);
7825 void visitInsertValueInst(InsertValueInst &
I) {
7828 Value *AggShadow = getShadow(
I.getAggregateOperand());
7829 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7835 setOriginForNaryOp(
I);
7838 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7847 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
7854 unsigned NumOperands =
I.getNumOperands();
7856 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
7868 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
7869 <<
I.getOpcodeName() <<
"(";
7871 for (
size_t i = 0; i < NumOperands; i++) {
7889 void visitResumeInst(ResumeInst &
I) {
7894 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
7899 void visitCatchReturnInst(CatchReturnInst &CRI) {
7904 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
7913 insertCheckShadowOf(Operand, &
I);
7920 auto Size =
DL.getTypeStoreSize(ElemTy);
7922 if (MS.CompileKernel) {
7923 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
7929 auto [ShadowPtr,
_] =
7930 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
7940 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
7941 int NumRetOutputs = 0;
7948 NumRetOutputs =
ST->getNumElements();
7953 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
7954 switch (
Info.Type) {
7962 return NumOutputs - NumRetOutputs;
7965 void visitAsmInstruction(Instruction &
I) {
7981 const DataLayout &
DL =
F.getDataLayout();
7985 int OutputArgs = getNumOutputArgs(IA, CB);
7991 for (
int i = OutputArgs; i < NumOperands; i++) {
7999 for (
int i = 0; i < OutputArgs; i++) {
8005 setShadow(&
I, getCleanShadow(&
I));
8006 setOrigin(&
I, getCleanOrigin());
8009 void visitFreezeInst(FreezeInst &
I) {
8011 setShadow(&
I, getCleanShadow(&
I));
8012 setOrigin(&
I, getCleanOrigin());
8015 void visitInstruction(Instruction &
I) {
8018 dumpInst(
I,
"Strict");
8020 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8021 Value *Operand =
I.getOperand(i);
8023 insertCheckShadowOf(Operand, &
I);
8025 setShadow(&
I, getCleanShadow(&
I));
8026 setOrigin(&
I, getCleanOrigin());
8030struct VarArgHelperBase :
public VarArgHelper {
8032 MemorySanitizer &MS;
8033 MemorySanitizerVisitor &MSV;
8035 const unsigned VAListTagSize;
8037 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
8038 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8039 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8043 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8049 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8058 return getShadowPtrForVAArgument(IRB, ArgOffset);
8067 ConstantInt::get(MS.IntptrTy, ArgOffset),
8072 unsigned BaseOffset) {
8081 TailSize,
Align(8));
8084 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8086 Value *VAListTag =
I.getArgOperand(0);
8088 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8089 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8092 VAListTagSize, Alignment,
false);
8095 void visitVAStartInst(VAStartInst &
I)
override {
8096 if (
F.getCallingConv() == CallingConv::Win64)
8099 unpoisonVAListTagForInst(
I);
8102 void visitVACopyInst(VACopyInst &
I)
override {
8103 if (
F.getCallingConv() == CallingConv::Win64)
8105 unpoisonVAListTagForInst(
I);
8110struct VarArgAMD64Helper :
public VarArgHelperBase {
8113 static const unsigned AMD64GpEndOffset = 48;
8114 static const unsigned AMD64FpEndOffsetSSE = 176;
8116 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8118 unsigned AMD64FpEndOffset;
8119 AllocaInst *VAArgTLSCopy =
nullptr;
8120 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8121 Value *VAArgOverflowSize =
nullptr;
8123 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8125 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
8126 MemorySanitizerVisitor &MSV)
8127 : VarArgHelperBase(
F, MS, MSV, 24) {
8128 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8129 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8130 if (Attr.isStringAttribute() &&
8131 (Attr.getKindAsString() ==
"target-features")) {
8132 if (Attr.getValueAsString().contains(
"-sse"))
8133 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8139 ArgKind classifyArgument(
Value *arg) {
8142 if (
T->isX86_FP80Ty())
8144 if (
T->isFPOrFPVectorTy())
8145 return AK_FloatingPoint;
8146 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8147 return AK_GeneralPurpose;
8148 if (
T->isPointerTy())
8149 return AK_GeneralPurpose;
8161 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8162 unsigned GpOffset = 0;
8163 unsigned FpOffset = AMD64GpEndOffset;
8164 unsigned OverflowOffset = AMD64FpEndOffset;
8165 const DataLayout &
DL =
F.getDataLayout();
8169 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8176 assert(
A->getType()->isPointerTy());
8178 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8179 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8180 unsigned BaseOffset = OverflowOffset;
8181 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8182 Value *OriginBase =
nullptr;
8183 if (MS.TrackOrigins)
8184 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8185 OverflowOffset += AlignedSize;
8188 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8192 Value *ShadowPtr, *OriginPtr;
8193 std::tie(ShadowPtr, OriginPtr) =
8198 if (MS.TrackOrigins)
8202 ArgKind AK = classifyArgument(
A);
8203 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8205 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8207 Value *ShadowBase, *OriginBase =
nullptr;
8209 case AK_GeneralPurpose:
8210 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8211 if (MS.TrackOrigins)
8212 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8216 case AK_FloatingPoint:
8217 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8218 if (MS.TrackOrigins)
8219 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8226 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8227 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8228 unsigned BaseOffset = OverflowOffset;
8229 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8230 if (MS.TrackOrigins) {
8231 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8233 OverflowOffset += AlignedSize;
8236 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8245 Value *Shadow = MSV.getShadow(
A);
8247 if (MS.TrackOrigins) {
8248 Value *Origin = MSV.getOrigin(
A);
8249 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8250 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8256 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8257 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8260 void finalizeInstrumentation()
override {
8261 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8262 "finalizeInstrumentation called twice");
8263 if (!VAStartInstrumentationList.
empty()) {
8270 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8271 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8277 Intrinsic::umin, CopySize,
8281 if (MS.TrackOrigins) {
8282 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8291 for (CallInst *OrigInst : VAStartInstrumentationList) {
8292 NextNodeIRBuilder IRB(OrigInst);
8293 Value *VAListTag = OrigInst->getArgOperand(0);
8295 Value *RegSaveAreaPtrPtr =
8296 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8298 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8300 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8301 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8303 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8305 if (MS.TrackOrigins)
8306 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8307 Alignment, AMD64FpEndOffset);
8308 Value *OverflowArgAreaPtrPtr =
8309 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8310 Value *OverflowArgAreaPtr =
8311 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8312 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8313 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8314 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8318 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8320 if (MS.TrackOrigins) {
8323 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8331struct VarArgAArch64Helper :
public VarArgHelperBase {
8332 static const unsigned kAArch64GrArgSize = 64;
8333 static const unsigned kAArch64VrArgSize = 128;
8335 static const unsigned AArch64GrBegOffset = 0;
8336 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8338 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8339 static const unsigned AArch64VrEndOffset =
8340 AArch64VrBegOffset + kAArch64VrArgSize;
8341 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8343 AllocaInst *VAArgTLSCopy =
nullptr;
8344 Value *VAArgOverflowSize =
nullptr;
8346 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8348 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
8349 MemorySanitizerVisitor &MSV)
8350 : VarArgHelperBase(
F, MS, MSV, 32) {}
8353 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8354 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8355 return {AK_GeneralPurpose, 1};
8356 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8357 return {AK_FloatingPoint, 1};
8359 if (
T->isArrayTy()) {
8360 auto R = classifyArgument(
T->getArrayElementType());
8361 R.second *=
T->getScalarType()->getArrayNumElements();
8366 auto R = classifyArgument(FV->getScalarType());
8367 R.second *= FV->getNumElements();
8372 return {AK_Memory, 0};
8384 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8385 unsigned GrOffset = AArch64GrBegOffset;
8386 unsigned VrOffset = AArch64VrBegOffset;
8387 unsigned OverflowOffset = AArch64VAEndOffset;
8389 const DataLayout &
DL =
F.getDataLayout();
8392 auto [AK, RegNum] = classifyArgument(
A->getType());
8393 if (AK == AK_GeneralPurpose &&
8394 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8396 if (AK == AK_FloatingPoint &&
8397 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8401 case AK_GeneralPurpose:
8402 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8403 GrOffset += 8 * RegNum;
8405 case AK_FloatingPoint:
8406 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8407 VrOffset += 16 * RegNum;
8414 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8415 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8416 unsigned BaseOffset = OverflowOffset;
8417 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8418 OverflowOffset += AlignedSize;
8421 CleanUnusedTLS(IRB,
Base, BaseOffset);
8433 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8434 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8439 Value *SaveAreaPtrPtr =
8440 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8441 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8446 Value *SaveAreaPtr =
8447 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8449 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8452 void finalizeInstrumentation()
override {
8453 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8454 "finalizeInstrumentation called twice");
8455 if (!VAStartInstrumentationList.empty()) {
8462 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8463 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8469 Intrinsic::umin, CopySize,
8475 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8476 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8480 for (CallInst *OrigInst : VAStartInstrumentationList) {
8481 NextNodeIRBuilder IRB(OrigInst);
8483 Value *VAListTag = OrigInst->getArgOperand(0);
8500 Value *StackSaveAreaPtr =
8501 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8504 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8505 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8508 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8511 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8512 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8515 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8521 Value *GrRegSaveAreaShadowPtrOff =
8522 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8524 Value *GrRegSaveAreaShadowPtr =
8525 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8531 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8537 Value *VrRegSaveAreaShadowPtrOff =
8538 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8540 Value *VrRegSaveAreaShadowPtr =
8541 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8548 VrRegSaveAreaShadowPtrOff);
8549 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8555 Value *StackSaveAreaShadowPtr =
8556 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8561 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8564 Align(16), VAArgOverflowSize);
8570struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8571 AllocaInst *VAArgTLSCopy =
nullptr;
8572 Value *VAArgSize =
nullptr;
8574 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
8575 MemorySanitizerVisitor &MSV)
8576 : VarArgHelperBase(
F, MS, MSV, 8) {}
8578 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8586 Triple TargetTriple(
F.getParent()->getTargetTriple());
8590 if (TargetTriple.isPPC64ELFv2ABI())
8594 unsigned VAArgOffset = VAArgBase;
8595 const DataLayout &
DL =
F.getDataLayout();
8598 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8600 assert(
A->getType()->isPointerTy());
8602 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8605 ArgAlign =
Align(8);
8606 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8609 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8611 Value *AShadowPtr, *AOriginPtr;
8612 std::tie(AShadowPtr, AOriginPtr) =
8613 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8623 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8625 if (
A->getType()->isArrayTy()) {
8628 Type *ElementTy =
A->getType()->getArrayElementType();
8630 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8631 }
else if (
A->getType()->isVectorTy()) {
8633 ArgAlign =
Align(ArgSize);
8636 ArgAlign =
Align(8);
8637 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8638 if (
DL.isBigEndian()) {
8642 VAArgOffset += (8 - ArgSize);
8646 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8650 VAArgOffset += ArgSize;
8654 VAArgBase = VAArgOffset;
8658 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8661 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8664 void finalizeInstrumentation()
override {
8665 assert(!VAArgSize && !VAArgTLSCopy &&
8666 "finalizeInstrumentation called twice");
8669 Value *CopySize = VAArgSize;
8671 if (!VAStartInstrumentationList.empty()) {
8675 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8681 Intrinsic::umin, CopySize,
8689 for (CallInst *OrigInst : VAStartInstrumentationList) {
8690 NextNodeIRBuilder IRB(OrigInst);
8691 Value *VAListTag = OrigInst->getArgOperand(0);
8694 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8697 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8698 const DataLayout &
DL =
F.getDataLayout();
8699 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8701 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8702 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8704 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8711struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8712 AllocaInst *VAArgTLSCopy =
nullptr;
8713 Value *VAArgSize =
nullptr;
8715 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
8716 MemorySanitizerVisitor &MSV)
8717 : VarArgHelperBase(
F, MS, MSV, 12) {}
8719 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8723 unsigned VAArgOffset = VAArgBase;
8724 const DataLayout &
DL =
F.getDataLayout();
8725 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8728 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8730 assert(
A->getType()->isPointerTy());
8732 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8734 if (ArgAlign < IntptrSize)
8735 ArgAlign =
Align(IntptrSize);
8736 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8739 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8741 Value *AShadowPtr, *AOriginPtr;
8742 std::tie(AShadowPtr, AOriginPtr) =
8743 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8753 Type *ArgTy =
A->getType();
8759 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8766 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8769 ArgAlign =
Align(ArgSize);
8771 if (ArgAlign < IntptrSize)
8772 ArgAlign =
Align(IntptrSize);
8773 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8774 if (
DL.isBigEndian()) {
8777 if (ArgSize < IntptrSize)
8778 VAArgOffset += (IntptrSize - ArgSize);
8781 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8787 VAArgOffset += ArgSize;
8794 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8797 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8800 void finalizeInstrumentation()
override {
8801 assert(!VAArgSize && !VAArgTLSCopy &&
8802 "finalizeInstrumentation called twice");
8804 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8805 Value *CopySize = VAArgSize;
8807 if (!VAStartInstrumentationList.empty()) {
8811 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8817 Intrinsic::umin, CopySize,
8825 for (CallInst *OrigInst : VAStartInstrumentationList) {
8826 NextNodeIRBuilder IRB(OrigInst);
8827 Value *VAListTag = OrigInst->getArgOperand(0);
8829 Value *RegSaveAreaSize = CopySize;
8833 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8837 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8839 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8842 const DataLayout &
DL =
F.getDataLayout();
8843 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8847 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8848 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8849 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8851 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
8852 Alignment, RegSaveAreaSize);
8854 RegSaveAreaShadowPtr =
8857 ConstantInt::get(MS.IntptrTy, 32));
8862 ConstantInt::get(MS.IntptrTy, 32), Alignment);
8867 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
8870 OverflowAreaPtrPtr =
8871 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
8872 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
8874 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
8876 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
8877 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
8878 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
8881 Value *OverflowVAArgTLSCopyPtr =
8883 OverflowVAArgTLSCopyPtr =
8884 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
8886 OverflowVAArgTLSCopyPtr =
8889 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
8896struct VarArgSystemZHelper :
public VarArgHelperBase {
8897 static const unsigned SystemZGpOffset = 16;
8898 static const unsigned SystemZGpEndOffset = 56;
8899 static const unsigned SystemZFpOffset = 128;
8900 static const unsigned SystemZFpEndOffset = 160;
8901 static const unsigned SystemZMaxVrArgs = 8;
8902 static const unsigned SystemZRegSaveAreaSize = 160;
8903 static const unsigned SystemZOverflowOffset = 160;
8904 static const unsigned SystemZVAListTagSize = 32;
8905 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
8906 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
8908 bool IsSoftFloatABI;
8909 AllocaInst *VAArgTLSCopy =
nullptr;
8910 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8911 Value *VAArgOverflowSize =
nullptr;
8913 enum class ArgKind {
8921 enum class ShadowExtension {
None,
Zero, Sign };
8923 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
8924 MemorySanitizerVisitor &MSV)
8925 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
8926 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
8928 ArgKind classifyArgument(
Type *
T) {
8935 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
8936 return ArgKind::Indirect;
8937 if (
T->isFloatingPointTy())
8938 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
8939 if (
T->isIntegerTy() ||
T->isPointerTy())
8940 return ArgKind::GeneralPurpose;
8941 if (
T->isVectorTy())
8942 return ArgKind::Vector;
8943 return ArgKind::Memory;
8946 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
8956 return ShadowExtension::Zero;
8960 return ShadowExtension::Sign;
8962 return ShadowExtension::None;
8965 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8966 unsigned GpOffset = SystemZGpOffset;
8967 unsigned FpOffset = SystemZFpOffset;
8968 unsigned VrIndex = 0;
8969 unsigned OverflowOffset = SystemZOverflowOffset;
8970 const DataLayout &
DL =
F.getDataLayout();
8976 ArgKind AK = classifyArgument(
T);
8977 if (AK == ArgKind::Indirect) {
8979 AK = ArgKind::GeneralPurpose;
8981 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
8982 AK = ArgKind::Memory;
8983 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
8984 AK = ArgKind::Memory;
8985 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
8986 AK = ArgKind::Memory;
8987 Value *ShadowBase =
nullptr;
8988 Value *OriginBase =
nullptr;
8989 ShadowExtension SE = ShadowExtension::None;
8991 case ArgKind::GeneralPurpose: {
8993 uint64_t ArgSize = 8;
8996 SE = getShadowExtension(CB, ArgNo);
8997 uint64_t GapSize = 0;
8998 if (SE == ShadowExtension::None) {
8999 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9000 assert(ArgAllocSize <= ArgSize);
9001 GapSize = ArgSize - ArgAllocSize;
9003 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9004 if (MS.TrackOrigins)
9005 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9007 GpOffset += ArgSize;
9013 case ArgKind::FloatingPoint: {
9015 uint64_t ArgSize = 8;
9022 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9023 if (MS.TrackOrigins)
9024 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9026 FpOffset += ArgSize;
9032 case ArgKind::Vector: {
9039 case ArgKind::Memory: {
9044 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9045 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
9047 SE = getShadowExtension(CB, ArgNo);
9049 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9051 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9052 if (MS.TrackOrigins)
9054 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9055 OverflowOffset += ArgSize;
9062 case ArgKind::Indirect:
9065 if (ShadowBase ==
nullptr)
9067 Value *Shadow = MSV.getShadow(
A);
9068 if (SE != ShadowExtension::None)
9069 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9070 SE == ShadowExtension::Sign);
9071 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9073 if (MS.TrackOrigins) {
9074 Value *Origin = MSV.getOrigin(
A);
9075 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9076 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9080 Constant *OverflowSize = ConstantInt::get(
9081 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9082 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9089 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9092 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9094 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9095 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9100 unsigned RegSaveAreaSize =
9101 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9102 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9104 if (MS.TrackOrigins)
9105 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9106 Alignment, RegSaveAreaSize);
9115 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9117 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9118 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9120 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9121 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9124 SystemZOverflowOffset);
9125 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9127 if (MS.TrackOrigins) {
9129 SystemZOverflowOffset);
9130 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9135 void finalizeInstrumentation()
override {
9136 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9137 "finalizeInstrumentation called twice");
9138 if (!VAStartInstrumentationList.empty()) {
9145 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9147 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9153 Intrinsic::umin, CopySize,
9157 if (MS.TrackOrigins) {
9158 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9167 for (CallInst *OrigInst : VAStartInstrumentationList) {
9168 NextNodeIRBuilder IRB(OrigInst);
9169 Value *VAListTag = OrigInst->getArgOperand(0);
9170 copyRegSaveArea(IRB, VAListTag);
9171 copyOverflowArea(IRB, VAListTag);
9177struct VarArgI386Helper :
public VarArgHelperBase {
9178 AllocaInst *VAArgTLSCopy =
nullptr;
9179 Value *VAArgSize =
nullptr;
9181 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
9182 MemorySanitizerVisitor &MSV)
9183 : VarArgHelperBase(
F, MS, MSV, 4) {}
9185 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9186 const DataLayout &
DL =
F.getDataLayout();
9187 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9188 unsigned VAArgOffset = 0;
9191 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
9193 assert(
A->getType()->isPointerTy());
9195 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9197 if (ArgAlign < IntptrSize)
9198 ArgAlign =
Align(IntptrSize);
9199 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9201 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9203 Value *AShadowPtr, *AOriginPtr;
9204 std::tie(AShadowPtr, AOriginPtr) =
9205 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9215 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9217 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9218 if (
DL.isBigEndian()) {
9221 if (ArgSize < IntptrSize)
9222 VAArgOffset += (IntptrSize - ArgSize);
9225 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9228 VAArgOffset += ArgSize;
9234 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9237 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9240 void finalizeInstrumentation()
override {
9241 assert(!VAArgSize && !VAArgTLSCopy &&
9242 "finalizeInstrumentation called twice");
9244 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9245 Value *CopySize = VAArgSize;
9247 if (!VAStartInstrumentationList.empty()) {
9250 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9256 Intrinsic::umin, CopySize,
9264 for (CallInst *OrigInst : VAStartInstrumentationList) {
9265 NextNodeIRBuilder IRB(OrigInst);
9266 Value *VAListTag = OrigInst->getArgOperand(0);
9267 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9268 Value *RegSaveAreaPtrPtr =
9270 PointerType::get(*MS.C, 0));
9271 Value *RegSaveAreaPtr =
9272 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9273 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9274 const DataLayout &
DL =
F.getDataLayout();
9275 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9277 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9278 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9280 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9288struct VarArgGenericHelper :
public VarArgHelperBase {
9289 AllocaInst *VAArgTLSCopy =
nullptr;
9290 Value *VAArgSize =
nullptr;
9292 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
9293 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9294 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9296 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9297 unsigned VAArgOffset = 0;
9298 const DataLayout &
DL =
F.getDataLayout();
9299 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9304 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9305 if (
DL.isBigEndian()) {
9308 if (ArgSize < IntptrSize)
9309 VAArgOffset += (IntptrSize - ArgSize);
9311 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9312 VAArgOffset += ArgSize;
9313 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9319 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9322 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9325 void finalizeInstrumentation()
override {
9326 assert(!VAArgSize && !VAArgTLSCopy &&
9327 "finalizeInstrumentation called twice");
9329 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9330 Value *CopySize = VAArgSize;
9332 if (!VAStartInstrumentationList.empty()) {
9335 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9341 Intrinsic::umin, CopySize,
9349 for (CallInst *OrigInst : VAStartInstrumentationList) {
9350 NextNodeIRBuilder IRB(OrigInst);
9351 Value *VAListTag = OrigInst->getArgOperand(0);
9352 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9353 Value *RegSaveAreaPtrPtr =
9355 PointerType::get(*MS.C, 0));
9356 Value *RegSaveAreaPtr =
9357 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9358 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9359 const DataLayout &
DL =
F.getDataLayout();
9360 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9362 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9363 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9365 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9373using VarArgARM32Helper = VarArgGenericHelper;
9374using VarArgRISCVHelper = VarArgGenericHelper;
9375using VarArgMIPSHelper = VarArgGenericHelper;
9376using VarArgLoongArch64Helper = VarArgGenericHelper;
9377using VarArgHexagonHelper = VarArgGenericHelper;
9380struct VarArgNoOpHelper :
public VarArgHelper {
9381 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
9382 MemorySanitizerVisitor &MSV) {}
9384 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9386 void visitVAStartInst(VAStartInst &
I)
override {}
9388 void visitVACopyInst(VACopyInst &
I)
override {}
9390 void finalizeInstrumentation()
override {}
9396 MemorySanitizerVisitor &Visitor) {
9399 Triple TargetTriple(Func.getParent()->getTargetTriple());
9402 return new VarArgI386Helper(Func, Msan, Visitor);
9405 return new VarArgAMD64Helper(Func, Msan, Visitor);
9407 if (TargetTriple.
isARM())
9408 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9411 return new VarArgAArch64Helper(Func, Msan, Visitor);
9414 return new VarArgSystemZHelper(Func, Msan, Visitor);
9419 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9422 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9425 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9428 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9431 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9434 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9437 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9441 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9443 return new VarArgNoOpHelper(Func, Msan, Visitor);
9450 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9453 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9460 return Visitor.runOnFunction();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isStore(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
VarLocInsertPt getNextNode(const DbgRecord *DVR)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static bool isAMustTailRetVal(Value *RetVal)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
Module.h This file contains the declarations for the Module class.
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
front - 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.
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...
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
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.
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.
LLVM_ABI CallInst * CreateAndReduce(Value *Src)
Create a vector int AND reduction intrinsic of the source vector.
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 CallInst * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
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 CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
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="")
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)
StringRef - Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
bool isRISCV32() const
Tests whether the target is 32-bit RISC-V.
bool isPPC32() const
Tests whether the target is 32-bit PowerPC (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isPPC64() const
Tests whether the target is 64-bit PowerPC (little and big endian).
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isSystemZ() const
Tests whether the target is SystemZ.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isPPC_FP128Ty() const
Return true if this is powerpc long double.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
int getNumOccurrences() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
initializer< Ty > init(const Ty &Val)
Function * Kernel
Summary of a kernel (=entry point for target offloading).
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
FunctionAddr VTableAddr Value
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.
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.
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.
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.