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);
114 void expandAtomicOpToLLSC(
118 void expandPartwordAtomicRMW(
126 Value *insertRMWCmpXchgLoop(
130 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
142 void expandAtomicLoadToLibcall(
LoadInst *LI);
143 void expandAtomicStoreToLibcall(
StoreInst *LI);
146 const Twine &AtomicOpName =
"cmpxchg",
150 CreateCmpXchgInstFun CreateCmpXchg);
175struct ReplacementIRBuilder
176 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
178 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);
822bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
826 case TargetLoweringBase::AtomicExpansionKind::None:
828 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
831 if (ValueSize < MinCASSize) {
832 expandPartwordAtomicRMW(AI,
833 TargetLoweringBase::AtomicExpansionKind::LLSC);
835 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
844 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
847 if (ValueSize < MinCASSize) {
848 expandPartwordAtomicRMW(AI,
849 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
858 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
859 <<
"A compare and swap loop was generated for an atomic "
867 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
870 if (ValueSize < MinCASSize) {
875 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
879 expandAtomicRMWToMaskedIntrinsic(AI);
882 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
886 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
890 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
892 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
902struct PartwordMaskValues {
904 Type *WordType =
nullptr;
906 Type *IntValueType =
nullptr;
907 Value *AlignedAddr =
nullptr;
908 Align AlignedAddrAlignment;
910 Value *ShiftAmt =
nullptr;
911 Value *Mask =
nullptr;
912 Value *Inv_Mask =
nullptr;
916raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
917 auto PrintObj = [&
O](
auto *
V) {
924 O <<
"PartwordMaskValues {\n";
926 PrintObj(PMV.WordType);
928 PrintObj(PMV.ValueType);
929 O <<
" AlignedAddr: ";
930 PrintObj(PMV.AlignedAddr);
931 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
933 PrintObj(PMV.ShiftAmt);
937 PrintObj(PMV.Inv_Mask);
963 unsigned MinWordSize) {
964 PartwordMaskValues PMV;
969 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
971 PMV.ValueType = PMV.IntValueType =
ValueType;
976 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
978 if (PMV.ValueType == PMV.WordType) {
979 PMV.AlignedAddr = Addr;
980 PMV.AlignedAddrAlignment = AddrAlign;
981 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
982 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
986 PMV.AlignedAddrAlignment =
Align(MinWordSize);
988 assert(ValueSize < MinWordSize);
991 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
994 if (AddrAlign < MinWordSize) {
995 PMV.AlignedAddr = Builder.CreateIntrinsic(
996 Intrinsic::ptrmask, {PtrTy, IntTy},
998 nullptr,
"AlignedAddr");
1000 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
1001 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1004 PMV.AlignedAddr = Addr;
1008 if (
DL.isLittleEndian()) {
1010 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1013 PMV.ShiftAmt = Builder.CreateShl(
1014 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1017 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1018 PMV.Mask = Builder.CreateShl(
1019 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1022 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1028 const PartwordMaskValues &PMV) {
1029 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1030 if (PMV.WordType == PMV.ValueType)
1033 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1034 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1035 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1039 Value *Updated,
const PartwordMaskValues &PMV) {
1040 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1041 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1042 if (PMV.WordType == PMV.ValueType)
1045 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1047 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1049 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1050 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1051 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1061 const PartwordMaskValues &PMV) {
1068 "Or/Xor/And handled by widenPartwordAtomicRMW");
1073 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1076 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1098 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1099 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1100 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1107 assert(!ValOperand_Shifted);
1121void AtomicExpandImpl::expandPartwordAtomicRMW(
1127 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1133 ReplacementIRBuilder Builder(AI, *
DL);
1135 PartwordMaskValues PMV =
1139 Value *ValOperand_Shifted =
nullptr;
1140 bool NeedsShiftedOperand =
1145 if (NeedsShiftedOperand) {
1147 ValOperand_Shifted =
1148 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1149 "ValOperand_Shifted");
1152 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1158 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1159 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1160 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1164 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1165 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1166 PMV.AlignedAddrAlignment, MemOpOrder,
1176AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1177 ReplacementIRBuilder Builder(AI, *
DL);
1182 "Unable to widen operation");
1184 PartwordMaskValues PMV =
1194 Value *ValOperand_Shifted =
1196 "ValOperand_Shifted");
1202 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1204 NewOperand = ValOperand_Shifted;
1207 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1219bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1261 ReplacementIRBuilder Builder(CI, *
DL);
1272 std::prev(BB->
end())->eraseFromParent();
1275 PartwordMaskValues PMV =
1280 Value *NewVal_Shifted =
1282 Value *Cmp_Shifted =
1287 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1288 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1293 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1294 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1307 processAtomicInstr(InitLoaded);
1311 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1312 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1314 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1342 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1357void AtomicExpandImpl::expandAtomicOpToLLSC(
1358 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1360 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1361 ReplacementIRBuilder Builder(
I, *
DL);
1362 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1363 MemOpOrder, PerformOp);
1365 I->replaceAllUsesWith(Loaded);
1366 I->eraseFromParent();
1369void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1370 ReplacementIRBuilder Builder(AI, *
DL);
1372 PartwordMaskValues PMV =
1382 CastOp = Instruction::SExt;
1386 PMV.ShiftAmt,
"ValOperand_Shifted");
1388 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1395void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1396 AtomicCmpXchgInst *CI) {
1397 ReplacementIRBuilder Builder(CI, *
DL);
1410 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1416 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1423Value *AtomicExpandImpl::insertRMWLLSCLoop(
1424 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1426 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1431 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1432 "Expected at least natural alignment at this point.");
1452 std::prev(BB->
end())->eraseFromParent();
1460 Value *NewVal = PerformOp(Builder, Loaded);
1462 Value *StoreSuccess =
1484AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1487 M->getDataLayout());
1489 ReplacementIRBuilder Builder(CI, *
DL);
1501 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1517bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1523 LLVMContext &Ctx =
F->getContext();
1530 ? AtomicOrdering::Monotonic
1542 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1543 SuccessOrder != AtomicOrdering::Monotonic &&
1544 SuccessOrder != AtomicOrdering::Acquire &&
1549 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1603 auto ReleasedLoadBB =
1607 auto ReleasingStoreBB =
1611 ReplacementIRBuilder Builder(CI, *
DL);
1616 std::prev(BB->
end())->eraseFromParent();
1618 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1621 PartwordMaskValues PMV =
1628 Value *UnreleasedLoad =
1629 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1630 Value *UnreleasedLoadExtract =
1637 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1638 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1641 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1646 PHINode *LoadedTryStore =
1647 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1648 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1649 Value *NewValueInsert =
1652 PMV.AlignedAddr, MemOpOrder);
1654 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1655 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1657 CI->
isWeak() ? FailureBB : RetryBB,
1658 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1662 if (HasReleasedLoadBB) {
1664 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1672 ShouldStore, TryStoreBB, NoStoreBB,
1673 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1675 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1682 if (ShouldInsertFencesForAtomic ||
1688 PHINode *LoadedNoStore =
1690 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1691 if (HasReleasedLoadBB)
1692 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1701 PHINode *LoadedFailure =
1703 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1705 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1706 if (ShouldInsertFencesForAtomic)
1715 PHINode *LoadedExit =
1717 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1718 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1725 Value *LoadedFull = LoadedExit;
1733 for (
auto *User : CI->
users()) {
1739 "weird extraction from { iN, i1 }");
1750 for (
auto *EV : PrunedInsts)
1767bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1782 return C->isMinusOne();
1784 return C->isMaxValue(
true);
1786 return C->isMinValue(
true);
1788 return C->isMaxValue(
false);
1790 return C->isMinValue(
false);
1796bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1798 tryExpandAtomicLoad(ResultingLoad);
1804Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1805 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1807 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1808 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1835 std::prev(BB->
end())->eraseFromParent();
1843 Loaded->addIncoming(InitLoaded, BB);
1852 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1856 processAtomicInstr(InitLoaded);
1859 Value *NewVal = PerformOp(Builder, Loaded);
1861 Value *NewLoaded =
nullptr;
1864 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1865 MemOpOrder == AtomicOrdering::Unordered
1866 ? AtomicOrdering::Monotonic
1868 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1871 Loaded->addIncoming(NewLoaded, LoopBB);
1884bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1891 case TargetLoweringBase::AtomicExpansionKind::None:
1892 if (ValueSize < MinCASSize)
1893 return expandPartwordCmpXchg(CI);
1895 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1896 return expandAtomicCmpXchg(CI);
1898 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1899 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1901 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1903 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1910bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1911 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1918 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1921 [&](IRBuilderBase &Builder,
Value *Loaded) {
1922 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1923 AI->getValOperand());
1946 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1947 return Alignment >=
Size &&
1949 Size <= LargestSize;
1952void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1953 static const RTLIB::Libcall Libcalls[6] = {
1954 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1955 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1958 bool Expanded = expandAtomicOpToLibcall(
1959 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1960 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1962 handleUnsupportedAtomicSize(
I,
"atomic load");
1965void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1966 static const RTLIB::Libcall Libcalls[6] = {
1967 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1968 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1971 bool Expanded = expandAtomicOpToLibcall(
1972 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1973 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1975 handleUnsupportedAtomicSize(
I,
"atomic store");
1978void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
1979 const Twine &AtomicOpName,
1980 Instruction *DiagnosticInst) {
1981 static const RTLIB::Libcall Libcalls[6] = {
1982 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1983 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1984 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1987 bool Expanded = expandAtomicOpToLibcall(
1988 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1989 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1992 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
1996 static const RTLIB::Libcall LibcallsXchg[6] = {
1997 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1998 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1999 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
2000 static const RTLIB::Libcall LibcallsAdd[6] = {
2001 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2002 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2003 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2004 static const RTLIB::Libcall LibcallsSub[6] = {
2005 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2006 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2007 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2008 static const RTLIB::Libcall LibcallsAnd[6] = {
2009 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2010 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2011 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2012 static const RTLIB::Libcall LibcallsOr[6] = {
2013 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2014 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2015 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2016 static const RTLIB::Libcall LibcallsXor[6] = {
2017 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2018 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2019 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2020 static const RTLIB::Libcall LibcallsNand[6] = {
2021 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2022 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2023 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2064void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2070 if (!Libcalls.
empty())
2071 Success = expandAtomicOpToLibcall(
2072 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2073 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2080 expandAtomicRMWToCmpXchg(
2081 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2084 Value *&NewLoaded, Instruction *MetadataSrc) {
2087 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2097 expandAtomicCASToLibcall(
2111bool AtomicExpandImpl::expandAtomicOpToLibcall(
2112 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2117 LLVMContext &Ctx =
I->getContext();
2119 const DataLayout &
DL =
M->getDataLayout();
2121 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2124 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2126 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2136 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2140 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2142 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2145 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2147 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2149 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2151 RTLIB::Libcall RTLibType;
2152 if (UseSizedLibcall) {
2155 RTLibType = Libcalls[1];
2158 RTLibType = Libcalls[2];
2161 RTLibType = Libcalls[3];
2164 RTLibType = Libcalls[4];
2167 RTLibType = Libcalls[5];
2170 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2171 RTLibType = Libcalls[0];
2178 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2179 if (LibcallImpl == RTLIB::Unsupported) {
2210 AllocaInst *AllocaCASExpected =
nullptr;
2211 AllocaInst *AllocaValue =
nullptr;
2212 AllocaInst *AllocaResult =
nullptr;
2219 if (!UseSizedLibcall) {
2221 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2229 Value *PtrVal = PointerOperand;
2231 Args.push_back(PtrVal);
2235 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2239 Args.push_back(AllocaCASExpected);
2244 if (UseSizedLibcall) {
2247 Args.push_back(IntValue);
2249 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2253 Args.push_back(AllocaValue);
2258 if (!CASExpected && HasResult && !UseSizedLibcall) {
2259 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2262 Args.push_back(AllocaResult);
2266 Args.push_back(OrderingVal);
2270 Args.push_back(Ordering2Val);
2274 ResultTy = Type::getInt1Ty(Ctx);
2275 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2276 }
else if (HasResult && UseSizedLibcall)
2277 ResultTy = SizedIntTy;
2279 ResultTy = Type::getVoidTy(Ctx);
2283 for (
Value *Arg : Args)
2285 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2286 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2294 if (ValueOperand && !UseSizedLibcall)
2300 Type *FinalResultTy =
I->getType();
2303 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2308 }
else if (HasResult) {
2310 if (UseSizedLibcall) {
2314 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2315 unsigned AS = PtrTy->getAddressSpace();
2317 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2326 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()
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)
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.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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.