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));
2637 void handleGenericVectorConvertIntrinsic(Instruction &
I,
bool FixedPoint) {
2638 [[maybe_unused]]
unsigned NumArgs =
I.getNumOperands();
2640 NumArgs = CI->arg_size();
2644 Value *Precision =
I.getOperand(1);
2645 insertCheckShadowOf(Precision, &
I);
2651 Value *S0 = getShadow(&
I, 0);
2660 setShadow(&
I, OutShadow);
2661 setOriginForNaryOp(
I);
2664 void visitFPToSIInst(CastInst &
I) {
2665 handleGenericVectorConvertIntrinsic(
I,
false);
2667 void visitFPToUIInst(CastInst &
I) {
2668 handleGenericVectorConvertIntrinsic(
I,
false);
2670 void visitSIToFPInst(CastInst &
I) {
2671 handleGenericVectorConvertIntrinsic(
I,
false);
2673 void visitUIToFPInst(CastInst &
I) {
2674 handleGenericVectorConvertIntrinsic(
I,
false);
2676 void visitFPExtInst(CastInst &
I) { handleShadowOr(
I); }
2677 void visitFPTruncInst(CastInst &
I) { handleShadowOr(
I); }
2708 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2712 void visitAnd(BinaryOperator &
I) {
2714 Value *V1 =
I.getOperand(0);
2715 Value *V2 =
I.getOperand(1);
2717 Value *S2 = getShadow(&
I, 1);
2719 Value *OutShadow = handleBitwiseAnd(IRB, V1, V2,
S1, S2);
2721 setShadow(&
I, OutShadow);
2722 setOriginForNaryOp(
I);
2725 void visitOr(BinaryOperator &
I) {
2738 Value *S2 = getShadow(&
I, 1);
2739 Value *V1 =
I.getOperand(0);
2740 Value *V2 =
I.getOperand(1);
2764 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2768 setOriginForNaryOp(
I);
2786 template <
bool CombineShadow>
class Combiner {
2787 Value *Shadow =
nullptr;
2788 Value *Origin =
nullptr;
2790 MemorySanitizerVisitor *MSV;
2793 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2794 : IRB(IRB), MSV(MSV) {}
2798 if (CombineShadow) {
2803 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2804 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2808 if (MSV->MS.TrackOrigins) {
2815 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2816 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2826 Value *OpShadow = MSV->getShadow(V);
2827 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2828 return Add(OpShadow, OpOrigin);
2833 void Done(Instruction *
I) {
2834 if (CombineShadow) {
2836 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2837 MSV->setShadow(
I, Shadow);
2839 if (MSV->MS.TrackOrigins) {
2841 MSV->setOrigin(
I, Origin);
2847 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2848 if (MSV->MS.TrackOrigins) {
2855 using ShadowAndOriginCombiner = Combiner<true>;
2856 using OriginCombiner = Combiner<false>;
2859 void setOriginForNaryOp(Instruction &
I) {
2860 if (!MS.TrackOrigins)
2863 OriginCombiner OC(
this, IRB);
2864 for (Use &
Op :
I.operands())
2869 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2871 "Vector of pointers is not a valid shadow type");
2881 Type *srcTy =
V->getType();
2884 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2885 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2886 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2904 Type *ShadowTy = getShadowTy(V);
2905 if (
V->getType() == ShadowTy)
2907 if (
V->getType()->isPtrOrPtrVectorTy())
2914 void handleShadowOr(Instruction &
I) {
2916 ShadowAndOriginCombiner SC(
this, IRB);
2917 for (Use &
Op :
I.operands())
2944 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2945 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2950 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2956 assert(NumElems % (ReductionFactor * Shards) == 0);
2961 for (
unsigned i = 0; i < ReductionFactor; i++) {
2962 SmallVector<int, 16>
Mask;
2964 for (
unsigned j = 0;
j < Shards;
j++) {
2965 unsigned Offset = NumElems / Shards *
j;
2967 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2971 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2996 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
2997 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
2999 assert(
I.getType()->isVectorTy());
3000 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3002 [[maybe_unused]] FixedVectorType *ParamType =
3006 [[maybe_unused]] FixedVectorType *
ReturnType =
3014 Value *FirstArgShadow = getShadow(&
I, 0);
3015 Value *SecondArgShadow =
nullptr;
3016 if (
I.arg_size() == 2)
3017 SecondArgShadow = getShadow(&
I, 1);
3019 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3020 FirstArgShadow, SecondArgShadow);
3022 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3024 setShadow(&
I, OrShadow);
3025 setOriginForNaryOp(
I);
3035 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3036 int ReinterpretElemWidth) {
3037 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3039 assert(
I.getType()->isVectorTy());
3040 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3042 FixedVectorType *ParamType =
3047 [[maybe_unused]] FixedVectorType *
ReturnType =
3054 FixedVectorType *ReinterpretShadowTy =
nullptr;
3062 Value *FirstArgShadow = getShadow(&
I, 0);
3063 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3073 Value *SecondArgShadow =
nullptr;
3074 if (
I.arg_size() == 2) {
3075 SecondArgShadow = getShadow(&
I, 1);
3076 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3079 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3080 FirstArgShadow, SecondArgShadow);
3082 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3084 setShadow(&
I, OrShadow);
3085 setOriginForNaryOp(
I);
3088 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3099 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3105 Type *EltTy = VTy->getElementType();
3107 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3108 if (ConstantInt *Elt =
3110 const APInt &
V = Elt->getValue();
3111 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3112 Elements.push_back(ConstantInt::get(EltTy, V2));
3114 Elements.push_back(ConstantInt::get(EltTy, 1));
3120 const APInt &
V = Elt->getValue();
3121 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3122 ShadowMul = ConstantInt::get(Ty, V2);
3124 ShadowMul = ConstantInt::get(Ty, 1);
3130 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3131 setOrigin(&
I, getOrigin(OtherArg));
3134 void visitMul(BinaryOperator &
I) {
3137 if (constOp0 && !constOp1)
3138 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3139 else if (constOp1 && !constOp0)
3140 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3145 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3146 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3147 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3148 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3149 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3150 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3152 void handleIntegerDiv(Instruction &
I) {
3155 insertCheckShadowOf(
I.getOperand(1), &
I);
3156 setShadow(&
I, getShadow(&
I, 0));
3157 setOrigin(&
I, getOrigin(&
I, 0));
3160 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3161 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3162 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3163 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3167 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3168 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3174 void handleEqualityComparison(ICmpInst &
I) {
3178 Value *Sa = getShadow(
A);
3179 Value *Sb = getShadow(
B);
3181 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3184 setOriginForNaryOp(
I);
3192 void handleRelationalComparisonExact(ICmpInst &
I) {
3196 Value *Sa = getShadow(
A);
3197 Value *Sb = getShadow(
B);
3208 bool IsSigned =
I.isSigned();
3210 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3220 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3225 return std::make_pair(Min, Max);
3228 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3229 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3235 setOriginForNaryOp(
I);
3242 void handleSignedRelationalComparison(ICmpInst &
I) {
3247 op =
I.getOperand(0);
3248 pre =
I.getPredicate();
3250 op =
I.getOperand(1);
3251 pre =
I.getSwappedPredicate();
3264 setShadow(&
I, Shadow);
3265 setOrigin(&
I, getOrigin(
op));
3271 void visitICmpInst(ICmpInst &
I) {
3276 if (
I.isEquality()) {
3277 handleEqualityComparison(
I);
3283 handleRelationalComparisonExact(
I);
3287 handleSignedRelationalComparison(
I);
3293 handleRelationalComparisonExact(
I);
3300 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3302 void handleShift(BinaryOperator &
I) {
3307 Value *S2 = getShadow(&
I, 1);
3310 Value *V2 =
I.getOperand(1);
3312 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3313 setOriginForNaryOp(
I);
3316 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3317 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3318 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3320 void handleFunnelShift(IntrinsicInst &
I) {
3324 Value *S0 = getShadow(&
I, 0);
3326 Value *S2 = getShadow(&
I, 2);
3329 Value *V2 =
I.getOperand(2);
3332 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3333 setOriginForNaryOp(
I);
3346 void visitMemMoveInst(MemMoveInst &
I) {
3347 getShadow(
I.getArgOperand(1));
3350 {I.getArgOperand(0), I.getArgOperand(1),
3351 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3369 void visitMemCpyInst(MemCpyInst &
I) {
3370 getShadow(
I.getArgOperand(1));
3373 {I.getArgOperand(0), I.getArgOperand(1),
3374 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3379 void visitMemSetInst(MemSetInst &
I) {
3383 {I.getArgOperand(0),
3384 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3385 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3389 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3391 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3397 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3401 Value *Addr =
I.getArgOperand(0);
3402 Value *Shadow = getShadow(&
I, 1);
3403 Value *ShadowPtr, *OriginPtr;
3407 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3412 insertCheckShadowOf(Addr, &
I);
3415 if (MS.TrackOrigins)
3424 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3428 Value *Addr =
I.getArgOperand(0);
3430 Type *ShadowTy = getShadowTy(&
I);
3431 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3432 if (PropagateShadow) {
3436 std::tie(ShadowPtr, OriginPtr) =
3437 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3441 setShadow(&
I, getCleanShadow(&
I));
3445 insertCheckShadowOf(Addr, &
I);
3447 if (MS.TrackOrigins) {
3448 if (PropagateShadow)
3449 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3451 setOrigin(&
I, getCleanOrigin());
3471 [[maybe_unused]]
bool
3472 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3473 unsigned int trailingFlags) {
3474 Type *RetTy =
I.getType();
3478 unsigned NumArgOperands =
I.arg_size();
3479 assert(NumArgOperands >= trailingFlags);
3480 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3481 Type *Ty =
I.getArgOperand(i)->getType();
3487 ShadowAndOriginCombiner SC(
this, IRB);
3488 for (
unsigned i = 0; i < NumArgOperands; ++i)
3489 SC.Add(
I.getArgOperand(i));
3506 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3507 unsigned NumArgOperands =
I.arg_size();
3508 if (NumArgOperands == 0)
3511 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3512 I.getArgOperand(1)->getType()->isVectorTy() &&
3513 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3515 return handleVectorStoreIntrinsic(
I);
3518 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3519 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3521 return handleVectorLoadIntrinsic(
I);
3524 if (
I.doesNotAccessMemory())
3525 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3533 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3534 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3536 dumpInst(
I,
"Heuristic");
3538 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3545 void handleInvariantGroup(IntrinsicInst &
I) {
3546 setShadow(&
I, getShadow(&
I, 0));
3547 setOrigin(&
I, getOrigin(&
I, 0));
3550 void handleLifetimeStart(IntrinsicInst &
I) {
3555 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3558 void handleBswap(IntrinsicInst &
I) {
3561 Type *OpType =
Op->getType();
3564 setOrigin(&
I, getOrigin(
Op));
3585 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3587 Value *Src =
I.getArgOperand(0);
3588 Value *SrcShadow = getShadow(Src);
3592 I.getType(),
I.getIntrinsicID(), {Src, False});
3594 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3597 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3599 Value *NotAllZeroShadow =
3601 Value *OutputShadow =
3602 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3608 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3611 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3613 setShadow(&
I, OutputShadow);
3614 setOriginForNaryOp(
I);
3623 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3643 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3648 Value *FullShadow = getCleanShadow(&
I);
3649 unsigned ShadowNumElems =
3651 unsigned FullShadowNumElems =
3654 assert((ShadowNumElems == FullShadowNumElems) ||
3655 (ShadowNumElems * 2 == FullShadowNumElems));
3657 if (ShadowNumElems == FullShadowNumElems) {
3658 FullShadow = Shadow;
3662 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3687 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3688 bool HasRoundingMode) {
3689 if (HasRoundingMode) {
3697 Value *Src =
I.getArgOperand(0);
3698 assert(Src->getType()->isVectorTy());
3702 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3705 Value *S0 = getShadow(&
I, 0);
3717 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3719 setShadow(&
I, FullShadow);
3720 setOriginForNaryOp(
I);
3741 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3742 bool HasRoundingMode =
false) {
3744 Value *CopyOp, *ConvertOp;
3746 assert((!HasRoundingMode ||
3748 "Invalid rounding mode");
3750 switch (
I.arg_size() - HasRoundingMode) {
3752 CopyOp =
I.getArgOperand(0);
3753 ConvertOp =
I.getArgOperand(1);
3756 ConvertOp =
I.getArgOperand(0);
3770 Value *ConvertShadow = getShadow(ConvertOp);
3771 Value *AggShadow =
nullptr;
3774 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3775 for (
int i = 1; i < NumUsedElements; ++i) {
3777 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3778 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3781 AggShadow = ConvertShadow;
3784 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3791 Value *ResultShadow = getShadow(CopyOp);
3793 for (
int i = 0; i < NumUsedElements; ++i) {
3795 ResultShadow, ConstantInt::getNullValue(EltTy),
3798 setShadow(&
I, ResultShadow);
3799 setOrigin(&
I, getOrigin(CopyOp));
3801 setShadow(&
I, getCleanShadow(&
I));
3802 setOrigin(&
I, getCleanOrigin());
3810 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3813 return CreateShadowCast(IRB, S2,
T,
true);
3821 return CreateShadowCast(IRB, S2,
T,
true);
3838 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3844 Value *S2 = getShadow(&
I, 1);
3846 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3847 Value *V1 =
I.getOperand(0);
3848 Value *V2 =
I.getOperand(1);
3850 {IRB.CreateBitCast(S1, V1->getType()), V2});
3852 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3853 setOriginForNaryOp(
I);
3858 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3859 unsigned X86_MMXSizeInBits = 64) {
3860 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3861 "Illegal MMX vector element size");
3863 X86_MMXSizeInBits / EltSizeInBits);
3870 case Intrinsic::x86_sse2_packsswb_128:
3871 case Intrinsic::x86_sse2_packuswb_128:
3872 return Intrinsic::x86_sse2_packsswb_128;
3874 case Intrinsic::x86_sse2_packssdw_128:
3875 case Intrinsic::x86_sse41_packusdw:
3876 return Intrinsic::x86_sse2_packssdw_128;
3878 case Intrinsic::x86_avx2_packsswb:
3879 case Intrinsic::x86_avx2_packuswb:
3880 return Intrinsic::x86_avx2_packsswb;
3882 case Intrinsic::x86_avx2_packssdw:
3883 case Intrinsic::x86_avx2_packusdw:
3884 return Intrinsic::x86_avx2_packssdw;
3886 case Intrinsic::x86_mmx_packsswb:
3887 case Intrinsic::x86_mmx_packuswb:
3888 return Intrinsic::x86_mmx_packsswb;
3890 case Intrinsic::x86_mmx_packssdw:
3891 return Intrinsic::x86_mmx_packssdw;
3893 case Intrinsic::x86_avx512_packssdw_512:
3894 case Intrinsic::x86_avx512_packusdw_512:
3895 return Intrinsic::x86_avx512_packssdw_512;
3897 case Intrinsic::x86_avx512_packsswb_512:
3898 case Intrinsic::x86_avx512_packuswb_512:
3899 return Intrinsic::x86_avx512_packsswb_512;
3915 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3916 unsigned MMXEltSizeInBits = 0) {
3920 Value *S2 = getShadow(&
I, 1);
3921 assert(
S1->getType()->isVectorTy());
3927 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3928 if (MMXEltSizeInBits) {
3936 if (MMXEltSizeInBits) {
3942 {S1_ext, S2_ext},
nullptr,
3943 "_msprop_vector_pack");
3944 if (MMXEltSizeInBits)
3947 setOriginForNaryOp(
I);
3951 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3952 SmallVector<Constant *, 4>
R(Width);
3964 const unsigned Width =
3971 Value *DstMaskV = createDppMask(Width, DstMask);
3988 void handleDppIntrinsic(IntrinsicInst &
I) {
3991 Value *S0 = getShadow(&
I, 0);
3995 const unsigned Width =
3997 assert(Width == 2 || Width == 4 || Width == 8);
4000 const unsigned SrcMask =
Mask >> 4;
4001 const unsigned DstMask =
Mask & 0xf;
4004 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4009 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4016 setOriginForNaryOp(
I);
4020 C = CreateAppToShadowCast(IRB,
C);
4029 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4034 Value *Sc = getShadow(&
I, 2);
4035 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4040 C = convertBlendvToSelectMask(IRB,
C);
4041 Sc = convertBlendvToSelectMask(IRB, Sc);
4047 handleSelectLikeInst(
I,
C,
T,
F);
4051 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4052 const unsigned SignificantBitsPerResultElement = 16;
4054 unsigned ZeroBitsPerResultElement =
4058 auto *Shadow0 = getShadow(&
I, 0);
4059 auto *Shadow1 = getShadow(&
I, 1);
4064 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4067 setOriginForNaryOp(
I);
4091 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4092 unsigned ReductionFactor,
4094 unsigned EltSizeInBits,
4098 [[maybe_unused]] FixedVectorType *
ReturnType =
4103 Value *Va =
nullptr;
4104 Value *Vb =
nullptr;
4105 Value *Sa =
nullptr;
4106 Value *Sb =
nullptr;
4108 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4109 if (
I.arg_size() == 2) {
4112 Va =
I.getOperand(0);
4113 Vb =
I.getOperand(1);
4115 Sa = getShadow(&
I, 0);
4116 Sb = getShadow(&
I, 1);
4117 }
else if (
I.arg_size() == 3) {
4119 Va =
I.getOperand(1);
4120 Vb =
I.getOperand(2);
4122 Sa = getShadow(&
I, 1);
4123 Sb = getShadow(&
I, 2);
4140 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4142 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4152 if (
I.arg_size() == 3) {
4153 [[maybe_unused]]
auto *AccumulatorType =
4155 assert(AccumulatorType == ReturnType);
4158 FixedVectorType *ImplicitReturnType =
4161 if (EltSizeInBits) {
4163 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4175 ReturnType->getNumElements() * ReductionFactor);
4192 VaInt = CreateAppToShadowCast(IRB, Va);
4193 VbInt = CreateAppToShadowCast(IRB, Vb);
4200 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4222 ImplicitReturnType);
4227 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4230 if (
I.arg_size() == 3)
4231 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4233 setShadow(&
I, OutShadow);
4234 setOriginForNaryOp(
I);
4251 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4252 bool PredicateAsOperand) {
4253 if (PredicateAsOperand) {
4255 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4263 Type *ResTy = getShadowTy(&
I);
4264 auto *Shadow0 = getShadow(&
I, 0);
4265 auto *Shadow1 = getShadow(&
I, 1);
4270 setOriginForNaryOp(
I);
4276 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4278 auto *Shadow0 = getShadow(&
I, 0);
4279 auto *Shadow1 = getShadow(&
I, 1);
4281 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4283 setOriginForNaryOp(
I);
4292 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4297 if (AllowShadowCast)
4298 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4302 setOriginForNaryOp(
I);
4312 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4316 Value *Shadow0 = getShadow(&
I, 0);
4322 setOriginForNaryOp(
I);
4328 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4332 Value *OperandShadow = getShadow(&
I, 0);
4334 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4342 setOrigin(&
I, getOrigin(&
I, 0));
4348 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4352 Value *OperandShadow = getShadow(&
I, 0);
4353 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4361 setOrigin(&
I, getOrigin(&
I, 0));
4364 void handleStmxcsr(IntrinsicInst &
I) {
4366 Value *Addr =
I.getArgOperand(0);
4369 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4374 insertCheckShadowOf(Addr, &
I);
4377 void handleLdmxcsr(IntrinsicInst &
I) {
4382 Value *Addr =
I.getArgOperand(0);
4385 Value *ShadowPtr, *OriginPtr;
4386 std::tie(ShadowPtr, OriginPtr) =
4387 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4390 insertCheckShadowOf(Addr, &
I);
4393 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4395 insertCheckShadow(Shadow, Origin, &
I);
4398 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4400 Value *Ptr =
I.getArgOperand(0);
4401 MaybeAlign
Align =
I.getParamAlign(0);
4403 Value *PassThru =
I.getArgOperand(2);
4406 insertCheckShadowOf(Ptr, &
I);
4407 insertCheckShadowOf(Mask, &
I);
4410 if (!PropagateShadow) {
4411 setShadow(&
I, getCleanShadow(&
I));
4412 setOrigin(&
I, getCleanOrigin());
4416 Type *ShadowTy = getShadowTy(&
I);
4418 auto [ShadowPtr, OriginPtr] =
4419 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4423 getShadow(PassThru),
"_msmaskedexpload");
4425 setShadow(&
I, Shadow);
4428 setOrigin(&
I, getCleanOrigin());
4431 void handleMaskedCompressStore(IntrinsicInst &
I) {
4433 Value *Values =
I.getArgOperand(0);
4434 Value *Ptr =
I.getArgOperand(1);
4435 MaybeAlign
Align =
I.getParamAlign(1);
4439 insertCheckShadowOf(Ptr, &
I);
4440 insertCheckShadowOf(Mask, &
I);
4443 Value *Shadow = getShadow(Values);
4444 Type *ElementShadowTy =
4446 auto [ShadowPtr, OriginPtrs] =
4447 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4454 void handleMaskedGather(IntrinsicInst &
I) {
4456 Value *Ptrs =
I.getArgOperand(0);
4457 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4459 Value *PassThru =
I.getArgOperand(2);
4461 Type *PtrsShadowTy = getShadowTy(Ptrs);
4463 insertCheckShadowOf(Mask, &
I);
4467 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4470 if (!PropagateShadow) {
4471 setShadow(&
I, getCleanShadow(&
I));
4472 setOrigin(&
I, getCleanOrigin());
4476 Type *ShadowTy = getShadowTy(&
I);
4478 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4479 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4483 getShadow(PassThru),
"_msmaskedgather");
4485 setShadow(&
I, Shadow);
4488 setOrigin(&
I, getCleanOrigin());
4491 void handleMaskedScatter(IntrinsicInst &
I) {
4493 Value *Values =
I.getArgOperand(0);
4494 Value *Ptrs =
I.getArgOperand(1);
4495 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4498 Type *PtrsShadowTy = getShadowTy(Ptrs);
4500 insertCheckShadowOf(Mask, &
I);
4504 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4507 Value *Shadow = getShadow(Values);
4508 Type *ElementShadowTy =
4510 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4511 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4522 void handleMaskedStore(IntrinsicInst &
I) {
4524 Value *
V =
I.getArgOperand(0);
4525 Value *Ptr =
I.getArgOperand(1);
4526 const Align Alignment =
I.getParamAlign(1).valueOrOne();
4528 Value *Shadow = getShadow(V);
4531 insertCheckShadowOf(Ptr, &
I);
4532 insertCheckShadowOf(Mask, &
I);
4537 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4538 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4542 if (!MS.TrackOrigins)
4545 auto &
DL =
F.getDataLayout();
4546 paintOrigin(IRB, getOrigin(V), OriginPtr,
4555 void handleMaskedLoad(IntrinsicInst &
I) {
4557 Value *Ptr =
I.getArgOperand(0);
4558 const Align Alignment =
I.getParamAlign(0).valueOrOne();
4560 Value *PassThru =
I.getArgOperand(2);
4563 insertCheckShadowOf(Ptr, &
I);
4564 insertCheckShadowOf(Mask, &
I);
4567 if (!PropagateShadow) {
4568 setShadow(&
I, getCleanShadow(&
I));
4569 setOrigin(&
I, getCleanOrigin());
4573 Type *ShadowTy = getShadowTy(&
I);
4574 Value *ShadowPtr, *OriginPtr;
4575 std::tie(ShadowPtr, OriginPtr) =
4576 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4578 getShadow(PassThru),
"_msmaskedld"));
4580 if (!MS.TrackOrigins)
4587 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4592 setOrigin(&
I, Origin);
4608 void handleAVXMaskedStore(IntrinsicInst &
I) {
4613 Value *Dst =
I.getArgOperand(0);
4614 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4619 Value *Src =
I.getArgOperand(2);
4624 Value *SrcShadow = getShadow(Src);
4627 insertCheckShadowOf(Dst, &
I);
4628 insertCheckShadowOf(Mask, &
I);
4631 Value *DstShadowPtr;
4632 Value *DstOriginPtr;
4633 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4634 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4636 SmallVector<Value *, 2> ShadowArgs;
4637 ShadowArgs.
append(1, DstShadowPtr);
4638 ShadowArgs.
append(1, Mask);
4649 if (!MS.TrackOrigins)
4653 auto &
DL =
F.getDataLayout();
4654 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4655 DL.getTypeStoreSize(SrcShadow->
getType()),
4674 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4679 Value *Src =
I.getArgOperand(0);
4680 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4688 insertCheckShadowOf(Mask, &
I);
4691 Type *SrcShadowTy = getShadowTy(Src);
4692 Value *SrcShadowPtr, *SrcOriginPtr;
4693 std::tie(SrcShadowPtr, SrcOriginPtr) =
4694 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4696 SmallVector<Value *, 2> ShadowArgs;
4697 ShadowArgs.
append(1, SrcShadowPtr);
4698 ShadowArgs.
append(1, Mask);
4707 if (!MS.TrackOrigins)
4714 setOrigin(&
I, PtrSrcOrigin);
4723 assert(isFixedIntVector(Idx));
4724 auto IdxVectorSize =
4732 auto *IdxShadow = getShadow(Idx);
4737 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4742 void handleAVXVpermilvar(IntrinsicInst &
I) {
4744 Value *Shadow = getShadow(&
I, 0);
4745 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4749 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4751 {Shadow, I.getArgOperand(1)});
4754 setOriginForNaryOp(
I);
4759 void handleAVXVpermi2var(IntrinsicInst &
I) {
4764 [[maybe_unused]]
auto ArgVectorSize =
4767 ->getNumElements() == ArgVectorSize);
4769 ->getNumElements() == ArgVectorSize);
4770 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4771 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4772 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4774 Value *AShadow = getShadow(&
I, 0);
4775 Value *Idx =
I.getArgOperand(1);
4776 Value *BShadow = getShadow(&
I, 2);
4778 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4782 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4783 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4785 {AShadow, Idx, BShadow});
4787 setOriginForNaryOp(
I);
4790 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4794 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4798 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4799 return isFixedIntVectorTy(
V->getType());
4802 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4803 return isFixedFPVectorTy(
V->getType());
4825 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4830 Value *WriteThrough;
4834 WriteThrough =
I.getOperand(2);
4835 Mask =
I.getOperand(3);
4838 WriteThrough =
I.getOperand(1);
4839 Mask =
I.getOperand(2);
4844 assert(isFixedIntVector(WriteThrough));
4846 unsigned ANumElements =
4848 [[maybe_unused]]
unsigned WriteThruNumElements =
4850 assert(ANumElements == WriteThruNumElements ||
4851 ANumElements * 2 == WriteThruNumElements);
4854 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4855 assert(ANumElements == MaskNumElements ||
4856 ANumElements * 2 == MaskNumElements);
4858 assert(WriteThruNumElements == MaskNumElements);
4862 insertCheckShadowOf(Mask, &
I);
4872 Value *AShadow = getShadow(
A);
4873 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4875 if (ANumElements * 2 == MaskNumElements) {
4887 "_ms_mask_bitcast");
4897 getShadowTy(&
I),
"_ms_a_shadow");
4899 Value *WriteThroughShadow = getShadow(WriteThrough);
4901 "_ms_writethru_select");
4903 setShadow(&
I, Shadow);
4904 setOriginForNaryOp(
I);
4912 void handleBmiIntrinsic(IntrinsicInst &
I) {
4914 Type *ShadowTy = getShadowTy(&
I);
4917 Value *SMask = getShadow(&
I, 1);
4922 {getShadow(&I, 0), I.getOperand(1)});
4925 setOriginForNaryOp(
I);
4928 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4929 SmallVector<int, 8>
Mask;
4930 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4944 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4949 "pclmul 3rd operand must be a constant");
4952 getPclmulMask(Width, Imm & 0x01));
4954 getPclmulMask(Width, Imm & 0x10));
4955 ShadowAndOriginCombiner SOC(
this, IRB);
4956 SOC.Add(Shuf0, getOrigin(&
I, 0));
4957 SOC.Add(Shuf1, getOrigin(&
I, 1));
4962 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4967 Value *Second = getShadow(&
I, 1);
4969 SmallVector<int, 16>
Mask;
4970 Mask.push_back(Width);
4971 for (
unsigned i = 1; i < Width; i++)
4975 setShadow(&
I, Shadow);
4976 setOriginForNaryOp(
I);
4979 void handleVtestIntrinsic(IntrinsicInst &
I) {
4981 Value *Shadow0 = getShadow(&
I, 0);
4982 Value *Shadow1 = getShadow(&
I, 1);
4988 setShadow(&
I, Shadow);
4989 setOriginForNaryOp(
I);
4992 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
4997 Value *Second = getShadow(&
I, 1);
5000 SmallVector<int, 16>
Mask;
5001 Mask.push_back(Width);
5002 for (
unsigned i = 1; i < Width; i++)
5006 setShadow(&
I, Shadow);
5007 setOriginForNaryOp(
I);
5013 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5014 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5019 ShadowAndOriginCombiner SC(
this, IRB);
5020 SC.Add(
I.getArgOperand(0));
5028 void handleAbsIntrinsic(IntrinsicInst &
I) {
5030 Value *Src =
I.getArgOperand(0);
5031 Value *IsIntMinPoison =
I.getArgOperand(1);
5033 assert(
I.getType()->isIntOrIntVectorTy());
5035 assert(Src->getType() ==
I.getType());
5041 Value *SrcShadow = getShadow(Src);
5045 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5048 Value *PoisonedShadow = getPoisonedShadow(Src);
5049 Value *PoisonedIfIntMinShadow =
5052 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5054 setShadow(&
I, Shadow);
5055 setOrigin(&
I, getOrigin(&
I, 0));
5058 void handleIsFpClass(IntrinsicInst &
I) {
5060 Value *Shadow = getShadow(&
I, 0);
5061 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5062 setOrigin(&
I, getOrigin(&
I, 0));
5065 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5067 Value *Shadow0 = getShadow(&
I, 0);
5068 Value *Shadow1 = getShadow(&
I, 1);
5071 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5077 setShadow(&
I, Shadow);
5078 setOriginForNaryOp(
I);
5084 Value *Shadow = getShadow(V);
5106 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5111 Value *WriteThrough =
I.getOperand(1);
5115 assert(isFixedIntVector(WriteThrough));
5117 unsigned ANumElements =
5119 unsigned OutputNumElements =
5121 assert(ANumElements == OutputNumElements ||
5122 ANumElements * 2 == OutputNumElements);
5132 insertCheckShadowOf(Mask, &
I);
5135 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5136 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5137 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5148 if (ANumElements != OutputNumElements) {
5150 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5157 Value *AShadow = getShadow(
A);
5161 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5171 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5172 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5174 Value *WriteThroughShadow = getShadow(WriteThrough);
5177 setShadow(&
I, Shadow);
5178 setOriginForNaryOp(
I);
5212 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5213 SmallVector<unsigned, 4> DataIndices,
5214 unsigned WriteThruIndex,
5215 unsigned MaskIndex) {
5218 unsigned NumArgs =
I.arg_size();
5220 assert(WriteThruIndex < NumArgs);
5221 assert(MaskIndex < NumArgs);
5222 assert(WriteThruIndex != MaskIndex);
5223 Value *WriteThru =
I.getOperand(WriteThruIndex);
5225 unsigned OutputNumElements =
5230 bool isData[16] = {
false};
5232 for (
unsigned i : DataIndices) {
5234 assert(i != WriteThruIndex);
5241 [[maybe_unused]]
unsigned ANumElements =
5243 assert(ANumElements == OutputNumElements);
5248 assert(isFixedFPVector(WriteThru));
5250 for (
unsigned i = 0; i < NumArgs; ++i) {
5251 if (!isData[i] && i != WriteThruIndex) {
5254 assert(
I.getOperand(i)->getType()->isIntegerTy());
5255 insertCheckShadowOf(
I.getOperand(i), &
I);
5260 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5261 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5262 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5269 Value *DataShadow =
nullptr;
5270 for (
unsigned i : DataIndices) {
5273 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5275 DataShadow = getShadow(
A);
5283 Value *WriteThruShadow = getShadow(WriteThru);
5286 setShadow(&
I, Shadow);
5288 setOriginForNaryOp(
I);
5298 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5304 Value *WriteThrough =
I.getOperand(2);
5311 insertCheckShadowOf(Mask, &
I);
5315 unsigned NumElements =
5317 assert(NumElements == 8);
5318 assert(
A->getType() ==
B->getType());
5320 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5323 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5324 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5326 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5328 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5335 Value *AShadow = getShadow(
A);
5336 Value *DstLowerShadow =
5337 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5339 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5342 setShadow(&
I, DstShadow);
5343 setOriginForNaryOp(
I);
5373 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5384 ->getScalarSizeInBits() == 8);
5386 assert(
A->getType() ==
X->getType());
5388 assert(
B->getType()->isIntegerTy());
5389 assert(
B->getType()->getScalarSizeInBits() == 8);
5391 assert(
I.getType() ==
A->getType());
5393 Value *AShadow = getShadow(
A);
5394 Value *XShadow = getShadow(
X);
5395 Value *BZeroShadow = getCleanShadow(
B);
5398 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5400 {X, AShadow, BZeroShadow});
5402 {XShadow, A, BZeroShadow});
5405 Value *BShadow = getShadow(
B);
5406 Value *BBroadcastShadow = getCleanShadow(AShadow);
5411 for (
unsigned i = 0; i < NumElements; i++)
5415 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5416 setOriginForNaryOp(
I);
5430 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5431 unsigned int numArgs =
I.arg_size();
5434 assert(
I.getType()->isStructTy());
5444 assert(4 <= numArgs && numArgs <= 6);
5458 for (
unsigned int i = 0; i < numArgs - 2; i++)
5459 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5462 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5466 insertCheckShadowOf(LaneNumber, &
I);
5469 Value *Src =
I.getArgOperand(numArgs - 1);
5470 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5472 Type *SrcShadowTy = getShadowTy(Src);
5473 auto [SrcShadowPtr, SrcOriginPtr] =
5474 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5484 if (!MS.TrackOrigins)
5488 setOrigin(&
I, PtrSrcOrigin);
5505 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5509 int numArgOperands =
I.arg_size();
5512 assert(numArgOperands >= 1);
5513 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5515 int skipTrailingOperands = 1;
5518 insertCheckShadowOf(Addr, &
I);
5522 skipTrailingOperands++;
5523 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5525 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5528 SmallVector<Value *, 8> ShadowArgs;
5530 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5532 Value *Shadow = getShadow(&
I, i);
5533 ShadowArgs.
append(1, Shadow);
5550 (numArgOperands - skipTrailingOperands));
5551 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5555 I.getArgOperand(numArgOperands - skipTrailingOperands));
5557 Value *OutputShadowPtr, *OutputOriginPtr;
5559 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5560 Addr, IRB, OutputShadowTy,
Align(1),
true);
5561 ShadowArgs.
append(1, OutputShadowPtr);
5567 if (MS.TrackOrigins) {
5575 OriginCombiner OC(
this, IRB);
5576 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5577 OC.Add(
I.getArgOperand(i));
5579 const DataLayout &
DL =
F.getDataLayout();
5580 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5613 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5617 Value *
R =
I.getArgOperand(0);
5618 Value *
A =
I.getArgOperand(1);
5619 Value *
B =
I.getArgOperand(2);
5621 assert(
I.getType() ==
R->getType());
5646 Value *ShadowR = getShadow(&
I, 0);
5647 Value *ShadowA = getShadow(&
I, 1);
5648 Value *ShadowB = getShadow(&
I, 2);
5666 {getCleanShadow(RTy), ShadowA, ShadowB});
5692 {RZeros, ShadowA, ShadowB});
5706 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5707 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5709 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5711 setOriginForNaryOp(
I);
5736 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5738 unsigned int trailingVerbatimArgs) {
5741 assert(trailingVerbatimArgs <
I.arg_size());
5743 SmallVector<Value *, 8> ShadowArgs;
5745 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5746 Value *Shadow = getShadow(&
I, i);
5754 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5756 Value *Arg =
I.getArgOperand(i);
5762 Value *CombinedShadow = CI;
5765 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5768 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5769 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5774 setOriginForNaryOp(
I);
5780 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5786 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5787 switch (
I.getIntrinsicID()) {
5788 case Intrinsic::uadd_with_overflow:
5789 case Intrinsic::sadd_with_overflow:
5790 case Intrinsic::usub_with_overflow:
5791 case Intrinsic::ssub_with_overflow:
5792 case Intrinsic::umul_with_overflow:
5793 case Intrinsic::smul_with_overflow:
5794 handleArithmeticWithOverflow(
I);
5796 case Intrinsic::abs:
5797 handleAbsIntrinsic(
I);
5799 case Intrinsic::bitreverse:
5800 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5803 case Intrinsic::is_fpclass:
5806 case Intrinsic::lifetime_start:
5807 handleLifetimeStart(
I);
5809 case Intrinsic::launder_invariant_group:
5810 case Intrinsic::strip_invariant_group:
5811 handleInvariantGroup(
I);
5813 case Intrinsic::bswap:
5816 case Intrinsic::ctlz:
5817 case Intrinsic::cttz:
5818 handleCountLeadingTrailingZeros(
I);
5820 case Intrinsic::masked_compressstore:
5821 handleMaskedCompressStore(
I);
5823 case Intrinsic::masked_expandload:
5824 handleMaskedExpandLoad(
I);
5826 case Intrinsic::masked_gather:
5827 handleMaskedGather(
I);
5829 case Intrinsic::masked_scatter:
5830 handleMaskedScatter(
I);
5832 case Intrinsic::masked_store:
5833 handleMaskedStore(
I);
5835 case Intrinsic::masked_load:
5836 handleMaskedLoad(
I);
5838 case Intrinsic::vector_reduce_and:
5839 handleVectorReduceAndIntrinsic(
I);
5841 case Intrinsic::vector_reduce_or:
5842 handleVectorReduceOrIntrinsic(
I);
5845 case Intrinsic::vector_reduce_add:
5846 case Intrinsic::vector_reduce_xor:
5847 case Intrinsic::vector_reduce_mul:
5850 case Intrinsic::vector_reduce_smax:
5851 case Intrinsic::vector_reduce_smin:
5852 case Intrinsic::vector_reduce_umax:
5853 case Intrinsic::vector_reduce_umin:
5856 case Intrinsic::vector_reduce_fmax:
5857 case Intrinsic::vector_reduce_fmin:
5858 handleVectorReduceIntrinsic(
I,
false);
5861 case Intrinsic::vector_reduce_fadd:
5862 case Intrinsic::vector_reduce_fmul:
5863 handleVectorReduceWithStarterIntrinsic(
I);
5866 case Intrinsic::scmp:
5867 case Intrinsic::ucmp: {
5872 case Intrinsic::fshl:
5873 case Intrinsic::fshr:
5874 handleFunnelShift(
I);
5877 case Intrinsic::is_constant:
5879 setShadow(&
I, getCleanShadow(&
I));
5880 setOrigin(&
I, getCleanOrigin());
5887 case Intrinsic::fptosi_sat:
5888 case Intrinsic::fptoui_sat:
5889 handleGenericVectorConvertIntrinsic(
I,
false);
5899 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
5900 switch (
I.getIntrinsicID()) {
5901 case Intrinsic::x86_sse_stmxcsr:
5904 case Intrinsic::x86_sse_ldmxcsr:
5911 case Intrinsic::x86_avx512_vcvtsd2usi64:
5912 case Intrinsic::x86_avx512_vcvtsd2usi32:
5913 case Intrinsic::x86_avx512_vcvtss2usi64:
5914 case Intrinsic::x86_avx512_vcvtss2usi32:
5915 case Intrinsic::x86_avx512_cvttss2usi64:
5916 case Intrinsic::x86_avx512_cvttss2usi:
5917 case Intrinsic::x86_avx512_cvttsd2usi64:
5918 case Intrinsic::x86_avx512_cvttsd2usi:
5919 case Intrinsic::x86_avx512_cvtusi2ss:
5920 case Intrinsic::x86_avx512_cvtusi642sd:
5921 case Intrinsic::x86_avx512_cvtusi642ss:
5922 handleSSEVectorConvertIntrinsic(
I, 1,
true);
5924 case Intrinsic::x86_sse2_cvtsd2si64:
5925 case Intrinsic::x86_sse2_cvtsd2si:
5926 case Intrinsic::x86_sse2_cvtsd2ss:
5927 case Intrinsic::x86_sse2_cvttsd2si64:
5928 case Intrinsic::x86_sse2_cvttsd2si:
5929 case Intrinsic::x86_sse_cvtss2si64:
5930 case Intrinsic::x86_sse_cvtss2si:
5931 case Intrinsic::x86_sse_cvttss2si64:
5932 case Intrinsic::x86_sse_cvttss2si:
5933 handleSSEVectorConvertIntrinsic(
I, 1);
5935 case Intrinsic::x86_sse_cvtps2pi:
5936 case Intrinsic::x86_sse_cvttps2pi:
5937 handleSSEVectorConvertIntrinsic(
I, 2);
5945 case Intrinsic::x86_vcvtps2ph_128:
5946 case Intrinsic::x86_vcvtps2ph_256: {
5947 handleSSEVectorConvertIntrinsicByProp(
I,
true);
5956 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
5957 handleAVX512VectorConvertFPToInt(
I,
false);
5962 case Intrinsic::x86_sse2_cvtpd2ps:
5963 case Intrinsic::x86_sse2_cvtps2dq:
5964 case Intrinsic::x86_sse2_cvtpd2dq:
5965 case Intrinsic::x86_sse2_cvttps2dq:
5966 case Intrinsic::x86_sse2_cvttpd2dq:
5967 case Intrinsic::x86_avx_cvt_pd2_ps_256:
5968 case Intrinsic::x86_avx_cvt_ps2dq_256:
5969 case Intrinsic::x86_avx_cvt_pd2dq_256:
5970 case Intrinsic::x86_avx_cvtt_ps2dq_256:
5971 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
5972 handleSSEVectorConvertIntrinsicByProp(
I,
false);
5983 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
5984 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
5985 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
5986 handleAVX512VectorConvertFPToInt(
I,
true);
5990 case Intrinsic::x86_avx512_psll_w_512:
5991 case Intrinsic::x86_avx512_psll_d_512:
5992 case Intrinsic::x86_avx512_psll_q_512:
5993 case Intrinsic::x86_avx512_pslli_w_512:
5994 case Intrinsic::x86_avx512_pslli_d_512:
5995 case Intrinsic::x86_avx512_pslli_q_512:
5996 case Intrinsic::x86_avx512_psrl_w_512:
5997 case Intrinsic::x86_avx512_psrl_d_512:
5998 case Intrinsic::x86_avx512_psrl_q_512:
5999 case Intrinsic::x86_avx512_psra_w_512:
6000 case Intrinsic::x86_avx512_psra_d_512:
6001 case Intrinsic::x86_avx512_psra_q_512:
6002 case Intrinsic::x86_avx512_psrli_w_512:
6003 case Intrinsic::x86_avx512_psrli_d_512:
6004 case Intrinsic::x86_avx512_psrli_q_512:
6005 case Intrinsic::x86_avx512_psrai_w_512:
6006 case Intrinsic::x86_avx512_psrai_d_512:
6007 case Intrinsic::x86_avx512_psrai_q_512:
6008 case Intrinsic::x86_avx512_psra_q_256:
6009 case Intrinsic::x86_avx512_psra_q_128:
6010 case Intrinsic::x86_avx512_psrai_q_256:
6011 case Intrinsic::x86_avx512_psrai_q_128:
6012 case Intrinsic::x86_avx2_psll_w:
6013 case Intrinsic::x86_avx2_psll_d:
6014 case Intrinsic::x86_avx2_psll_q:
6015 case Intrinsic::x86_avx2_pslli_w:
6016 case Intrinsic::x86_avx2_pslli_d:
6017 case Intrinsic::x86_avx2_pslli_q:
6018 case Intrinsic::x86_avx2_psrl_w:
6019 case Intrinsic::x86_avx2_psrl_d:
6020 case Intrinsic::x86_avx2_psrl_q:
6021 case Intrinsic::x86_avx2_psra_w:
6022 case Intrinsic::x86_avx2_psra_d:
6023 case Intrinsic::x86_avx2_psrli_w:
6024 case Intrinsic::x86_avx2_psrli_d:
6025 case Intrinsic::x86_avx2_psrli_q:
6026 case Intrinsic::x86_avx2_psrai_w:
6027 case Intrinsic::x86_avx2_psrai_d:
6028 case Intrinsic::x86_sse2_psll_w:
6029 case Intrinsic::x86_sse2_psll_d:
6030 case Intrinsic::x86_sse2_psll_q:
6031 case Intrinsic::x86_sse2_pslli_w:
6032 case Intrinsic::x86_sse2_pslli_d:
6033 case Intrinsic::x86_sse2_pslli_q:
6034 case Intrinsic::x86_sse2_psrl_w:
6035 case Intrinsic::x86_sse2_psrl_d:
6036 case Intrinsic::x86_sse2_psrl_q:
6037 case Intrinsic::x86_sse2_psra_w:
6038 case Intrinsic::x86_sse2_psra_d:
6039 case Intrinsic::x86_sse2_psrli_w:
6040 case Intrinsic::x86_sse2_psrli_d:
6041 case Intrinsic::x86_sse2_psrli_q:
6042 case Intrinsic::x86_sse2_psrai_w:
6043 case Intrinsic::x86_sse2_psrai_d:
6044 case Intrinsic::x86_mmx_psll_w:
6045 case Intrinsic::x86_mmx_psll_d:
6046 case Intrinsic::x86_mmx_psll_q:
6047 case Intrinsic::x86_mmx_pslli_w:
6048 case Intrinsic::x86_mmx_pslli_d:
6049 case Intrinsic::x86_mmx_pslli_q:
6050 case Intrinsic::x86_mmx_psrl_w:
6051 case Intrinsic::x86_mmx_psrl_d:
6052 case Intrinsic::x86_mmx_psrl_q:
6053 case Intrinsic::x86_mmx_psra_w:
6054 case Intrinsic::x86_mmx_psra_d:
6055 case Intrinsic::x86_mmx_psrli_w:
6056 case Intrinsic::x86_mmx_psrli_d:
6057 case Intrinsic::x86_mmx_psrli_q:
6058 case Intrinsic::x86_mmx_psrai_w:
6059 case Intrinsic::x86_mmx_psrai_d:
6060 handleVectorShiftIntrinsic(
I,
false);
6062 case Intrinsic::x86_avx2_psllv_d:
6063 case Intrinsic::x86_avx2_psllv_d_256:
6064 case Intrinsic::x86_avx512_psllv_d_512:
6065 case Intrinsic::x86_avx2_psllv_q:
6066 case Intrinsic::x86_avx2_psllv_q_256:
6067 case Intrinsic::x86_avx512_psllv_q_512:
6068 case Intrinsic::x86_avx2_psrlv_d:
6069 case Intrinsic::x86_avx2_psrlv_d_256:
6070 case Intrinsic::x86_avx512_psrlv_d_512:
6071 case Intrinsic::x86_avx2_psrlv_q:
6072 case Intrinsic::x86_avx2_psrlv_q_256:
6073 case Intrinsic::x86_avx512_psrlv_q_512:
6074 case Intrinsic::x86_avx2_psrav_d:
6075 case Intrinsic::x86_avx2_psrav_d_256:
6076 case Intrinsic::x86_avx512_psrav_d_512:
6077 case Intrinsic::x86_avx512_psrav_q_128:
6078 case Intrinsic::x86_avx512_psrav_q_256:
6079 case Intrinsic::x86_avx512_psrav_q_512:
6080 handleVectorShiftIntrinsic(
I,
true);
6084 case Intrinsic::x86_sse2_packsswb_128:
6085 case Intrinsic::x86_sse2_packssdw_128:
6086 case Intrinsic::x86_sse2_packuswb_128:
6087 case Intrinsic::x86_sse41_packusdw:
6088 case Intrinsic::x86_avx2_packsswb:
6089 case Intrinsic::x86_avx2_packssdw:
6090 case Intrinsic::x86_avx2_packuswb:
6091 case Intrinsic::x86_avx2_packusdw:
6097 case Intrinsic::x86_avx512_packsswb_512:
6098 case Intrinsic::x86_avx512_packssdw_512:
6099 case Intrinsic::x86_avx512_packuswb_512:
6100 case Intrinsic::x86_avx512_packusdw_512:
6101 handleVectorPackIntrinsic(
I);
6104 case Intrinsic::x86_sse41_pblendvb:
6105 case Intrinsic::x86_sse41_blendvpd:
6106 case Intrinsic::x86_sse41_blendvps:
6107 case Intrinsic::x86_avx_blendv_pd_256:
6108 case Intrinsic::x86_avx_blendv_ps_256:
6109 case Intrinsic::x86_avx2_pblendvb:
6110 handleBlendvIntrinsic(
I);
6113 case Intrinsic::x86_avx_dp_ps_256:
6114 case Intrinsic::x86_sse41_dppd:
6115 case Intrinsic::x86_sse41_dpps:
6116 handleDppIntrinsic(
I);
6119 case Intrinsic::x86_mmx_packsswb:
6120 case Intrinsic::x86_mmx_packuswb:
6121 handleVectorPackIntrinsic(
I, 16);
6124 case Intrinsic::x86_mmx_packssdw:
6125 handleVectorPackIntrinsic(
I, 32);
6128 case Intrinsic::x86_mmx_psad_bw:
6129 handleVectorSadIntrinsic(
I,
true);
6131 case Intrinsic::x86_sse2_psad_bw:
6132 case Intrinsic::x86_avx2_psad_bw:
6133 handleVectorSadIntrinsic(
I);
6159 case Intrinsic::x86_sse2_pmadd_wd:
6160 case Intrinsic::x86_avx2_pmadd_wd:
6161 case Intrinsic::x86_avx512_pmaddw_d_512:
6162 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6163 case Intrinsic::x86_avx2_pmadd_ub_sw:
6164 case Intrinsic::x86_avx512_pmaddubs_w_512:
6165 handleVectorDotProductIntrinsic(
I, 2,
6172 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6173 handleVectorDotProductIntrinsic(
I, 2,
6180 case Intrinsic::x86_mmx_pmadd_wd:
6181 handleVectorDotProductIntrinsic(
I, 2,
6190 case Intrinsic::aarch64_neon_bfmlalt:
6191 handleVectorDotProductIntrinsic(
I, 2,
6199 case Intrinsic::aarch64_neon_bfmlalb:
6200 handleVectorDotProductIntrinsic(
I, 2,
6298 case Intrinsic::x86_avx512_vpdpbusd_128:
6299 case Intrinsic::x86_avx512_vpdpbusd_256:
6300 case Intrinsic::x86_avx512_vpdpbusd_512:
6301 case Intrinsic::x86_avx512_vpdpbusds_128:
6302 case Intrinsic::x86_avx512_vpdpbusds_256:
6303 case Intrinsic::x86_avx512_vpdpbusds_512:
6304 case Intrinsic::x86_avx2_vpdpbssd_128:
6305 case Intrinsic::x86_avx2_vpdpbssd_256:
6306 case Intrinsic::x86_avx10_vpdpbssd_512:
6307 case Intrinsic::x86_avx2_vpdpbssds_128:
6308 case Intrinsic::x86_avx2_vpdpbssds_256:
6309 case Intrinsic::x86_avx10_vpdpbssds_512:
6310 case Intrinsic::x86_avx2_vpdpbsud_128:
6311 case Intrinsic::x86_avx2_vpdpbsud_256:
6312 case Intrinsic::x86_avx10_vpdpbsud_512:
6313 case Intrinsic::x86_avx2_vpdpbsuds_128:
6314 case Intrinsic::x86_avx2_vpdpbsuds_256:
6315 case Intrinsic::x86_avx10_vpdpbsuds_512:
6316 case Intrinsic::x86_avx2_vpdpbuud_128:
6317 case Intrinsic::x86_avx2_vpdpbuud_256:
6318 case Intrinsic::x86_avx10_vpdpbuud_512:
6319 case Intrinsic::x86_avx2_vpdpbuuds_128:
6320 case Intrinsic::x86_avx2_vpdpbuuds_256:
6321 case Intrinsic::x86_avx10_vpdpbuuds_512:
6322 handleVectorDotProductIntrinsic(
I, 4,
6420 case Intrinsic::x86_avx512_vpdpwssd_128:
6421 case Intrinsic::x86_avx512_vpdpwssd_256:
6422 case Intrinsic::x86_avx512_vpdpwssd_512:
6423 case Intrinsic::x86_avx512_vpdpwssds_128:
6424 case Intrinsic::x86_avx512_vpdpwssds_256:
6425 case Intrinsic::x86_avx512_vpdpwssds_512:
6426 case Intrinsic::x86_avx2_vpdpwsud_128:
6427 case Intrinsic::x86_avx2_vpdpwsud_256:
6428 case Intrinsic::x86_avx10_vpdpwsud_512:
6429 case Intrinsic::x86_avx2_vpdpwsuds_128:
6430 case Intrinsic::x86_avx2_vpdpwsuds_256:
6431 case Intrinsic::x86_avx10_vpdpwsuds_512:
6432 case Intrinsic::x86_avx2_vpdpwusd_128:
6433 case Intrinsic::x86_avx2_vpdpwusd_256:
6434 case Intrinsic::x86_avx10_vpdpwusd_512:
6435 case Intrinsic::x86_avx2_vpdpwusds_128:
6436 case Intrinsic::x86_avx2_vpdpwusds_256:
6437 case Intrinsic::x86_avx10_vpdpwusds_512:
6438 case Intrinsic::x86_avx2_vpdpwuud_128:
6439 case Intrinsic::x86_avx2_vpdpwuud_256:
6440 case Intrinsic::x86_avx10_vpdpwuud_512:
6441 case Intrinsic::x86_avx2_vpdpwuuds_128:
6442 case Intrinsic::x86_avx2_vpdpwuuds_256:
6443 case Intrinsic::x86_avx10_vpdpwuuds_512:
6444 handleVectorDotProductIntrinsic(
I, 2,
6458 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6459 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6460 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6461 handleVectorDotProductIntrinsic(
I, 2,
6467 case Intrinsic::x86_sse_cmp_ss:
6468 case Intrinsic::x86_sse2_cmp_sd:
6469 case Intrinsic::x86_sse_comieq_ss:
6470 case Intrinsic::x86_sse_comilt_ss:
6471 case Intrinsic::x86_sse_comile_ss:
6472 case Intrinsic::x86_sse_comigt_ss:
6473 case Intrinsic::x86_sse_comige_ss:
6474 case Intrinsic::x86_sse_comineq_ss:
6475 case Intrinsic::x86_sse_ucomieq_ss:
6476 case Intrinsic::x86_sse_ucomilt_ss:
6477 case Intrinsic::x86_sse_ucomile_ss:
6478 case Intrinsic::x86_sse_ucomigt_ss:
6479 case Intrinsic::x86_sse_ucomige_ss:
6480 case Intrinsic::x86_sse_ucomineq_ss:
6481 case Intrinsic::x86_sse2_comieq_sd:
6482 case Intrinsic::x86_sse2_comilt_sd:
6483 case Intrinsic::x86_sse2_comile_sd:
6484 case Intrinsic::x86_sse2_comigt_sd:
6485 case Intrinsic::x86_sse2_comige_sd:
6486 case Intrinsic::x86_sse2_comineq_sd:
6487 case Intrinsic::x86_sse2_ucomieq_sd:
6488 case Intrinsic::x86_sse2_ucomilt_sd:
6489 case Intrinsic::x86_sse2_ucomile_sd:
6490 case Intrinsic::x86_sse2_ucomigt_sd:
6491 case Intrinsic::x86_sse2_ucomige_sd:
6492 case Intrinsic::x86_sse2_ucomineq_sd:
6493 handleVectorCompareScalarIntrinsic(
I);
6496 case Intrinsic::x86_avx_cmp_pd_256:
6497 case Intrinsic::x86_avx_cmp_ps_256:
6498 case Intrinsic::x86_sse2_cmp_pd:
6499 case Intrinsic::x86_sse_cmp_ps:
6500 handleVectorComparePackedIntrinsic(
I,
true);
6503 case Intrinsic::x86_bmi_bextr_32:
6504 case Intrinsic::x86_bmi_bextr_64:
6505 case Intrinsic::x86_bmi_bzhi_32:
6506 case Intrinsic::x86_bmi_bzhi_64:
6507 case Intrinsic::x86_bmi_pdep_32:
6508 case Intrinsic::x86_bmi_pdep_64:
6509 case Intrinsic::x86_bmi_pext_32:
6510 case Intrinsic::x86_bmi_pext_64:
6511 handleBmiIntrinsic(
I);
6514 case Intrinsic::x86_pclmulqdq:
6515 case Intrinsic::x86_pclmulqdq_256:
6516 case Intrinsic::x86_pclmulqdq_512:
6517 handlePclmulIntrinsic(
I);
6520 case Intrinsic::x86_avx_round_pd_256:
6521 case Intrinsic::x86_avx_round_ps_256:
6522 case Intrinsic::x86_sse41_round_pd:
6523 case Intrinsic::x86_sse41_round_ps:
6524 handleRoundPdPsIntrinsic(
I);
6527 case Intrinsic::x86_sse41_round_sd:
6528 case Intrinsic::x86_sse41_round_ss:
6529 handleUnarySdSsIntrinsic(
I);
6532 case Intrinsic::x86_sse2_max_sd:
6533 case Intrinsic::x86_sse_max_ss:
6534 case Intrinsic::x86_sse2_min_sd:
6535 case Intrinsic::x86_sse_min_ss:
6536 handleBinarySdSsIntrinsic(
I);
6539 case Intrinsic::x86_avx_vtestc_pd:
6540 case Intrinsic::x86_avx_vtestc_pd_256:
6541 case Intrinsic::x86_avx_vtestc_ps:
6542 case Intrinsic::x86_avx_vtestc_ps_256:
6543 case Intrinsic::x86_avx_vtestnzc_pd:
6544 case Intrinsic::x86_avx_vtestnzc_pd_256:
6545 case Intrinsic::x86_avx_vtestnzc_ps:
6546 case Intrinsic::x86_avx_vtestnzc_ps_256:
6547 case Intrinsic::x86_avx_vtestz_pd:
6548 case Intrinsic::x86_avx_vtestz_pd_256:
6549 case Intrinsic::x86_avx_vtestz_ps:
6550 case Intrinsic::x86_avx_vtestz_ps_256:
6551 case Intrinsic::x86_avx_ptestc_256:
6552 case Intrinsic::x86_avx_ptestnzc_256:
6553 case Intrinsic::x86_avx_ptestz_256:
6554 case Intrinsic::x86_sse41_ptestc:
6555 case Intrinsic::x86_sse41_ptestnzc:
6556 case Intrinsic::x86_sse41_ptestz:
6557 handleVtestIntrinsic(
I);
6561 case Intrinsic::x86_ssse3_phadd_w:
6562 case Intrinsic::x86_ssse3_phadd_w_128:
6563 case Intrinsic::x86_ssse3_phsub_w:
6564 case Intrinsic::x86_ssse3_phsub_w_128:
6565 handlePairwiseShadowOrIntrinsic(
I, 1,
6569 case Intrinsic::x86_avx2_phadd_w:
6570 case Intrinsic::x86_avx2_phsub_w:
6571 handlePairwiseShadowOrIntrinsic(
I, 2,
6576 case Intrinsic::x86_ssse3_phadd_d:
6577 case Intrinsic::x86_ssse3_phadd_d_128:
6578 case Intrinsic::x86_ssse3_phsub_d:
6579 case Intrinsic::x86_ssse3_phsub_d_128:
6580 handlePairwiseShadowOrIntrinsic(
I, 1,
6584 case Intrinsic::x86_avx2_phadd_d:
6585 case Intrinsic::x86_avx2_phsub_d:
6586 handlePairwiseShadowOrIntrinsic(
I, 2,
6591 case Intrinsic::x86_ssse3_phadd_sw:
6592 case Intrinsic::x86_ssse3_phadd_sw_128:
6593 case Intrinsic::x86_ssse3_phsub_sw:
6594 case Intrinsic::x86_ssse3_phsub_sw_128:
6595 handlePairwiseShadowOrIntrinsic(
I, 1,
6599 case Intrinsic::x86_avx2_phadd_sw:
6600 case Intrinsic::x86_avx2_phsub_sw:
6601 handlePairwiseShadowOrIntrinsic(
I, 2,
6606 case Intrinsic::x86_sse3_hadd_ps:
6607 case Intrinsic::x86_sse3_hadd_pd:
6608 case Intrinsic::x86_sse3_hsub_ps:
6609 case Intrinsic::x86_sse3_hsub_pd:
6610 handlePairwiseShadowOrIntrinsic(
I, 1);
6613 case Intrinsic::x86_avx_hadd_pd_256:
6614 case Intrinsic::x86_avx_hadd_ps_256:
6615 case Intrinsic::x86_avx_hsub_pd_256:
6616 case Intrinsic::x86_avx_hsub_ps_256:
6617 handlePairwiseShadowOrIntrinsic(
I, 2);
6620 case Intrinsic::x86_avx_maskstore_ps:
6621 case Intrinsic::x86_avx_maskstore_pd:
6622 case Intrinsic::x86_avx_maskstore_ps_256:
6623 case Intrinsic::x86_avx_maskstore_pd_256:
6624 case Intrinsic::x86_avx2_maskstore_d:
6625 case Intrinsic::x86_avx2_maskstore_q:
6626 case Intrinsic::x86_avx2_maskstore_d_256:
6627 case Intrinsic::x86_avx2_maskstore_q_256: {
6628 handleAVXMaskedStore(
I);
6632 case Intrinsic::x86_avx_maskload_ps:
6633 case Intrinsic::x86_avx_maskload_pd:
6634 case Intrinsic::x86_avx_maskload_ps_256:
6635 case Intrinsic::x86_avx_maskload_pd_256:
6636 case Intrinsic::x86_avx2_maskload_d:
6637 case Intrinsic::x86_avx2_maskload_q:
6638 case Intrinsic::x86_avx2_maskload_d_256:
6639 case Intrinsic::x86_avx2_maskload_q_256: {
6640 handleAVXMaskedLoad(
I);
6645 case Intrinsic::x86_avx512fp16_add_ph_512:
6646 case Intrinsic::x86_avx512fp16_sub_ph_512:
6647 case Intrinsic::x86_avx512fp16_mul_ph_512:
6648 case Intrinsic::x86_avx512fp16_div_ph_512:
6649 case Intrinsic::x86_avx512fp16_max_ph_512:
6650 case Intrinsic::x86_avx512fp16_min_ph_512:
6651 case Intrinsic::x86_avx512_min_ps_512:
6652 case Intrinsic::x86_avx512_min_pd_512:
6653 case Intrinsic::x86_avx512_max_ps_512:
6654 case Intrinsic::x86_avx512_max_pd_512: {
6659 [[maybe_unused]]
bool Success =
6660 maybeHandleSimpleNomemIntrinsic(
I, 1);
6665 case Intrinsic::x86_avx_vpermilvar_pd:
6666 case Intrinsic::x86_avx_vpermilvar_pd_256:
6667 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6668 case Intrinsic::x86_avx_vpermilvar_ps:
6669 case Intrinsic::x86_avx_vpermilvar_ps_256:
6670 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6671 handleAVXVpermilvar(
I);
6675 case Intrinsic::x86_avx512_vpermi2var_d_128:
6676 case Intrinsic::x86_avx512_vpermi2var_d_256:
6677 case Intrinsic::x86_avx512_vpermi2var_d_512:
6678 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6679 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6680 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6681 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6682 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6683 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6684 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6685 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6686 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6687 case Intrinsic::x86_avx512_vpermi2var_q_128:
6688 case Intrinsic::x86_avx512_vpermi2var_q_256:
6689 case Intrinsic::x86_avx512_vpermi2var_q_512:
6690 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6691 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6692 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6693 handleAVXVpermi2var(
I);
6707 case Intrinsic::x86_avx2_pshuf_b:
6708 case Intrinsic::x86_sse_pshuf_w:
6709 case Intrinsic::x86_ssse3_pshuf_b_128:
6710 case Intrinsic::x86_ssse3_pshuf_b:
6711 case Intrinsic::x86_avx512_pshuf_b_512:
6712 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6718 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6719 case Intrinsic::x86_avx512_mask_pmov_db_128:
6720 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6721 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6722 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6723 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6724 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6725 case Intrinsic::x86_avx512_mask_pmov_db_256:
6726 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6727 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6728 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6729 case Intrinsic::x86_avx512_mask_pmov_db_512:
6730 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6731 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6734 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6742 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6743 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6744 handleIntrinsicByApplyingToShadow(
I,
6745 Intrinsic::x86_avx512_mask_pmov_dw_512,
6750 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6751 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6752 handleIntrinsicByApplyingToShadow(
I,
6753 Intrinsic::x86_avx512_mask_pmov_dw_256,
6757 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6758 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6759 handleIntrinsicByApplyingToShadow(
I,
6760 Intrinsic::x86_avx512_mask_pmov_dw_128,
6764 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6765 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6766 handleIntrinsicByApplyingToShadow(
I,
6767 Intrinsic::x86_avx512_mask_pmov_db_512,
6772 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6773 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6774 handleIntrinsicByApplyingToShadow(
I,
6775 Intrinsic::x86_avx512_mask_pmov_db_256,
6779 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6780 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6781 handleIntrinsicByApplyingToShadow(
I,
6782 Intrinsic::x86_avx512_mask_pmov_db_128,
6786 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6787 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6788 handleIntrinsicByApplyingToShadow(
I,
6789 Intrinsic::x86_avx512_mask_pmov_qb_512,
6794 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6795 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6796 handleIntrinsicByApplyingToShadow(
I,
6797 Intrinsic::x86_avx512_mask_pmov_qb_256,
6801 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6802 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6803 handleIntrinsicByApplyingToShadow(
I,
6804 Intrinsic::x86_avx512_mask_pmov_qb_128,
6808 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6809 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6810 handleIntrinsicByApplyingToShadow(
I,
6811 Intrinsic::x86_avx512_mask_pmov_qw_512,
6816 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6817 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6818 handleIntrinsicByApplyingToShadow(
I,
6819 Intrinsic::x86_avx512_mask_pmov_qw_256,
6823 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6824 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6825 handleIntrinsicByApplyingToShadow(
I,
6826 Intrinsic::x86_avx512_mask_pmov_qw_128,
6830 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6831 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6832 handleIntrinsicByApplyingToShadow(
I,
6833 Intrinsic::x86_avx512_mask_pmov_qd_128,
6837 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6838 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6839 handleIntrinsicByApplyingToShadow(
I,
6840 Intrinsic::x86_avx512_mask_pmov_wb_128,
6844 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6845 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6846 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6847 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6848 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6849 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6850 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6851 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6855 handleAVX512VectorDownConvert(
I);
6895 case Intrinsic::x86_avx512_rsqrt14_ps_512:
6896 case Intrinsic::x86_avx512_rsqrt14_ps_256:
6897 case Intrinsic::x86_avx512_rsqrt14_ps_128:
6898 case Intrinsic::x86_avx512_rsqrt14_pd_512:
6899 case Intrinsic::x86_avx512_rsqrt14_pd_256:
6900 case Intrinsic::x86_avx512_rsqrt14_pd_128:
6901 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
6902 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
6903 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
6904 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
6905 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
6906 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
6907 handleAVX512VectorGenericMaskedFP(
I, {0},
6948 case Intrinsic::x86_avx512_rcp14_ps_512:
6949 case Intrinsic::x86_avx512_rcp14_ps_256:
6950 case Intrinsic::x86_avx512_rcp14_ps_128:
6951 case Intrinsic::x86_avx512_rcp14_pd_512:
6952 case Intrinsic::x86_avx512_rcp14_pd_256:
6953 case Intrinsic::x86_avx512_rcp14_pd_128:
6954 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
6955 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
6956 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
6957 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
6958 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
6959 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
6960 handleAVX512VectorGenericMaskedFP(
I, {0},
7005 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7006 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7007 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7008 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7009 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7010 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7011 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7012 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7013 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7014 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7015 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7016 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7017 handleAVX512VectorGenericMaskedFP(
I, {0},
7053 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7054 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7055 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7056 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7057 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7058 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7059 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7060 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7061 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7065 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7085 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7086 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7087 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7088 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7089 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7090 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7091 visitGenericScalarHalfwordInst(
I);
7096 case Intrinsic::x86_vgf2p8affineqb_128:
7097 case Intrinsic::x86_vgf2p8affineqb_256:
7098 case Intrinsic::x86_vgf2p8affineqb_512:
7099 handleAVXGF2P8Affine(
I);
7109 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7110 switch (
I.getIntrinsicID()) {
7114 case Intrinsic::aarch64_neon_rshrn:
7115 case Intrinsic::aarch64_neon_sqrshl:
7116 case Intrinsic::aarch64_neon_sqrshrn:
7117 case Intrinsic::aarch64_neon_sqrshrun:
7118 case Intrinsic::aarch64_neon_sqshl:
7119 case Intrinsic::aarch64_neon_sqshlu:
7120 case Intrinsic::aarch64_neon_sqshrn:
7121 case Intrinsic::aarch64_neon_sqshrun:
7122 case Intrinsic::aarch64_neon_srshl:
7123 case Intrinsic::aarch64_neon_sshl:
7124 case Intrinsic::aarch64_neon_uqrshl:
7125 case Intrinsic::aarch64_neon_uqrshrn:
7126 case Intrinsic::aarch64_neon_uqshl:
7127 case Intrinsic::aarch64_neon_uqshrn:
7128 case Intrinsic::aarch64_neon_urshl:
7129 case Intrinsic::aarch64_neon_ushl:
7130 handleVectorShiftIntrinsic(
I,
false);
7143 case Intrinsic::aarch64_neon_vsli:
7144 case Intrinsic::aarch64_neon_vsri:
7145 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7151 case Intrinsic::aarch64_neon_fmaxp:
7152 case Intrinsic::aarch64_neon_fminp:
7154 case Intrinsic::aarch64_neon_fmaxnmp:
7155 case Intrinsic::aarch64_neon_fminnmp:
7157 case Intrinsic::aarch64_neon_smaxp:
7158 case Intrinsic::aarch64_neon_sminp:
7159 case Intrinsic::aarch64_neon_umaxp:
7160 case Intrinsic::aarch64_neon_uminp:
7162 case Intrinsic::aarch64_neon_addp:
7164 case Intrinsic::aarch64_neon_faddp:
7166 case Intrinsic::aarch64_neon_saddlp:
7167 case Intrinsic::aarch64_neon_uaddlp: {
7168 handlePairwiseShadowOrIntrinsic(
I, 1);
7173 case Intrinsic::aarch64_neon_fcvtas:
7174 case Intrinsic::aarch64_neon_fcvtau:
7176 case Intrinsic::aarch64_neon_fcvtms:
7177 case Intrinsic::aarch64_neon_fcvtmu:
7179 case Intrinsic::aarch64_neon_fcvtns:
7180 case Intrinsic::aarch64_neon_fcvtnu:
7182 case Intrinsic::aarch64_neon_fcvtps:
7183 case Intrinsic::aarch64_neon_fcvtpu:
7185 case Intrinsic::aarch64_neon_fcvtzs:
7186 case Intrinsic::aarch64_neon_fcvtzu:
7188 case Intrinsic::aarch64_neon_fcvtxn:
7190 case Intrinsic::aarch64_neon_vcvthf2fp:
7191 case Intrinsic::aarch64_neon_vcvtfp2hf:
7192 handleGenericVectorConvertIntrinsic(
I,
false);
7196 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7197 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7198 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7199 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7200 handleGenericVectorConvertIntrinsic(
I,
true);
7209 case Intrinsic::aarch64_neon_faddv:
7210 case Intrinsic::aarch64_neon_saddv:
7211 case Intrinsic::aarch64_neon_uaddv:
7214 case Intrinsic::aarch64_neon_smaxv:
7215 case Intrinsic::aarch64_neon_sminv:
7216 case Intrinsic::aarch64_neon_umaxv:
7217 case Intrinsic::aarch64_neon_uminv:
7221 case Intrinsic::aarch64_neon_fmaxv:
7222 case Intrinsic::aarch64_neon_fminv:
7223 case Intrinsic::aarch64_neon_fmaxnmv:
7224 case Intrinsic::aarch64_neon_fminnmv:
7226 case Intrinsic::aarch64_neon_saddlv:
7227 case Intrinsic::aarch64_neon_uaddlv:
7228 handleVectorReduceIntrinsic(
I,
true);
7231 case Intrinsic::aarch64_neon_ld1x2:
7232 case Intrinsic::aarch64_neon_ld1x3:
7233 case Intrinsic::aarch64_neon_ld1x4:
7234 case Intrinsic::aarch64_neon_ld2:
7235 case Intrinsic::aarch64_neon_ld3:
7236 case Intrinsic::aarch64_neon_ld4:
7237 case Intrinsic::aarch64_neon_ld2r:
7238 case Intrinsic::aarch64_neon_ld3r:
7239 case Intrinsic::aarch64_neon_ld4r: {
7240 handleNEONVectorLoad(
I,
false);
7244 case Intrinsic::aarch64_neon_ld2lane:
7245 case Intrinsic::aarch64_neon_ld3lane:
7246 case Intrinsic::aarch64_neon_ld4lane: {
7247 handleNEONVectorLoad(
I,
true);
7252 case Intrinsic::aarch64_neon_sqxtn:
7253 case Intrinsic::aarch64_neon_sqxtun:
7254 case Intrinsic::aarch64_neon_uqxtn:
7261 case Intrinsic::aarch64_neon_st1x2:
7262 case Intrinsic::aarch64_neon_st1x3:
7263 case Intrinsic::aarch64_neon_st1x4:
7264 case Intrinsic::aarch64_neon_st2:
7265 case Intrinsic::aarch64_neon_st3:
7266 case Intrinsic::aarch64_neon_st4: {
7267 handleNEONVectorStoreIntrinsic(
I,
false);
7271 case Intrinsic::aarch64_neon_st2lane:
7272 case Intrinsic::aarch64_neon_st3lane:
7273 case Intrinsic::aarch64_neon_st4lane: {
7274 handleNEONVectorStoreIntrinsic(
I,
true);
7287 case Intrinsic::aarch64_neon_tbl1:
7288 case Intrinsic::aarch64_neon_tbl2:
7289 case Intrinsic::aarch64_neon_tbl3:
7290 case Intrinsic::aarch64_neon_tbl4:
7291 case Intrinsic::aarch64_neon_tbx1:
7292 case Intrinsic::aarch64_neon_tbx2:
7293 case Intrinsic::aarch64_neon_tbx3:
7294 case Intrinsic::aarch64_neon_tbx4: {
7296 handleIntrinsicByApplyingToShadow(
7297 I,
I.getIntrinsicID(),
7302 case Intrinsic::aarch64_neon_fmulx:
7303 case Intrinsic::aarch64_neon_pmul:
7304 case Intrinsic::aarch64_neon_pmull:
7305 case Intrinsic::aarch64_neon_smull:
7306 case Intrinsic::aarch64_neon_pmull64:
7307 case Intrinsic::aarch64_neon_umull: {
7308 handleNEONVectorMultiplyIntrinsic(
I);
7312 case Intrinsic::aarch64_neon_smmla:
7313 case Intrinsic::aarch64_neon_ummla:
7314 case Intrinsic::aarch64_neon_usmmla:
7315 case Intrinsic::aarch64_neon_bfmmla:
7316 handleNEONMatrixMultiply(
I);
7323 case Intrinsic::aarch64_neon_sdot:
7324 case Intrinsic::aarch64_neon_udot:
7325 case Intrinsic::aarch64_neon_usdot:
7326 handleVectorDotProductIntrinsic(
I, 4,
7336 case Intrinsic::aarch64_neon_bfdot:
7337 handleVectorDotProductIntrinsic(
I, 2,
7344 case Intrinsic::aarch64_neon_facge:
7345 case Intrinsic::aarch64_neon_facgt:
7346 handleVectorComparePackedIntrinsic(
I,
false);
7356 void visitIntrinsicInst(IntrinsicInst &
I) {
7357 if (maybeHandleCrossPlatformIntrinsic(
I))
7360 if (maybeHandleX86SIMDIntrinsic(
I))
7363 if (maybeHandleArmSIMDIntrinsic(
I))
7366 if (maybeHandleUnknownIntrinsic(
I))
7369 visitInstruction(
I);
7372 void visitLibAtomicLoad(CallBase &CB) {
7383 Value *NewOrdering =
7387 NextNodeIRBuilder NextIRB(&CB);
7388 Value *SrcShadowPtr, *SrcOriginPtr;
7389 std::tie(SrcShadowPtr, SrcOriginPtr) =
7390 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7392 Value *DstShadowPtr =
7393 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7397 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7398 if (MS.TrackOrigins) {
7399 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7401 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7402 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7406 void visitLibAtomicStore(CallBase &CB) {
7413 Value *NewOrdering =
7417 Value *DstShadowPtr =
7427 void visitCallBase(CallBase &CB) {
7435 visitAsmInstruction(CB);
7437 visitInstruction(CB);
7446 case LibFunc_atomic_load:
7448 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7452 visitLibAtomicLoad(CB);
7454 case LibFunc_atomic_store:
7455 visitLibAtomicStore(CB);
7471 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7475 Func->removeFnAttrs(
B);
7481 bool MayCheckCall = MS.EagerChecks;
7485 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7488 unsigned ArgOffset = 0;
7491 if (!
A->getType()->isSized()) {
7492 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7496 if (
A->getType()->isScalableTy()) {
7497 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7499 insertCheckShadowOf(
A, &CB);
7504 const DataLayout &
DL =
F.getDataLayout();
7508 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7511 insertCheckShadowOf(
A, &CB);
7512 Size =
DL.getTypeAllocSize(
A->getType());
7518 Value *ArgShadow = getShadow(
A);
7519 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7521 <<
" Shadow: " << *ArgShadow <<
"\n");
7525 assert(
A->getType()->isPointerTy() &&
7526 "ByVal argument is not a pointer!");
7531 MaybeAlign Alignment = std::nullopt;
7534 Value *AShadowPtr, *AOriginPtr;
7535 std::tie(AShadowPtr, AOriginPtr) =
7536 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7538 if (!PropagateShadow) {
7545 if (MS.TrackOrigins) {
7546 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7560 Size =
DL.getTypeAllocSize(
A->getType());
7566 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7568 getOriginPtrForArgument(IRB, ArgOffset));
7571 assert(Store !=
nullptr);
7580 if (FT->isVarArg()) {
7581 VAHelper->visitCallBase(CB, IRB);
7591 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7592 setShadow(&CB, getCleanShadow(&CB));
7593 setOrigin(&CB, getCleanOrigin());
7599 Value *
Base = getShadowPtrForRetval(IRBBefore);
7600 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7612 setShadow(&CB, getCleanShadow(&CB));
7613 setOrigin(&CB, getCleanOrigin());
7620 "Could not find insertion point for retval shadow load");
7623 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7626 setShadow(&CB, RetvalShadow);
7627 if (MS.TrackOrigins)
7628 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7633 RetVal =
I->getOperand(0);
7636 return I->isMustTailCall();
7641 void visitReturnInst(ReturnInst &
I) {
7643 Value *RetVal =
I.getReturnValue();
7649 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7650 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7651 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7654 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7656 Value *Shadow = getShadow(RetVal);
7657 bool StoreOrigin =
true;
7659 insertCheckShadowOf(RetVal, &
I);
7660 Shadow = getCleanShadow(RetVal);
7661 StoreOrigin =
false;
7668 if (MS.TrackOrigins && StoreOrigin)
7669 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7673 void visitPHINode(PHINode &
I) {
7675 if (!PropagateShadow) {
7676 setShadow(&
I, getCleanShadow(&
I));
7677 setOrigin(&
I, getCleanOrigin());
7681 ShadowPHINodes.push_back(&
I);
7682 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7684 if (MS.TrackOrigins)
7686 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7689 Value *getLocalVarIdptr(AllocaInst &
I) {
7690 ConstantInt *IntConst =
7691 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7692 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7697 Value *getLocalVarDescription(AllocaInst &
I) {
7703 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7705 Value *ShadowBase, *OriginBase;
7706 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7710 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7713 if (PoisonStack && MS.TrackOrigins) {
7714 Value *Idptr = getLocalVarIdptr(
I);
7716 Value *Descr = getLocalVarDescription(
I);
7717 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7718 {&I, Len, Idptr, Descr});
7720 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7726 Value *Descr = getLocalVarDescription(
I);
7728 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7730 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7734 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7737 NextNodeIRBuilder IRB(InsPoint);
7740 if (MS.CompileKernel)
7741 poisonAllocaKmsan(
I, IRB, Len);
7743 poisonAllocaUserspace(
I, IRB, Len);
7746 void visitAllocaInst(AllocaInst &
I) {
7747 setShadow(&
I, getCleanShadow(&
I));
7748 setOrigin(&
I, getCleanOrigin());
7754 void visitSelectInst(SelectInst &
I) {
7760 handleSelectLikeInst(
I,
B,
C,
D);
7766 Value *Sb = getShadow(
B);
7767 Value *Sc = getShadow(
C);
7768 Value *Sd = getShadow(
D);
7770 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7771 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7772 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7777 if (
I.getType()->isAggregateType()) {
7781 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7782 }
else if (isScalableNonVectorType(
I.getType())) {
7790 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7798 C = CreateAppToShadowCast(IRB,
C);
7799 D = CreateAppToShadowCast(IRB,
D);
7806 if (MS.TrackOrigins) {
7809 if (
B->getType()->isVectorTy()) {
7810 B = convertToBool(
B, IRB);
7811 Sb = convertToBool(Sb, IRB);
7819 void visitLandingPadInst(LandingPadInst &
I) {
7822 setShadow(&
I, getCleanShadow(&
I));
7823 setOrigin(&
I, getCleanOrigin());
7826 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7827 setShadow(&
I, getCleanShadow(&
I));
7828 setOrigin(&
I, getCleanOrigin());
7831 void visitFuncletPadInst(FuncletPadInst &
I) {
7832 setShadow(&
I, getCleanShadow(&
I));
7833 setOrigin(&
I, getCleanOrigin());
7836 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7838 void visitExtractValueInst(ExtractValueInst &
I) {
7840 Value *Agg =
I.getAggregateOperand();
7842 Value *AggShadow = getShadow(Agg);
7846 setShadow(&
I, ResShadow);
7847 setOriginForNaryOp(
I);
7850 void visitInsertValueInst(InsertValueInst &
I) {
7853 Value *AggShadow = getShadow(
I.getAggregateOperand());
7854 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7860 setOriginForNaryOp(
I);
7863 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7872 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
7879 unsigned NumOperands =
I.getNumOperands();
7881 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
7893 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
7894 <<
I.getOpcodeName() <<
"(";
7896 for (
size_t i = 0; i < NumOperands; i++) {
7914 void visitResumeInst(ResumeInst &
I) {
7919 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
7924 void visitCatchReturnInst(CatchReturnInst &CRI) {
7929 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
7938 insertCheckShadowOf(Operand, &
I);
7945 auto Size =
DL.getTypeStoreSize(ElemTy);
7947 if (MS.CompileKernel) {
7948 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
7954 auto [ShadowPtr,
_] =
7955 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
7965 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
7966 int NumRetOutputs = 0;
7973 NumRetOutputs =
ST->getNumElements();
7978 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
7979 switch (
Info.Type) {
7987 return NumOutputs - NumRetOutputs;
7990 void visitAsmInstruction(Instruction &
I) {
8006 const DataLayout &
DL =
F.getDataLayout();
8010 int OutputArgs = getNumOutputArgs(IA, CB);
8016 for (
int i = OutputArgs; i < NumOperands; i++) {
8024 for (
int i = 0; i < OutputArgs; i++) {
8030 setShadow(&
I, getCleanShadow(&
I));
8031 setOrigin(&
I, getCleanOrigin());
8034 void visitFreezeInst(FreezeInst &
I) {
8036 setShadow(&
I, getCleanShadow(&
I));
8037 setOrigin(&
I, getCleanOrigin());
8040 void visitInstruction(Instruction &
I) {
8043 dumpInst(
I,
"Strict");
8045 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8046 Value *Operand =
I.getOperand(i);
8048 insertCheckShadowOf(Operand, &
I);
8050 setShadow(&
I, getCleanShadow(&
I));
8051 setOrigin(&
I, getCleanOrigin());
8055struct VarArgHelperBase :
public VarArgHelper {
8057 MemorySanitizer &MS;
8058 MemorySanitizerVisitor &MSV;
8060 const unsigned VAListTagSize;
8062 VarArgHelperBase(Function &
F, MemorySanitizer &MS,
8063 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8064 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8068 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8074 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8083 return getShadowPtrForVAArgument(IRB, ArgOffset);
8092 ConstantInt::get(MS.IntptrTy, ArgOffset),
8097 unsigned BaseOffset) {
8106 TailSize,
Align(8));
8109 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8111 Value *VAListTag =
I.getArgOperand(0);
8113 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8114 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8117 VAListTagSize, Alignment,
false);
8120 void visitVAStartInst(VAStartInst &
I)
override {
8121 if (
F.getCallingConv() == CallingConv::Win64)
8124 unpoisonVAListTagForInst(
I);
8127 void visitVACopyInst(VACopyInst &
I)
override {
8128 if (
F.getCallingConv() == CallingConv::Win64)
8130 unpoisonVAListTagForInst(
I);
8135struct VarArgAMD64Helper :
public VarArgHelperBase {
8138 static const unsigned AMD64GpEndOffset = 48;
8139 static const unsigned AMD64FpEndOffsetSSE = 176;
8141 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8143 unsigned AMD64FpEndOffset;
8144 AllocaInst *VAArgTLSCopy =
nullptr;
8145 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8146 Value *VAArgOverflowSize =
nullptr;
8148 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8150 VarArgAMD64Helper(Function &
F, MemorySanitizer &MS,
8151 MemorySanitizerVisitor &MSV)
8152 : VarArgHelperBase(
F, MS, MSV, 24) {
8153 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8154 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8155 if (Attr.isStringAttribute() &&
8156 (Attr.getKindAsString() ==
"target-features")) {
8157 if (Attr.getValueAsString().contains(
"-sse"))
8158 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8164 ArgKind classifyArgument(
Value *arg) {
8167 if (
T->isX86_FP80Ty())
8169 if (
T->isFPOrFPVectorTy())
8170 return AK_FloatingPoint;
8171 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8172 return AK_GeneralPurpose;
8173 if (
T->isPointerTy())
8174 return AK_GeneralPurpose;
8186 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8187 unsigned GpOffset = 0;
8188 unsigned FpOffset = AMD64GpEndOffset;
8189 unsigned OverflowOffset = AMD64FpEndOffset;
8190 const DataLayout &
DL =
F.getDataLayout();
8194 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8201 assert(
A->getType()->isPointerTy());
8203 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8204 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8205 unsigned BaseOffset = OverflowOffset;
8206 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8207 Value *OriginBase =
nullptr;
8208 if (MS.TrackOrigins)
8209 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8210 OverflowOffset += AlignedSize;
8213 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8217 Value *ShadowPtr, *OriginPtr;
8218 std::tie(ShadowPtr, OriginPtr) =
8223 if (MS.TrackOrigins)
8227 ArgKind AK = classifyArgument(
A);
8228 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8230 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8232 Value *ShadowBase, *OriginBase =
nullptr;
8234 case AK_GeneralPurpose:
8235 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8236 if (MS.TrackOrigins)
8237 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8241 case AK_FloatingPoint:
8242 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8243 if (MS.TrackOrigins)
8244 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8251 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8252 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8253 unsigned BaseOffset = OverflowOffset;
8254 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8255 if (MS.TrackOrigins) {
8256 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8258 OverflowOffset += AlignedSize;
8261 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8270 Value *Shadow = MSV.getShadow(
A);
8272 if (MS.TrackOrigins) {
8273 Value *Origin = MSV.getOrigin(
A);
8274 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8275 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8281 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8282 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8285 void finalizeInstrumentation()
override {
8286 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8287 "finalizeInstrumentation called twice");
8288 if (!VAStartInstrumentationList.
empty()) {
8295 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8296 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8302 Intrinsic::umin, CopySize,
8306 if (MS.TrackOrigins) {
8307 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8316 for (CallInst *OrigInst : VAStartInstrumentationList) {
8317 NextNodeIRBuilder IRB(OrigInst);
8318 Value *VAListTag = OrigInst->getArgOperand(0);
8320 Value *RegSaveAreaPtrPtr =
8321 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8323 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8325 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8326 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8328 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8330 if (MS.TrackOrigins)
8331 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8332 Alignment, AMD64FpEndOffset);
8333 Value *OverflowArgAreaPtrPtr =
8334 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8335 Value *OverflowArgAreaPtr =
8336 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8337 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8338 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8339 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8343 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8345 if (MS.TrackOrigins) {
8348 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8356struct VarArgAArch64Helper :
public VarArgHelperBase {
8357 static const unsigned kAArch64GrArgSize = 64;
8358 static const unsigned kAArch64VrArgSize = 128;
8360 static const unsigned AArch64GrBegOffset = 0;
8361 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8363 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8364 static const unsigned AArch64VrEndOffset =
8365 AArch64VrBegOffset + kAArch64VrArgSize;
8366 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8368 AllocaInst *VAArgTLSCopy =
nullptr;
8369 Value *VAArgOverflowSize =
nullptr;
8371 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8373 VarArgAArch64Helper(Function &
F, MemorySanitizer &MS,
8374 MemorySanitizerVisitor &MSV)
8375 : VarArgHelperBase(
F, MS, MSV, 32) {}
8378 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8379 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8380 return {AK_GeneralPurpose, 1};
8381 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8382 return {AK_FloatingPoint, 1};
8384 if (
T->isArrayTy()) {
8385 auto R = classifyArgument(
T->getArrayElementType());
8386 R.second *=
T->getScalarType()->getArrayNumElements();
8391 auto R = classifyArgument(FV->getScalarType());
8392 R.second *= FV->getNumElements();
8397 return {AK_Memory, 0};
8409 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8410 unsigned GrOffset = AArch64GrBegOffset;
8411 unsigned VrOffset = AArch64VrBegOffset;
8412 unsigned OverflowOffset = AArch64VAEndOffset;
8414 const DataLayout &
DL =
F.getDataLayout();
8417 auto [AK, RegNum] = classifyArgument(
A->getType());
8418 if (AK == AK_GeneralPurpose &&
8419 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8421 if (AK == AK_FloatingPoint &&
8422 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8426 case AK_GeneralPurpose:
8427 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8428 GrOffset += 8 * RegNum;
8430 case AK_FloatingPoint:
8431 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8432 VrOffset += 16 * RegNum;
8439 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8440 uint64_t AlignedSize =
alignTo(ArgSize, 8);
8441 unsigned BaseOffset = OverflowOffset;
8442 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8443 OverflowOffset += AlignedSize;
8446 CleanUnusedTLS(IRB,
Base, BaseOffset);
8458 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8459 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8464 Value *SaveAreaPtrPtr =
8465 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8466 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8471 Value *SaveAreaPtr =
8472 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8474 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8477 void finalizeInstrumentation()
override {
8478 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8479 "finalizeInstrumentation called twice");
8480 if (!VAStartInstrumentationList.empty()) {
8487 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8488 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8494 Intrinsic::umin, CopySize,
8500 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8501 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8505 for (CallInst *OrigInst : VAStartInstrumentationList) {
8506 NextNodeIRBuilder IRB(OrigInst);
8508 Value *VAListTag = OrigInst->getArgOperand(0);
8525 Value *StackSaveAreaPtr =
8526 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8529 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8530 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8533 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8536 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8537 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8540 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8546 Value *GrRegSaveAreaShadowPtrOff =
8547 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8549 Value *GrRegSaveAreaShadowPtr =
8550 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8556 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8562 Value *VrRegSaveAreaShadowPtrOff =
8563 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8565 Value *VrRegSaveAreaShadowPtr =
8566 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8573 VrRegSaveAreaShadowPtrOff);
8574 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8580 Value *StackSaveAreaShadowPtr =
8581 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8586 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8589 Align(16), VAArgOverflowSize);
8595struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8596 AllocaInst *VAArgTLSCopy =
nullptr;
8597 Value *VAArgSize =
nullptr;
8599 VarArgPowerPC64Helper(Function &
F, MemorySanitizer &MS,
8600 MemorySanitizerVisitor &MSV)
8601 : VarArgHelperBase(
F, MS, MSV, 8) {}
8603 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8611 Triple TargetTriple(
F.getParent()->getTargetTriple());
8615 if (TargetTriple.isPPC64ELFv2ABI())
8619 unsigned VAArgOffset = VAArgBase;
8620 const DataLayout &
DL =
F.getDataLayout();
8623 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8625 assert(
A->getType()->isPointerTy());
8627 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8630 ArgAlign =
Align(8);
8631 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8634 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8636 Value *AShadowPtr, *AOriginPtr;
8637 std::tie(AShadowPtr, AOriginPtr) =
8638 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8648 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8650 if (
A->getType()->isArrayTy()) {
8653 Type *ElementTy =
A->getType()->getArrayElementType();
8655 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8656 }
else if (
A->getType()->isVectorTy()) {
8658 ArgAlign =
Align(ArgSize);
8661 ArgAlign =
Align(8);
8662 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8663 if (
DL.isBigEndian()) {
8667 VAArgOffset += (8 - ArgSize);
8671 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8675 VAArgOffset += ArgSize;
8679 VAArgBase = VAArgOffset;
8683 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8686 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8689 void finalizeInstrumentation()
override {
8690 assert(!VAArgSize && !VAArgTLSCopy &&
8691 "finalizeInstrumentation called twice");
8694 Value *CopySize = VAArgSize;
8696 if (!VAStartInstrumentationList.empty()) {
8700 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8706 Intrinsic::umin, CopySize,
8714 for (CallInst *OrigInst : VAStartInstrumentationList) {
8715 NextNodeIRBuilder IRB(OrigInst);
8716 Value *VAListTag = OrigInst->getArgOperand(0);
8719 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8722 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8723 const DataLayout &
DL =
F.getDataLayout();
8724 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8726 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8727 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8729 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8736struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8737 AllocaInst *VAArgTLSCopy =
nullptr;
8738 Value *VAArgSize =
nullptr;
8740 VarArgPowerPC32Helper(Function &
F, MemorySanitizer &MS,
8741 MemorySanitizerVisitor &MSV)
8742 : VarArgHelperBase(
F, MS, MSV, 12) {}
8744 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8748 unsigned VAArgOffset = VAArgBase;
8749 const DataLayout &
DL =
F.getDataLayout();
8750 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8753 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
8755 assert(
A->getType()->isPointerTy());
8757 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8759 if (ArgAlign < IntptrSize)
8760 ArgAlign =
Align(IntptrSize);
8761 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8764 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8766 Value *AShadowPtr, *AOriginPtr;
8767 std::tie(AShadowPtr, AOriginPtr) =
8768 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8778 Type *ArgTy =
A->getType();
8784 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8791 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8794 ArgAlign =
Align(ArgSize);
8796 if (ArgAlign < IntptrSize)
8797 ArgAlign =
Align(IntptrSize);
8798 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8799 if (
DL.isBigEndian()) {
8802 if (ArgSize < IntptrSize)
8803 VAArgOffset += (IntptrSize - ArgSize);
8806 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8812 VAArgOffset += ArgSize;
8819 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8822 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8825 void finalizeInstrumentation()
override {
8826 assert(!VAArgSize && !VAArgTLSCopy &&
8827 "finalizeInstrumentation called twice");
8829 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8830 Value *CopySize = VAArgSize;
8832 if (!VAStartInstrumentationList.empty()) {
8836 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8842 Intrinsic::umin, CopySize,
8850 for (CallInst *OrigInst : VAStartInstrumentationList) {
8851 NextNodeIRBuilder IRB(OrigInst);
8852 Value *VAListTag = OrigInst->getArgOperand(0);
8854 Value *RegSaveAreaSize = CopySize;
8858 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8862 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8864 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8867 const DataLayout &
DL =
F.getDataLayout();
8868 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8872 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8873 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8874 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8876 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
8877 Alignment, RegSaveAreaSize);
8879 RegSaveAreaShadowPtr =
8882 ConstantInt::get(MS.IntptrTy, 32));
8887 ConstantInt::get(MS.IntptrTy, 32), Alignment);
8892 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
8895 OverflowAreaPtrPtr =
8896 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
8897 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
8899 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
8901 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
8902 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
8903 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
8906 Value *OverflowVAArgTLSCopyPtr =
8908 OverflowVAArgTLSCopyPtr =
8909 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
8911 OverflowVAArgTLSCopyPtr =
8914 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
8921struct VarArgSystemZHelper :
public VarArgHelperBase {
8922 static const unsigned SystemZGpOffset = 16;
8923 static const unsigned SystemZGpEndOffset = 56;
8924 static const unsigned SystemZFpOffset = 128;
8925 static const unsigned SystemZFpEndOffset = 160;
8926 static const unsigned SystemZMaxVrArgs = 8;
8927 static const unsigned SystemZRegSaveAreaSize = 160;
8928 static const unsigned SystemZOverflowOffset = 160;
8929 static const unsigned SystemZVAListTagSize = 32;
8930 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
8931 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
8933 bool IsSoftFloatABI;
8934 AllocaInst *VAArgTLSCopy =
nullptr;
8935 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8936 Value *VAArgOverflowSize =
nullptr;
8938 enum class ArgKind {
8946 enum class ShadowExtension {
None,
Zero, Sign };
8948 VarArgSystemZHelper(Function &
F, MemorySanitizer &MS,
8949 MemorySanitizerVisitor &MSV)
8950 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
8951 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
8953 ArgKind classifyArgument(
Type *
T) {
8960 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
8961 return ArgKind::Indirect;
8962 if (
T->isFloatingPointTy())
8963 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
8964 if (
T->isIntegerTy() ||
T->isPointerTy())
8965 return ArgKind::GeneralPurpose;
8966 if (
T->isVectorTy())
8967 return ArgKind::Vector;
8968 return ArgKind::Memory;
8971 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
8981 return ShadowExtension::Zero;
8985 return ShadowExtension::Sign;
8987 return ShadowExtension::None;
8990 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8991 unsigned GpOffset = SystemZGpOffset;
8992 unsigned FpOffset = SystemZFpOffset;
8993 unsigned VrIndex = 0;
8994 unsigned OverflowOffset = SystemZOverflowOffset;
8995 const DataLayout &
DL =
F.getDataLayout();
9001 ArgKind AK = classifyArgument(
T);
9002 if (AK == ArgKind::Indirect) {
9004 AK = ArgKind::GeneralPurpose;
9006 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9007 AK = ArgKind::Memory;
9008 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9009 AK = ArgKind::Memory;
9010 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9011 AK = ArgKind::Memory;
9012 Value *ShadowBase =
nullptr;
9013 Value *OriginBase =
nullptr;
9014 ShadowExtension SE = ShadowExtension::None;
9016 case ArgKind::GeneralPurpose: {
9018 uint64_t ArgSize = 8;
9021 SE = getShadowExtension(CB, ArgNo);
9022 uint64_t GapSize = 0;
9023 if (SE == ShadowExtension::None) {
9024 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9025 assert(ArgAllocSize <= ArgSize);
9026 GapSize = ArgSize - ArgAllocSize;
9028 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9029 if (MS.TrackOrigins)
9030 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9032 GpOffset += ArgSize;
9038 case ArgKind::FloatingPoint: {
9040 uint64_t ArgSize = 8;
9047 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9048 if (MS.TrackOrigins)
9049 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9051 FpOffset += ArgSize;
9057 case ArgKind::Vector: {
9064 case ArgKind::Memory: {
9069 uint64_t ArgAllocSize =
DL.getTypeAllocSize(
T);
9070 uint64_t ArgSize =
alignTo(ArgAllocSize, 8);
9072 SE = getShadowExtension(CB, ArgNo);
9074 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9076 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9077 if (MS.TrackOrigins)
9079 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9080 OverflowOffset += ArgSize;
9087 case ArgKind::Indirect:
9090 if (ShadowBase ==
nullptr)
9092 Value *Shadow = MSV.getShadow(
A);
9093 if (SE != ShadowExtension::None)
9094 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9095 SE == ShadowExtension::Sign);
9096 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9098 if (MS.TrackOrigins) {
9099 Value *Origin = MSV.getOrigin(
A);
9100 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9101 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9105 Constant *OverflowSize = ConstantInt::get(
9106 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9107 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9114 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9117 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9119 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9120 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9125 unsigned RegSaveAreaSize =
9126 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9127 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9129 if (MS.TrackOrigins)
9130 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9131 Alignment, RegSaveAreaSize);
9140 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9142 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9143 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9145 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9146 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9149 SystemZOverflowOffset);
9150 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9152 if (MS.TrackOrigins) {
9154 SystemZOverflowOffset);
9155 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9160 void finalizeInstrumentation()
override {
9161 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9162 "finalizeInstrumentation called twice");
9163 if (!VAStartInstrumentationList.empty()) {
9170 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9172 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9178 Intrinsic::umin, CopySize,
9182 if (MS.TrackOrigins) {
9183 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9192 for (CallInst *OrigInst : VAStartInstrumentationList) {
9193 NextNodeIRBuilder IRB(OrigInst);
9194 Value *VAListTag = OrigInst->getArgOperand(0);
9195 copyRegSaveArea(IRB, VAListTag);
9196 copyOverflowArea(IRB, VAListTag);
9202struct VarArgI386Helper :
public VarArgHelperBase {
9203 AllocaInst *VAArgTLSCopy =
nullptr;
9204 Value *VAArgSize =
nullptr;
9206 VarArgI386Helper(Function &
F, MemorySanitizer &MS,
9207 MemorySanitizerVisitor &MSV)
9208 : VarArgHelperBase(
F, MS, MSV, 4) {}
9210 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9211 const DataLayout &
DL =
F.getDataLayout();
9212 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9213 unsigned VAArgOffset = 0;
9216 bool IsByVal = CB.
paramHasAttr(ArgNo, Attribute::ByVal);
9218 assert(
A->getType()->isPointerTy());
9220 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9222 if (ArgAlign < IntptrSize)
9223 ArgAlign =
Align(IntptrSize);
9224 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9226 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9228 Value *AShadowPtr, *AOriginPtr;
9229 std::tie(AShadowPtr, AOriginPtr) =
9230 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9240 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9242 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9243 if (
DL.isBigEndian()) {
9246 if (ArgSize < IntptrSize)
9247 VAArgOffset += (IntptrSize - ArgSize);
9250 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9253 VAArgOffset += ArgSize;
9259 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9262 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9265 void finalizeInstrumentation()
override {
9266 assert(!VAArgSize && !VAArgTLSCopy &&
9267 "finalizeInstrumentation called twice");
9269 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9270 Value *CopySize = VAArgSize;
9272 if (!VAStartInstrumentationList.empty()) {
9275 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9281 Intrinsic::umin, CopySize,
9289 for (CallInst *OrigInst : VAStartInstrumentationList) {
9290 NextNodeIRBuilder IRB(OrigInst);
9291 Value *VAListTag = OrigInst->getArgOperand(0);
9292 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9293 Value *RegSaveAreaPtrPtr =
9295 PointerType::get(*MS.C, 0));
9296 Value *RegSaveAreaPtr =
9297 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9298 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9299 const DataLayout &
DL =
F.getDataLayout();
9300 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9302 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9303 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9305 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9313struct VarArgGenericHelper :
public VarArgHelperBase {
9314 AllocaInst *VAArgTLSCopy =
nullptr;
9315 Value *VAArgSize =
nullptr;
9317 VarArgGenericHelper(Function &
F, MemorySanitizer &MS,
9318 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9319 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9321 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9322 unsigned VAArgOffset = 0;
9323 const DataLayout &
DL =
F.getDataLayout();
9324 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9329 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9330 if (
DL.isBigEndian()) {
9333 if (ArgSize < IntptrSize)
9334 VAArgOffset += (IntptrSize - ArgSize);
9336 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9337 VAArgOffset += ArgSize;
9338 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9344 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9347 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9350 void finalizeInstrumentation()
override {
9351 assert(!VAArgSize && !VAArgTLSCopy &&
9352 "finalizeInstrumentation called twice");
9354 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9355 Value *CopySize = VAArgSize;
9357 if (!VAStartInstrumentationList.empty()) {
9360 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9366 Intrinsic::umin, CopySize,
9374 for (CallInst *OrigInst : VAStartInstrumentationList) {
9375 NextNodeIRBuilder IRB(OrigInst);
9376 Value *VAListTag = OrigInst->getArgOperand(0);
9377 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9378 Value *RegSaveAreaPtrPtr =
9380 PointerType::get(*MS.C, 0));
9381 Value *RegSaveAreaPtr =
9382 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9383 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9384 const DataLayout &
DL =
F.getDataLayout();
9385 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9387 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9388 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9390 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9398using VarArgARM32Helper = VarArgGenericHelper;
9399using VarArgRISCVHelper = VarArgGenericHelper;
9400using VarArgMIPSHelper = VarArgGenericHelper;
9401using VarArgLoongArch64Helper = VarArgGenericHelper;
9402using VarArgHexagonHelper = VarArgGenericHelper;
9405struct VarArgNoOpHelper :
public VarArgHelper {
9406 VarArgNoOpHelper(Function &
F, MemorySanitizer &MS,
9407 MemorySanitizerVisitor &MSV) {}
9409 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9411 void visitVAStartInst(VAStartInst &
I)
override {}
9413 void visitVACopyInst(VACopyInst &
I)
override {}
9415 void finalizeInstrumentation()
override {}
9421 MemorySanitizerVisitor &Visitor) {
9424 Triple TargetTriple(Func.getParent()->getTargetTriple());
9427 return new VarArgI386Helper(Func, Msan, Visitor);
9430 return new VarArgAMD64Helper(Func, Msan, Visitor);
9432 if (TargetTriple.
isARM())
9433 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9436 return new VarArgAArch64Helper(Func, Msan, Visitor);
9439 return new VarArgSystemZHelper(Func, Msan, Visitor);
9444 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9447 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9450 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9453 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9456 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9459 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9462 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9466 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9468 return new VarArgNoOpHelper(Func, Msan, Visitor);
9475 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9478 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9485 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
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 * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI 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.
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)
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.