184#include "llvm/IR/IntrinsicsAArch64.h"
185#include "llvm/IR/IntrinsicsX86.h"
216#define DEBUG_TYPE "msan"
219 "Controls which checks to insert");
222 "Controls which instruction to instrument");
241 "msan-track-origins",
246 cl::desc(
"keep going after reporting a UMR"),
255 "msan-poison-stack-with-call",
260 "msan-poison-stack-pattern",
261 cl::desc(
"poison uninitialized stack variables with the given pattern"),
266 cl::desc(
"Print name of local stack variable"),
271 cl::desc(
"Poison fully undef temporary values. "
272 "Partially undefined constant vectors "
273 "are unaffected by this flag (see "
274 "-msan-poison-undef-vectors)."),
278 "msan-poison-undef-vectors",
279 cl::desc(
"Precisely poison partially undefined constant vectors. "
280 "If false (legacy behavior), the entire vector is "
281 "considered fully initialized, which may lead to false "
282 "negatives. Fully undefined constant vectors are "
283 "unaffected by this flag (see -msan-poison-undef)."),
287 "msan-precise-disjoint-or",
288 cl::desc(
"Precisely poison disjoint OR. If false (legacy behavior), "
289 "disjointedness is ignored (i.e., 1|1 is initialized)."),
294 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
299 cl::desc(
"exact handling of relational integer ICmp"),
303 "msan-switch-precision",
304 cl::desc(
"Controls the number of cases considered by MSan for LLVM switch "
305 "instructions. 0 means no UUMs detected. Higher values lead to "
306 "fewer false negatives but may impact compiler and/or "
307 "application performance. N.B. LLVM switch instructions do not "
308 "correspond exactly to C++ switch statements."),
312 "msan-handle-lifetime-intrinsics",
314 "when possible, poison scoped variables at the beginning of the scope "
315 "(slower, but more precise)"),
326 "msan-handle-asm-conservative",
337 "msan-check-access-address",
338 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
343 cl::desc(
"check arguments and return values at function call boundaries"),
347 "msan-dump-strict-instructions",
348 cl::desc(
"print out instructions with default strict semantics i.e.,"
349 "check that all the inputs are fully initialized, and mark "
350 "the output as fully initialized. These semantics are applied "
351 "to instructions that could not be handled explicitly nor "
360 "msan-dump-heuristic-instructions",
361 cl::desc(
"Prints 'unknown' instructions that were handled heuristically. "
362 "Use -msan-dump-strict-instructions to print instructions that "
363 "could not be handled explicitly nor heuristically."),
367 "msan-instrumentation-with-call-threshold",
369 "If the function being instrumented requires more than "
370 "this number of checks and origin stores, use callbacks instead of "
371 "inline checks (-1 means never use callbacks)."),
376 cl::desc(
"Enable KernelMemorySanitizer instrumentation"),
386 cl::desc(
"Insert checks for constant shadow values"),
393 cl::desc(
"Place MSan constructors in comdat sections"),
399 cl::desc(
"Define custom MSan AndMask"),
403 cl::desc(
"Define custom MSan XorMask"),
407 cl::desc(
"Define custom MSan ShadowBase"),
411 cl::desc(
"Define custom MSan OriginBase"),
416 cl::desc(
"Define threshold for number of checks per "
417 "debug location to force origin update."),
429struct MemoryMapParams {
436struct PlatformMemoryMapParams {
437 const MemoryMapParams *bits32;
438 const MemoryMapParams *bits64;
615class MemorySanitizer {
624 MemorySanitizer(MemorySanitizer &&) =
delete;
625 MemorySanitizer &operator=(MemorySanitizer &&) =
delete;
626 MemorySanitizer(
const MemorySanitizer &) =
delete;
627 MemorySanitizer &operator=(
const MemorySanitizer &) =
delete;
629 bool sanitizeFunction(
Function &
F, TargetLibraryInfo &TLI);
632 friend struct MemorySanitizerVisitor;
633 friend struct VarArgHelperBase;
634 friend struct VarArgAMD64Helper;
635 friend struct VarArgAArch64Helper;
636 friend struct VarArgPowerPC64Helper;
637 friend struct VarArgPowerPC32Helper;
638 friend struct VarArgSystemZHelper;
639 friend struct VarArgI386Helper;
640 friend struct VarArgGenericHelper;
642 void initializeModule(
Module &M);
643 void initializeCallbacks(
Module &M,
const TargetLibraryInfo &TLI);
644 void createKernelApi(
Module &M,
const TargetLibraryInfo &TLI);
645 void createUserspaceApi(
Module &M,
const TargetLibraryInfo &TLI);
647 template <
typename... ArgsTy>
648 FunctionCallee getOrInsertMsanMetadataFunction(
Module &M, StringRef Name,
674 Value *ParamOriginTLS;
680 Value *RetvalOriginTLS;
686 Value *VAArgOriginTLS;
689 Value *VAArgOverflowSizeTLS;
692 bool CallbacksInitialized =
false;
695 FunctionCallee WarningFn;
699 FunctionCallee MaybeWarningVarSizeFn;
704 FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
706 FunctionCallee MsanSetAllocaOriginNoDescriptionFn;
709 FunctionCallee MsanPoisonStackFn;
713 FunctionCallee MsanChainOriginFn;
716 FunctionCallee MsanSetOriginFn;
719 FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
722 StructType *MsanContextStateTy;
723 FunctionCallee MsanGetContextStateFn;
726 FunctionCallee MsanPoisonAllocaFn, MsanUnpoisonAllocaFn;
732 FunctionCallee MsanMetadataPtrForLoadN, MsanMetadataPtrForStoreN;
733 FunctionCallee MsanMetadataPtrForLoad_1_8[4];
734 FunctionCallee MsanMetadataPtrForStore_1_8[4];
735 FunctionCallee MsanInstrumentAsmStoreFn;
738 Value *MsanMetadataAlloca;
741 FunctionCallee getKmsanShadowOriginAccessFn(
bool isStore,
int size);
744 const MemoryMapParams *MapParams;
748 MemoryMapParams CustomMapParams;
750 MDNode *ColdCallWeights;
753 MDNode *OriginStoreWeights;
793 if (!Options.Kernel) {
802 MemorySanitizer Msan(*
F.getParent(), Options);
820 static_cast<PassInfoMixin<MemorySanitizerPass> *
>(
this)->
printPipeline(
821 OS, MapClassName2PassName);
827 if (Options.EagerChecks)
828 OS <<
"eager-checks;";
829 OS <<
"track-origins=" << Options.TrackOrigins;
845template <
typename... ArgsTy>
847MemorySanitizer::getOrInsertMsanMetadataFunction(
Module &M,
StringRef Name,
852 std::forward<ArgsTy>(Args)...);
855 return M.getOrInsertFunction(Name, MsanMetadata,
856 std::forward<ArgsTy>(Args)...);
865 RetvalOriginTLS =
nullptr;
867 ParamOriginTLS =
nullptr;
869 VAArgOriginTLS =
nullptr;
870 VAArgOverflowSizeTLS =
nullptr;
872 WarningFn =
M.getOrInsertFunction(
"__msan_warning",
874 IRB.getVoidTy(), IRB.getInt32Ty());
885 MsanGetContextStateFn =
886 M.getOrInsertFunction(
"__msan_get_context_state", PtrTy);
890 for (
int ind = 0,
size = 1; ind < 4; ind++,
size <<= 1) {
891 std::string name_load =
892 "__msan_metadata_ptr_for_load_" + std::to_string(
size);
893 std::string name_store =
894 "__msan_metadata_ptr_for_store_" + std::to_string(
size);
895 MsanMetadataPtrForLoad_1_8[ind] =
896 getOrInsertMsanMetadataFunction(M, name_load, PtrTy);
897 MsanMetadataPtrForStore_1_8[ind] =
898 getOrInsertMsanMetadataFunction(M, name_store, PtrTy);
901 MsanMetadataPtrForLoadN = getOrInsertMsanMetadataFunction(
902 M,
"__msan_metadata_ptr_for_load_n", PtrTy, IntptrTy);
903 MsanMetadataPtrForStoreN = getOrInsertMsanMetadataFunction(
904 M,
"__msan_metadata_ptr_for_store_n", PtrTy, IntptrTy);
907 MsanPoisonAllocaFn =
M.getOrInsertFunction(
908 "__msan_poison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
909 MsanUnpoisonAllocaFn =
M.getOrInsertFunction(
910 "__msan_unpoison_alloca", IRB.getVoidTy(), PtrTy, IntptrTy);
914 return M.getOrInsertGlobal(Name, Ty, [&] {
916 nullptr, Name,
nullptr,
922void MemorySanitizer::createUserspaceApi(
Module &M,
930 StringRef WarningFnName = Recover ?
"__msan_warning_with_origin"
931 :
"__msan_warning_with_origin_noreturn";
932 WarningFn =
M.getOrInsertFunction(WarningFnName,
934 IRB.getVoidTy(), IRB.getInt32Ty());
937 Recover ?
"__msan_warning" :
"__msan_warning_noreturn";
938 WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
965 IRB.getIntPtrTy(
M.getDataLayout()));
969 unsigned AccessSize = 1 << AccessSizeIndex;
970 std::string FunctionName =
"__msan_maybe_warning_" +
itostr(AccessSize);
971 MaybeWarningFn[AccessSizeIndex] =
M.getOrInsertFunction(
973 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), IRB.getInt32Ty());
974 MaybeWarningVarSizeFn =
M.getOrInsertFunction(
975 "__msan_maybe_warning_N", TLI.
getAttrList(
C, {},
false),
976 IRB.getVoidTy(), PtrTy, IRB.getInt64Ty(), IRB.getInt32Ty());
977 FunctionName =
"__msan_maybe_store_origin_" +
itostr(AccessSize);
978 MaybeStoreOriginFn[AccessSizeIndex] =
M.getOrInsertFunction(
980 IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), PtrTy,
984 MsanSetAllocaOriginWithDescriptionFn =
985 M.getOrInsertFunction(
"__msan_set_alloca_origin_with_descr",
986 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy, PtrTy);
987 MsanSetAllocaOriginNoDescriptionFn =
988 M.getOrInsertFunction(
"__msan_set_alloca_origin_no_descr",
989 IRB.getVoidTy(), PtrTy, IntptrTy, PtrTy);
990 MsanPoisonStackFn =
M.getOrInsertFunction(
"__msan_poison_stack",
991 IRB.getVoidTy(), PtrTy, IntptrTy);
995void MemorySanitizer::initializeCallbacks(
Module &M,
998 if (CallbacksInitialized)
1004 MsanChainOriginFn =
M.getOrInsertFunction(
1005 "__msan_chain_origin",
1006 TLI.
getAttrList(
C, {0},
false,
true), IRB.getInt32Ty(),
1008 MsanSetOriginFn =
M.getOrInsertFunction(
1010 IRB.getVoidTy(), PtrTy, IntptrTy, IRB.getInt32Ty());
1012 M.getOrInsertFunction(
"__msan_memmove", PtrTy, PtrTy, PtrTy, IntptrTy);
1014 M.getOrInsertFunction(
"__msan_memcpy", PtrTy, PtrTy, PtrTy, IntptrTy);
1015 MemsetFn =
M.getOrInsertFunction(
"__msan_memset",
1017 PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
1019 MsanInstrumentAsmStoreFn =
M.getOrInsertFunction(
1020 "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
1022 if (CompileKernel) {
1023 createKernelApi(M, TLI);
1025 createUserspaceApi(M, TLI);
1027 CallbacksInitialized =
true;
1033 isStore ? MsanMetadataPtrForStore_1_8 : MsanMetadataPtrForLoad_1_8;
1051void MemorySanitizer::initializeModule(
Module &M) {
1052 auto &
DL =
M.getDataLayout();
1054 TargetTriple =
M.getTargetTriple();
1056 bool ShadowPassed =
ClShadowBase.getNumOccurrences() > 0;
1057 bool OriginPassed =
ClOriginBase.getNumOccurrences() > 0;
1059 if (ShadowPassed || OriginPassed) {
1064 MapParams = &CustomMapParams;
1066 switch (TargetTriple.getOS()) {
1068 switch (TargetTriple.getArch()) {
1083 switch (TargetTriple.getArch()) {
1092 switch (TargetTriple.getArch()) {
1129 C = &(
M.getContext());
1131 IntptrTy = IRB.getIntPtrTy(
DL);
1132 OriginTy = IRB.getInt32Ty();
1133 PtrTy = IRB.getPtrTy();
1138 if (!CompileKernel) {
1140 M.getOrInsertGlobal(
"__msan_track_origins", IRB.getInt32Ty(), [&] {
1141 return new GlobalVariable(
1142 M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1143 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
1147 M.getOrInsertGlobal(
"__msan_keep_going", IRB.getInt32Ty(), [&] {
1148 return new GlobalVariable(M, IRB.getInt32Ty(), true,
1149 GlobalValue::WeakODRLinkage,
1150 IRB.getInt32(Recover),
"__msan_keep_going");
1165struct VarArgHelper {
1166 virtual ~VarArgHelper() =
default;
1169 virtual void visitCallBase(CallBase &CB,
IRBuilder<> &IRB) = 0;
1172 virtual void visitVAStartInst(VAStartInst &
I) = 0;
1175 virtual void visitVACopyInst(VACopyInst &
I) = 0;
1181 virtual void finalizeInstrumentation() = 0;
1184struct MemorySanitizerVisitor;
1189 MemorySanitizerVisitor &Visitor);
1196 if (TypeSizeFixed <= 8)
1205class NextNodeIRBuilder :
public IRBuilder<> {
1218struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
1220 MemorySanitizer &MS;
1222 ValueMap<Value *, Value *> ShadowMap, OriginMap;
1223 std::unique_ptr<VarArgHelper> VAHelper;
1224 const TargetLibraryInfo *TLI;
1231 bool PropagateShadow;
1234 bool PoisonUndefVectors;
1236 struct ShadowOriginAndInsertPoint {
1241 ShadowOriginAndInsertPoint(
Value *S,
Value *O, Instruction *
I)
1242 : Shadow(S), Origin(
O), OrigIns(
I) {}
1245 DenseMap<const DILocation *, int> LazyWarningDebugLocationCount;
1246 SmallSetVector<AllocaInst *, 16> AllocaSet;
1249 int64_t SplittableBlocksCount = 0;
1251 MemorySanitizerVisitor(
Function &
F, MemorySanitizer &MS,
1252 const TargetLibraryInfo &TLI)
1254 bool SanitizeFunction =
1256 InsertChecks = SanitizeFunction;
1257 PropagateShadow = SanitizeFunction;
1268 MS.initializeCallbacks(*
F.getParent(), TLI);
1270 IRBuilder<>(&
F.getEntryBlock(),
F.getEntryBlock().getFirstNonPHIIt())
1271 .CreateIntrinsicWithoutFolding(Intrinsic::donothing, {});
1273 if (MS.CompileKernel) {
1275 insertKmsanPrologue(IRB);
1279 <<
"MemorySanitizer is not inserting checks into '"
1280 <<
F.getName() <<
"'\n");
1283 bool instrumentWithCalls(
Value *V) {
1287 ++SplittableBlocksCount;
1292 bool isInPrologue(Instruction &
I) {
1293 return I.getParent() == FnPrologueEnd->
getParent() &&
1302 if (MS.TrackOrigins <= 1)
1304 return IRB.
CreateCall(MS.MsanChainOriginFn, V);
1308 const DataLayout &
DL =
F.getDataLayout();
1309 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1319 TypeSize TS, Align Alignment) {
1320 const DataLayout &
DL =
F.getDataLayout();
1321 const Align IntptrAlignment =
DL.getABITypeAlign(MS.IntptrTy);
1322 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
1334 auto [InsertPt,
Index] =
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;
1419 std::tie(ShadowPtr, OriginPtr) =
1420 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
true);
1422 [[maybe_unused]] StoreInst *NewSI =
1429 if (MS.TrackOrigins && !
SI->isAtomic())
1430 storeOrigin(IRB, Addr, Shadow, getOrigin(Val), OriginPtr,
1437 if (MS.TrackOrigins < 2)
1440 if (LazyWarningDebugLocationCount.
empty())
1441 for (
const auto &
I : InstrumentationList)
1442 ++LazyWarningDebugLocationCount[
I.OrigIns->getDebugLoc()];
1458 auto NewDebugLoc = OI->getDebugLoc();
1465 IRBOrigin.SetCurrentDebugLocation(NewDebugLoc);
1466 Origin = updateOrigin(Origin, IRBOrigin);
1471 if (MS.CompileKernel || MS.TrackOrigins)
1482 const DataLayout &
DL =
F.getDataLayout();
1483 TypeSize TypeSizeInBits =
DL.getTypeSizeInBits(ConvertedShadow->
getType());
1485 if (instrumentWithCalls(ConvertedShadow) && !MS.CompileKernel) {
1487 ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
1488 Value *ConvertedShadow2 =
1492 FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1496 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1500 FunctionCallee Fn = MS.MaybeWarningVarSizeFn;
1503 unsigned ShadowSize =
DL.getTypeAllocSize(ConvertedShadow2->
getType());
1506 {ShadowAlloca, ConstantInt::get(IRB.
getInt64Ty(), ShadowSize),
1507 MS.TrackOrigins && Origin ? Origin : (
Value *)IRB.
getInt32(0)});
1512 Value *
Cmp = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1515 !MS.Recover, MS.ColdCallWeights);
1518 insertWarningFn(IRB, Origin);
1523 void materializeInstructionChecks(
1525 const DataLayout &
DL =
F.getDataLayout();
1528 bool Combine = !MS.TrackOrigins;
1530 Value *Shadow =
nullptr;
1531 for (
const auto &ShadowData : InstructionChecks) {
1532 assert(ShadowData.OrigIns == Instruction);
1535 Value *ConvertedShadow = ShadowData.Shadow;
1544 insertWarningFn(IRB, ShadowData.Origin);
1554 materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin);
1559 Shadow = ConvertedShadow;
1563 Shadow = convertToBool(Shadow, IRB,
"_mscmp");
1564 ConvertedShadow = convertToBool(ConvertedShadow, IRB,
"_mscmp");
1565 Shadow = IRB.
CreateOr(Shadow, ConvertedShadow,
"_msor");
1571 materializeOneCheck(IRB, Shadow,
nullptr);
1575 static bool isAArch64SVCount(
Type *Ty) {
1577 return TTy->
getName() ==
"aarch64.svcount";
1583 static bool isScalableNonVectorType(
Type *Ty) {
1584 if (!isAArch64SVCount(Ty))
1585 LLVM_DEBUG(
dbgs() <<
"isScalableNonVectorType: Unexpected type " << *Ty
1591 void materializeChecks() {
1594 SmallPtrSet<Instruction *, 16>
Done;
1597 for (
auto I = InstrumentationList.begin();
1598 I != InstrumentationList.end();) {
1599 auto OrigIns =
I->OrigIns;
1603 auto J = std::find_if(
I + 1, InstrumentationList.end(),
1604 [OrigIns](
const ShadowOriginAndInsertPoint &R) {
1605 return OrigIns != R.OrigIns;
1619 MS.ParamTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1620 {Zero, IRB.getInt32(0)},
"param_shadow");
1621 MS.RetvalTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1622 {Zero, IRB.getInt32(1)},
"retval_shadow");
1623 MS.VAArgTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1624 {Zero, IRB.getInt32(2)},
"va_arg_shadow");
1625 MS.VAArgOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1626 {Zero, IRB.getInt32(3)},
"va_arg_origin");
1627 MS.VAArgOverflowSizeTLS =
1628 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1629 {Zero, IRB.getInt32(4)},
"va_arg_overflow_size");
1630 MS.ParamOriginTLS = IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1631 {Zero, IRB.getInt32(5)},
"param_origin");
1632 MS.RetvalOriginTLS =
1633 IRB.
CreateGEP(MS.MsanContextStateTy, ContextState,
1634 {Zero, IRB.getInt32(6)},
"retval_origin");
1636 MS.MsanMetadataAlloca = IRB.
CreateAlloca(MS.MsanMetadata, 0u);
1649 for (Instruction *
I : Instructions)
1653 for (PHINode *PN : ShadowPHINodes) {
1655 PHINode *PNO = MS.TrackOrigins ?
cast<PHINode>(getOrigin(PN)) : nullptr;
1656 size_t NumValues = PN->getNumIncomingValues();
1657 for (
size_t v = 0;
v < NumValues;
v++) {
1658 PNS->
addIncoming(getShadow(PN, v), PN->getIncomingBlock(v));
1660 PNO->
addIncoming(getOrigin(PN, v), PN->getIncomingBlock(v));
1664 VAHelper->finalizeInstrumentation();
1669 for (
auto Item : LifetimeStartList) {
1670 instrumentAlloca(*Item.second, Item.first);
1671 AllocaSet.
remove(Item.second);
1676 for (AllocaInst *AI : AllocaSet)
1677 instrumentAlloca(*AI);
1680 materializeChecks();
1684 materializeStores();
1690 Type *getShadowTy(
Value *V) {
return getShadowTy(
V->getType()); }
1701 const DataLayout &
DL =
F.getDataLayout();
1703 uint32_t EltSize =
DL.getTypeSizeInBits(VT->getElementType());
1705 VT->getElementCount());
1708 return ArrayType::get(getShadowTy(AT->getElementType()),
1709 AT->getNumElements());
1713 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
1714 Elements.push_back(getShadowTy(
ST->getElementType(i)));
1716 LLVM_DEBUG(
dbgs() <<
"getShadowTy: " << *ST <<
" ===> " << *Res <<
"\n");
1719 if (isScalableNonVectorType(OrigTy)) {
1720 LLVM_DEBUG(
dbgs() <<
"getShadowTy: Scalable non-vector type: " << *OrigTy
1725 uint32_t TypeSize =
DL.getTypeSizeInBits(OrigTy);
1730 Value *collapseStructShadow(StructType *Struct,
Value *Shadow,
1735 for (
unsigned Idx = 0; Idx <
Struct->getNumElements(); Idx++) {
1738 Value *ShadowBool = convertToBool(ShadowItem, IRB);
1740 if (Aggregator != FalseVal)
1741 Aggregator = IRB.
CreateOr(Aggregator, ShadowBool);
1743 Aggregator = ShadowBool;
1750 Value *collapseArrayShadow(ArrayType *Array,
Value *Shadow,
1752 if (!
Array->getNumElements())
1756 Value *Aggregator = convertShadowToScalar(FirstItem, IRB);
1758 for (
unsigned Idx = 1; Idx <
Array->getNumElements(); Idx++) {
1760 Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB);
1761 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1771 return collapseStructShadow(Struct, V, IRB);
1773 return collapseArrayShadow(Array, V, IRB);
1778 V->getType()->getPrimitiveSizeInBits().getFixedValue();
1786 Type *VTy =
V->getType();
1788 return convertToBool(convertShadowToScalar(V, IRB), IRB,
name);
1795 Type *ptrToIntPtrType(
Type *PtrTy)
const {
1797 return VectorType::get(ptrToIntPtrType(VectTy->getElementType()),
1798 VectTy->getElementCount());
1806 return VectorType::get(
1807 getPtrToShadowPtrType(VectTy->getElementType(), ShadowTy),
1808 VectTy->getElementCount());
1817 VectTy->getElementCount(),
1818 constToIntPtr(VectTy->getElementType(),
C));
1823 return ConstantInt::get(MS.IntptrTy,
C,
false,
1837 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1840 if (
uint64_t AndMask = MS.MapParams->AndMask)
1841 OffsetLong = IRB.
CreateAnd(OffsetLong, constToIntPtr(IntptrTy, ~AndMask));
1843 if (
uint64_t XorMask = MS.MapParams->XorMask)
1844 OffsetLong = IRB.
CreateXor(OffsetLong, constToIntPtr(IntptrTy, XorMask));
1856 std::pair<Value *, Value *>
1858 MaybeAlign Alignment) {
1863 assert(VectTy->getElementType()->isPointerTy());
1865 Type *IntptrTy = ptrToIntPtrType(Addr->
getType());
1866 Value *ShadowOffset = getShadowPtrOffset(Addr, IRB);
1867 Value *ShadowLong = ShadowOffset;
1868 if (
uint64_t ShadowBase = MS.MapParams->ShadowBase) {
1870 IRB.
CreateAdd(ShadowLong, constToIntPtr(IntptrTy, ShadowBase));
1873 ShadowLong, getPtrToShadowPtrType(IntptrTy, ShadowTy));
1875 Value *OriginPtr =
nullptr;
1876 if (MS.TrackOrigins) {
1877 Value *OriginLong = ShadowOffset;
1878 uint64_t OriginBase = MS.MapParams->OriginBase;
1879 if (OriginBase != 0)
1881 IRB.
CreateAdd(OriginLong, constToIntPtr(IntptrTy, OriginBase));
1884 OriginLong = IRB.
CreateAnd(OriginLong, constToIntPtr(IntptrTy, ~Mask));
1887 OriginLong, getPtrToShadowPtrType(IntptrTy, MS.OriginTy));
1889 return std::make_pair(ShadowPtr, OriginPtr);
1892 template <
typename... ArgsTy>
1897 {MS.MsanMetadataAlloca, std::forward<ArgsTy>(Args)...});
1898 return IRB.
CreateLoad(MS.MsanMetadata, MS.MsanMetadataAlloca);
1901 return IRB.
CreateCall(Callee, {std::forward<ArgsTy>(Args)...});
1904 std::pair<Value *, Value *> getShadowOriginPtrKernelNoVec(
Value *Addr,
1908 Value *ShadowOriginPtrs;
1909 const DataLayout &
DL =
F.getDataLayout();
1910 TypeSize
Size =
DL.getTypeStoreSize(ShadowTy);
1912 FunctionCallee Getter = MS.getKmsanShadowOriginAccessFn(
isStore,
Size);
1915 ShadowOriginPtrs = createMetadataCall(IRB, Getter, AddrCast);
1917 Value *SizeVal = ConstantInt::get(MS.IntptrTy,
Size);
1918 ShadowOriginPtrs = createMetadataCall(
1920 isStore ? MS.MsanMetadataPtrForStoreN : MS.MsanMetadataPtrForLoadN,
1927 return std::make_pair(ShadowPtr, OriginPtr);
1933 std::pair<Value *, Value *> getShadowOriginPtrKernel(
Value *Addr,
1940 return getShadowOriginPtrKernelNoVec(Addr, IRB, ShadowTy,
isStore);
1945 Value *ShadowPtrs = ConstantInt::getNullValue(
1947 Value *OriginPtrs =
nullptr;
1948 if (MS.TrackOrigins)
1949 OriginPtrs = ConstantInt::getNullValue(
1951 for (
unsigned i = 0; i < NumElements; ++i) {
1954 auto [ShadowPtr, OriginPtr] =
1955 getShadowOriginPtrKernelNoVec(OneAddr, IRB, ShadowTy,
isStore);
1958 ShadowPtrs, ShadowPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1959 if (MS.TrackOrigins)
1961 OriginPtrs, OriginPtr, ConstantInt::get(IRB.
getInt32Ty(), i));
1963 return {ShadowPtrs, OriginPtrs};
1966 std::pair<Value *, Value *> getShadowOriginPtr(
Value *Addr,
IRBuilder<> &IRB,
1968 MaybeAlign Alignment,
1970 if (MS.CompileKernel)
1971 return getShadowOriginPtrKernel(Addr, IRB, ShadowTy,
isStore);
1972 return getShadowOriginPtrUserspace(Addr, IRB, ShadowTy, Alignment);
1980 ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg");
1985 if (!MS.TrackOrigins)
1988 ConstantInt::get(MS.IntptrTy, ArgOffset),
1998 Value *getOriginPtrForRetval() {
2000 return MS.RetvalOriginTLS;
2005 assert(!ShadowMap.
count(V) &&
"Values may only have one shadow");
2006 ShadowMap[
V] = PropagateShadow ? SV : getCleanShadow(V);
2011 if (!MS.TrackOrigins)
2013 assert(!OriginMap.
count(V) &&
"Values may only have one origin");
2014 LLVM_DEBUG(
dbgs() <<
"ORIGIN: " << *V <<
" ==> " << *Origin <<
"\n");
2015 OriginMap[
V] = Origin;
2019 Type *ShadowTy = getShadowTy(OrigTy);
2029 Constant *getCleanShadow(
Value *V) {
return getCleanShadow(
V->getType()); }
2037 SmallVector<Constant *, 4> Vals(AT->getNumElements(),
2038 getPoisonedShadow(AT->getElementType()));
2042 SmallVector<Constant *, 4> Vals;
2043 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
2044 Vals.
push_back(getPoisonedShadow(
ST->getElementType(i)));
2052 Type *ShadowTy = getShadowTy(V);
2055 return getPoisonedShadow(ShadowTy);
2067 if (!PropagateShadow ||
I->getMetadata(LLVMContext::MD_nosanitize))
2068 return getCleanShadow(V);
2070 Value *Shadow = ShadowMap[
V];
2072 LLVM_DEBUG(
dbgs() <<
"No shadow: " << *V <<
"\n" << *(
I->getParent()));
2073 assert(Shadow &&
"No shadow for a value");
2080 Value *
AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
2081 : getCleanShadow(V);
2087 Value *&ShadowPtr = ShadowMap[
V];
2092 unsigned ArgOffset = 0;
2093 const DataLayout &
DL =
F->getDataLayout();
2094 for (
auto &FArg :
F->args()) {
2095 if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
2097 ?
"vscale not fully supported\n"
2098 :
"Arg is not sized\n"));
2100 ShadowPtr = getCleanShadow(V);
2101 setOrigin(
A, getCleanOrigin());
2107 unsigned Size = FArg.hasByValAttr()
2108 ?
DL.getTypeAllocSize(FArg.getParamByValType())
2109 :
DL.getTypeAllocSize(FArg.getType());
2113 if (FArg.hasByValAttr()) {
2117 const Align ArgAlign =
DL.getValueOrABITypeAlignment(
2118 FArg.getParamAlign(), FArg.getParamByValType());
2119 Value *CpShadowPtr, *CpOriginPtr;
2120 std::tie(CpShadowPtr, CpOriginPtr) =
2121 getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign,
2123 if (!PropagateShadow || Overflow) {
2125 EntryIRB.CreateMemSet(
2129 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2131 [[maybe_unused]]
Value *Cpy = EntryIRB.CreateMemCpy(
2132 CpShadowPtr, CopyAlign,
Base, CopyAlign,
Size);
2135 if (MS.TrackOrigins) {
2136 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2140 EntryIRB.CreateMemCpy(
2149 if (!PropagateShadow || Overflow || FArg.hasByValAttr() ||
2150 (MS.EagerChecks && FArg.hasAttribute(Attribute::NoUndef))) {
2151 ShadowPtr = getCleanShadow(V);
2152 setOrigin(
A, getCleanOrigin());
2155 Value *
Base = getShadowPtrForArgument(EntryIRB, ArgOffset);
2156 ShadowPtr = EntryIRB.CreateAlignedLoad(getShadowTy(&FArg),
Base,
2158 if (MS.TrackOrigins) {
2159 Value *OriginPtr = getOriginPtrForArgument(EntryIRB, ArgOffset);
2160 setOrigin(
A, EntryIRB.CreateLoad(MS.OriginTy, OriginPtr));
2164 <<
" ARG: " << FArg <<
" ==> " << *ShadowPtr <<
"\n");
2170 assert(ShadowPtr &&
"Could not find shadow for an argument");
2177 cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
2178 PoisonUndefVectors) {
2181 for (
unsigned i = 0; i != NumElems; ++i) {
2184 : getCleanShadow(Elem);
2188 LLVM_DEBUG(
dbgs() <<
"Partial undef constant vector: " << *V <<
" ==> "
2189 << *ShadowConstant <<
"\n");
2191 return ShadowConstant;
2197 return getCleanShadow(V);
2201 Value *getShadow(Instruction *
I,
int i) {
2202 return getShadow(
I->getOperand(i));
2207 if (!MS.TrackOrigins)
2210 return getCleanOrigin();
2212 "Unexpected value type in getOrigin()");
2214 if (
I->getMetadata(LLVMContext::MD_nosanitize))
2215 return getCleanOrigin();
2217 Value *Origin = OriginMap[
V];
2218 assert(Origin &&
"Missing origin");
2223 Value *getOrigin(Instruction *
I,
int i) {
2224 return getOrigin(
I->getOperand(i));
2231 void insertCheckShadow(
Value *Shadow,
Value *Origin, Instruction *OrigIns) {
2237 LLVM_DEBUG(
dbgs() <<
"Skipping check of " << *Shadow <<
" before "
2238 << *OrigIns <<
"\n");
2243 if (isScalableNonVectorType(ShadowTy)) {
2244 LLVM_DEBUG(
dbgs() <<
"Skipping check of scalable non-vector " << *Shadow
2245 <<
" before " << *OrigIns <<
"\n");
2251 "Can only insert checks for integer, vector, and aggregate shadow "
2254 InstrumentationList.push_back(
2255 ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
2263 void insertCheckShadowOf(
Value *Val, Instruction *OrigIns) {
2265 Value *Shadow, *Origin;
2267 Shadow = getShadow(Val);
2270 Origin = getOrigin(Val);
2277 insertCheckShadow(Shadow, Origin, OrigIns);
2282 case AtomicOrdering::NotAtomic:
2283 return AtomicOrdering::NotAtomic;
2284 case AtomicOrdering::Unordered:
2285 case AtomicOrdering::Monotonic:
2286 case AtomicOrdering::Release:
2287 return AtomicOrdering::Release;
2288 case AtomicOrdering::Acquire:
2289 case AtomicOrdering::AcquireRelease:
2290 return AtomicOrdering::AcquireRelease;
2291 case AtomicOrdering::SequentiallyConsistent:
2292 return AtomicOrdering::SequentiallyConsistent;
2298 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2299 uint32_t OrderingTable[NumOrderings] = {};
2301 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2302 OrderingTable[(
int)AtomicOrderingCABI::release] =
2303 (int)AtomicOrderingCABI::release;
2304 OrderingTable[(int)AtomicOrderingCABI::consume] =
2305 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2306 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
2307 (
int)AtomicOrderingCABI::acq_rel;
2308 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2309 (
int)AtomicOrderingCABI::seq_cst;
2316 case AtomicOrdering::NotAtomic:
2317 return AtomicOrdering::NotAtomic;
2318 case AtomicOrdering::Unordered:
2319 case AtomicOrdering::Monotonic:
2320 case AtomicOrdering::Acquire:
2321 return AtomicOrdering::Acquire;
2322 case AtomicOrdering::Release:
2323 case AtomicOrdering::AcquireRelease:
2324 return AtomicOrdering::AcquireRelease;
2325 case AtomicOrdering::SequentiallyConsistent:
2326 return AtomicOrdering::SequentiallyConsistent;
2332 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
2333 uint32_t OrderingTable[NumOrderings] = {};
2335 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
2336 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
2337 OrderingTable[(int)AtomicOrderingCABI::consume] =
2338 (
int)AtomicOrderingCABI::acquire;
2339 OrderingTable[(int)AtomicOrderingCABI::release] =
2340 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
2341 (int)AtomicOrderingCABI::acq_rel;
2342 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
2343 (
int)AtomicOrderingCABI::seq_cst;
2349 using InstVisitor<MemorySanitizerVisitor>
::visit;
2350 void visit(Instruction &
I) {
2351 if (
I.getMetadata(LLVMContext::MD_nosanitize))
2354 if (isInPrologue(
I))
2359 setShadow(&
I, getCleanShadow(&
I));
2360 setOrigin(&
I, getCleanOrigin());
2371 void visitLoadInst(LoadInst &
I) {
2372 assert(
I.getType()->isSized() &&
"Load type must have size");
2373 assert(!
I.getMetadata(LLVMContext::MD_nosanitize));
2374 NextNodeIRBuilder IRB(&
I);
2375 Type *ShadowTy = getShadowTy(&
I);
2376 Value *Addr =
I.getPointerOperand();
2377 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
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 visitPtrToAddrInst(PtrToAddrInst &
I) {
2615 "_msprop_ptrtoaddr"));
2616 setOrigin(&
I, getOrigin(&
I, 0));
2619 void visitIntToPtrInst(IntToPtrInst &
I) {
2622 "_msprop_inttoptr"));
2623 setOrigin(&
I, getOrigin(&
I, 0));
2644 void handleGenericVectorConvertIntrinsic(Instruction &
I,
bool FixedPoint) {
2645 [[maybe_unused]]
unsigned NumArgs =
I.getNumOperands();
2647 NumArgs = CI->arg_size();
2651 Value *Precision =
I.getOperand(1);
2652 insertCheckShadowOf(Precision, &
I);
2658 Value *S0 = getShadow(&
I, 0);
2668 setShadow(&
I, OutShadow);
2669 setOriginForNaryOp(
I);
2672 void visitFPToSIInst(CastInst &
I) {
2673 handleGenericVectorConvertIntrinsic(
I,
false);
2675 void visitFPToUIInst(CastInst &
I) {
2676 handleGenericVectorConvertIntrinsic(
I,
false);
2678 void visitSIToFPInst(CastInst &
I) {
2679 handleGenericVectorConvertIntrinsic(
I,
false);
2681 void visitUIToFPInst(CastInst &
I) {
2682 handleGenericVectorConvertIntrinsic(
I,
false);
2685 void visitFPExtInst(CastInst &
I) {
2686 handleGenericVectorConvertIntrinsic(
I,
false);
2688 void visitFPTruncInst(CastInst &
I) {
2689 handleGenericVectorConvertIntrinsic(
I,
false);
2710 assert(
V1->getType()->isIntOrIntVectorTy());
2721 return IRB.
CreateOr({S1S2, V1S2, S1V2});
2725 void visitAnd(BinaryOperator &
I) {
2728 Value *V2 =
I.getOperand(1);
2730 Value *S2 = getShadow(&
I, 1);
2732 Value *OutShadow = handleBitwiseAnd(IRB,
V1, V2,
S1, S2);
2734 setShadow(&
I, OutShadow);
2735 setOriginForNaryOp(
I);
2738 void visitOr(BinaryOperator &
I) {
2751 Value *S2 = getShadow(&
I, 1);
2753 Value *V2 =
I.getOperand(1);
2757 assert(
V1->getType()->isIntOrIntVectorTy());
2777 S = IRB.
CreateOr(S, DisjointOrShadow,
"_ms_disjoint");
2781 setOriginForNaryOp(
I);
2799 template <
bool CombineShadow>
class Combiner {
2800 Value *Shadow =
nullptr;
2801 Value *Origin =
nullptr;
2803 MemorySanitizerVisitor *MSV;
2806 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB)
2807 : IRB(IRB), MSV(MSV) {}
2811 if (CombineShadow) {
2816 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->getType());
2817 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
2821 if (MSV->MS.TrackOrigins) {
2828 if (!ConstOrigin || !ConstOrigin->
isNullValue()) {
2829 Value *
Cond = MSV->convertToBool(OpShadow, IRB);
2839 Value *OpShadow = MSV->getShadow(V);
2840 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) :
nullptr;
2841 return Add(OpShadow, OpOrigin);
2846 void Done(Instruction *
I) {
2847 if (CombineShadow) {
2849 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(
I));
2850 MSV->setShadow(
I, Shadow);
2852 if (MSV->MS.TrackOrigins) {
2854 MSV->setOrigin(
I, Origin);
2860 void DoneAndStoreOrigin(TypeSize TS,
Value *OriginPtr) {
2861 if (MSV->MS.TrackOrigins) {
2868 using ShadowAndOriginCombiner = Combiner<true>;
2869 using OriginCombiner = Combiner<false>;
2872 void setOriginForNaryOp(Instruction &
I) {
2873 if (!MS.TrackOrigins)
2876 OriginCombiner OC(
this, IRB);
2877 for (Use &
Op :
I.operands())
2882 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
2884 "Vector of pointers is not a valid shadow type");
2894 Type *srcTy =
V->getType();
2897 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
2898 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
2899 if (srcSizeInBits > 1 && dstSizeInBits == 1)
2917 Type *ShadowTy = getShadowTy(V);
2918 if (
V->getType() == ShadowTy)
2920 if (
V->getType()->isPtrOrPtrVectorTy())
2927 void handleShadowOr(Instruction &
I) {
2929 ShadowAndOriginCombiner SC(
this, IRB);
2930 for (Use &
Op :
I.operands())
2957 Value *horizontalReduce(IntrinsicInst &
I,
unsigned ReductionFactor,
2958 unsigned Shards,
Value *VectorA,
Value *VectorB) {
2963 [[maybe_unused]]
unsigned TotalNumElems = NumElems;
2969 assert(NumElems % (ReductionFactor * Shards) == 0);
2974 for (
unsigned i = 0; i < ReductionFactor; i++) {
2975 SmallVector<int, 16>
Mask;
2977 for (
unsigned j = 0;
j < Shards;
j++) {
2978 unsigned Offset = NumElems / Shards *
j;
2980 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
2984 for (
unsigned X = 0;
X < NumElems / Shards;
X += ReductionFactor)
3009 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards) {
3010 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3012 assert(
I.getType()->isVectorTy());
3013 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3015 [[maybe_unused]] FixedVectorType *ParamType =
3019 [[maybe_unused]] FixedVectorType *
ReturnType =
3027 Value *FirstArgShadow = getShadow(&
I, 0);
3028 Value *SecondArgShadow =
nullptr;
3029 if (
I.arg_size() == 2)
3030 SecondArgShadow = getShadow(&
I, 1);
3032 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3033 FirstArgShadow, SecondArgShadow);
3035 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3037 setShadow(&
I, OrShadow);
3038 setOriginForNaryOp(
I);
3048 void handlePairwiseShadowOrIntrinsic(IntrinsicInst &
I,
unsigned Shards,
3049 int ReinterpretElemWidth) {
3050 assert(
I.arg_size() == 1 ||
I.arg_size() == 2);
3052 assert(
I.getType()->isVectorTy());
3053 assert(
I.getArgOperand(0)->getType()->isVectorTy());
3055 FixedVectorType *ParamType =
3060 [[maybe_unused]] FixedVectorType *
ReturnType =
3067 FixedVectorType *ReinterpretShadowTy =
nullptr;
3075 Value *FirstArgShadow = getShadow(&
I, 0);
3076 FirstArgShadow = IRB.
CreateBitCast(FirstArgShadow, ReinterpretShadowTy);
3086 Value *SecondArgShadow =
nullptr;
3087 if (
I.arg_size() == 2) {
3088 SecondArgShadow = getShadow(&
I, 1);
3089 SecondArgShadow = IRB.
CreateBitCast(SecondArgShadow, ReinterpretShadowTy);
3092 Value *OrShadow = horizontalReduce(
I, 2, Shards,
3093 FirstArgShadow, SecondArgShadow);
3095 OrShadow = CreateShadowCast(IRB, OrShadow, getShadowTy(&
I));
3097 setShadow(&
I, OrShadow);
3098 setOriginForNaryOp(
I);
3101 void visitFNeg(UnaryOperator &
I) { handleShadowOr(
I); }
3112 void handleMulByConstant(BinaryOperator &
I, Constant *ConstArg,
3118 Type *EltTy = VTy->getElementType();
3120 for (
unsigned Idx = 0; Idx < NumElements; ++Idx) {
3121 if (ConstantInt *Elt =
3123 const APInt &
V = Elt->getValue();
3124 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3125 Elements.push_back(ConstantInt::get(EltTy, V2));
3127 Elements.push_back(ConstantInt::get(EltTy, 1));
3133 const APInt &
V = Elt->getValue();
3134 APInt V2 = APInt(
V.getBitWidth(), 1) <<
V.countr_zero();
3135 ShadowMul = ConstantInt::get(Ty, V2);
3137 ShadowMul = ConstantInt::get(Ty, 1);
3143 IRB.
CreateMul(getShadow(OtherArg), ShadowMul,
"msprop_mul_cst"));
3144 setOrigin(&
I, getOrigin(OtherArg));
3147 void visitMul(BinaryOperator &
I) {
3150 if (constOp0 && !constOp1)
3151 handleMulByConstant(
I, constOp0,
I.getOperand(1));
3152 else if (constOp1 && !constOp0)
3153 handleMulByConstant(
I, constOp1,
I.getOperand(0));
3158 void visitFAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3159 void visitFSub(BinaryOperator &
I) { handleShadowOr(
I); }
3160 void visitFMul(BinaryOperator &
I) { handleShadowOr(
I); }
3161 void visitAdd(BinaryOperator &
I) { handleShadowOr(
I); }
3162 void visitSub(BinaryOperator &
I) { handleShadowOr(
I); }
3163 void visitXor(BinaryOperator &
I) { handleShadowOr(
I); }
3165 void handleIntegerDiv(Instruction &
I) {
3168 insertCheckShadowOf(
I.getOperand(1), &
I);
3169 setShadow(&
I, getShadow(&
I, 0));
3170 setOrigin(&
I, getOrigin(&
I, 0));
3173 void visitUDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3174 void visitSDiv(BinaryOperator &
I) { handleIntegerDiv(
I); }
3175 void visitURem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3176 void visitSRem(BinaryOperator &
I) { handleIntegerDiv(
I); }
3180 void visitFDiv(BinaryOperator &
I) { handleShadowOr(
I); }
3181 void visitFRem(BinaryOperator &
I) { handleShadowOr(
I); }
3187 void handleEqualityComparison(ICmpInst &
I) {
3191 Value *Sa = getShadow(
A);
3192 Value *Sb = getShadow(
B);
3194 Value *Si = propagateEqualityComparison(IRB,
A,
B, Sa, Sb);
3197 setOriginForNaryOp(
I);
3205 void handleRelationalComparisonExact(ICmpInst &
I) {
3209 Value *Sa = getShadow(
A);
3210 Value *Sb = getShadow(
B);
3221 bool IsSigned =
I.isSigned();
3223 auto GetMinMaxUnsigned = [&](
Value *
V,
Value *S) {
3233 V = IRB.
CreateXor(V, ConstantInt::get(
V->getType(), MinVal));
3238 return std::make_pair(Min, Max);
3241 auto [Amin, Amax] = GetMinMaxUnsigned(
A, Sa);
3242 auto [Bmin, Bmax] = GetMinMaxUnsigned(
B, Sb);
3248 setOriginForNaryOp(
I);
3255 void handleSignedRelationalComparison(ICmpInst &
I) {
3260 op =
I.getOperand(0);
3261 pre =
I.getPredicate();
3263 op =
I.getOperand(1);
3264 pre =
I.getSwappedPredicate();
3277 setShadow(&
I, Shadow);
3278 setOrigin(&
I, getOrigin(
op));
3284 void visitICmpInst(ICmpInst &
I) {
3289 if (
I.isEquality()) {
3290 handleEqualityComparison(
I);
3296 handleRelationalComparisonExact(
I);
3300 handleSignedRelationalComparison(
I);
3306 handleRelationalComparisonExact(
I);
3313 void visitFCmpInst(FCmpInst &
I) { handleShadowOr(
I); }
3315 void handleShift(BinaryOperator &
I) {
3320 Value *S2 = getShadow(&
I, 1);
3323 Value *V2 =
I.getOperand(1);
3325 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3326 setOriginForNaryOp(
I);
3329 void visitShl(BinaryOperator &
I) { handleShift(
I); }
3330 void visitAShr(BinaryOperator &
I) { handleShift(
I); }
3331 void visitLShr(BinaryOperator &
I) { handleShift(
I); }
3333 void handleFunnelShift(IntrinsicInst &
I) {
3337 Value *S0 = getShadow(&
I, 0);
3339 Value *S2 = getShadow(&
I, 2);
3342 Value *V2 =
I.getOperand(2);
3345 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3346 setOriginForNaryOp(
I);
3354 void handleGenericBitManipulation(IntrinsicInst &
I) {
3356 Type *ShadowTy = getShadowTy(&
I);
3359 Value *SMask = getShadow(&
I, 1);
3364 if (
Function *Func =
I.getCalledFunction())
3365 S = IRB.
CreateCall(Func, {getShadow(&
I, 0),
I.getOperand(1)});
3368 {getShadow(&I, 0), I.getOperand(1)});
3371 setOriginForNaryOp(
I);
3384 void visitMemMoveInst(MemMoveInst &
I) {
3385 getShadow(
I.getArgOperand(1));
3388 {I.getArgOperand(0), I.getArgOperand(1),
3389 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3407 void visitMemCpyInst(MemCpyInst &
I) {
3408 getShadow(
I.getArgOperand(1));
3411 {I.getArgOperand(0), I.getArgOperand(1),
3412 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3417 void visitMemSetInst(MemSetInst &
I) {
3421 {I.getArgOperand(0),
3422 IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
3423 IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
3427 void visitVAStartInst(VAStartInst &
I) { VAHelper->visitVAStartInst(
I); }
3429 void visitVACopyInst(VACopyInst &
I) { VAHelper->visitVACopyInst(
I); }
3435 bool handleVectorStoreIntrinsic(IntrinsicInst &
I) {
3439 Value *Addr =
I.getArgOperand(0);
3440 Value *Shadow = getShadow(&
I, 1);
3441 Value *ShadowPtr, *OriginPtr;
3445 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
3450 insertCheckShadowOf(Addr, &
I);
3453 if (MS.TrackOrigins)
3462 bool handleVectorLoadIntrinsic(IntrinsicInst &
I) {
3466 Value *Addr =
I.getArgOperand(0);
3468 Type *ShadowTy = getShadowTy(&
I);
3469 Value *ShadowPtr =
nullptr, *OriginPtr =
nullptr;
3470 if (PropagateShadow) {
3474 std::tie(ShadowPtr, OriginPtr) =
3475 getShadowOriginPtr(Addr, IRB, ShadowTy, Alignment,
false);
3479 setShadow(&
I, getCleanShadow(&
I));
3483 insertCheckShadowOf(Addr, &
I);
3485 if (MS.TrackOrigins) {
3486 if (PropagateShadow)
3487 setOrigin(&
I, IRB.
CreateLoad(MS.OriginTy, OriginPtr));
3489 setOrigin(&
I, getCleanOrigin());
3509 [[maybe_unused]]
bool
3510 maybeHandleSimpleNomemIntrinsic(IntrinsicInst &
I,
3511 unsigned int trailingFlags) {
3512 Type *RetTy =
I.getType();
3516 unsigned NumArgOperands =
I.arg_size();
3517 assert(NumArgOperands >= trailingFlags);
3518 for (
unsigned i = 0; i < NumArgOperands - trailingFlags; ++i) {
3519 Type *Ty =
I.getArgOperand(i)->getType();
3525 ShadowAndOriginCombiner SC(
this, IRB);
3526 for (
unsigned i = 0; i < NumArgOperands; ++i)
3527 SC.Add(
I.getArgOperand(i));
3544 bool maybeHandleUnknownIntrinsicUnlogged(IntrinsicInst &
I) {
3545 unsigned NumArgOperands =
I.arg_size();
3546 if (NumArgOperands == 0)
3549 if (NumArgOperands == 2 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3550 I.getArgOperand(1)->getType()->isVectorTy() &&
3551 I.getType()->isVoidTy() && !
I.onlyReadsMemory()) {
3553 return handleVectorStoreIntrinsic(
I);
3556 if (NumArgOperands == 1 &&
I.getArgOperand(0)->getType()->isPointerTy() &&
3557 I.getType()->isVectorTy() &&
I.onlyReadsMemory()) {
3559 return handleVectorLoadIntrinsic(
I);
3562 if (
I.doesNotAccessMemory())
3563 if (maybeHandleSimpleNomemIntrinsic(
I, 0))
3571 bool maybeHandleUnknownIntrinsic(IntrinsicInst &
I) {
3572 if (maybeHandleUnknownIntrinsicUnlogged(
I)) {
3574 dumpInst(
I,
"Heuristic");
3576 LLVM_DEBUG(
dbgs() <<
"UNKNOWN INSTRUCTION HANDLED HEURISTICALLY: " <<
I
3583 void handleInvariantGroup(IntrinsicInst &
I) {
3584 setShadow(&
I, getShadow(&
I, 0));
3585 setOrigin(&
I, getOrigin(&
I, 0));
3588 void handleLifetimeStart(IntrinsicInst &
I) {
3593 LifetimeStartList.push_back(std::make_pair(&
I, AI));
3596 void handleBswap(IntrinsicInst &
I) {
3599 Type *OpType =
Op->getType();
3602 setOrigin(&
I, getOrigin(
Op));
3623 void handleCountLeadingTrailingZeros(IntrinsicInst &
I) {
3625 Value *Src =
I.getArgOperand(0);
3626 Value *SrcShadow = getShadow(Src);
3630 I.getType(),
I.getIntrinsicID(), {Src, False});
3632 I.getType(),
I.getIntrinsicID(), {SrcShadow, False});
3635 ConcreteZerosCount, ShadowZerosCount,
"_mscz_cmp_zeros");
3637 Value *NotAllZeroShadow =
3639 Value *OutputShadow =
3640 IRB.
CreateAnd(CompareConcreteZeros, NotAllZeroShadow,
"_mscz_main");
3646 OutputShadow = IRB.
CreateOr(OutputShadow, BoolZeroPoison,
"_mscz_bs");
3649 OutputShadow = IRB.
CreateSExt(OutputShadow, getShadowTy(Src),
"_mscz_os");
3651 setShadow(&
I, OutputShadow);
3652 setOriginForNaryOp(
I);
3661 FixedVectorType *maybeShrinkVectorShadowType(
Value *Src, IntrinsicInst &
I) {
3681 Value *maybeExtendVectorShadowWithZeros(
Value *Shadow, IntrinsicInst &
I) {
3686 Value *FullShadow = getCleanShadow(&
I);
3687 unsigned ShadowNumElems =
3689 unsigned FullShadowNumElems =
3692 assert((ShadowNumElems == FullShadowNumElems) ||
3693 (ShadowNumElems * 2 == FullShadowNumElems));
3695 if (ShadowNumElems == FullShadowNumElems) {
3696 FullShadow = Shadow;
3700 std::iota(ShadowMask.begin(), ShadowMask.end(), 0);
3725 void handleSSEVectorConvertIntrinsicByProp(IntrinsicInst &
I,
3726 bool HasRoundingMode) {
3727 if (HasRoundingMode) {
3735 Value *Src =
I.getArgOperand(0);
3736 assert(Src->getType()->isVectorTy());
3740 VectorType *ShadowType = maybeShrinkVectorShadowType(Src,
I);
3743 Value *S0 = getShadow(&
I, 0);
3755 Value *FullShadow = maybeExtendVectorShadowWithZeros(Shadow,
I);
3757 setShadow(&
I, FullShadow);
3758 setOriginForNaryOp(
I);
3779 void handleSSEVectorConvertIntrinsic(IntrinsicInst &
I,
int NumUsedElements,
3780 bool HasRoundingMode =
false) {
3782 Value *CopyOp, *ConvertOp;
3784 assert((!HasRoundingMode ||
3786 "Invalid rounding mode");
3788 switch (
I.arg_size() - HasRoundingMode) {
3790 CopyOp =
I.getArgOperand(0);
3791 ConvertOp =
I.getArgOperand(1);
3794 ConvertOp =
I.getArgOperand(0);
3808 Value *ConvertShadow = getShadow(ConvertOp);
3809 Value *AggShadow =
nullptr;
3812 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), 0));
3813 for (
int i = 1; i < NumUsedElements; ++i) {
3815 ConvertShadow, ConstantInt::get(IRB.
getInt32Ty(), i));
3816 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
3819 AggShadow = ConvertShadow;
3822 insertCheckShadow(AggShadow, getOrigin(ConvertOp), &
I);
3829 Value *ResultShadow = getShadow(CopyOp);
3831 for (
int i = 0; i < NumUsedElements; ++i) {
3833 ResultShadow, ConstantInt::getNullValue(EltTy),
3836 setShadow(&
I, ResultShadow);
3837 setOrigin(&
I, getOrigin(CopyOp));
3839 setShadow(&
I, getCleanShadow(&
I));
3840 setOrigin(&
I, getCleanOrigin());
3848 S = CreateShadowCast(IRB, S, IRB.
getInt64Ty(),
true);
3851 return CreateShadowCast(IRB, S2,
T,
true);
3859 return CreateShadowCast(IRB, S2,
T,
true);
3876 void handleVectorShiftIntrinsic(IntrinsicInst &
I,
bool Variable) {
3882 Value *S2 = getShadow(&
I, 1);
3884 : Lower64ShadowExtend(IRB, S2, getShadowTy(&
I));
3886 Value *V2 =
I.getOperand(1);
3888 {IRB.CreateBitCast(S1, V1->getType()), V2});
3890 setShadow(&
I, IRB.
CreateOr(Shift, S2Conv));
3891 setOriginForNaryOp(
I);
3896 Type *getMMXVectorTy(
unsigned EltSizeInBits,
3897 unsigned X86_MMXSizeInBits = 64) {
3898 assert(EltSizeInBits != 0 && (X86_MMXSizeInBits % EltSizeInBits) == 0 &&
3899 "Illegal MMX vector element size");
3901 X86_MMXSizeInBits / EltSizeInBits);
3908 case Intrinsic::x86_sse2_packsswb_128:
3909 case Intrinsic::x86_sse2_packuswb_128:
3910 return Intrinsic::x86_sse2_packsswb_128;
3912 case Intrinsic::x86_sse2_packssdw_128:
3913 case Intrinsic::x86_sse41_packusdw:
3914 return Intrinsic::x86_sse2_packssdw_128;
3916 case Intrinsic::x86_avx2_packsswb:
3917 case Intrinsic::x86_avx2_packuswb:
3918 return Intrinsic::x86_avx2_packsswb;
3920 case Intrinsic::x86_avx2_packssdw:
3921 case Intrinsic::x86_avx2_packusdw:
3922 return Intrinsic::x86_avx2_packssdw;
3924 case Intrinsic::x86_mmx_packsswb:
3925 case Intrinsic::x86_mmx_packuswb:
3926 return Intrinsic::x86_mmx_packsswb;
3928 case Intrinsic::x86_mmx_packssdw:
3929 return Intrinsic::x86_mmx_packssdw;
3931 case Intrinsic::x86_avx512_packssdw_512:
3932 case Intrinsic::x86_avx512_packusdw_512:
3933 return Intrinsic::x86_avx512_packssdw_512;
3935 case Intrinsic::x86_avx512_packsswb_512:
3936 case Intrinsic::x86_avx512_packuswb_512:
3937 return Intrinsic::x86_avx512_packsswb_512;
3953 void handleVectorPackIntrinsic(IntrinsicInst &
I,
3954 unsigned MMXEltSizeInBits = 0) {
3958 Value *S2 = getShadow(&
I, 1);
3959 assert(
S1->getType()->isVectorTy());
3965 MMXEltSizeInBits ? getMMXVectorTy(MMXEltSizeInBits) :
S1->
getType();
3966 if (MMXEltSizeInBits) {
3974 if (MMXEltSizeInBits) {
3980 {S1_ext, S2_ext},
nullptr,
3981 "_msprop_vector_pack");
3982 if (MMXEltSizeInBits)
3985 setOriginForNaryOp(
I);
3989 Constant *createDppMask(
unsigned Width,
unsigned Mask) {
3990 SmallVector<Constant *, 4>
R(Width);
4002 const unsigned Width =
4009 Value *DstMaskV = createDppMask(Width, DstMask);
4026 void handleDppIntrinsic(IntrinsicInst &
I) {
4029 Value *S0 = getShadow(&
I, 0);
4033 const unsigned Width =
4035 assert(Width == 2 || Width == 4 || Width == 8);
4038 const unsigned SrcMask =
Mask >> 4;
4039 const unsigned DstMask =
Mask & 0xf;
4042 Value *SI1 = findDppPoisonedOutput(IRB, S, SrcMask, DstMask);
4047 SI1, findDppPoisonedOutput(IRB, S, SrcMask << 4, DstMask << 4));
4054 setOriginForNaryOp(
I);
4058 C = CreateAppToShadowCast(IRB,
C);
4067 void handleBlendvIntrinsic(IntrinsicInst &
I) {
4072 Value *Sc = getShadow(&
I, 2);
4073 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
4078 C = convertBlendvToSelectMask(IRB,
C);
4079 Sc = convertBlendvToSelectMask(IRB, Sc);
4085 handleSelectLikeInst(
I,
C,
T,
F);
4089 void handleVectorSadIntrinsic(IntrinsicInst &
I,
bool IsMMX =
false) {
4090 const unsigned SignificantBitsPerResultElement = 16;
4092 unsigned ZeroBitsPerResultElement =
4096 auto *Shadow0 = getShadow(&
I, 0);
4097 auto *Shadow1 = getShadow(&
I, 1);
4102 S = IRB.
CreateLShr(S, ZeroBitsPerResultElement);
4105 setOriginForNaryOp(
I);
4129 void handleVectorDotProductIntrinsic(IntrinsicInst &
I,
4130 unsigned ReductionFactor,
4132 unsigned EltSizeInBits,
4136 [[maybe_unused]] FixedVectorType *
ReturnType =
4141 Value *Va =
nullptr;
4142 Value *Vb =
nullptr;
4143 Value *Sa =
nullptr;
4144 Value *Sb =
nullptr;
4146 assert(
I.arg_size() == 2 ||
I.arg_size() == 3);
4147 if (
I.arg_size() == 2) {
4150 Va =
I.getOperand(0);
4151 Vb =
I.getOperand(1);
4153 Sa = getShadow(&
I, 0);
4154 Sb = getShadow(&
I, 1);
4155 }
else if (
I.arg_size() == 3) {
4157 Va =
I.getOperand(1);
4158 Vb =
I.getOperand(2);
4160 Sa = getShadow(&
I, 1);
4161 Sb = getShadow(&
I, 2);
4178 Sa, getPclmulMask(Width, Lanes ==
kOddLanes));
4180 Sb, getPclmulMask(Width, Lanes ==
kOddLanes));
4190 if (
I.arg_size() == 3) {
4191 [[maybe_unused]]
auto *AccumulatorType =
4193 assert(AccumulatorType == ReturnType);
4196 FixedVectorType *ImplicitReturnType =
4199 if (EltSizeInBits) {
4201 getMMXVectorTy(EltSizeInBits * ReductionFactor,
4213 ReturnType->getNumElements() * ReductionFactor);
4230 VaInt = CreateAppToShadowCast(IRB, Va);
4231 VbInt = CreateAppToShadowCast(IRB, Vb);
4238 And = handleBitwiseAnd(IRB, VaNonZero, VbNonZero, SaNonZero, SbNonZero);
4260 ImplicitReturnType);
4265 OutShadow = CreateShadowCast(IRB, OutShadow, getShadowTy(&
I));
4268 if (
I.arg_size() == 3)
4269 OutShadow = IRB.
CreateOr(OutShadow, getShadow(&
I, 0));
4271 setShadow(&
I, OutShadow);
4272 setOriginForNaryOp(
I);
4289 void handleVectorComparePackedIntrinsic(IntrinsicInst &
I,
4290 bool PredicateAsOperand) {
4291 if (PredicateAsOperand) {
4293 assert(
I.paramHasAttr(2, Attribute::ImmArg));
4301 Type *ResTy = getShadowTy(&
I);
4302 auto *Shadow0 = getShadow(&
I, 0);
4303 auto *Shadow1 = getShadow(&
I, 1);
4308 setOriginForNaryOp(
I);
4314 void handleVectorCompareScalarIntrinsic(IntrinsicInst &
I) {
4316 auto *Shadow0 = getShadow(&
I, 0);
4317 auto *Shadow1 = getShadow(&
I, 1);
4319 Value *S = LowerElementShadowExtend(IRB, S0, getShadowTy(&
I));
4321 setOriginForNaryOp(
I);
4330 void handleVectorReduceIntrinsic(IntrinsicInst &
I,
bool AllowShadowCast) {
4335 if (AllowShadowCast)
4336 S = CreateShadowCast(IRB, S, getShadowTy(&
I));
4340 setOriginForNaryOp(
I);
4350 void handleVectorReduceWithStarterIntrinsic(IntrinsicInst &
I) {
4354 Value *Shadow0 = getShadow(&
I, 0);
4360 setOriginForNaryOp(
I);
4366 void handleVectorReduceOrIntrinsic(IntrinsicInst &
I) {
4370 Value *OperandShadow = getShadow(&
I, 0);
4372 Value *OperandUnsetOrPoison = IRB.
CreateOr(OperandUnsetBits, OperandShadow);
4380 setOrigin(&
I, getOrigin(&
I, 0));
4386 void handleVectorReduceAndIntrinsic(IntrinsicInst &
I) {
4390 Value *OperandShadow = getShadow(&
I, 0);
4391 Value *OperandSetOrPoison = IRB.
CreateOr(
I.getOperand(0), OperandShadow);
4399 setOrigin(&
I, getOrigin(&
I, 0));
4402 void handleStmxcsr(IntrinsicInst &
I) {
4404 Value *Addr =
I.getArgOperand(0);
4407 getShadowOriginPtr(Addr, IRB, Ty,
Align(1),
true).first;
4412 insertCheckShadowOf(Addr, &
I);
4415 void handleLdmxcsr(IntrinsicInst &
I) {
4420 Value *Addr =
I.getArgOperand(0);
4423 Value *ShadowPtr, *OriginPtr;
4424 std::tie(ShadowPtr, OriginPtr) =
4425 getShadowOriginPtr(Addr, IRB, Ty, Alignment,
false);
4428 insertCheckShadowOf(Addr, &
I);
4431 Value *Origin = MS.TrackOrigins ? IRB.
CreateLoad(MS.OriginTy, OriginPtr)
4433 insertCheckShadow(Shadow, Origin, &
I);
4436 void handleMaskedExpandLoad(IntrinsicInst &
I) {
4438 Value *Ptr =
I.getArgOperand(0);
4439 MaybeAlign
Align =
I.getParamAlign(0);
4441 Value *PassThru =
I.getArgOperand(2);
4444 insertCheckShadowOf(Ptr, &
I);
4445 insertCheckShadowOf(Mask, &
I);
4448 if (!PropagateShadow) {
4449 setShadow(&
I, getCleanShadow(&
I));
4450 setOrigin(&
I, getCleanOrigin());
4454 Type *ShadowTy = getShadowTy(&
I);
4456 auto [ShadowPtr, OriginPtr] =
4457 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
false);
4461 getShadow(PassThru),
"_msmaskedexpload");
4463 setShadow(&
I, Shadow);
4466 setOrigin(&
I, getCleanOrigin());
4469 void handleMaskedCompressStore(IntrinsicInst &
I) {
4472 Value *Ptr =
I.getArgOperand(1);
4473 MaybeAlign
Align =
I.getParamAlign(1);
4477 insertCheckShadowOf(Ptr, &
I);
4478 insertCheckShadowOf(Mask, &
I);
4482 Type *ElementShadowTy =
4484 auto [ShadowPtr, OriginPtrs] =
4485 getShadowOriginPtr(Ptr, IRB, ElementShadowTy, Align,
true);
4492 void handleMaskedGather(IntrinsicInst &
I) {
4494 Value *Ptrs =
I.getArgOperand(0);
4497 Value *PassThru =
I.getArgOperand(2);
4499 Type *PtrsShadowTy = getShadowTy(Ptrs);
4501 insertCheckShadowOf(Mask, &
I);
4505 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4508 if (!PropagateShadow) {
4509 setShadow(&
I, getCleanShadow(&
I));
4510 setOrigin(&
I, getCleanOrigin());
4514 Type *ShadowTy = getShadowTy(&
I);
4516 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4517 Ptrs, IRB, ElementShadowTy, Alignment,
false);
4521 getShadow(PassThru),
"_msmaskedgather");
4523 setShadow(&
I, Shadow);
4526 setOrigin(&
I, getCleanOrigin());
4529 void handleMaskedScatter(IntrinsicInst &
I) {
4532 Value *Ptrs =
I.getArgOperand(1);
4536 Type *PtrsShadowTy = getShadowTy(Ptrs);
4538 insertCheckShadowOf(Mask, &
I);
4542 insertCheckShadow(MaskedPtrShadow, getOrigin(Ptrs), &
I);
4546 Type *ElementShadowTy =
4548 auto [ShadowPtrs, OriginPtrs] = getShadowOriginPtr(
4549 Ptrs, IRB, ElementShadowTy, Alignment,
true);
4560 void handleMaskedStore(IntrinsicInst &
I) {
4562 Value *
V =
I.getArgOperand(0);
4563 Value *Ptr =
I.getArgOperand(1);
4566 Value *Shadow = getShadow(V);
4569 insertCheckShadowOf(Ptr, &
I);
4570 insertCheckShadowOf(Mask, &
I);
4575 std::tie(ShadowPtr, OriginPtr) = getShadowOriginPtr(
4576 Ptr, IRB, Shadow->
getType(), Alignment,
true);
4580 if (!MS.TrackOrigins)
4583 auto &
DL =
F.getDataLayout();
4584 paintOrigin(IRB, getOrigin(V), OriginPtr,
4593 void handleMaskedLoad(IntrinsicInst &
I) {
4595 Value *Ptr =
I.getArgOperand(0);
4598 Value *PassThru =
I.getArgOperand(2);
4601 insertCheckShadowOf(Ptr, &
I);
4602 insertCheckShadowOf(Mask, &
I);
4605 if (!PropagateShadow) {
4606 setShadow(&
I, getCleanShadow(&
I));
4607 setOrigin(&
I, getCleanOrigin());
4611 Type *ShadowTy = getShadowTy(&
I);
4612 Value *ShadowPtr, *OriginPtr;
4613 std::tie(ShadowPtr, OriginPtr) =
4614 getShadowOriginPtr(Ptr, IRB, ShadowTy, Alignment,
false);
4616 getShadow(PassThru),
"_msmaskedld"));
4618 if (!MS.TrackOrigins)
4625 Value *NotNull = convertToBool(MaskedPassThruShadow, IRB,
"_mscmp");
4630 setOrigin(&
I, Origin);
4646 void handleAVXMaskedStore(IntrinsicInst &
I) {
4651 Value *Dst =
I.getArgOperand(0);
4652 assert(Dst->getType()->isPointerTy() &&
"Destination is not a pointer!");
4657 Value *Src =
I.getArgOperand(2);
4662 Value *SrcShadow = getShadow(Src);
4665 insertCheckShadowOf(Dst, &
I);
4666 insertCheckShadowOf(Mask, &
I);
4669 Value *DstShadowPtr;
4670 Value *DstOriginPtr;
4671 std::tie(DstShadowPtr, DstOriginPtr) = getShadowOriginPtr(
4672 Dst, IRB, SrcShadow->
getType(), Alignment,
true);
4674 SmallVector<Value *, 2> ShadowArgs;
4675 ShadowArgs.
append(1, DstShadowPtr);
4676 ShadowArgs.
append(1, Mask);
4684 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
4687 if (!MS.TrackOrigins)
4691 auto &
DL =
F.getDataLayout();
4692 paintOrigin(IRB, getOrigin(Src), DstOriginPtr,
4693 DL.getTypeStoreSize(SrcShadow->
getType()),
4712 void handleAVXMaskedLoad(IntrinsicInst &
I) {
4717 Value *Src =
I.getArgOperand(0);
4718 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
4726 insertCheckShadowOf(Mask, &
I);
4729 Type *SrcShadowTy = getShadowTy(Src);
4730 Value *SrcShadowPtr, *SrcOriginPtr;
4731 std::tie(SrcShadowPtr, SrcOriginPtr) =
4732 getShadowOriginPtr(Src, IRB, SrcShadowTy, Alignment,
false);
4734 SmallVector<Value *, 2> ShadowArgs;
4735 ShadowArgs.
append(1, SrcShadowPtr);
4736 ShadowArgs.
append(1, Mask);
4739 I.getType(),
I.getIntrinsicID(), ShadowArgs);
4745 if (!MS.TrackOrigins)
4752 setOrigin(&
I, PtrSrcOrigin);
4761 assert(isFixedIntVector(Idx));
4762 auto IdxVectorSize =
4770 auto *IdxShadow = getShadow(Idx);
4775 insertCheckShadow(Truncated, getOrigin(Idx),
I);
4780 void handleAVXVpermilvar(IntrinsicInst &
I) {
4782 Value *Shadow = getShadow(&
I, 0);
4783 maskedCheckAVXIndexShadow(IRB,
I.getArgOperand(1), &
I);
4787 Shadow = IRB.
CreateBitCast(Shadow,
I.getArgOperand(0)->getType());
4789 I.getType(),
I.getIntrinsicID(), {Shadow, I.getArgOperand(1)});
4792 setOriginForNaryOp(
I);
4797 void handleAVXVpermi2var(IntrinsicInst &
I) {
4802 [[maybe_unused]]
auto ArgVectorSize =
4805 ->getNumElements() == ArgVectorSize);
4807 ->getNumElements() == ArgVectorSize);
4808 assert(
I.getArgOperand(0)->getType() ==
I.getArgOperand(2)->getType());
4809 assert(
I.getType() ==
I.getArgOperand(0)->getType());
4810 assert(
I.getArgOperand(1)->getType()->isIntOrIntVectorTy());
4812 Value *AShadow = getShadow(&
I, 0);
4813 Value *Idx =
I.getArgOperand(1);
4814 Value *BShadow = getShadow(&
I, 2);
4816 maskedCheckAVXIndexShadow(IRB, Idx, &
I);
4820 AShadow = IRB.
CreateBitCast(AShadow,
I.getArgOperand(0)->getType());
4821 BShadow = IRB.
CreateBitCast(BShadow,
I.getArgOperand(2)->getType());
4823 I.getType(),
I.getIntrinsicID(), {AShadow, Idx, BShadow});
4825 setOriginForNaryOp(
I);
4828 [[maybe_unused]]
static bool isFixedIntVectorTy(
const Type *
T) {
4832 [[maybe_unused]]
static bool isFixedFPVectorTy(
const Type *
T) {
4836 [[maybe_unused]]
static bool isFixedIntVector(
const Value *V) {
4837 return isFixedIntVectorTy(
V->getType());
4840 [[maybe_unused]]
static bool isFixedFPVector(
const Value *V) {
4841 return isFixedFPVectorTy(
V->getType());
4863 void handleAVX512VectorConvertFPToInt(IntrinsicInst &
I,
bool LastMask) {
4868 Value *WriteThrough;
4872 WriteThrough =
I.getOperand(2);
4873 Mask =
I.getOperand(3);
4876 WriteThrough =
I.getOperand(1);
4877 Mask =
I.getOperand(2);
4882 assert(isFixedIntVector(WriteThrough));
4884 unsigned ANumElements =
4886 [[maybe_unused]]
unsigned WriteThruNumElements =
4888 assert(ANumElements == WriteThruNumElements ||
4889 ANumElements * 2 == WriteThruNumElements);
4892 unsigned MaskNumElements =
Mask->getType()->getScalarSizeInBits();
4893 assert(ANumElements == MaskNumElements ||
4894 ANumElements * 2 == MaskNumElements);
4896 assert(WriteThruNumElements == MaskNumElements);
4900 insertCheckShadowOf(Mask, &
I);
4910 Value *AShadow = getShadow(
A);
4911 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
4913 if (ANumElements * 2 == MaskNumElements) {
4925 "_ms_mask_bitcast");
4935 getShadowTy(&
I),
"_ms_a_shadow");
4937 Value *WriteThroughShadow = getShadow(WriteThrough);
4939 "_ms_writethru_select");
4941 setShadow(&
I, Shadow);
4942 setOriginForNaryOp(
I);
4945 static SmallVector<int, 8> getPclmulMask(
unsigned Width,
bool OddElements) {
4946 SmallVector<int, 8>
Mask;
4947 for (
unsigned X = OddElements ? 1 : 0;
X < Width;
X += 2) {
4961 void handlePclmulIntrinsic(IntrinsicInst &
I) {
4966 "pclmul 3rd operand must be a constant");
4969 getPclmulMask(Width,
Imm & 0x01));
4971 getPclmulMask(Width,
Imm & 0x10));
4972 ShadowAndOriginCombiner SOC(
this, IRB);
4973 SOC.Add(Shuf0, getOrigin(&
I, 0));
4974 SOC.Add(Shuf1, getOrigin(&
I, 1));
4979 void handleUnarySdSsIntrinsic(IntrinsicInst &
I) {
4984 Value *Second = getShadow(&
I, 1);
4986 SmallVector<int, 16>
Mask;
4987 Mask.push_back(Width);
4988 for (
unsigned i = 1; i < Width; i++)
4992 setShadow(&
I, Shadow);
4993 setOriginForNaryOp(
I);
4996 void handleVtestIntrinsic(IntrinsicInst &
I) {
4998 Value *Shadow0 = getShadow(&
I, 0);
4999 Value *Shadow1 = getShadow(&
I, 1);
5005 setShadow(&
I, Shadow);
5006 setOriginForNaryOp(
I);
5009 void handleBinarySdSsIntrinsic(IntrinsicInst &
I) {
5014 Value *Second = getShadow(&
I, 1);
5017 SmallVector<int, 16>
Mask;
5018 Mask.push_back(Width);
5019 for (
unsigned i = 1; i < Width; i++)
5023 setShadow(&
I, Shadow);
5024 setOriginForNaryOp(
I);
5030 void handleRoundPdPsIntrinsic(IntrinsicInst &
I) {
5031 assert(
I.getArgOperand(0)->getType() ==
I.getType());
5036 ShadowAndOriginCombiner SC(
this, IRB);
5037 SC.Add(
I.getArgOperand(0));
5045 void handleAbsIntrinsic(IntrinsicInst &
I) {
5047 Value *Src =
I.getArgOperand(0);
5048 Value *IsIntMinPoison =
I.getArgOperand(1);
5050 assert(
I.getType()->isIntOrIntVectorTy());
5052 assert(Src->getType() ==
I.getType());
5058 Value *SrcShadow = getShadow(Src);
5062 Value *MinValVec = ConstantInt::get(Src->getType(), MinVal);
5065 Value *PoisonedShadow = getPoisonedShadow(Src);
5066 Value *PoisonedIfIntMinShadow =
5069 IRB.
CreateSelect(IsIntMinPoison, PoisonedIfIntMinShadow, SrcShadow);
5071 setShadow(&
I, Shadow);
5072 setOrigin(&
I, getOrigin(&
I, 0));
5075 void handleIsFpClass(IntrinsicInst &
I) {
5077 Value *Shadow = getShadow(&
I, 0);
5078 setShadow(&
I, IRB.
CreateICmpNE(Shadow, getCleanShadow(Shadow)));
5079 setOrigin(&
I, getOrigin(&
I, 0));
5082 void handleArithmeticWithOverflow(IntrinsicInst &
I) {
5084 Value *Shadow0 = getShadow(&
I, 0);
5085 Value *Shadow1 = getShadow(&
I, 1);
5088 IRB.
CreateICmpNE(ShadowElt0, getCleanShadow(ShadowElt0));
5094 setShadow(&
I, Shadow);
5095 setOriginForNaryOp(
I);
5098 void handleModfOrSincos(IntrinsicInst &
I) {
5100 Value *ArgShadow = getShadow(&
I, 0);
5104 setShadow(&
I, Shadow);
5105 setOrigin(&
I, getOrigin(&
I, 0));
5111 Value *Shadow = getShadow(V);
5133 void handleAVX512VectorDownConvert(IntrinsicInst &
I) {
5138 Value *WriteThrough =
I.getOperand(1);
5142 assert(isFixedIntVector(WriteThrough));
5144 unsigned ANumElements =
5146 unsigned OutputNumElements =
5148 assert(ANumElements == OutputNumElements ||
5149 ANumElements * 2 == OutputNumElements);
5159 insertCheckShadowOf(Mask, &
I);
5162 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5163 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5164 assert(
Mask->getType()->getScalarSizeInBits() == ANumElements);
5175 if (ANumElements != OutputNumElements) {
5177 Mask = IRB.
CreateZExt(Mask, Type::getIntNTy(*MS.C, OutputNumElements),
5184 Value *AShadow = getShadow(
A);
5188 VectorType *ShadowType = maybeShrinkVectorShadowType(
A,
I);
5198 AShadow = IRB.
CreateTrunc(AShadow, ShadowType,
"_ms_trunc_shadow");
5199 AShadow = maybeExtendVectorShadowWithZeros(AShadow,
I);
5201 Value *WriteThroughShadow = getShadow(WriteThrough);
5204 setShadow(&
I, Shadow);
5205 setOriginForNaryOp(
I);
5239 void handleAVX512VectorGenericMaskedFP(IntrinsicInst &
I,
5240 SmallVector<unsigned, 4> DataIndices,
5241 unsigned WriteThruIndex,
5242 unsigned MaskIndex) {
5245 unsigned NumArgs =
I.arg_size();
5247 assert(WriteThruIndex < NumArgs);
5248 assert(MaskIndex < NumArgs);
5249 assert(WriteThruIndex != MaskIndex);
5250 Value *WriteThru =
I.getOperand(WriteThruIndex);
5252 unsigned OutputNumElements =
5257 bool isData[16] = {
false};
5259 for (
unsigned i : DataIndices) {
5261 assert(i != WriteThruIndex);
5268 [[maybe_unused]]
unsigned ANumElements =
5270 assert(ANumElements == OutputNumElements);
5275 assert(isFixedFPVector(WriteThru));
5277 for (
unsigned i = 0; i < NumArgs; ++i) {
5278 if (!isData[i] && i != WriteThruIndex) {
5281 assert(
I.getOperand(i)->getType()->isIntegerTy());
5282 insertCheckShadowOf(
I.getOperand(i), &
I);
5287 if (
Mask->getType()->getScalarSizeInBits() == 8 && OutputNumElements < 8)
5288 Mask = IRB.
CreateTrunc(Mask, Type::getIntNTy(*MS.C, OutputNumElements));
5289 assert(
Mask->getType()->getScalarSizeInBits() == OutputNumElements);
5296 Value *DataShadow =
nullptr;
5297 for (
unsigned i : DataIndices) {
5300 DataShadow = IRB.
CreateOr(DataShadow, getShadow(
A));
5302 DataShadow = getShadow(
A);
5310 Value *WriteThruShadow = getShadow(WriteThru);
5313 setShadow(&
I, Shadow);
5315 setOriginForNaryOp(
I);
5325 void handleAVX512FPClass(IntrinsicInst &
I) {
5330 Value *Input =
I.getOperand(0);
5331 assert(isFixedFPVector(Input));
5334 Value *Classifiers =
I.getOperand(1);
5338 assert(isFixedIntVectorTy(
I.getType()));
5344 Value *OutputShadow;
5349 OutputShadow = getCleanShadow(OutputType);
5355 OutputShadow = IRB.
CreateICmpNE(getShadow(Input), getCleanShadow(Input));
5357 setShadow(&
I, OutputShadow);
5359 setOriginForNaryOp(
I);
5369 void visitGenericScalarHalfwordInst(IntrinsicInst &
I) {
5375 Value *WriteThrough =
I.getOperand(2);
5382 insertCheckShadowOf(Mask, &
I);
5386 unsigned NumElements =
5388 assert(NumElements == 8);
5389 assert(
A->getType() ==
B->getType());
5391 assert(
Mask->getType()->getPrimitiveSizeInBits() == NumElements);
5394 Value *ALowerShadow = extractLowerShadow(IRB,
A);
5395 Value *BLowerShadow = extractLowerShadow(IRB,
B);
5397 Value *ABLowerShadow = IRB.
CreateOr(ALowerShadow, BLowerShadow);
5399 Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
5406 Value *AShadow = getShadow(
A);
5407 Value *DstLowerShadow =
5408 IRB.
CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
5410 AShadow, DstLowerShadow, ConstantInt::get(IRB.
getInt32Ty(), 0),
5413 setShadow(&
I, DstShadow);
5414 setOriginForNaryOp(
I);
5444 void handleAVXGF2P8Affine(IntrinsicInst &
I) {
5455 ->getScalarSizeInBits() == 8);
5457 assert(
A->getType() ==
X->getType());
5459 assert(
B->getType()->isIntegerTy());
5460 assert(
B->getType()->getScalarSizeInBits() == 8);
5462 assert(
I.getType() ==
A->getType());
5464 Value *AShadow = getShadow(
A);
5465 Value *XShadow = getShadow(
X);
5466 Value *BZeroShadow = getCleanShadow(
B);
5469 I.getType(),
I.getIntrinsicID(), {XShadow, AShadow, BZeroShadow});
5471 {X, AShadow, BZeroShadow});
5473 {XShadow, A, BZeroShadow});
5476 Value *BShadow = getShadow(
B);
5477 Value *BBroadcastShadow = getCleanShadow(AShadow);
5482 for (
unsigned i = 0; i < NumElements; i++)
5486 {AShadowXShadow, AShadowX, XShadowA, BBroadcastShadow}));
5487 setOriginForNaryOp(
I);
5501 void handleNEONVectorLoad(IntrinsicInst &
I,
bool WithLane) {
5502 unsigned int numArgs =
I.arg_size();
5505 assert(
I.getType()->isStructTy());
5515 assert(4 <= numArgs && numArgs <= 6);
5529 for (
unsigned int i = 0; i < numArgs - 2; i++)
5530 ShadowArgs.
push_back(getShadow(
I.getArgOperand(i)));
5533 Value *LaneNumber =
I.getArgOperand(numArgs - 2);
5537 insertCheckShadowOf(LaneNumber, &
I);
5540 Value *Src =
I.getArgOperand(numArgs - 1);
5541 assert(Src->getType()->isPointerTy() &&
"Source is not a pointer!");
5543 Type *SrcShadowTy = getShadowTy(Src);
5544 auto [SrcShadowPtr, SrcOriginPtr] =
5545 getShadowOriginPtr(Src, IRB, SrcShadowTy,
Align(1),
false);
5552 getShadowTy(&
I),
I.getIntrinsicID(), ShadowArgs);
5555 if (!MS.TrackOrigins)
5559 setOrigin(&
I, PtrSrcOrigin);
5576 void handleNEONVectorStoreIntrinsic(IntrinsicInst &
I,
bool useLane) {
5580 int numArgOperands =
I.arg_size();
5583 assert(numArgOperands >= 1);
5584 Value *Addr =
I.getArgOperand(numArgOperands - 1);
5586 int skipTrailingOperands = 1;
5589 insertCheckShadowOf(Addr, &
I);
5593 skipTrailingOperands++;
5594 assert(numArgOperands >=
static_cast<int>(skipTrailingOperands));
5596 I.getArgOperand(numArgOperands - skipTrailingOperands)->getType()));
5599 SmallVector<Value *, 8> ShadowArgs;
5601 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++) {
5603 Value *Shadow = getShadow(&
I, i);
5604 ShadowArgs.
append(1, Shadow);
5621 (numArgOperands - skipTrailingOperands));
5622 Type *OutputShadowTy = getShadowTy(OutputVectorTy);
5626 I.getArgOperand(numArgOperands - skipTrailingOperands));
5628 Value *OutputShadowPtr, *OutputOriginPtr;
5630 std::tie(OutputShadowPtr, OutputOriginPtr) = getShadowOriginPtr(
5631 Addr, IRB, OutputShadowTy,
Align(1),
true);
5632 ShadowArgs.
append(1, OutputShadowPtr);
5635 IRB.
getVoidTy(),
I.getIntrinsicID(), ShadowArgs);
5638 if (MS.TrackOrigins) {
5646 OriginCombiner OC(
this, IRB);
5647 for (
int i = 0; i < numArgOperands - skipTrailingOperands; i++)
5648 OC.Add(
I.getArgOperand(i));
5650 const DataLayout &
DL =
F.getDataLayout();
5651 OC.DoneAndStoreOrigin(
DL.getTypeStoreSize(OutputVectorTy),
5684 void handleNEONMatrixMultiply(IntrinsicInst &
I) {
5688 Value *
R =
I.getArgOperand(0);
5689 Value *
A =
I.getArgOperand(1);
5690 Value *
B =
I.getArgOperand(2);
5692 assert(
I.getType() ==
R->getType());
5717 Value *ShadowR = getShadow(&
I, 0);
5718 Value *ShadowA = getShadow(&
I, 1);
5719 Value *ShadowB = getShadow(&
I, 2);
5737 {getCleanShadow(RTy), ShadowA, ShadowB});
5763 {RZeros, ShadowA, ShadowB});
5777 ShadowR = IRB.
CreateICmpNE(ShadowR, getCleanShadow(RTy));
5778 ShadowR = IRB.
CreateOr(ShadowAB, ShadowR);
5780 setShadow(&
I, IRB.
CreateSExt(ShadowR, getShadowTy(RTy)));
5782 setOriginForNaryOp(
I);
5822 void handleIntrinsicByApplyingToShadow(IntrinsicInst &
I,
5824 unsigned int trailingVerbatimArgs,
5825 bool forceIntegerIntrinsic) {
5828 assert(trailingVerbatimArgs <
I.arg_size());
5830 SmallVector<Value *, 8> ShadowArgs;
5832 for (
unsigned int i = 0; i <
I.arg_size() - trailingVerbatimArgs; i++) {
5833 Value *Shadow = getShadow(&
I, i);
5835 if (forceIntegerIntrinsic)
5842 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5844 Value *Arg =
I.getArgOperand(i);
5845 if (forceIntegerIntrinsic)
5850 Value *CombinedShadow;
5851 if (forceIntegerIntrinsic) {
5861 for (
unsigned int i =
I.arg_size() - trailingVerbatimArgs; i <
I.arg_size();
5864 CreateShadowCast(IRB, getShadow(&
I, i), CombinedShadow->
getType());
5865 CombinedShadow = IRB.
CreateOr(Shadow, CombinedShadow,
"_msprop");
5868 setShadow(&
I, CombinedShadow);
5870 setOriginForNaryOp(
I);
5876 void handleNEONVectorMultiplyIntrinsic(IntrinsicInst &
I) {
5882 bool maybeHandleCrossPlatformIntrinsic(IntrinsicInst &
I) {
5883 switch (
I.getIntrinsicID()) {
5884 case Intrinsic::uadd_with_overflow:
5885 case Intrinsic::sadd_with_overflow:
5886 case Intrinsic::usub_with_overflow:
5887 case Intrinsic::ssub_with_overflow:
5888 case Intrinsic::umul_with_overflow:
5889 case Intrinsic::smul_with_overflow:
5890 handleArithmeticWithOverflow(
I);
5892 case Intrinsic::modf:
5893 case Intrinsic::sincos:
5894 case Intrinsic::sincospi:
5895 handleModfOrSincos(
I);
5897 case Intrinsic::abs:
5898 handleAbsIntrinsic(
I);
5900 case Intrinsic::bitreverse:
5901 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
5905 case Intrinsic::is_fpclass:
5908 case Intrinsic::lifetime_start:
5909 handleLifetimeStart(
I);
5911 case Intrinsic::launder_invariant_group:
5912 case Intrinsic::strip_invariant_group:
5913 handleInvariantGroup(
I);
5915 case Intrinsic::bswap:
5918 case Intrinsic::ctlz:
5919 case Intrinsic::cttz:
5920 handleCountLeadingTrailingZeros(
I);
5922 case Intrinsic::masked_compressstore:
5923 handleMaskedCompressStore(
I);
5925 case Intrinsic::masked_expandload:
5926 handleMaskedExpandLoad(
I);
5928 case Intrinsic::masked_gather:
5929 handleMaskedGather(
I);
5931 case Intrinsic::masked_scatter:
5932 handleMaskedScatter(
I);
5934 case Intrinsic::masked_store:
5935 handleMaskedStore(
I);
5937 case Intrinsic::masked_load:
5938 handleMaskedLoad(
I);
5940 case Intrinsic::vector_reduce_and:
5941 handleVectorReduceAndIntrinsic(
I);
5943 case Intrinsic::vector_reduce_or:
5944 handleVectorReduceOrIntrinsic(
I);
5947 case Intrinsic::vector_reduce_add:
5948 case Intrinsic::vector_reduce_xor:
5949 case Intrinsic::vector_reduce_mul:
5952 case Intrinsic::vector_reduce_smax:
5953 case Intrinsic::vector_reduce_smin:
5954 case Intrinsic::vector_reduce_umax:
5955 case Intrinsic::vector_reduce_umin:
5958 case Intrinsic::vector_reduce_fmax:
5959 case Intrinsic::vector_reduce_fmin:
5960 handleVectorReduceIntrinsic(
I,
false);
5963 case Intrinsic::vector_reduce_fadd:
5964 case Intrinsic::vector_reduce_fmul:
5965 handleVectorReduceWithStarterIntrinsic(
I);
5968 case Intrinsic::scmp:
5969 case Intrinsic::ucmp: {
5974 case Intrinsic::fshl:
5975 case Intrinsic::fshr:
5976 handleFunnelShift(
I);
5979 case Intrinsic::pdep:
5980 case Intrinsic::pext:
5981 handleGenericBitManipulation(
I);
5984 case Intrinsic::is_constant:
5986 setShadow(&
I, getCleanShadow(&
I));
5987 setOrigin(&
I, getCleanOrigin());
5994 case Intrinsic::fptosi_sat:
5995 case Intrinsic::fptoui_sat:
5996 handleGenericVectorConvertIntrinsic(
I,
false);
6006 bool maybeHandleX86SIMDIntrinsic(IntrinsicInst &
I) {
6007 switch (
I.getIntrinsicID()) {
6008 case Intrinsic::x86_sse_stmxcsr:
6011 case Intrinsic::x86_sse_ldmxcsr:
6018 case Intrinsic::x86_avx512_vcvtsd2usi64:
6019 case Intrinsic::x86_avx512_vcvtsd2usi32:
6020 case Intrinsic::x86_avx512_vcvtss2usi64:
6021 case Intrinsic::x86_avx512_vcvtss2usi32:
6022 case Intrinsic::x86_avx512_cvttss2usi64:
6023 case Intrinsic::x86_avx512_cvttss2usi:
6024 case Intrinsic::x86_avx512_cvttsd2usi64:
6025 case Intrinsic::x86_avx512_cvttsd2usi:
6026 case Intrinsic::x86_avx512_cvtusi2ss:
6027 case Intrinsic::x86_avx512_cvtusi642sd:
6028 case Intrinsic::x86_avx512_cvtusi642ss:
6029 handleSSEVectorConvertIntrinsic(
I, 1,
true);
6031 case Intrinsic::x86_sse2_cvtsd2si64:
6032 case Intrinsic::x86_sse2_cvtsd2si:
6033 case Intrinsic::x86_sse2_cvtsd2ss:
6034 case Intrinsic::x86_sse2_cvttsd2si64:
6035 case Intrinsic::x86_sse2_cvttsd2si:
6036 case Intrinsic::x86_sse_cvtss2si64:
6037 case Intrinsic::x86_sse_cvtss2si:
6038 case Intrinsic::x86_sse_cvttss2si64:
6039 case Intrinsic::x86_sse_cvttss2si:
6040 handleSSEVectorConvertIntrinsic(
I, 1);
6042 case Intrinsic::x86_sse_cvtps2pi:
6043 case Intrinsic::x86_sse_cvttps2pi:
6044 handleSSEVectorConvertIntrinsic(
I, 2);
6052 case Intrinsic::x86_vcvtps2ph_128:
6053 case Intrinsic::x86_vcvtps2ph_256: {
6054 handleSSEVectorConvertIntrinsicByProp(
I,
true);
6063 case Intrinsic::x86_avx512_mask_cvtps2dq_512:
6064 handleAVX512VectorConvertFPToInt(
I,
false);
6069 case Intrinsic::x86_sse2_cvtpd2ps:
6070 case Intrinsic::x86_sse2_cvtps2dq:
6071 case Intrinsic::x86_sse2_cvtpd2dq:
6072 case Intrinsic::x86_sse2_cvttps2dq:
6073 case Intrinsic::x86_sse2_cvttpd2dq:
6074 case Intrinsic::x86_avx_cvt_pd2_ps_256:
6075 case Intrinsic::x86_avx_cvt_ps2dq_256:
6076 case Intrinsic::x86_avx_cvt_pd2dq_256:
6077 case Intrinsic::x86_avx_cvtt_ps2dq_256:
6078 case Intrinsic::x86_avx_cvtt_pd2dq_256: {
6079 handleSSEVectorConvertIntrinsicByProp(
I,
false);
6090 case Intrinsic::x86_avx512_mask_vcvtps2ph_512:
6091 case Intrinsic::x86_avx512_mask_vcvtps2ph_256:
6092 case Intrinsic::x86_avx512_mask_vcvtps2ph_128:
6093 handleAVX512VectorConvertFPToInt(
I,
true);
6097 case Intrinsic::x86_avx512_psll_w_512:
6098 case Intrinsic::x86_avx512_psll_d_512:
6099 case Intrinsic::x86_avx512_psll_q_512:
6100 case Intrinsic::x86_avx512_pslli_w_512:
6101 case Intrinsic::x86_avx512_pslli_d_512:
6102 case Intrinsic::x86_avx512_pslli_q_512:
6103 case Intrinsic::x86_avx512_psrl_w_512:
6104 case Intrinsic::x86_avx512_psrl_d_512:
6105 case Intrinsic::x86_avx512_psrl_q_512:
6106 case Intrinsic::x86_avx512_psra_w_512:
6107 case Intrinsic::x86_avx512_psra_d_512:
6108 case Intrinsic::x86_avx512_psra_q_512:
6109 case Intrinsic::x86_avx512_psrli_w_512:
6110 case Intrinsic::x86_avx512_psrli_d_512:
6111 case Intrinsic::x86_avx512_psrli_q_512:
6112 case Intrinsic::x86_avx512_psrai_w_512:
6113 case Intrinsic::x86_avx512_psrai_d_512:
6114 case Intrinsic::x86_avx512_psrai_q_512:
6115 case Intrinsic::x86_avx512_psra_q_256:
6116 case Intrinsic::x86_avx512_psra_q_128:
6117 case Intrinsic::x86_avx512_psrai_q_256:
6118 case Intrinsic::x86_avx512_psrai_q_128:
6119 case Intrinsic::x86_avx2_psll_w:
6120 case Intrinsic::x86_avx2_psll_d:
6121 case Intrinsic::x86_avx2_psll_q:
6122 case Intrinsic::x86_avx2_pslli_w:
6123 case Intrinsic::x86_avx2_pslli_d:
6124 case Intrinsic::x86_avx2_pslli_q:
6125 case Intrinsic::x86_avx2_psrl_w:
6126 case Intrinsic::x86_avx2_psrl_d:
6127 case Intrinsic::x86_avx2_psrl_q:
6128 case Intrinsic::x86_avx2_psra_w:
6129 case Intrinsic::x86_avx2_psra_d:
6130 case Intrinsic::x86_avx2_psrli_w:
6131 case Intrinsic::x86_avx2_psrli_d:
6132 case Intrinsic::x86_avx2_psrli_q:
6133 case Intrinsic::x86_avx2_psrai_w:
6134 case Intrinsic::x86_avx2_psrai_d:
6135 case Intrinsic::x86_sse2_psll_w:
6136 case Intrinsic::x86_sse2_psll_d:
6137 case Intrinsic::x86_sse2_psll_q:
6138 case Intrinsic::x86_sse2_pslli_w:
6139 case Intrinsic::x86_sse2_pslli_d:
6140 case Intrinsic::x86_sse2_pslli_q:
6141 case Intrinsic::x86_sse2_psrl_w:
6142 case Intrinsic::x86_sse2_psrl_d:
6143 case Intrinsic::x86_sse2_psrl_q:
6144 case Intrinsic::x86_sse2_psra_w:
6145 case Intrinsic::x86_sse2_psra_d:
6146 case Intrinsic::x86_sse2_psrli_w:
6147 case Intrinsic::x86_sse2_psrli_d:
6148 case Intrinsic::x86_sse2_psrli_q:
6149 case Intrinsic::x86_sse2_psrai_w:
6150 case Intrinsic::x86_sse2_psrai_d:
6151 case Intrinsic::x86_mmx_psll_w:
6152 case Intrinsic::x86_mmx_psll_d:
6153 case Intrinsic::x86_mmx_psll_q:
6154 case Intrinsic::x86_mmx_pslli_w:
6155 case Intrinsic::x86_mmx_pslli_d:
6156 case Intrinsic::x86_mmx_pslli_q:
6157 case Intrinsic::x86_mmx_psrl_w:
6158 case Intrinsic::x86_mmx_psrl_d:
6159 case Intrinsic::x86_mmx_psrl_q:
6160 case Intrinsic::x86_mmx_psra_w:
6161 case Intrinsic::x86_mmx_psra_d:
6162 case Intrinsic::x86_mmx_psrli_w:
6163 case Intrinsic::x86_mmx_psrli_d:
6164 case Intrinsic::x86_mmx_psrli_q:
6165 case Intrinsic::x86_mmx_psrai_w:
6166 case Intrinsic::x86_mmx_psrai_d:
6167 handleVectorShiftIntrinsic(
I,
false);
6169 case Intrinsic::x86_avx2_psllv_d:
6170 case Intrinsic::x86_avx2_psllv_d_256:
6171 case Intrinsic::x86_avx512_psllv_d_512:
6172 case Intrinsic::x86_avx2_psllv_q:
6173 case Intrinsic::x86_avx2_psllv_q_256:
6174 case Intrinsic::x86_avx512_psllv_q_512:
6175 case Intrinsic::x86_avx2_psrlv_d:
6176 case Intrinsic::x86_avx2_psrlv_d_256:
6177 case Intrinsic::x86_avx512_psrlv_d_512:
6178 case Intrinsic::x86_avx2_psrlv_q:
6179 case Intrinsic::x86_avx2_psrlv_q_256:
6180 case Intrinsic::x86_avx512_psrlv_q_512:
6181 case Intrinsic::x86_avx2_psrav_d:
6182 case Intrinsic::x86_avx2_psrav_d_256:
6183 case Intrinsic::x86_avx512_psrav_d_512:
6184 case Intrinsic::x86_avx512_psrav_q_128:
6185 case Intrinsic::x86_avx512_psrav_q_256:
6186 case Intrinsic::x86_avx512_psrav_q_512:
6187 handleVectorShiftIntrinsic(
I,
true);
6191 case Intrinsic::x86_sse2_packsswb_128:
6192 case Intrinsic::x86_sse2_packssdw_128:
6193 case Intrinsic::x86_sse2_packuswb_128:
6194 case Intrinsic::x86_sse41_packusdw:
6195 case Intrinsic::x86_avx2_packsswb:
6196 case Intrinsic::x86_avx2_packssdw:
6197 case Intrinsic::x86_avx2_packuswb:
6198 case Intrinsic::x86_avx2_packusdw:
6204 case Intrinsic::x86_avx512_packsswb_512:
6205 case Intrinsic::x86_avx512_packssdw_512:
6206 case Intrinsic::x86_avx512_packuswb_512:
6207 case Intrinsic::x86_avx512_packusdw_512:
6208 handleVectorPackIntrinsic(
I);
6211 case Intrinsic::x86_sse41_pblendvb:
6212 case Intrinsic::x86_sse41_blendvpd:
6213 case Intrinsic::x86_sse41_blendvps:
6214 case Intrinsic::x86_avx_blendv_pd_256:
6215 case Intrinsic::x86_avx_blendv_ps_256:
6216 case Intrinsic::x86_avx2_pblendvb:
6217 handleBlendvIntrinsic(
I);
6220 case Intrinsic::x86_avx_dp_ps_256:
6221 case Intrinsic::x86_sse41_dppd:
6222 case Intrinsic::x86_sse41_dpps:
6223 handleDppIntrinsic(
I);
6226 case Intrinsic::x86_mmx_packsswb:
6227 case Intrinsic::x86_mmx_packuswb:
6228 handleVectorPackIntrinsic(
I, 16);
6231 case Intrinsic::x86_mmx_packssdw:
6232 handleVectorPackIntrinsic(
I, 32);
6235 case Intrinsic::x86_mmx_psad_bw:
6236 handleVectorSadIntrinsic(
I,
true);
6238 case Intrinsic::x86_sse2_psad_bw:
6239 case Intrinsic::x86_avx2_psad_bw:
6240 handleVectorSadIntrinsic(
I);
6266 case Intrinsic::x86_sse2_pmadd_wd:
6267 case Intrinsic::x86_avx2_pmadd_wd:
6268 case Intrinsic::x86_avx512_pmaddw_d_512:
6269 case Intrinsic::x86_ssse3_pmadd_ub_sw_128:
6270 case Intrinsic::x86_avx2_pmadd_ub_sw:
6271 case Intrinsic::x86_avx512_pmaddubs_w_512:
6272 handleVectorDotProductIntrinsic(
I, 2,
6279 case Intrinsic::x86_ssse3_pmadd_ub_sw:
6280 handleVectorDotProductIntrinsic(
I, 2,
6287 case Intrinsic::x86_mmx_pmadd_wd:
6288 handleVectorDotProductIntrinsic(
I, 2,
6297 case Intrinsic::aarch64_neon_bfmlalt:
6298 handleVectorDotProductIntrinsic(
I, 2,
6306 case Intrinsic::aarch64_neon_bfmlalb:
6307 handleVectorDotProductIntrinsic(
I, 2,
6405 case Intrinsic::x86_avx512_vpdpbusd_128:
6406 case Intrinsic::x86_avx512_vpdpbusd_256:
6407 case Intrinsic::x86_avx512_vpdpbusd_512:
6408 case Intrinsic::x86_avx512_vpdpbusds_128:
6409 case Intrinsic::x86_avx512_vpdpbusds_256:
6410 case Intrinsic::x86_avx512_vpdpbusds_512:
6411 case Intrinsic::x86_avx2_vpdpbssd_128:
6412 case Intrinsic::x86_avx2_vpdpbssd_256:
6413 case Intrinsic::x86_avx10_vpdpbssd_512:
6414 case Intrinsic::x86_avx2_vpdpbssds_128:
6415 case Intrinsic::x86_avx2_vpdpbssds_256:
6416 case Intrinsic::x86_avx10_vpdpbssds_512:
6417 case Intrinsic::x86_avx2_vpdpbsud_128:
6418 case Intrinsic::x86_avx2_vpdpbsud_256:
6419 case Intrinsic::x86_avx10_vpdpbsud_512:
6420 case Intrinsic::x86_avx2_vpdpbsuds_128:
6421 case Intrinsic::x86_avx2_vpdpbsuds_256:
6422 case Intrinsic::x86_avx10_vpdpbsuds_512:
6423 case Intrinsic::x86_avx2_vpdpbuud_128:
6424 case Intrinsic::x86_avx2_vpdpbuud_256:
6425 case Intrinsic::x86_avx10_vpdpbuud_512:
6426 case Intrinsic::x86_avx2_vpdpbuuds_128:
6427 case Intrinsic::x86_avx2_vpdpbuuds_256:
6428 case Intrinsic::x86_avx10_vpdpbuuds_512:
6429 handleVectorDotProductIntrinsic(
I, 4,
6527 case Intrinsic::x86_avx512_vpdpwssd_128:
6528 case Intrinsic::x86_avx512_vpdpwssd_256:
6529 case Intrinsic::x86_avx512_vpdpwssd_512:
6530 case Intrinsic::x86_avx512_vpdpwssds_128:
6531 case Intrinsic::x86_avx512_vpdpwssds_256:
6532 case Intrinsic::x86_avx512_vpdpwssds_512:
6533 case Intrinsic::x86_avx2_vpdpwsud_128:
6534 case Intrinsic::x86_avx2_vpdpwsud_256:
6535 case Intrinsic::x86_avx10_vpdpwsud_512:
6536 case Intrinsic::x86_avx2_vpdpwsuds_128:
6537 case Intrinsic::x86_avx2_vpdpwsuds_256:
6538 case Intrinsic::x86_avx10_vpdpwsuds_512:
6539 case Intrinsic::x86_avx2_vpdpwusd_128:
6540 case Intrinsic::x86_avx2_vpdpwusd_256:
6541 case Intrinsic::x86_avx10_vpdpwusd_512:
6542 case Intrinsic::x86_avx2_vpdpwusds_128:
6543 case Intrinsic::x86_avx2_vpdpwusds_256:
6544 case Intrinsic::x86_avx10_vpdpwusds_512:
6545 case Intrinsic::x86_avx2_vpdpwuud_128:
6546 case Intrinsic::x86_avx2_vpdpwuud_256:
6547 case Intrinsic::x86_avx10_vpdpwuud_512:
6548 case Intrinsic::x86_avx2_vpdpwuuds_128:
6549 case Intrinsic::x86_avx2_vpdpwuuds_256:
6550 case Intrinsic::x86_avx10_vpdpwuuds_512:
6551 handleVectorDotProductIntrinsic(
I, 2,
6565 case Intrinsic::x86_avx512bf16_dpbf16ps_128:
6566 case Intrinsic::x86_avx512bf16_dpbf16ps_256:
6567 case Intrinsic::x86_avx512bf16_dpbf16ps_512:
6568 handleVectorDotProductIntrinsic(
I, 2,
6574 case Intrinsic::x86_sse_cmp_ss:
6575 case Intrinsic::x86_sse2_cmp_sd:
6576 case Intrinsic::x86_sse_comieq_ss:
6577 case Intrinsic::x86_sse_comilt_ss:
6578 case Intrinsic::x86_sse_comile_ss:
6579 case Intrinsic::x86_sse_comigt_ss:
6580 case Intrinsic::x86_sse_comige_ss:
6581 case Intrinsic::x86_sse_comineq_ss:
6582 case Intrinsic::x86_sse_ucomieq_ss:
6583 case Intrinsic::x86_sse_ucomilt_ss:
6584 case Intrinsic::x86_sse_ucomile_ss:
6585 case Intrinsic::x86_sse_ucomigt_ss:
6586 case Intrinsic::x86_sse_ucomige_ss:
6587 case Intrinsic::x86_sse_ucomineq_ss:
6588 case Intrinsic::x86_sse2_comieq_sd:
6589 case Intrinsic::x86_sse2_comilt_sd:
6590 case Intrinsic::x86_sse2_comile_sd:
6591 case Intrinsic::x86_sse2_comigt_sd:
6592 case Intrinsic::x86_sse2_comige_sd:
6593 case Intrinsic::x86_sse2_comineq_sd:
6594 case Intrinsic::x86_sse2_ucomieq_sd:
6595 case Intrinsic::x86_sse2_ucomilt_sd:
6596 case Intrinsic::x86_sse2_ucomile_sd:
6597 case Intrinsic::x86_sse2_ucomigt_sd:
6598 case Intrinsic::x86_sse2_ucomige_sd:
6599 case Intrinsic::x86_sse2_ucomineq_sd:
6600 handleVectorCompareScalarIntrinsic(
I);
6603 case Intrinsic::x86_avx_cmp_pd_256:
6604 case Intrinsic::x86_avx_cmp_ps_256:
6605 case Intrinsic::x86_sse2_cmp_pd:
6606 case Intrinsic::x86_sse_cmp_ps:
6607 handleVectorComparePackedIntrinsic(
I,
true);
6610 case Intrinsic::x86_bmi_bextr_32:
6611 case Intrinsic::x86_bmi_bextr_64:
6612 case Intrinsic::x86_bmi_bzhi_32:
6613 case Intrinsic::x86_bmi_bzhi_64:
6614 handleGenericBitManipulation(
I);
6617 case Intrinsic::x86_pclmulqdq:
6618 case Intrinsic::x86_pclmulqdq_256:
6619 case Intrinsic::x86_pclmulqdq_512:
6620 handlePclmulIntrinsic(
I);
6623 case Intrinsic::x86_avx_round_pd_256:
6624 case Intrinsic::x86_avx_round_ps_256:
6625 case Intrinsic::x86_sse41_round_pd:
6626 case Intrinsic::x86_sse41_round_ps:
6627 handleRoundPdPsIntrinsic(
I);
6630 case Intrinsic::x86_sse41_round_sd:
6631 case Intrinsic::x86_sse41_round_ss:
6632 handleUnarySdSsIntrinsic(
I);
6635 case Intrinsic::x86_sse2_max_sd:
6636 case Intrinsic::x86_sse_max_ss:
6637 case Intrinsic::x86_sse2_min_sd:
6638 case Intrinsic::x86_sse_min_ss:
6639 handleBinarySdSsIntrinsic(
I);
6642 case Intrinsic::x86_avx_vtestc_pd:
6643 case Intrinsic::x86_avx_vtestc_pd_256:
6644 case Intrinsic::x86_avx_vtestc_ps:
6645 case Intrinsic::x86_avx_vtestc_ps_256:
6646 case Intrinsic::x86_avx_vtestnzc_pd:
6647 case Intrinsic::x86_avx_vtestnzc_pd_256:
6648 case Intrinsic::x86_avx_vtestnzc_ps:
6649 case Intrinsic::x86_avx_vtestnzc_ps_256:
6650 case Intrinsic::x86_avx_vtestz_pd:
6651 case Intrinsic::x86_avx_vtestz_pd_256:
6652 case Intrinsic::x86_avx_vtestz_ps:
6653 case Intrinsic::x86_avx_vtestz_ps_256:
6654 case Intrinsic::x86_avx_ptestc_256:
6655 case Intrinsic::x86_avx_ptestnzc_256:
6656 case Intrinsic::x86_avx_ptestz_256:
6657 case Intrinsic::x86_sse41_ptestc:
6658 case Intrinsic::x86_sse41_ptestnzc:
6659 case Intrinsic::x86_sse41_ptestz:
6660 handleVtestIntrinsic(
I);
6664 case Intrinsic::x86_ssse3_phadd_w:
6665 case Intrinsic::x86_ssse3_phadd_w_128:
6666 case Intrinsic::x86_ssse3_phsub_w:
6667 case Intrinsic::x86_ssse3_phsub_w_128:
6668 handlePairwiseShadowOrIntrinsic(
I, 1,
6672 case Intrinsic::x86_avx2_phadd_w:
6673 case Intrinsic::x86_avx2_phsub_w:
6674 handlePairwiseShadowOrIntrinsic(
I, 2,
6679 case Intrinsic::x86_ssse3_phadd_d:
6680 case Intrinsic::x86_ssse3_phadd_d_128:
6681 case Intrinsic::x86_ssse3_phsub_d:
6682 case Intrinsic::x86_ssse3_phsub_d_128:
6683 handlePairwiseShadowOrIntrinsic(
I, 1,
6687 case Intrinsic::x86_avx2_phadd_d:
6688 case Intrinsic::x86_avx2_phsub_d:
6689 handlePairwiseShadowOrIntrinsic(
I, 2,
6694 case Intrinsic::x86_ssse3_phadd_sw:
6695 case Intrinsic::x86_ssse3_phadd_sw_128:
6696 case Intrinsic::x86_ssse3_phsub_sw:
6697 case Intrinsic::x86_ssse3_phsub_sw_128:
6698 handlePairwiseShadowOrIntrinsic(
I, 1,
6702 case Intrinsic::x86_avx2_phadd_sw:
6703 case Intrinsic::x86_avx2_phsub_sw:
6704 handlePairwiseShadowOrIntrinsic(
I, 2,
6709 case Intrinsic::x86_sse3_hadd_ps:
6710 case Intrinsic::x86_sse3_hadd_pd:
6711 case Intrinsic::x86_sse3_hsub_ps:
6712 case Intrinsic::x86_sse3_hsub_pd:
6713 handlePairwiseShadowOrIntrinsic(
I, 1);
6716 case Intrinsic::x86_avx_hadd_pd_256:
6717 case Intrinsic::x86_avx_hadd_ps_256:
6718 case Intrinsic::x86_avx_hsub_pd_256:
6719 case Intrinsic::x86_avx_hsub_ps_256:
6720 handlePairwiseShadowOrIntrinsic(
I, 2);
6723 case Intrinsic::x86_avx_maskstore_ps:
6724 case Intrinsic::x86_avx_maskstore_pd:
6725 case Intrinsic::x86_avx_maskstore_ps_256:
6726 case Intrinsic::x86_avx_maskstore_pd_256:
6727 case Intrinsic::x86_avx2_maskstore_d:
6728 case Intrinsic::x86_avx2_maskstore_q:
6729 case Intrinsic::x86_avx2_maskstore_d_256:
6730 case Intrinsic::x86_avx2_maskstore_q_256: {
6731 handleAVXMaskedStore(
I);
6735 case Intrinsic::x86_avx_maskload_ps:
6736 case Intrinsic::x86_avx_maskload_pd:
6737 case Intrinsic::x86_avx_maskload_ps_256:
6738 case Intrinsic::x86_avx_maskload_pd_256:
6739 case Intrinsic::x86_avx2_maskload_d:
6740 case Intrinsic::x86_avx2_maskload_q:
6741 case Intrinsic::x86_avx2_maskload_d_256:
6742 case Intrinsic::x86_avx2_maskload_q_256: {
6743 handleAVXMaskedLoad(
I);
6748 case Intrinsic::x86_avx512fp16_add_ph_512:
6749 case Intrinsic::x86_avx512fp16_sub_ph_512:
6750 case Intrinsic::x86_avx512fp16_mul_ph_512:
6751 case Intrinsic::x86_avx512fp16_div_ph_512:
6752 case Intrinsic::x86_avx512fp16_max_ph_512:
6753 case Intrinsic::x86_avx512fp16_min_ph_512:
6754 case Intrinsic::x86_avx512_min_ps_512:
6755 case Intrinsic::x86_avx512_min_pd_512:
6756 case Intrinsic::x86_avx512_max_ps_512:
6757 case Intrinsic::x86_avx512_max_pd_512: {
6762 [[maybe_unused]]
bool Success =
6763 maybeHandleSimpleNomemIntrinsic(
I, 1);
6768 case Intrinsic::x86_avx_vpermilvar_pd:
6769 case Intrinsic::x86_avx_vpermilvar_pd_256:
6770 case Intrinsic::x86_avx512_vpermilvar_pd_512:
6771 case Intrinsic::x86_avx_vpermilvar_ps:
6772 case Intrinsic::x86_avx_vpermilvar_ps_256:
6773 case Intrinsic::x86_avx512_vpermilvar_ps_512: {
6774 handleAVXVpermilvar(
I);
6778 case Intrinsic::x86_avx512_vpermi2var_d_128:
6779 case Intrinsic::x86_avx512_vpermi2var_d_256:
6780 case Intrinsic::x86_avx512_vpermi2var_d_512:
6781 case Intrinsic::x86_avx512_vpermi2var_hi_128:
6782 case Intrinsic::x86_avx512_vpermi2var_hi_256:
6783 case Intrinsic::x86_avx512_vpermi2var_hi_512:
6784 case Intrinsic::x86_avx512_vpermi2var_pd_128:
6785 case Intrinsic::x86_avx512_vpermi2var_pd_256:
6786 case Intrinsic::x86_avx512_vpermi2var_pd_512:
6787 case Intrinsic::x86_avx512_vpermi2var_ps_128:
6788 case Intrinsic::x86_avx512_vpermi2var_ps_256:
6789 case Intrinsic::x86_avx512_vpermi2var_ps_512:
6790 case Intrinsic::x86_avx512_vpermi2var_q_128:
6791 case Intrinsic::x86_avx512_vpermi2var_q_256:
6792 case Intrinsic::x86_avx512_vpermi2var_q_512:
6793 case Intrinsic::x86_avx512_vpermi2var_qi_128:
6794 case Intrinsic::x86_avx512_vpermi2var_qi_256:
6795 case Intrinsic::x86_avx512_vpermi2var_qi_512:
6796 handleAVXVpermi2var(
I);
6810 case Intrinsic::x86_avx2_pshuf_b:
6811 case Intrinsic::x86_sse_pshuf_w:
6812 case Intrinsic::x86_ssse3_pshuf_b_128:
6813 case Intrinsic::x86_ssse3_pshuf_b:
6814 case Intrinsic::x86_avx512_pshuf_b_512:
6815 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6822 case Intrinsic::x86_avx512_mask_pmov_dw_128:
6823 case Intrinsic::x86_avx512_mask_pmov_db_128:
6824 case Intrinsic::x86_avx512_mask_pmov_qb_128:
6825 case Intrinsic::x86_avx512_mask_pmov_qw_128:
6826 case Intrinsic::x86_avx512_mask_pmov_qd_128:
6827 case Intrinsic::x86_avx512_mask_pmov_wb_128:
6828 case Intrinsic::x86_avx512_mask_pmov_dw_256:
6829 case Intrinsic::x86_avx512_mask_pmov_db_256:
6830 case Intrinsic::x86_avx512_mask_pmov_qb_256:
6831 case Intrinsic::x86_avx512_mask_pmov_qw_256:
6832 case Intrinsic::x86_avx512_mask_pmov_dw_512:
6833 case Intrinsic::x86_avx512_mask_pmov_db_512:
6834 case Intrinsic::x86_avx512_mask_pmov_qb_512:
6835 case Intrinsic::x86_avx512_mask_pmov_qw_512: {
6838 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
6847 case Intrinsic::x86_avx512_mask_pmovs_dw_512:
6848 case Intrinsic::x86_avx512_mask_pmovus_dw_512: {
6849 handleIntrinsicByApplyingToShadow(
6850 I, Intrinsic::x86_avx512_mask_pmov_dw_512,
6855 case Intrinsic::x86_avx512_mask_pmovs_dw_256:
6856 case Intrinsic::x86_avx512_mask_pmovus_dw_256:
6857 handleIntrinsicByApplyingToShadow(
6858 I, Intrinsic::x86_avx512_mask_pmov_dw_256,
6862 case Intrinsic::x86_avx512_mask_pmovs_dw_128:
6863 case Intrinsic::x86_avx512_mask_pmovus_dw_128:
6864 handleIntrinsicByApplyingToShadow(
6865 I, Intrinsic::x86_avx512_mask_pmov_dw_128,
6869 case Intrinsic::x86_avx512_mask_pmovs_db_512:
6870 case Intrinsic::x86_avx512_mask_pmovus_db_512: {
6871 handleIntrinsicByApplyingToShadow(
6872 I, Intrinsic::x86_avx512_mask_pmov_db_512,
6877 case Intrinsic::x86_avx512_mask_pmovs_db_256:
6878 case Intrinsic::x86_avx512_mask_pmovus_db_256:
6879 handleIntrinsicByApplyingToShadow(
6880 I, Intrinsic::x86_avx512_mask_pmov_db_256,
6884 case Intrinsic::x86_avx512_mask_pmovs_db_128:
6885 case Intrinsic::x86_avx512_mask_pmovus_db_128:
6886 handleIntrinsicByApplyingToShadow(
6887 I, Intrinsic::x86_avx512_mask_pmov_db_128,
6891 case Intrinsic::x86_avx512_mask_pmovs_qb_512:
6892 case Intrinsic::x86_avx512_mask_pmovus_qb_512: {
6893 handleIntrinsicByApplyingToShadow(
6894 I, Intrinsic::x86_avx512_mask_pmov_qb_512,
6899 case Intrinsic::x86_avx512_mask_pmovs_qb_256:
6900 case Intrinsic::x86_avx512_mask_pmovus_qb_256:
6901 handleIntrinsicByApplyingToShadow(
6902 I, Intrinsic::x86_avx512_mask_pmov_qb_256,
6906 case Intrinsic::x86_avx512_mask_pmovs_qb_128:
6907 case Intrinsic::x86_avx512_mask_pmovus_qb_128:
6908 handleIntrinsicByApplyingToShadow(
6909 I, Intrinsic::x86_avx512_mask_pmov_qb_128,
6913 case Intrinsic::x86_avx512_mask_pmovs_qw_512:
6914 case Intrinsic::x86_avx512_mask_pmovus_qw_512: {
6915 handleIntrinsicByApplyingToShadow(
6916 I, Intrinsic::x86_avx512_mask_pmov_qw_512,
6921 case Intrinsic::x86_avx512_mask_pmovs_qw_256:
6922 case Intrinsic::x86_avx512_mask_pmovus_qw_256:
6923 handleIntrinsicByApplyingToShadow(
6924 I, Intrinsic::x86_avx512_mask_pmov_qw_256,
6928 case Intrinsic::x86_avx512_mask_pmovs_qw_128:
6929 case Intrinsic::x86_avx512_mask_pmovus_qw_128:
6930 handleIntrinsicByApplyingToShadow(
6931 I, Intrinsic::x86_avx512_mask_pmov_qw_128,
6935 case Intrinsic::x86_avx512_mask_pmovs_qd_128:
6936 case Intrinsic::x86_avx512_mask_pmovus_qd_128:
6937 handleIntrinsicByApplyingToShadow(
6938 I, Intrinsic::x86_avx512_mask_pmov_qd_128,
6942 case Intrinsic::x86_avx512_mask_pmovs_wb_128:
6943 case Intrinsic::x86_avx512_mask_pmovus_wb_128:
6944 handleIntrinsicByApplyingToShadow(
6945 I, Intrinsic::x86_avx512_mask_pmov_wb_128,
6949 case Intrinsic::x86_avx512_mask_pmovs_qd_256:
6950 case Intrinsic::x86_avx512_mask_pmovus_qd_256:
6951 case Intrinsic::x86_avx512_mask_pmovs_wb_256:
6952 case Intrinsic::x86_avx512_mask_pmovus_wb_256:
6953 case Intrinsic::x86_avx512_mask_pmovs_qd_512:
6954 case Intrinsic::x86_avx512_mask_pmovus_qd_512:
6955 case Intrinsic::x86_avx512_mask_pmovs_wb_512:
6956 case Intrinsic::x86_avx512_mask_pmovus_wb_512: {
6960 handleAVX512VectorDownConvert(
I);
6971 case Intrinsic::x86_avx512_mask_compress:
6972 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7013 case Intrinsic::x86_avx512_rsqrt14_ps_512:
7014 case Intrinsic::x86_avx512_rsqrt14_ps_256:
7015 case Intrinsic::x86_avx512_rsqrt14_ps_128:
7016 case Intrinsic::x86_avx512_rsqrt14_pd_512:
7017 case Intrinsic::x86_avx512_rsqrt14_pd_256:
7018 case Intrinsic::x86_avx512_rsqrt14_pd_128:
7019 case Intrinsic::x86_avx10_mask_rsqrt_bf16_512:
7020 case Intrinsic::x86_avx10_mask_rsqrt_bf16_256:
7021 case Intrinsic::x86_avx10_mask_rsqrt_bf16_128:
7022 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_512:
7023 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_256:
7024 case Intrinsic::x86_avx512fp16_mask_rsqrt_ph_128:
7025 handleAVX512VectorGenericMaskedFP(
I, {0},
7066 case Intrinsic::x86_avx512_rcp14_ps_512:
7067 case Intrinsic::x86_avx512_rcp14_ps_256:
7068 case Intrinsic::x86_avx512_rcp14_ps_128:
7069 case Intrinsic::x86_avx512_rcp14_pd_512:
7070 case Intrinsic::x86_avx512_rcp14_pd_256:
7071 case Intrinsic::x86_avx512_rcp14_pd_128:
7072 case Intrinsic::x86_avx10_mask_rcp_bf16_512:
7073 case Intrinsic::x86_avx10_mask_rcp_bf16_256:
7074 case Intrinsic::x86_avx10_mask_rcp_bf16_128:
7075 case Intrinsic::x86_avx512fp16_mask_rcp_ph_512:
7076 case Intrinsic::x86_avx512fp16_mask_rcp_ph_256:
7077 case Intrinsic::x86_avx512fp16_mask_rcp_ph_128:
7078 handleAVX512VectorGenericMaskedFP(
I, {0},
7123 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_512:
7124 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_256:
7125 case Intrinsic::x86_avx512fp16_mask_rndscale_ph_128:
7126 case Intrinsic::x86_avx512_mask_rndscale_ps_512:
7127 case Intrinsic::x86_avx512_mask_rndscale_ps_256:
7128 case Intrinsic::x86_avx512_mask_rndscale_ps_128:
7129 case Intrinsic::x86_avx512_mask_rndscale_pd_512:
7130 case Intrinsic::x86_avx512_mask_rndscale_pd_256:
7131 case Intrinsic::x86_avx512_mask_rndscale_pd_128:
7132 case Intrinsic::x86_avx10_mask_rndscale_bf16_512:
7133 case Intrinsic::x86_avx10_mask_rndscale_bf16_256:
7134 case Intrinsic::x86_avx10_mask_rndscale_bf16_128:
7135 handleAVX512VectorGenericMaskedFP(
I, {0},
7171 case Intrinsic::x86_avx512_mask_scalef_pd_512:
7172 case Intrinsic::x86_avx512_mask_scalef_pd_256:
7173 case Intrinsic::x86_avx512_mask_scalef_pd_128:
7174 case Intrinsic::x86_avx512_mask_scalef_ps_512:
7175 case Intrinsic::x86_avx512_mask_scalef_ps_256:
7176 case Intrinsic::x86_avx512_mask_scalef_ps_128:
7177 case Intrinsic::x86_avx512fp16_mask_scalef_ph_512:
7178 case Intrinsic::x86_avx512fp16_mask_scalef_ph_256:
7179 case Intrinsic::x86_avx512fp16_mask_scalef_ph_128:
7183 handleAVX512VectorGenericMaskedFP(
I, {0, 1},
7203 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
7204 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
7205 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
7206 case Intrinsic::x86_avx512fp16_mask_div_sh_round:
7207 case Intrinsic::x86_avx512fp16_mask_max_sh_round:
7208 case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
7209 visitGenericScalarHalfwordInst(
I);
7216 case Intrinsic::x86_avx512_fpclass_pd_512:
7217 case Intrinsic::x86_avx512_fpclass_ps_512:
7218 handleAVX512FPClass(
I);
7222 case Intrinsic::x86_vgf2p8affineqb_128:
7223 case Intrinsic::x86_vgf2p8affineqb_256:
7224 case Intrinsic::x86_vgf2p8affineqb_512:
7225 handleAVXGF2P8Affine(
I);
7235 bool maybeHandleArmSIMDIntrinsic(IntrinsicInst &
I) {
7236 switch (
I.getIntrinsicID()) {
7240 case Intrinsic::aarch64_neon_rshrn:
7241 case Intrinsic::aarch64_neon_sqrshl:
7242 case Intrinsic::aarch64_neon_sqrshrn:
7243 case Intrinsic::aarch64_neon_sqrshrun:
7244 case Intrinsic::aarch64_neon_sqshl:
7245 case Intrinsic::aarch64_neon_sqshlu:
7246 case Intrinsic::aarch64_neon_sqshrn:
7247 case Intrinsic::aarch64_neon_sqshrun:
7248 case Intrinsic::aarch64_neon_srshl:
7249 case Intrinsic::aarch64_neon_sshl:
7250 case Intrinsic::aarch64_neon_uqrshl:
7251 case Intrinsic::aarch64_neon_uqrshrn:
7252 case Intrinsic::aarch64_neon_uqshl:
7253 case Intrinsic::aarch64_neon_uqshrn:
7254 case Intrinsic::aarch64_neon_urshl:
7255 case Intrinsic::aarch64_neon_ushl:
7256 handleVectorShiftIntrinsic(
I,
false);
7269 case Intrinsic::aarch64_neon_vsli:
7270 case Intrinsic::aarch64_neon_vsri:
7271 handleIntrinsicByApplyingToShadow(
I,
I.getIntrinsicID(),
7278 case Intrinsic::aarch64_neon_fmaxp:
7279 case Intrinsic::aarch64_neon_fminp:
7281 case Intrinsic::aarch64_neon_fmaxnmp:
7282 case Intrinsic::aarch64_neon_fminnmp:
7284 case Intrinsic::aarch64_neon_smaxp:
7285 case Intrinsic::aarch64_neon_sminp:
7286 case Intrinsic::aarch64_neon_umaxp:
7287 case Intrinsic::aarch64_neon_uminp:
7289 case Intrinsic::aarch64_neon_addp:
7291 case Intrinsic::aarch64_neon_faddp:
7293 case Intrinsic::aarch64_neon_saddlp:
7294 case Intrinsic::aarch64_neon_uaddlp: {
7295 handlePairwiseShadowOrIntrinsic(
I, 1);
7300 case Intrinsic::aarch64_neon_fcvtas:
7301 case Intrinsic::aarch64_neon_fcvtau:
7303 case Intrinsic::aarch64_neon_fcvtms:
7304 case Intrinsic::aarch64_neon_fcvtmu:
7306 case Intrinsic::aarch64_neon_fcvtns:
7307 case Intrinsic::aarch64_neon_fcvtnu:
7309 case Intrinsic::aarch64_neon_fcvtps:
7310 case Intrinsic::aarch64_neon_fcvtpu:
7312 case Intrinsic::aarch64_neon_fcvtzs:
7313 case Intrinsic::aarch64_neon_fcvtzu:
7315 case Intrinsic::aarch64_neon_fcvtxn:
7316 handleGenericVectorConvertIntrinsic(
I,
false);
7320 case Intrinsic::aarch64_neon_vcvtfxs2fp:
7321 case Intrinsic::aarch64_neon_vcvtfp2fxs:
7322 case Intrinsic::aarch64_neon_vcvtfxu2fp:
7323 case Intrinsic::aarch64_neon_vcvtfp2fxu:
7324 handleGenericVectorConvertIntrinsic(
I,
true);
7333 case Intrinsic::aarch64_neon_faddv:
7334 case Intrinsic::aarch64_neon_saddv:
7335 case Intrinsic::aarch64_neon_uaddv:
7338 case Intrinsic::aarch64_neon_smaxv:
7339 case Intrinsic::aarch64_neon_sminv:
7340 case Intrinsic::aarch64_neon_umaxv:
7341 case Intrinsic::aarch64_neon_uminv:
7345 case Intrinsic::aarch64_neon_fmaxv:
7346 case Intrinsic::aarch64_neon_fminv:
7347 case Intrinsic::aarch64_neon_fmaxnmv:
7348 case Intrinsic::aarch64_neon_fminnmv:
7350 case Intrinsic::aarch64_neon_saddlv:
7351 case Intrinsic::aarch64_neon_uaddlv:
7352 handleVectorReduceIntrinsic(
I,
true);
7355 case Intrinsic::aarch64_neon_ld1x2:
7356 case Intrinsic::aarch64_neon_ld1x3:
7357 case Intrinsic::aarch64_neon_ld1x4:
7358 case Intrinsic::aarch64_neon_ld2:
7359 case Intrinsic::aarch64_neon_ld3:
7360 case Intrinsic::aarch64_neon_ld4:
7361 case Intrinsic::aarch64_neon_ld2r:
7362 case Intrinsic::aarch64_neon_ld3r:
7363 case Intrinsic::aarch64_neon_ld4r: {
7364 handleNEONVectorLoad(
I,
false);
7368 case Intrinsic::aarch64_neon_ld2lane:
7369 case Intrinsic::aarch64_neon_ld3lane:
7370 case Intrinsic::aarch64_neon_ld4lane: {
7371 handleNEONVectorLoad(
I,
true);
7376 case Intrinsic::aarch64_neon_sqxtn:
7377 case Intrinsic::aarch64_neon_sqxtun:
7378 case Intrinsic::aarch64_neon_uqxtn:
7385 case Intrinsic::aarch64_neon_st1x2:
7386 case Intrinsic::aarch64_neon_st1x3:
7387 case Intrinsic::aarch64_neon_st1x4:
7388 case Intrinsic::aarch64_neon_st2:
7389 case Intrinsic::aarch64_neon_st3:
7390 case Intrinsic::aarch64_neon_st4: {
7391 handleNEONVectorStoreIntrinsic(
I,
false);
7395 case Intrinsic::aarch64_neon_st2lane:
7396 case Intrinsic::aarch64_neon_st3lane:
7397 case Intrinsic::aarch64_neon_st4lane: {
7398 handleNEONVectorStoreIntrinsic(
I,
true);
7411 case Intrinsic::aarch64_neon_tbl1:
7412 case Intrinsic::aarch64_neon_tbl2:
7413 case Intrinsic::aarch64_neon_tbl3:
7414 case Intrinsic::aarch64_neon_tbl4:
7415 case Intrinsic::aarch64_neon_tbx1:
7416 case Intrinsic::aarch64_neon_tbx2:
7417 case Intrinsic::aarch64_neon_tbx3:
7418 case Intrinsic::aarch64_neon_tbx4: {
7420 handleIntrinsicByApplyingToShadow(
7421 I,
I.getIntrinsicID(),
7426 case Intrinsic::aarch64_neon_fmulx:
7427 case Intrinsic::aarch64_neon_pmul:
7428 case Intrinsic::aarch64_neon_pmull:
7429 case Intrinsic::aarch64_neon_smull:
7430 case Intrinsic::aarch64_neon_pmull64:
7431 case Intrinsic::aarch64_neon_umull: {
7432 handleNEONVectorMultiplyIntrinsic(
I);
7436 case Intrinsic::aarch64_neon_smmla:
7437 case Intrinsic::aarch64_neon_ummla:
7438 case Intrinsic::aarch64_neon_usmmla:
7439 case Intrinsic::aarch64_neon_bfmmla:
7440 handleNEONMatrixMultiply(
I);
7447 case Intrinsic::aarch64_neon_sdot:
7448 case Intrinsic::aarch64_neon_udot:
7449 case Intrinsic::aarch64_neon_usdot:
7450 handleVectorDotProductIntrinsic(
I, 4,
7460 case Intrinsic::aarch64_neon_bfdot:
7461 handleVectorDotProductIntrinsic(
I, 2,
7468 case Intrinsic::aarch64_neon_facge:
7469 case Intrinsic::aarch64_neon_facgt:
7470 handleVectorComparePackedIntrinsic(
I,
false);
7480 void visitIntrinsicInst(IntrinsicInst &
I) {
7481 if (maybeHandleCrossPlatformIntrinsic(
I))
7484 if (maybeHandleX86SIMDIntrinsic(
I))
7487 if (maybeHandleArmSIMDIntrinsic(
I))
7490 if (maybeHandleUnknownIntrinsic(
I))
7493 visitInstruction(
I);
7496 void visitLibAtomicLoad(CallBase &CB) {
7507 Value *NewOrdering =
7511 NextNodeIRBuilder NextIRB(&CB);
7512 Value *SrcShadowPtr, *SrcOriginPtr;
7513 std::tie(SrcShadowPtr, SrcOriginPtr) =
7514 getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7516 Value *DstShadowPtr =
7517 getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(),
Align(1),
7521 NextIRB.CreateMemCpy(DstShadowPtr,
Align(1), SrcShadowPtr,
Align(1),
Size);
7522 if (MS.TrackOrigins) {
7523 Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr,
7525 Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB);
7526 NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin});
7530 void visitLibAtomicStore(CallBase &CB) {
7537 Value *NewOrdering =
7541 Value *DstShadowPtr =
7551 void visitCallBase(CallBase &CB) {
7559 visitAsmInstruction(CB);
7561 visitInstruction(CB);
7565 if (LF != NotLibFunc) {
7570 case LibFunc_atomic_load:
7572 llvm::errs() <<
"MSAN -- cannot instrument invoke of libatomic load."
7576 visitLibAtomicLoad(CB);
7578 case LibFunc_atomic_store:
7579 visitLibAtomicStore(CB);
7595 B.addAttribute(Attribute::Memory).addAttribute(Attribute::Speculatable);
7599 Func->removeFnAttrs(
B);
7605 bool MayCheckCall = MS.EagerChecks;
7609 MayCheckCall &= !
Func->getName().starts_with(
"__sanitizer_unaligned_");
7612 unsigned ArgOffset = 0;
7615 if (!
A->getType()->isSized()) {
7616 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << CB <<
"\n");
7620 if (
A->getType()->isScalableTy()) {
7621 LLVM_DEBUG(
dbgs() <<
"Arg " << i <<
" is vscale: " << CB <<
"\n");
7623 insertCheckShadowOf(
A, &CB);
7628 const DataLayout &
DL =
F.getDataLayout();
7632 bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
7635 insertCheckShadowOf(
A, &CB);
7636 Size =
DL.getTypeAllocSize(
A->getType());
7642 Value *ArgShadow = getShadow(
A);
7643 Value *ArgShadowBase = getShadowPtrForArgument(IRB, ArgOffset);
7645 <<
" Shadow: " << *ArgShadow <<
"\n");
7649 assert(
A->getType()->isPointerTy() &&
7650 "ByVal argument is not a pointer!");
7658 Value *AShadowPtr, *AOriginPtr;
7659 std::tie(AShadowPtr, AOriginPtr) =
7660 getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(), Alignment,
7662 if (!PropagateShadow) {
7669 if (MS.TrackOrigins) {
7670 Value *ArgOriginBase = getOriginPtrForArgument(IRB, ArgOffset);
7684 Size =
DL.getTypeAllocSize(
A->getType());
7690 if (MS.TrackOrigins && !(Cst && Cst->
isNullValue())) {
7692 getOriginPtrForArgument(IRB, ArgOffset));
7704 if (FT->isVarArg()) {
7705 VAHelper->visitCallBase(CB, IRB);
7715 if (MayCheckCall && CB.
hasRetAttr(Attribute::NoUndef)) {
7716 setShadow(&CB, getCleanShadow(&CB));
7717 setOrigin(&CB, getCleanOrigin());
7723 Value *
Base = getShadowPtrForRetval(IRBBefore);
7724 IRBBefore.CreateAlignedStore(getCleanShadow(&CB),
Base,
7736 setShadow(&CB, getCleanShadow(&CB));
7737 setOrigin(&CB, getCleanOrigin());
7744 "Could not find insertion point for retval shadow load");
7747 Value *RetvalShadow = IRBAfter.CreateAlignedLoad(
7750 setShadow(&CB, RetvalShadow);
7751 if (MS.TrackOrigins)
7752 setOrigin(&CB, IRBAfter.CreateLoad(MS.OriginTy, getOriginPtrForRetval()));
7757 RetVal =
I->getOperand(0);
7760 return I->isMustTailCall();
7765 void visitReturnInst(ReturnInst &
I) {
7767 Value *RetVal =
I.getReturnValue();
7773 Value *ShadowPtr = getShadowPtrForRetval(IRB);
7774 bool HasNoUndef =
F.hasRetAttribute(Attribute::NoUndef);
7775 bool StoreShadow = !(MS.EagerChecks && HasNoUndef);
7778 bool EagerCheck = (MS.EagerChecks && HasNoUndef) || (
F.getName() ==
"main");
7780 Value *Shadow = getShadow(RetVal);
7781 bool StoreOrigin =
true;
7783 insertCheckShadowOf(RetVal, &
I);
7784 Shadow = getCleanShadow(RetVal);
7785 StoreOrigin =
false;
7792 if (MS.TrackOrigins && StoreOrigin)
7793 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval());
7797 void visitPHINode(PHINode &
I) {
7799 if (!PropagateShadow) {
7800 setShadow(&
I, getCleanShadow(&
I));
7801 setOrigin(&
I, getCleanOrigin());
7805 ShadowPHINodes.push_back(&
I);
7806 setShadow(&
I, IRB.
CreatePHI(getShadowTy(&
I),
I.getNumIncomingValues(),
7808 if (MS.TrackOrigins)
7810 &
I, IRB.
CreatePHI(MS.OriginTy,
I.getNumIncomingValues(),
"_msphi_o"));
7813 Value *getLocalVarIdptr(AllocaInst &
I) {
7814 ConstantInt *IntConst =
7815 ConstantInt::get(Type::getInt32Ty((*
F.getParent()).getContext()), 0);
7816 return new GlobalVariable(*
F.getParent(), IntConst->
getType(),
7821 Value *getLocalVarDescription(AllocaInst &
I) {
7827 IRB.
CreateCall(MS.MsanPoisonStackFn, {&I, Len});
7829 Value *ShadowBase, *OriginBase;
7830 std::tie(ShadowBase, OriginBase) = getShadowOriginPtr(
7834 IRB.
CreateMemSet(ShadowBase, PoisonValue, Len,
I.getAlign());
7837 if (PoisonStack && MS.TrackOrigins) {
7838 Value *Idptr = getLocalVarIdptr(
I);
7840 Value *Descr = getLocalVarDescription(
I);
7841 IRB.
CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
7842 {&I, Len, Idptr, Descr});
7844 IRB.
CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, {&I, Len, Idptr});
7850 Value *Descr = getLocalVarDescription(
I);
7852 IRB.
CreateCall(MS.MsanPoisonAllocaFn, {&I, Len, Descr});
7854 IRB.
CreateCall(MS.MsanUnpoisonAllocaFn, {&I, Len});
7858 void instrumentAlloca(AllocaInst &
I, Instruction *InsPoint =
nullptr) {
7861 NextNodeIRBuilder IRB(InsPoint);
7864 if (MS.CompileKernel)
7865 poisonAllocaKmsan(
I, IRB, Len);
7867 poisonAllocaUserspace(
I, IRB, Len);
7870 void visitAllocaInst(AllocaInst &
I) {
7871 setShadow(&
I, getCleanShadow(&
I));
7872 setOrigin(&
I, getCleanOrigin());
7878 void visitSelectInst(SelectInst &
I) {
7884 handleSelectLikeInst(
I,
B,
C,
D);
7890 Value *Sb = getShadow(
B);
7891 Value *Sc = getShadow(
C);
7892 Value *Sd = getShadow(
D);
7894 Value *Ob = MS.TrackOrigins ? getOrigin(
B) : nullptr;
7895 Value *Oc = MS.TrackOrigins ? getOrigin(
C) : nullptr;
7896 Value *Od = MS.TrackOrigins ? getOrigin(
D) : nullptr;
7901 if (
I.getType()->isAggregateType()) {
7905 Sa1 = getPoisonedShadow(getShadowTy(
I.getType()));
7906 }
else if (isScalableNonVectorType(
I.getType())) {
7914 Sa1 = getCleanShadow(getShadowTy(
I.getType()));
7922 C = CreateAppToShadowCast(IRB,
C);
7923 D = CreateAppToShadowCast(IRB,
D);
7930 if (MS.TrackOrigins) {
7933 if (
B->getType()->isVectorTy()) {
7934 B = convertToBool(
B, IRB);
7935 Sb = convertToBool(Sb, IRB);
7943 void visitLandingPadInst(LandingPadInst &
I) {
7946 setShadow(&
I, getCleanShadow(&
I));
7947 setOrigin(&
I, getCleanOrigin());
7950 void visitCatchSwitchInst(CatchSwitchInst &
I) {
7951 setShadow(&
I, getCleanShadow(&
I));
7952 setOrigin(&
I, getCleanOrigin());
7955 void visitFuncletPadInst(FuncletPadInst &
I) {
7956 setShadow(&
I, getCleanShadow(&
I));
7957 setOrigin(&
I, getCleanOrigin());
7960 void visitGetElementPtrInst(GetElementPtrInst &
I) { handleShadowOr(
I); }
7962 void visitExtractValueInst(ExtractValueInst &
I) {
7964 Value *Agg =
I.getAggregateOperand();
7966 Value *AggShadow = getShadow(Agg);
7970 setShadow(&
I, ResShadow);
7971 setOriginForNaryOp(
I);
7974 void visitInsertValueInst(InsertValueInst &
I) {
7977 Value *AggShadow = getShadow(
I.getAggregateOperand());
7978 Value *InsShadow = getShadow(
I.getInsertedValueOperand());
7984 setOriginForNaryOp(
I);
7987 void dumpInst(Instruction &
I,
const Twine &Prefix) {
7994 << CI->getCalledFunction()->
getName() <<
"\n";
7996 errs() <<
"ZZZ:" <<
Prefix <<
" " <<
I.getOpcodeName() <<
"\n";
8003 unsigned NumOperands =
I.getNumOperands();
8005 errs() <<
"YYY:" <<
Prefix <<
" call " << *
I.getType() <<
" @";
8017 errs() <<
"YYY:" <<
Prefix <<
" " << *
I.getType() <<
" "
8018 <<
I.getOpcodeName() <<
"(";
8020 for (
size_t i = 0; i < NumOperands; i++) {
8038 void visitResumeInst(ResumeInst &
I) {
8043 void visitCleanupReturnInst(CleanupReturnInst &CRI) {
8048 void visitCatchReturnInst(CatchReturnInst &CRI) {
8053 void instrumentAsmArgument(
Value *Operand,
Type *ElemTy, Instruction &
I,
8062 insertCheckShadowOf(Operand, &
I);
8069 auto Size =
DL.getTypeStoreSize(ElemTy);
8071 if (MS.CompileKernel) {
8072 IRB.
CreateCall(MS.MsanInstrumentAsmStoreFn, {Operand, SizeVal});
8078 auto [ShadowPtr,
_] =
8079 getShadowOriginPtrUserspace(Operand, IRB, IRB.
getInt8Ty(),
Align(1));
8089 int getNumOutputArgs(InlineAsm *IA, CallBase *CB) {
8090 int NumRetOutputs = 0;
8097 NumRetOutputs =
ST->getNumElements();
8102 for (
const InlineAsm::ConstraintInfo &Info : Constraints) {
8103 switch (
Info.Type) {
8111 return NumOutputs - NumRetOutputs;
8114 void visitAsmInstruction(Instruction &
I) {
8130 const DataLayout &
DL =
F.getDataLayout();
8134 int OutputArgs = getNumOutputArgs(IA, CB);
8140 for (
int i = OutputArgs; i < NumOperands; i++) {
8148 for (
int i = 0; i < OutputArgs; i++) {
8154 setShadow(&
I, getCleanShadow(&
I));
8155 setOrigin(&
I, getCleanOrigin());
8158 void visitFreezeInst(FreezeInst &
I) {
8160 setShadow(&
I, getCleanShadow(&
I));
8161 setOrigin(&
I, getCleanOrigin());
8164 void visitInstruction(Instruction &
I) {
8167 dumpInst(
I,
"Strict");
8169 for (
size_t i = 0, n =
I.getNumOperands(); i < n; i++) {
8170 Value *Operand =
I.getOperand(i);
8172 insertCheckShadowOf(Operand, &
I);
8174 setShadow(&
I, getCleanShadow(&
I));
8175 setOrigin(&
I, getCleanOrigin());
8179struct VarArgHelperBase :
public VarArgHelper {
8181 MemorySanitizer &MS;
8182 MemorySanitizerVisitor &MSV;
8184 const unsigned VAListTagSize;
8186 VarArgHelperBase(
Function &
F, MemorySanitizer &MS,
8187 MemorySanitizerVisitor &MSV,
unsigned VAListTagSize)
8188 :
F(
F), MS(MS), MSV(MSV), VAListTagSize(VAListTagSize) {}
8192 return IRB.
CreateAdd(
Base, ConstantInt::get(MS.IntptrTy, ArgOffset));
8198 MS.VAArgTLS, ConstantInt::get(MS.IntptrTy, ArgOffset),
"_msarg_va_s");
8207 return getShadowPtrForVAArgument(IRB, ArgOffset);
8216 ConstantInt::get(MS.IntptrTy, ArgOffset),
8221 unsigned BaseOffset) {
8230 TailSize,
Align(8));
8233 void unpoisonVAListTagForInst(IntrinsicInst &
I) {
8235 Value *VAListTag =
I.getArgOperand(0);
8237 auto [ShadowPtr, OriginPtr] = MSV.getShadowOriginPtr(
8238 VAListTag, IRB, IRB.
getInt8Ty(), Alignment,
true);
8241 VAListTagSize, Alignment,
false);
8244 void visitVAStartInst(VAStartInst &
I)
override {
8245 if (
F.getCallingConv() == CallingConv::Win64)
8248 unpoisonVAListTagForInst(
I);
8251 void visitVACopyInst(VACopyInst &
I)
override {
8252 if (
F.getCallingConv() == CallingConv::Win64)
8254 unpoisonVAListTagForInst(
I);
8259struct VarArgAMD64Helper :
public VarArgHelperBase {
8262 static const unsigned AMD64GpEndOffset = 48;
8263 static const unsigned AMD64FpEndOffsetSSE = 176;
8265 static const unsigned AMD64FpEndOffsetNoSSE = AMD64GpEndOffset;
8267 unsigned AMD64FpEndOffset;
8268 AllocaInst *VAArgTLSCopy =
nullptr;
8269 AllocaInst *VAArgTLSOriginCopy =
nullptr;
8270 Value *VAArgOverflowSize =
nullptr;
8272 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8274 VarArgAMD64Helper(
Function &
F, MemorySanitizer &MS,
8275 MemorySanitizerVisitor &MSV)
8276 : VarArgHelperBase(
F, MS, MSV, 24) {
8277 AMD64FpEndOffset = AMD64FpEndOffsetSSE;
8278 for (
const auto &Attr :
F.getAttributes().getFnAttrs()) {
8279 if (Attr.isStringAttribute() &&
8280 (Attr.getKindAsString() ==
"target-features")) {
8281 if (Attr.getValueAsString().contains(
"-sse"))
8282 AMD64FpEndOffset = AMD64FpEndOffsetNoSSE;
8288 ArgKind classifyArgument(
Value *arg) {
8291 if (
T->isX86_FP80Ty())
8293 if (
T->isFPOrFPVectorTy())
8294 return AK_FloatingPoint;
8295 if (
T->isIntegerTy() &&
T->getPrimitiveSizeInBits() <= 64)
8296 return AK_GeneralPurpose;
8297 if (
T->isPointerTy())
8298 return AK_GeneralPurpose;
8310 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8311 unsigned GpOffset = 0;
8312 unsigned FpOffset = AMD64GpEndOffset;
8313 unsigned OverflowOffset = AMD64FpEndOffset;
8314 const DataLayout &
DL =
F.getDataLayout();
8325 assert(
A->getType()->isPointerTy());
8327 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8329 unsigned BaseOffset = OverflowOffset;
8330 Value *ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8331 Value *OriginBase =
nullptr;
8332 if (MS.TrackOrigins)
8333 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8334 OverflowOffset += AlignedSize;
8337 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8341 Value *ShadowPtr, *OriginPtr;
8342 std::tie(ShadowPtr, OriginPtr) =
8347 if (MS.TrackOrigins)
8351 ArgKind AK = classifyArgument(
A);
8352 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
8354 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
8356 Value *ShadowBase, *OriginBase =
nullptr;
8358 case AK_GeneralPurpose:
8359 ShadowBase = getShadowPtrForVAArgument(IRB, GpOffset);
8360 if (MS.TrackOrigins)
8361 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset);
8365 case AK_FloatingPoint:
8366 ShadowBase = getShadowPtrForVAArgument(IRB, FpOffset);
8367 if (MS.TrackOrigins)
8368 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
8375 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8377 unsigned BaseOffset = OverflowOffset;
8378 ShadowBase = getShadowPtrForVAArgument(IRB, OverflowOffset);
8379 if (MS.TrackOrigins) {
8380 OriginBase = getOriginPtrForVAArgument(IRB, OverflowOffset);
8382 OverflowOffset += AlignedSize;
8385 CleanUnusedTLS(IRB, ShadowBase, BaseOffset);
8394 Value *Shadow = MSV.getShadow(
A);
8396 if (MS.TrackOrigins) {
8397 Value *Origin = MSV.getOrigin(
A);
8398 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
8399 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
8405 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AMD64FpEndOffset);
8406 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8409 void finalizeInstrumentation()
override {
8410 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8411 "finalizeInstrumentation called twice");
8412 if (!VAStartInstrumentationList.
empty()) {
8419 ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize);
8420 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8426 Intrinsic::umin, CopySize,
8430 if (MS.TrackOrigins) {
8431 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8440 for (CallInst *OrigInst : VAStartInstrumentationList) {
8441 NextNodeIRBuilder IRB(OrigInst);
8442 Value *VAListTag = OrigInst->getArgOperand(0);
8444 Value *RegSaveAreaPtrPtr =
8445 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 16));
8447 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8449 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8450 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8452 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8454 if (MS.TrackOrigins)
8455 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
8456 Alignment, AMD64FpEndOffset);
8457 Value *OverflowArgAreaPtrPtr =
8458 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, 8));
8459 Value *OverflowArgAreaPtr =
8460 IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
8461 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
8462 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
8463 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
8467 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
8469 if (MS.TrackOrigins) {
8472 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
8480struct VarArgAArch64Helper :
public VarArgHelperBase {
8481 static const unsigned kAArch64GrArgSize = 64;
8482 static const unsigned kAArch64VrArgSize = 128;
8484 static const unsigned AArch64GrBegOffset = 0;
8485 static const unsigned AArch64GrEndOffset = kAArch64GrArgSize;
8487 static const unsigned AArch64VrBegOffset = AArch64GrEndOffset;
8488 static const unsigned AArch64VrEndOffset =
8489 AArch64VrBegOffset + kAArch64VrArgSize;
8490 static const unsigned AArch64VAEndOffset = AArch64VrEndOffset;
8492 AllocaInst *VAArgTLSCopy =
nullptr;
8493 Value *VAArgOverflowSize =
nullptr;
8495 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
8497 VarArgAArch64Helper(
Function &
F, MemorySanitizer &MS,
8498 MemorySanitizerVisitor &MSV)
8499 : VarArgHelperBase(
F, MS, MSV, 32) {}
8502 std::pair<ArgKind, uint64_t> classifyArgument(
Type *
T) {
8503 if (
T->isIntOrPtrTy() &&
T->getPrimitiveSizeInBits() <= 64)
8504 return {AK_GeneralPurpose, 1};
8505 if (
T->isFloatingPointTy() &&
T->getPrimitiveSizeInBits() <= 128)
8506 return {AK_FloatingPoint, 1};
8508 if (
T->isArrayTy()) {
8509 auto R = classifyArgument(
T->getArrayElementType());
8510 R.second *=
T->getScalarType()->getArrayNumElements();
8515 auto R = classifyArgument(FV->getScalarType());
8516 R.second *= FV->getNumElements();
8521 return {AK_Memory, 0};
8533 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8534 unsigned GrOffset = AArch64GrBegOffset;
8535 unsigned VrOffset = AArch64VrBegOffset;
8536 unsigned OverflowOffset = AArch64VAEndOffset;
8538 const DataLayout &
DL =
F.getDataLayout();
8541 auto [AK, RegNum] = classifyArgument(
A->getType());
8542 if (AK == AK_GeneralPurpose &&
8543 (GrOffset + RegNum * 8) > AArch64GrEndOffset)
8545 if (AK == AK_FloatingPoint &&
8546 (VrOffset + RegNum * 16) > AArch64VrEndOffset)
8550 case AK_GeneralPurpose:
8551 Base = getShadowPtrForVAArgument(IRB, GrOffset);
8552 GrOffset += 8 * RegNum;
8554 case AK_FloatingPoint:
8555 Base = getShadowPtrForVAArgument(IRB, VrOffset);
8556 VrOffset += 16 * RegNum;
8563 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8565 unsigned BaseOffset = OverflowOffset;
8566 Base = getShadowPtrForVAArgument(IRB, BaseOffset);
8567 OverflowOffset += AlignedSize;
8570 CleanUnusedTLS(IRB,
Base, BaseOffset);
8582 ConstantInt::get(IRB.
getInt64Ty(), OverflowOffset - AArch64VAEndOffset);
8583 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
8588 Value *SaveAreaPtrPtr =
8589 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8590 return IRB.
CreateLoad(Type::getInt64Ty(*MS.C), SaveAreaPtrPtr);
8595 Value *SaveAreaPtr =
8596 IRB.
CreatePtrAdd(VAListTag, ConstantInt::get(MS.IntptrTy, offset));
8598 return IRB.
CreateSExt(SaveArea32, MS.IntptrTy);
8601 void finalizeInstrumentation()
override {
8602 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
8603 "finalizeInstrumentation called twice");
8604 if (!VAStartInstrumentationList.empty()) {
8611 ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize);
8612 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8618 Intrinsic::umin, CopySize,
8624 Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize);
8625 Value *VrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64VrArgSize);
8629 for (CallInst *OrigInst : VAStartInstrumentationList) {
8630 NextNodeIRBuilder IRB(OrigInst);
8632 Value *VAListTag = OrigInst->getArgOperand(0);
8649 Value *StackSaveAreaPtr =
8650 IRB.
CreateIntToPtr(getVAField64(IRB, VAListTag, 0), RegSaveAreaPtrTy);
8653 Value *GrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 8);
8654 Value *GrOffSaveArea = getVAField32(IRB, VAListTag, 24);
8657 IRB.
CreateAdd(GrTopSaveAreaPtr, GrOffSaveArea), RegSaveAreaPtrTy);
8660 Value *VrTopSaveAreaPtr = getVAField64(IRB, VAListTag, 16);
8661 Value *VrOffSaveArea = getVAField32(IRB, VAListTag, 28);
8664 IRB.
CreateAdd(VrTopSaveAreaPtr, VrOffSaveArea), RegSaveAreaPtrTy);
8670 Value *GrRegSaveAreaShadowPtrOff =
8671 IRB.
CreateAdd(GrArgSize, GrOffSaveArea);
8673 Value *GrRegSaveAreaShadowPtr =
8674 MSV.getShadowOriginPtr(GrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8680 Value *GrCopySize = IRB.
CreateSub(GrArgSize, GrRegSaveAreaShadowPtrOff);
8686 Value *VrRegSaveAreaShadowPtrOff =
8687 IRB.
CreateAdd(VrArgSize, VrOffSaveArea);
8689 Value *VrRegSaveAreaShadowPtr =
8690 MSV.getShadowOriginPtr(VrRegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8697 VrRegSaveAreaShadowPtrOff);
8698 Value *VrCopySize = IRB.
CreateSub(VrArgSize, VrRegSaveAreaShadowPtrOff);
8704 Value *StackSaveAreaShadowPtr =
8705 MSV.getShadowOriginPtr(StackSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8710 VAArgTLSCopy, IRB.
getInt32(AArch64VAEndOffset));
8713 Align(16), VAArgOverflowSize);
8719struct VarArgPowerPC64Helper :
public VarArgHelperBase {
8720 AllocaInst *VAArgTLSCopy =
nullptr;
8721 Value *VAArgSize =
nullptr;
8723 VarArgPowerPC64Helper(
Function &
F, MemorySanitizer &MS,
8724 MemorySanitizerVisitor &MSV)
8725 : VarArgHelperBase(
F, MS, MSV, 8) {}
8727 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8735 Triple TargetTriple(
F.getParent()->getTargetTriple());
8739 if (TargetTriple.isPPC64ELFv2ABI())
8743 unsigned VAArgOffset = VAArgBase;
8744 const DataLayout &
DL =
F.getDataLayout();
8749 assert(
A->getType()->isPointerTy());
8751 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8754 ArgAlign =
Align(8);
8755 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8758 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8760 Value *AShadowPtr, *AOriginPtr;
8761 std::tie(AShadowPtr, AOriginPtr) =
8762 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8772 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
8774 if (
A->getType()->isArrayTy()) {
8777 Type *ElementTy =
A->getType()->getArrayElementType();
8779 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8780 }
else if (
A->getType()->isVectorTy()) {
8782 ArgAlign =
Align(ArgSize);
8785 ArgAlign =
Align(8);
8786 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8787 if (
DL.isBigEndian()) {
8791 VAArgOffset += (8 - ArgSize);
8795 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8799 VAArgOffset += ArgSize;
8803 VAArgBase = VAArgOffset;
8807 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8810 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8813 void finalizeInstrumentation()
override {
8814 assert(!VAArgSize && !VAArgTLSCopy &&
8815 "finalizeInstrumentation called twice");
8818 Value *CopySize = VAArgSize;
8820 if (!VAStartInstrumentationList.empty()) {
8824 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8830 Intrinsic::umin, CopySize,
8838 for (CallInst *OrigInst : VAStartInstrumentationList) {
8839 NextNodeIRBuilder IRB(OrigInst);
8840 Value *VAListTag = OrigInst->getArgOperand(0);
8843 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8846 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8847 const DataLayout &
DL =
F.getDataLayout();
8848 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8850 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8851 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
8853 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
8860struct VarArgPowerPC32Helper :
public VarArgHelperBase {
8861 AllocaInst *VAArgTLSCopy =
nullptr;
8862 Value *VAArgSize =
nullptr;
8864 VarArgPowerPC32Helper(
Function &
F, MemorySanitizer &MS,
8865 MemorySanitizerVisitor &MSV)
8866 : VarArgHelperBase(
F, MS, MSV, 12) {}
8868 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
8872 unsigned VAArgOffset = VAArgBase;
8873 const DataLayout &
DL =
F.getDataLayout();
8874 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8879 assert(
A->getType()->isPointerTy());
8881 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
8883 if (ArgAlign < IntptrSize)
8884 ArgAlign =
Align(IntptrSize);
8885 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8888 getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase, ArgSize);
8890 Value *AShadowPtr, *AOriginPtr;
8891 std::tie(AShadowPtr, AOriginPtr) =
8892 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
8902 Type *ArgTy =
A->getType();
8908 uint64_t ArgSize =
DL.getTypeAllocSize(ArgTy);
8915 ArgAlign =
Align(
DL.getTypeAllocSize(ElementTy));
8918 ArgAlign =
Align(ArgSize);
8920 if (ArgAlign < IntptrSize)
8921 ArgAlign =
Align(IntptrSize);
8922 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
8923 if (
DL.isBigEndian()) {
8926 if (ArgSize < IntptrSize)
8927 VAArgOffset += (IntptrSize - ArgSize);
8930 Base = getShadowPtrForVAArgument(IRB, VAArgOffset - VAArgBase,
8936 VAArgOffset += ArgSize;
8943 ConstantInt::get(MS.IntptrTy, VAArgOffset - VAArgBase);
8946 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
8949 void finalizeInstrumentation()
override {
8950 assert(!VAArgSize && !VAArgTLSCopy &&
8951 "finalizeInstrumentation called twice");
8953 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
8954 Value *CopySize = VAArgSize;
8956 if (!VAStartInstrumentationList.empty()) {
8960 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
8966 Intrinsic::umin, CopySize,
8974 for (CallInst *OrigInst : VAStartInstrumentationList) {
8975 NextNodeIRBuilder IRB(OrigInst);
8976 Value *VAListTag = OrigInst->getArgOperand(0);
8978 Value *RegSaveAreaSize = CopySize;
8982 IRB.
CreateAdd(RegSaveAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 8));
8986 Intrinsic::umin, CopySize, ConstantInt::get(MS.IntptrTy, 32));
8988 RegSaveAreaPtrPtr = IRB.
CreateIntToPtr(RegSaveAreaPtrPtr, MS.PtrTy);
8991 const DataLayout &
DL =
F.getDataLayout();
8992 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
8996 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
8997 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
8998 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9000 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
9001 Alignment, RegSaveAreaSize);
9003 RegSaveAreaShadowPtr =
9006 ConstantInt::get(MS.IntptrTy, 32));
9011 ConstantInt::get(MS.IntptrTy, 32), Alignment);
9016 Value *OverflowAreaSize = IRB.
CreateSub(CopySize, RegSaveAreaSize);
9019 OverflowAreaPtrPtr =
9020 IRB.
CreateAdd(OverflowAreaPtrPtr, ConstantInt::get(MS.IntptrTy, 4));
9021 OverflowAreaPtrPtr = IRB.
CreateIntToPtr(OverflowAreaPtrPtr, MS.PtrTy);
9023 Value *OverflowAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowAreaPtrPtr);
9025 Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
9026 std::tie(OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
9027 MSV.getShadowOriginPtr(OverflowAreaPtr, IRB, IRB.
getInt8Ty(),
9030 Value *OverflowVAArgTLSCopyPtr =
9032 OverflowVAArgTLSCopyPtr =
9033 IRB.
CreateAdd(OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
9035 OverflowVAArgTLSCopyPtr =
9038 OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
9045struct VarArgSystemZHelper :
public VarArgHelperBase {
9046 static const unsigned SystemZGpOffset = 16;
9047 static const unsigned SystemZGpEndOffset = 56;
9048 static const unsigned SystemZFpOffset = 128;
9049 static const unsigned SystemZFpEndOffset = 160;
9050 static const unsigned SystemZMaxVrArgs = 8;
9051 static const unsigned SystemZRegSaveAreaSize = 160;
9052 static const unsigned SystemZOverflowOffset = 160;
9053 static const unsigned SystemZVAListTagSize = 32;
9054 static const unsigned SystemZOverflowArgAreaPtrOffset = 16;
9055 static const unsigned SystemZRegSaveAreaPtrOffset = 24;
9057 bool IsSoftFloatABI;
9058 AllocaInst *VAArgTLSCopy =
nullptr;
9059 AllocaInst *VAArgTLSOriginCopy =
nullptr;
9060 Value *VAArgOverflowSize =
nullptr;
9062 enum class ArgKind {
9070 enum class ShadowExtension {
None,
Zero, Sign };
9072 VarArgSystemZHelper(
Function &
F, MemorySanitizer &MS,
9073 MemorySanitizerVisitor &MSV)
9074 : VarArgHelperBase(
F, MS, MSV, SystemZVAListTagSize),
9075 IsSoftFloatABI(
F.getFnAttribute(
"use-soft-float").getValueAsBool()) {}
9077 ArgKind classifyArgument(
Type *
T) {
9084 if (
T->isIntegerTy(128) ||
T->isFP128Ty())
9085 return ArgKind::Indirect;
9086 if (
T->isFloatingPointTy())
9087 return IsSoftFloatABI ? ArgKind::GeneralPurpose : ArgKind::FloatingPoint;
9088 if (
T->isIntegerTy() ||
T->isPointerTy())
9089 return ArgKind::GeneralPurpose;
9090 if (
T->isVectorTy())
9091 return ArgKind::Vector;
9092 return ArgKind::Memory;
9095 ShadowExtension getShadowExtension(
const CallBase &CB,
unsigned ArgNo) {
9105 return ShadowExtension::Zero;
9109 return ShadowExtension::Sign;
9111 return ShadowExtension::None;
9114 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9115 unsigned GpOffset = SystemZGpOffset;
9116 unsigned FpOffset = SystemZFpOffset;
9117 unsigned VrIndex = 0;
9118 unsigned OverflowOffset = SystemZOverflowOffset;
9119 const DataLayout &
DL =
F.getDataLayout();
9125 ArgKind AK = classifyArgument(
T);
9126 if (AK == ArgKind::Indirect) {
9128 AK = ArgKind::GeneralPurpose;
9130 if (AK == ArgKind::GeneralPurpose && GpOffset >= SystemZGpEndOffset)
9131 AK = ArgKind::Memory;
9132 if (AK == ArgKind::FloatingPoint && FpOffset >= SystemZFpEndOffset)
9133 AK = ArgKind::Memory;
9134 if (AK == ArgKind::Vector && (VrIndex >= SystemZMaxVrArgs || !IsFixed))
9135 AK = ArgKind::Memory;
9136 Value *ShadowBase =
nullptr;
9137 Value *OriginBase =
nullptr;
9138 ShadowExtension SE = ShadowExtension::None;
9140 case ArgKind::GeneralPurpose: {
9145 SE = getShadowExtension(CB, ArgNo);
9147 if (SE == ShadowExtension::None) {
9149 assert(ArgAllocSize <= ArgSize);
9150 GapSize = ArgSize - ArgAllocSize;
9152 ShadowBase = getShadowAddrForVAArgument(IRB, GpOffset + GapSize);
9153 if (MS.TrackOrigins)
9154 OriginBase = getOriginPtrForVAArgument(IRB, GpOffset + GapSize);
9156 GpOffset += ArgSize;
9162 case ArgKind::FloatingPoint: {
9171 ShadowBase = getShadowAddrForVAArgument(IRB, FpOffset);
9172 if (MS.TrackOrigins)
9173 OriginBase = getOriginPtrForVAArgument(IRB, FpOffset);
9175 FpOffset += ArgSize;
9181 case ArgKind::Vector: {
9188 case ArgKind::Memory: {
9196 SE = getShadowExtension(CB, ArgNo);
9198 SE == ShadowExtension::None ? ArgSize - ArgAllocSize : 0;
9200 getShadowAddrForVAArgument(IRB, OverflowOffset + GapSize);
9201 if (MS.TrackOrigins)
9203 getOriginPtrForVAArgument(IRB, OverflowOffset + GapSize);
9204 OverflowOffset += ArgSize;
9211 case ArgKind::Indirect:
9214 if (ShadowBase ==
nullptr)
9216 Value *Shadow = MSV.getShadow(
A);
9217 if (SE != ShadowExtension::None)
9218 Shadow = MSV.CreateShadowCast(IRB, Shadow, IRB.
getInt64Ty(),
9219 SE == ShadowExtension::Sign);
9220 ShadowBase = IRB.
CreateIntToPtr(ShadowBase, MS.PtrTy,
"_msarg_va_s");
9222 if (MS.TrackOrigins) {
9223 Value *Origin = MSV.getOrigin(
A);
9224 TypeSize StoreSize =
DL.getTypeStoreSize(Shadow->
getType());
9225 MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize,
9229 Constant *OverflowSize = ConstantInt::get(
9230 IRB.
getInt64Ty(), OverflowOffset - SystemZOverflowOffset);
9231 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
9238 ConstantInt::get(MS.IntptrTy, SystemZRegSaveAreaPtrOffset)),
9241 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9243 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9244 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(), Alignment,
9249 unsigned RegSaveAreaSize =
9250 IsSoftFloatABI ? SystemZGpEndOffset : SystemZRegSaveAreaSize;
9251 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9253 if (MS.TrackOrigins)
9254 IRB.
CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy,
9255 Alignment, RegSaveAreaSize);
9264 ConstantInt::get(MS.IntptrTy, SystemZOverflowArgAreaPtrOffset)),
9266 Value *OverflowArgAreaPtr = IRB.
CreateLoad(MS.PtrTy, OverflowArgAreaPtrPtr);
9267 Value *OverflowArgAreaShadowPtr, *OverflowArgAreaOriginPtr;
9269 std::tie(OverflowArgAreaShadowPtr, OverflowArgAreaOriginPtr) =
9270 MSV.getShadowOriginPtr(OverflowArgAreaPtr, IRB, IRB.
getInt8Ty(),
9273 SystemZOverflowOffset);
9274 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment,
9276 if (MS.TrackOrigins) {
9278 SystemZOverflowOffset);
9279 IRB.
CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment,
9284 void finalizeInstrumentation()
override {
9285 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
9286 "finalizeInstrumentation called twice");
9287 if (!VAStartInstrumentationList.empty()) {
9294 IRB.
CreateAdd(ConstantInt::get(MS.IntptrTy, SystemZOverflowOffset),
9296 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9302 Intrinsic::umin, CopySize,
9306 if (MS.TrackOrigins) {
9307 VAArgTLSOriginCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9316 for (CallInst *OrigInst : VAStartInstrumentationList) {
9317 NextNodeIRBuilder IRB(OrigInst);
9318 Value *VAListTag = OrigInst->getArgOperand(0);
9319 copyRegSaveArea(IRB, VAListTag);
9320 copyOverflowArea(IRB, VAListTag);
9326struct VarArgI386Helper :
public VarArgHelperBase {
9327 AllocaInst *VAArgTLSCopy =
nullptr;
9328 Value *VAArgSize =
nullptr;
9330 VarArgI386Helper(
Function &
F, MemorySanitizer &MS,
9331 MemorySanitizerVisitor &MSV)
9332 : VarArgHelperBase(
F, MS, MSV, 4) {}
9334 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9335 const DataLayout &
DL =
F.getDataLayout();
9336 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9337 unsigned VAArgOffset = 0;
9342 assert(
A->getType()->isPointerTy());
9344 uint64_t ArgSize =
DL.getTypeAllocSize(RealTy);
9346 if (ArgAlign < IntptrSize)
9347 ArgAlign =
Align(IntptrSize);
9348 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9350 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9352 Value *AShadowPtr, *AOriginPtr;
9353 std::tie(AShadowPtr, AOriginPtr) =
9354 MSV.getShadowOriginPtr(
A, IRB, IRB.
getInt8Ty(),
9364 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9366 VAArgOffset =
alignTo(VAArgOffset, ArgAlign);
9367 if (
DL.isBigEndian()) {
9370 if (ArgSize < IntptrSize)
9371 VAArgOffset += (IntptrSize - ArgSize);
9374 Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9377 VAArgOffset += ArgSize;
9383 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9386 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9389 void finalizeInstrumentation()
override {
9390 assert(!VAArgSize && !VAArgTLSCopy &&
9391 "finalizeInstrumentation called twice");
9393 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9394 Value *CopySize = VAArgSize;
9396 if (!VAStartInstrumentationList.empty()) {
9399 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9405 Intrinsic::umin, CopySize,
9413 for (CallInst *OrigInst : VAStartInstrumentationList) {
9414 NextNodeIRBuilder IRB(OrigInst);
9415 Value *VAListTag = OrigInst->getArgOperand(0);
9416 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9417 Value *RegSaveAreaPtrPtr =
9419 PointerType::get(*MS.C, 0));
9420 Value *RegSaveAreaPtr =
9421 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9422 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9423 const DataLayout &
DL =
F.getDataLayout();
9424 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9426 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9427 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9429 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9437struct VarArgGenericHelper :
public VarArgHelperBase {
9438 AllocaInst *VAArgTLSCopy =
nullptr;
9439 Value *VAArgSize =
nullptr;
9441 VarArgGenericHelper(
Function &
F, MemorySanitizer &MS,
9442 MemorySanitizerVisitor &MSV,
const unsigned VAListTagSize)
9443 : VarArgHelperBase(
F, MS, MSV, VAListTagSize) {}
9445 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {
9446 unsigned VAArgOffset = 0;
9447 const DataLayout &
DL =
F.getDataLayout();
9448 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9453 uint64_t ArgSize =
DL.getTypeAllocSize(
A->getType());
9454 if (
DL.isBigEndian()) {
9457 if (ArgSize < IntptrSize)
9458 VAArgOffset += (IntptrSize - ArgSize);
9460 Value *
Base = getShadowPtrForVAArgument(IRB, VAArgOffset, ArgSize);
9461 VAArgOffset += ArgSize;
9462 VAArgOffset =
alignTo(VAArgOffset, IntptrSize);
9468 Constant *TotalVAArgSize = ConstantInt::get(MS.IntptrTy, VAArgOffset);
9471 IRB.
CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS);
9474 void finalizeInstrumentation()
override {
9475 assert(!VAArgSize && !VAArgTLSCopy &&
9476 "finalizeInstrumentation called twice");
9478 VAArgSize = IRB.
CreateLoad(MS.IntptrTy, MS.VAArgOverflowSizeTLS);
9479 Value *CopySize = VAArgSize;
9481 if (!VAStartInstrumentationList.empty()) {
9484 VAArgTLSCopy = IRB.
CreateAlloca(Type::getInt8Ty(*MS.C), CopySize);
9490 Intrinsic::umin, CopySize,
9498 for (CallInst *OrigInst : VAStartInstrumentationList) {
9499 NextNodeIRBuilder IRB(OrigInst);
9500 Value *VAListTag = OrigInst->getArgOperand(0);
9501 Type *RegSaveAreaPtrTy = PointerType::getUnqual(*MS.C);
9502 Value *RegSaveAreaPtrPtr =
9504 PointerType::get(*MS.C, 0));
9505 Value *RegSaveAreaPtr =
9506 IRB.
CreateLoad(RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
9507 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
9508 const DataLayout &
DL =
F.getDataLayout();
9509 unsigned IntptrSize =
DL.getTypeStoreSize(MS.IntptrTy);
9511 std::tie(RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
9512 MSV.getShadowOriginPtr(RegSaveAreaPtr, IRB, IRB.
getInt8Ty(),
9514 IRB.
CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
9522using VarArgARM32Helper = VarArgGenericHelper;
9523using VarArgRISCVHelper = VarArgGenericHelper;
9524using VarArgMIPSHelper = VarArgGenericHelper;
9525using VarArgLoongArch64Helper = VarArgGenericHelper;
9526using VarArgHexagonHelper = VarArgGenericHelper;
9529struct VarArgNoOpHelper :
public VarArgHelper {
9530 VarArgNoOpHelper(
Function &
F, MemorySanitizer &MS,
9531 MemorySanitizerVisitor &MSV) {}
9533 void visitCallBase(CallBase &CB,
IRBuilder<> &IRB)
override {}
9535 void visitVAStartInst(VAStartInst &
I)
override {}
9537 void visitVACopyInst(VACopyInst &
I)
override {}
9539 void finalizeInstrumentation()
override {}
9545 MemorySanitizerVisitor &Visitor) {
9548 Triple TargetTriple(Func.getParent()->getTargetTriple());
9551 return new VarArgI386Helper(Func, Msan, Visitor);
9554 return new VarArgAMD64Helper(Func, Msan, Visitor);
9556 if (TargetTriple.
isARM())
9557 return new VarArgARM32Helper(Func, Msan, Visitor, 4);
9560 return new VarArgAArch64Helper(Func, Msan, Visitor);
9563 return new VarArgSystemZHelper(Func, Msan, Visitor);
9568 return new VarArgPowerPC32Helper(Func, Msan, Visitor);
9571 return new VarArgPowerPC64Helper(Func, Msan, Visitor);
9574 return new VarArgRISCVHelper(Func, Msan, Visitor, 4);
9577 return new VarArgRISCVHelper(Func, Msan, Visitor, 8);
9580 return new VarArgMIPSHelper(Func, Msan, Visitor, 4);
9583 return new VarArgMIPSHelper(Func, Msan, Visitor, 8);
9586 return new VarArgLoongArch64Helper(Func, Msan, Visitor,
9590 return new VarArgHexagonHelper(Func, Msan, Visitor, 12);
9592 return new VarArgNoOpHelper(Func, Msan, Visitor);
9599 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
9602 MemorySanitizerVisitor Visitor(
F, *
this, TLI);
9609 return Visitor.runOnFunction();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool isStore(int Opcode)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
VarLocInsertPt getNextNode(const DbgRecord *DVR)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool insertModuleCtor(Module &M)
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static bool isAMustTailRetVal(Value *RetVal)
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
Module.h This file contains the declarations for the Module class.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
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.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
void removeFnAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the function.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getCalledOperand() const
Type * getParamElementType(unsigned ArgNo) const
Extract the elementtype type for a parameter.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ ICMP_SGT
signed greater than
@ ICMP_SGE
signed greater or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getBool(LLVMContext &Context, bool V)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getSplat(ElementCount EC, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
LLVM_ABI bool isAllOnesValue() const
Return true if this is the value that would be returned by getAllOnesValue.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
static bool shouldExecute(CounterInfo &Counter)
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
static FixedVectorType * getHalfElementsVectorType(FixedVectorType *VTy)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
LLVM_ABI void setComdat(Comdat *C)
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ ExternalLinkage
Externally visible function.
Analysis pass providing a never-invalidated alias analysis result.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI Value * CreateAndReduce(Value *Src)
Create a vector int AND reduction intrinsic of the source vector.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
LLVM_ABI CallInst * CreateMaskedCompressStore(Value *Val, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr)
Create a call to Masked Compress Store intrinsic.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateAllocationSize(Type *DestTy, AllocaInst *AI)
Get allocation size of an alloca as a runtime Value* (handles both static and dynamic allocas and vsc...
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memcpy between the specified pointers.
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateMaskedLoad(Type *Ty, Value *Ptr, Align Alignment, Value *Mask, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Load intrinsic.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
LLVM_ABI Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with 2 operands which is mangled on the first type.
LLVM_ABI Value * CreateOrReduce(Value *Src)
Create a vector int OR reduction intrinsic of the source vector.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI DebugLoc getCurrentDebugLocation() const
Get location information used by debugging information.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended from a 64-bit value.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedStore(Value *Val, Value *Ptr, Align Alignment, Value *Mask)
Create a call to Masked Store intrinsic.
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
LLVM_ABI CallInst * CreateMaskedExpandLoad(Type *Ty, Value *Ptr, MaybeAlign Align, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Expand Load intrinsic.
Value * CreateInBoundsPtrAdd(Value *Ptr, Value *Offset, const Twine &Name="")
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI CallInst * CreateMaskedScatter(Value *Val, Value *Ptrs, Align Alignment, Value *Mask=nullptr)
Create a call to Masked Scatter intrinsic.
LLVM_ABI CallInst * CreateMaskedGather(Type *Ty, Value *Ptrs, Align Alignment, Value *Mask=nullptr, Value *PassThru=nullptr, const Twine &Name="")
Create a call to Masked Gather intrinsic.
Value * CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
std::vector< ConstraintInfo > ConstraintInfoVector
void visit(Iterator Start, Iterator End)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
A Module instance is used to store all the information related to an LLVM module.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
bool remove(const value_type &X)
Remove an item from the set vector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
Triple - Helper class for working with autoconf configuration names.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
bool isRISCV32() const
Tests whether the target is 32-bit RISC-V.
bool isPPC32() const
Tests whether the target is 32-bit PowerPC (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isPPC64() const
Tests whether the target is 64-bit PowerPC (little and big endian).
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isSystemZ() const
Tests whether the target is SystemZ.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const
Return true if this is a type whose size is a known multiple of vscale.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isPPC_FP128Ty() const
Return true if this is powerpc long double.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
ElementCount getElementCount() const
Return an ElementCount instance to represent the (possibly scalable) number of elements in the vector...
Type * getElementType() const
int getNumOccurrences() const
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
LLVM_ABI StringRef getBaseName(ID id)
Return the LLVM name for an intrinsic, without encoded types for overloading, such as "llvm....
initializer< Ty > init(const Ty &Val)
Function * Kernel
Summary of a kernel (=entry point for target offloading).
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
RelativeUniformCounterPtr Values
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI std::pair< Instruction *, Value * > SplitBlockAndInsertSimpleForLoop(Value *End, BasicBlock::iterator SplitBefore)
Insert a for (int i = 0; i < End; i++) loop structure (with the exception that End is assumed > 0,...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
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 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)