60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
84 Ctx.
emitError(DiagnosticInst ? DiagnosticInst : &FailedInst,
Msg);
86 if (!FailedInst.getType()->isVoidTy())
88 FailedInst.eraseFromParent();
91 template <
typename Inst>
92 void handleUnsupportedAtomicSize(Inst *
I,
const Twine &AtomicOpName,
96 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
97 template <
typename AtomicInst>
98 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
102 bool tryExpandAtomicLoad(
LoadInst *LI);
103 bool expandAtomicLoadToLL(
LoadInst *LI);
104 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
115 void expandAtomicOpToLLSC(
119 void expandPartwordAtomicRMW(
127 Value *insertRMWCmpXchgLoop(
131 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
143 void expandAtomicLoadToLibcall(
LoadInst *LI);
144 void expandAtomicStoreToLibcall(
StoreInst *LI);
147 const Twine &AtomicOpName =
"cmpxchg",
151 CreateCmpXchgInstFun CreateCmpXchg);
176struct ReplacementIRBuilder
177 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
179 MDNode *PCSectionsMD =
nullptr;
187 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
188 this->setIsFPConstrained(
true);
190 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
191 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
196 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
197 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
203char AtomicExpandLegacy::ID = 0;
208 "Expand Atomic instructions",
false,
false)
217 return DL.getTypeStoreSize(LI->getType());
222 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
239 Source.getAllMetadata(MD);
243 for (
auto [ID,
N] : MD) {
245 case LLVMContext::MD_dbg:
246 case LLVMContext::MD_tbaa:
247 case LLVMContext::MD_tbaa_struct:
248 case LLVMContext::MD_alias_scope:
249 case LLVMContext::MD_mem_cache_hint:
250 case LLVMContext::MD_noalias:
251 case LLVMContext::MD_noalias_addrspace:
252 case LLVMContext::MD_access_group:
253 case LLVMContext::MD_mmra:
257 if (ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
259 else if (ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
269template <
typename Inst>
272 Align Alignment =
I->getAlign();
274 return Alignment >=
Size &&
Size <= MaxSize;
277template <
typename Inst>
281 Align Alignment =
I->getAlign();
282 bool NeedSeparator =
false;
284 if (Alignment <
Size) {
285 OS <<
"instruction alignment " << Alignment.value()
286 <<
" is smaller than the required " <<
Size
287 <<
"-byte alignment for this atomic operation";
288 NeedSeparator =
true;
292 if (
Size > MaxSize) {
295 OS <<
"target supports atomics up to " << MaxSize
296 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
300template <
typename Inst>
301void AtomicExpandImpl::handleUnsupportedAtomicSize(
304 SmallString<128> FailureReason;
305 raw_svector_ostream OS(FailureReason);
307 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
311bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
317 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
318 TrailingFence->moveAfter(AtomicI);
324template <
typename AtomicInst>
325bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
326 bool OrderingRequiresFence,
329 if (OrderingRequiresFence && ShouldInsertFences) {
331 AtomicI->setOrdering(NewOrdering);
332 return bracketInstWithFences(AtomicI, FenceOrdering);
334 if (!ShouldInsertFences)
335 return tryInsertTrailingSeqCstFence(AtomicI);
342bool AtomicExpandImpl::lowerToNonAtomic(Instruction *
I) {
344 FI->eraseFromParent();
355 if (LI->isAtomic()) {
356 LI->setAtomic(AtomicOrdering::NotAtomic);
357 LI->setElementwise(
false);
365 if (
SI->isAtomic()) {
366 SI->setAtomic(AtomicOrdering::NotAtomic);
367 SI->setElementwise(
false);
377bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
379 return lowerToNonAtomic(
I);
386 expandAtomicLoadToLibcall(LI);
390 bool MadeChange =
false;
392 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
393 LI = convertAtomicLoadToIntegerType(LI);
397 MadeChange |= tryInsertFencesForAtomic(
400 MadeChange |= tryExpandAtomicLoad(LI);
409 expandAtomicStoreToLibcall(SI);
413 bool MadeChange =
false;
415 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
416 SI = convertAtomicStoreToIntegerType(SI);
420 MadeChange |= tryInsertFencesForAtomic(
423 MadeChange |= tryExpandAtomicStore(SI);
429 expandAtomicRMWToLibcall(RMWI);
433 bool MadeChange =
false;
435 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
436 RMWI = convertAtomicXchgToIntegerType(RMWI);
440 MadeChange |= tryInsertFencesForAtomic(
450 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
451 tryExpandAtomicRMW(RMWI);
457 expandAtomicCASToLibcall(CASI);
463 bool MadeChange =
false;
464 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
467 CASI = convertCmpXchgToIntegerType(CASI);
473 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
484 CASI->setSuccessOrdering(CASOrdering);
485 CASI->setFailureOrdering(CASOrdering);
486 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
488 }
else if (CmpXchgExpansion !=
489 TargetLoweringBase::AtomicExpansionKind::LLSC) {
491 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
494 MadeChange |= tryExpandAtomicCmpXchg(CASI);
502 const ModuleLibcallLoweringInfo &LibcallResult,
503 const TargetMachine *TM) {
504 SingleThreaded =
F.getParent()->getThreadModel() == ThreadModel::Single;
510 TLI = Subtarget->getTargetLowering();
512 DL = &
F.getDataLayout();
514 bool MadeChange =
false;
526 if (processAtomicInstr(&Inst)) {
538bool AtomicExpandLegacy::runOnFunction(
Function &
F) {
540 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
543 auto *TM = &TPC->getTM<TargetMachine>();
545 const ModuleLibcallLoweringInfo &LibcallResult =
546 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
548 return AE.run(
F, LibcallResult, TM);
552 return new AtomicExpandLegacy();
562 if (!LibcallResult) {
564 "' analysis required");
570 bool Changed = AE.run(
F, *LibcallResult, TM);
577bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
579 ReplacementIRBuilder Builder(
I, *
DL);
589 return (LeadingFence || TrailingFence);
604LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
606 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
608 ReplacementIRBuilder Builder(LI, *
DL);
612 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
613 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
616 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
617 : Builder.CreateBitCast(NewLI, LI->
getType());
624AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
629 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
631 ReplacementIRBuilder Builder(RMWI, *
DL);
635 Value *NewVal = Builder.CreateBitPreservingCastChain(*
DL, Val, NewTy);
642 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
645 Builder.CreateBitPreservingCastChain(*
DL, NewRMWI, RMWI->
getType());
651bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
653 case TargetLoweringBase::AtomicExpansionKind::None:
655 case TargetLoweringBase::AtomicExpansionKind::LLSC:
656 expandAtomicOpToLLSC(
659 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
661 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
662 return expandAtomicLoadToLL(LI);
663 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
664 return expandAtomicLoadToCmpXchg(LI);
665 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
666 LI->
setAtomic(AtomicOrdering::NotAtomic);
668 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
676bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
678 case TargetLoweringBase::AtomicExpansionKind::None:
680 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
683 case TargetLoweringBase::AtomicExpansionKind::Expand:
684 expandAtomicStoreToXChg(SI);
686 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
687 SI->setAtomic(AtomicOrdering::NotAtomic);
694bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
695 ReplacementIRBuilder Builder(LI, *
DL);
710bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
711 ReplacementIRBuilder Builder(LI, *
DL);
713 if (Order == AtomicOrdering::Unordered)
714 Order = AtomicOrdering::Monotonic;
723 Type *CmpXchgTy = Ty;
728 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
729 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
733 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
735 Loaded = Builder.CreateBitCast(Loaded, Ty);
751StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
752 ReplacementIRBuilder Builder(SI, *
DL);
753 auto *
M =
SI->getModule();
754 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
756 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
757 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
758 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
760 Value *Addr =
SI->getPointerOperand();
762 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
764 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
765 SI->eraseFromParent();
769void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
776 ReplacementIRBuilder Builder(SI, *
DL);
778 assert(Ordering != AtomicOrdering::NotAtomic);
780 ? AtomicOrdering::Monotonic
782 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
784 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
786 SI->eraseFromParent();
789 tryExpandAtomicRMW(AI);
804 NewVal = Builder.CreateBitCast(NewVal, IntTy);
805 Loaded = Builder.CreateBitCast(Loaded, IntTy);
809 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
815 Success = Builder.CreateExtractValue(Pair, 1,
"success");
816 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
819 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
822void AtomicExpandImpl::expandAtomicSubToAdd(AtomicRMWInst *AI) {
823 ReplacementIRBuilder Builder(AI, *
DL);
844bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
848 case TargetLoweringBase::AtomicExpansionKind::None:
850 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
853 if (ValueSize < MinCASSize) {
854 expandPartwordAtomicRMW(AI,
855 TargetLoweringBase::AtomicExpansionKind::LLSC);
857 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
866 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
869 if (ValueSize < MinCASSize) {
870 expandPartwordAtomicRMW(AI,
871 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
880 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
881 <<
"A compare and swap loop was generated for an atomic "
889 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
892 if (ValueSize < MinCASSize) {
897 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
901 expandAtomicRMWToMaskedIntrinsic(AI);
904 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
908 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
912 case TargetLoweringBase::AtomicExpansionKind::Expand:
913 expandAtomicSubToAdd(AI);
915 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
917 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
927struct PartwordMaskValues {
929 Type *WordType =
nullptr;
931 Type *IntValueType =
nullptr;
932 Value *AlignedAddr =
nullptr;
933 Align AlignedAddrAlignment;
935 Value *ShiftAmt =
nullptr;
936 Value *Mask =
nullptr;
937 Value *Inv_Mask =
nullptr;
941raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
942 auto PrintObj = [&
O](
auto *
V) {
949 O <<
"PartwordMaskValues {\n";
951 PrintObj(PMV.WordType);
953 PrintObj(PMV.ValueType);
954 O <<
" AlignedAddr: ";
955 PrintObj(PMV.AlignedAddr);
956 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
958 PrintObj(PMV.ShiftAmt);
962 PrintObj(PMV.Inv_Mask);
988 unsigned MinWordSize) {
989 PartwordMaskValues PMV;
994 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
996 PMV.ValueType = PMV.IntValueType =
ValueType;
1001 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
1003 if (PMV.ValueType == PMV.WordType) {
1004 PMV.AlignedAddr = Addr;
1005 PMV.AlignedAddrAlignment = AddrAlign;
1006 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
1007 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
1011 PMV.AlignedAddrAlignment =
Align(MinWordSize);
1013 assert(ValueSize < MinWordSize);
1016 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
1019 if (AddrAlign < MinWordSize) {
1020 PMV.AlignedAddr = Builder.CreateIntrinsic(
1021 Intrinsic::ptrmask, {PtrTy, IntTy},
1023 nullptr,
"AlignedAddr");
1025 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
1026 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1029 PMV.AlignedAddr = Addr;
1033 if (
DL.isLittleEndian()) {
1035 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1038 PMV.ShiftAmt = Builder.CreateShl(
1039 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1042 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1043 PMV.Mask = Builder.CreateShl(
1044 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1047 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1053 const PartwordMaskValues &PMV) {
1054 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1055 if (PMV.WordType == PMV.ValueType)
1058 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1059 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1060 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1064 Value *Updated,
const PartwordMaskValues &PMV) {
1065 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1066 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1067 if (PMV.WordType == PMV.ValueType)
1070 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1072 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1074 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1075 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1076 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1086 const PartwordMaskValues &PMV) {
1093 "Or/Xor/And handled by widenPartwordAtomicRMW");
1098 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1101 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1123 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1124 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1125 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1132 assert(!ValOperand_Shifted);
1146void AtomicExpandImpl::expandPartwordAtomicRMW(
1152 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1158 ReplacementIRBuilder Builder(AI, *
DL);
1160 PartwordMaskValues PMV =
1164 Value *ValOperand_Shifted =
nullptr;
1165 bool NeedsShiftedOperand =
1170 if (NeedsShiftedOperand) {
1172 ValOperand_Shifted =
1173 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1174 "ValOperand_Shifted");
1177 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1183 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1184 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1185 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1189 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1190 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1191 PMV.AlignedAddrAlignment, MemOpOrder,
1201AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1202 ReplacementIRBuilder Builder(AI, *
DL);
1207 "Unable to widen operation");
1209 PartwordMaskValues PMV =
1219 Value *ValOperand_Shifted =
1221 "ValOperand_Shifted");
1227 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1229 NewOperand = ValOperand_Shifted;
1232 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1244bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1286 ReplacementIRBuilder Builder(CI, *
DL);
1297 std::prev(BB->
end())->eraseFromParent();
1300 PartwordMaskValues PMV =
1305 Value *NewVal_Shifted =
1307 Value *Cmp_Shifted =
1312 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1313 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1318 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1319 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1332 processAtomicInstr(InitLoaded);
1336 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1337 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1339 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1367 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1382void AtomicExpandImpl::expandAtomicOpToLLSC(
1383 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1385 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1386 ReplacementIRBuilder Builder(
I, *
DL);
1387 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1388 MemOpOrder, PerformOp);
1390 I->replaceAllUsesWith(Loaded);
1391 I->eraseFromParent();
1394void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1395 ReplacementIRBuilder Builder(AI, *
DL);
1397 PartwordMaskValues PMV =
1407 CastOp = Instruction::SExt;
1411 PMV.ShiftAmt,
"ValOperand_Shifted");
1413 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1420void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1421 AtomicCmpXchgInst *CI) {
1422 ReplacementIRBuilder Builder(CI, *
DL);
1435 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1441 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1448Value *AtomicExpandImpl::insertRMWLLSCLoop(
1449 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1451 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1456 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1457 "Expected at least natural alignment at this point.");
1477 std::prev(BB->
end())->eraseFromParent();
1485 Value *NewVal = PerformOp(Builder, Loaded);
1487 Value *StoreSuccess =
1509AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1512 M->getDataLayout());
1514 ReplacementIRBuilder Builder(CI, *
DL);
1526 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1542bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1548 LLVMContext &Ctx =
F->getContext();
1555 ? AtomicOrdering::Monotonic
1567 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1568 SuccessOrder != AtomicOrdering::Monotonic &&
1569 SuccessOrder != AtomicOrdering::Acquire &&
1574 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1628 auto ReleasedLoadBB =
1632 auto ReleasingStoreBB =
1636 ReplacementIRBuilder Builder(CI, *
DL);
1641 std::prev(BB->
end())->eraseFromParent();
1643 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1646 PartwordMaskValues PMV =
1653 Value *UnreleasedLoad =
1654 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1655 Value *UnreleasedLoadExtract =
1662 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1663 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1666 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1671 PHINode *LoadedTryStore =
1672 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1673 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1674 Value *NewValueInsert =
1677 PMV.AlignedAddr, MemOpOrder);
1679 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1680 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1682 CI->
isWeak() ? FailureBB : RetryBB,
1683 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1687 if (HasReleasedLoadBB) {
1689 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1697 ShouldStore, TryStoreBB, NoStoreBB,
1698 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1700 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1707 if (ShouldInsertFencesForAtomic ||
1713 PHINode *LoadedNoStore =
1715 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1716 if (HasReleasedLoadBB)
1717 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1726 PHINode *LoadedFailure =
1728 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1730 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1731 if (ShouldInsertFencesForAtomic)
1740 PHINode *LoadedExit =
1742 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1743 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1750 Value *LoadedFull = LoadedExit;
1758 for (
auto *User : CI->
users()) {
1764 "weird extraction from { iN, i1 }");
1775 for (
auto *EV : PrunedInsts)
1792bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1807 return C->isMinusOne();
1809 return C->isMaxValue(
true);
1811 return C->isMinValue(
true);
1813 return C->isMaxValue(
false);
1815 return C->isMinValue(
false);
1821bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1823 tryExpandAtomicLoad(ResultingLoad);
1829Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1830 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1832 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1833 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1860 std::prev(BB->
end())->eraseFromParent();
1868 Loaded->addIncoming(InitLoaded, BB);
1877 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1881 processAtomicInstr(InitLoaded);
1884 Value *NewVal = PerformOp(Builder, Loaded);
1886 Value *NewLoaded =
nullptr;
1889 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1890 MemOpOrder == AtomicOrdering::Unordered
1891 ? AtomicOrdering::Monotonic
1893 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1896 Loaded->addIncoming(NewLoaded, LoopBB);
1909bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1916 case TargetLoweringBase::AtomicExpansionKind::None:
1917 if (ValueSize < MinCASSize)
1918 return expandPartwordCmpXchg(CI);
1920 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1921 return expandAtomicCmpXchg(CI);
1923 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1924 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1926 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1928 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1935bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1936 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1943 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1946 [&](IRBuilderBase &Builder,
Value *Loaded) {
1947 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1948 AI->getValOperand());
1971 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1972 return Alignment >=
Size &&
1974 Size <= LargestSize;
1977void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1978 static const RTLIB::Libcall Libcalls[6] = {
1979 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1980 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1983 bool Expanded = expandAtomicOpToLibcall(
1984 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1985 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1987 handleUnsupportedAtomicSize(
I,
"atomic load");
1990void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1991 static const RTLIB::Libcall Libcalls[6] = {
1992 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1993 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1996 bool Expanded = expandAtomicOpToLibcall(
1997 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1998 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2000 handleUnsupportedAtomicSize(
I,
"atomic store");
2003void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
2004 const Twine &AtomicOpName,
2005 Instruction *DiagnosticInst) {
2006 static const RTLIB::Libcall Libcalls[6] = {
2007 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
2008 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
2009 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
2012 bool Expanded = expandAtomicOpToLibcall(
2013 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
2014 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
2017 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
2021 static const RTLIB::Libcall LibcallsXchg[6] = {
2022 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
2023 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
2024 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
2025 static const RTLIB::Libcall LibcallsAdd[6] = {
2026 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2027 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2028 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2029 static const RTLIB::Libcall LibcallsSub[6] = {
2030 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2031 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2032 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2033 static const RTLIB::Libcall LibcallsAnd[6] = {
2034 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2035 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2036 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2037 static const RTLIB::Libcall LibcallsOr[6] = {
2038 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2039 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2040 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2041 static const RTLIB::Libcall LibcallsXor[6] = {
2042 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2043 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2044 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2045 static const RTLIB::Libcall LibcallsNand[6] = {
2046 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2047 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2048 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2089void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2095 if (!Libcalls.
empty())
2096 Success = expandAtomicOpToLibcall(
2097 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2098 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2105 expandAtomicRMWToCmpXchg(
2106 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2109 Value *&NewLoaded, Instruction *MetadataSrc) {
2112 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2122 expandAtomicCASToLibcall(
2136bool AtomicExpandImpl::expandAtomicOpToLibcall(
2137 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2142 LLVMContext &Ctx =
I->getContext();
2144 const DataLayout &
DL =
M->getDataLayout();
2146 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2149 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2151 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2161 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2165 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2167 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2170 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2172 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2174 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2176 RTLIB::Libcall RTLibType;
2177 if (UseSizedLibcall) {
2180 RTLibType = Libcalls[1];
2183 RTLibType = Libcalls[2];
2186 RTLibType = Libcalls[3];
2189 RTLibType = Libcalls[4];
2192 RTLibType = Libcalls[5];
2195 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2196 RTLibType = Libcalls[0];
2203 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2204 if (LibcallImpl == RTLIB::Unsupported) {
2235 AllocaInst *AllocaCASExpected =
nullptr;
2236 AllocaInst *AllocaValue =
nullptr;
2237 AllocaInst *AllocaResult =
nullptr;
2244 if (!UseSizedLibcall) {
2246 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2254 Value *PtrVal = PointerOperand;
2256 Args.push_back(PtrVal);
2260 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2264 Args.push_back(AllocaCASExpected);
2269 if (UseSizedLibcall) {
2272 Args.push_back(IntValue);
2274 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2278 Args.push_back(AllocaValue);
2283 if (!CASExpected && HasResult && !UseSizedLibcall) {
2284 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2287 Args.push_back(AllocaResult);
2291 Args.push_back(OrderingVal);
2295 Args.push_back(Ordering2Val);
2299 ResultTy = Type::getInt1Ty(Ctx);
2300 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2301 }
else if (HasResult && UseSizedLibcall)
2302 ResultTy = SizedIntTy;
2304 ResultTy = Type::getVoidTy(Ctx);
2308 for (
Value *Arg : Args)
2310 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2311 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2319 if (ValueOperand && !UseSizedLibcall)
2325 Type *FinalResultTy =
I->getType();
2328 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2333 }
else if (HasResult) {
2335 if (UseSizedLibcall) {
2339 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2340 unsigned AS = PtrTy->getAddressSpace();
2342 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2351 I->replaceAllUsesWith(V);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static Value * performMaskedAtomicOp(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *ValOperand_Shifted, Value *Inc, const PartwordMaskValues &PMV)
Emit IR to implement a masked version of a given atomicrmw operation.
static PartwordMaskValues createMaskInstrs(IRBuilderBase &Builder, Instruction *I, Type *ValueType, Value *Addr, Align AddrAlign, unsigned MinWordSize)
This is a helper function which builds instructions to provide values necessary for partword atomic o...
static bool canUseSizedAtomicCall(unsigned Size, Align Alignment, const DataLayout &DL)
static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, bool IsVolatile, Value *&Success, Value *&NewLoaded, Instruction *MetadataSrc)
static Value * extractMaskedValue(IRBuilderBase &Builder, Value *WideWord, const PartwordMaskValues &PMV)
Expand Atomic static false unsigned getAtomicOpSize(LoadInst *LI)
static void writeUnsupportedAtomicSizeReason(const TargetLowering *TLI, Inst *I, raw_ostream &OS)
static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I)
static Value * insertMaskedValue(IRBuilderBase &Builder, Value *WideWord, Value *Updated, const PartwordMaskValues &PMV)
static void copyMetadataForAtomic(Instruction &Dest, const Instruction &Source)
Copy metadata that's safe to preserve when widening atomics.
static ArrayRef< RTLIB::Libcall > GetRMWLibcall(AtomicRMWInst::BinOp Op)
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
static bool isIdempotentRMW(AtomicRMWInst &RMWI)
Return true if and only if the given instruction does not modify the memory location referenced.
Machine Check Debug Module
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
This file defines the SmallString class.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
void setAlignment(Align Align)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
AtomicOrdering getMergedOrdering() const
Returns a single ordering which is at least as strong as both the success and failure orderings for t...
void setWeak(bool IsWeak)
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
Value * getPointerOperand()
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isWeak() const
Return true if this cmpxchg may spuriously fail.
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
AtomicOrdering getSuccessOrdering() const
Returns the success ordering constraint of this cmpxchg instruction.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this cmpxchg instruction.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
void setVolatile(bool V)
Specify whether this is a volatile RMW or not.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
Value * getPointerOperand()
void setOperation(BinOp Operation)
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
iterator begin()
Instruction iterator methods.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::reverse_iterator reverse_iterator
void setAttributes(AttributeList A)
Set the attributes for this call.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
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 * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
BasicBlockListType::iterator iterator
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNull=false)
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateLifetimeStart(Value *Ptr)
Create a lifetime.start intrinsic.
LLVM_ABI CallInst * CreateLifetimeEnd(Value *Ptr)
Create a lifetime.end intrinsic.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
UnreachableInst * CreateUnreachable()
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
BasicBlock * GetInsertBlock() const
LLVM_ABI Value * CreateBitPreservingCastChain(const DataLayout &DL, Value *V, Type *NewTy)
Create a chain of casts to convert V to NewTy, preserving the bit pattern of V.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
void setIsFPConstrained(bool IsCon)
Enable/Disable use of constrained floating point math.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
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)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, bool Elementwise=false)
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void moveAfter(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void getSyncScopeNames(SmallVectorImpl< StringRef > &SSNs) const
getSyncScopeNames - Populates client supplied SmallVector with synchronization scope names registered...
Tracks which library functions to use for a particular subtarget or function.
RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
An instruction for reading from memory.
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
void setVolatile(bool V)
Specify whether this is a volatile load or not.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
LoadStoreInstProperties getProperties() const
Returns the properties of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
Records a mapping from an opaque lowering context to its LibcallLoweringInfo.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
virtual Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const
Perform a store-conditional operation to Addr.
EVT getMemValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
virtual void emitBitTestAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a bit test atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
virtual bool shouldInsertFencesForAtomic(const Instruction *I) const
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
virtual AtomicOrdering atomicOperationOrderAfterFenceSplit(const Instruction *I) const
virtual void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const
Perform a cmpxchg expansion using a target-specific method.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const
Perform a masked atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
virtual void emitExpandAtomicRMW(AtomicRMWInst *AI) const
Perform a atomicrmw expansion using a target-specific way.
virtual void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const
virtual void emitExpandAtomicStore(StoreInst *SI) const
Perform a atomic store using a target-specific way.
virtual AtomicExpansionKind shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const
Returns how the given atomic atomicrmw should be cast by the IR-level AtomicExpand pass.
virtual bool shouldInsertTrailingSeqCstFenceForAtomicStore(const Instruction *I) const
Whether AtomicExpandPass should automatically insert a seq_cst trailing fence without reducing the or...
virtual AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const
Perform a masked cmpxchg using a target-specific intrinsic.
virtual bool shouldIssueAtomicLoadForAtomicEmulationLoop(void) const
unsigned getMaxAtomicSizeInBitsSupported() const
Returns the maximum atomic operation size (in bits) supported by the backend.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual void emitExpandAtomicLoad(LoadInst *LI) const
Perform a atomic load using a target-specific way.
virtual AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
virtual void emitCmpArithAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a atomicrmw which the result is only used by comparison, using a target-specific intrinsic.
virtual AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be cast by the IR-level AtomicExpand pass into.
virtual Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
virtual AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be cast by the IR-level AtomicExpand pass.
virtual Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
Inserts in the IR a target-specific intrinsic specifying a fence.
virtual LoadInst * lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const
On some platforms, an AtomicRMW that never actually modifies the value (such as fetch_add of 0) can b...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
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 char Args[]
Key for Kernel::Metadata::mArgs.
@ BasicBlock
Various leaf nodes.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool canInstructionHaveMMRAs(const Instruction &I)
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool isReleaseOrStronger(AtomicOrdering AO)
AtomicOrderingCABI toCABI(AtomicOrdering AO)
LLVM_ABI const LibcallLoweringInfo & getLibcallLowering(const ModuleLibcallLoweringInfo &ModuleInfo, const TargetSubtargetInfo &Subtarget)
Resolve the LibcallLoweringInfo for Subtarget from the module-level ModuleInfo, applying the subtarge...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
LLVM_ABI bool lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Convert the given Cmpxchg into primitive load and compare.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI FunctionPass * createAtomicExpandLegacyPass()
AtomicExpandPass - At IR level this pass replace atomic instructions with __atomic_* library calls,...
LLVM_ABI char & AtomicExpandID
AtomicExpandID – Lowers atomic operations in terms of either cmpxchg load-linked/store-conditional lo...
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.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.