59#define DEBUG_TYPE "atomic-expand"
63class AtomicExpandImpl {
89 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
90 template <
typename AtomicInst>
91 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
95 bool tryExpandAtomicLoad(
LoadInst *LI);
96 bool expandAtomicLoadToLL(
LoadInst *LI);
97 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
107 void expandAtomicOpToLLSC(
111 void expandPartwordAtomicRMW(
119 static Value *insertRMWCmpXchgLoop(
123 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
135 void expandAtomicLoadToLibcall(
LoadInst *LI);
136 void expandAtomicStoreToLibcall(
StoreInst *LI);
141 CreateCmpXchgInstFun CreateCmpXchg);
166struct ReplacementIRBuilder
167 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
177 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
178 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
179 this->setIsFPConstrained(
true);
181 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
186 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
192char AtomicExpandLegacy::ID = 0;
197 "Expand Atomic instructions",
false,
false)
206 return DL.getTypeStoreSize(LI->getType());
211 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
228 Source.getAllMetadata(MD);
232 for (
auto [
ID,
N] : MD) {
234 case LLVMContext::MD_dbg:
235 case LLVMContext::MD_tbaa:
236 case LLVMContext::MD_tbaa_struct:
237 case LLVMContext::MD_alias_scope:
238 case LLVMContext::MD_noalias:
239 case LLVMContext::MD_noalias_addrspace:
240 case LLVMContext::MD_access_group:
241 case LLVMContext::MD_mmra:
245 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
247 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
260template <
typename Inst>
263 Align Alignment =
I->getAlign();
264 return Alignment >=
Size &&
268bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(
Instruction *AtomicI) {
274 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
275 TrailingFence->moveAfter(AtomicI);
281template <
typename AtomicInst>
282bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
283 bool OrderingRequiresFence,
286 if (OrderingRequiresFence && ShouldInsertFences) {
288 AtomicI->setOrdering(NewOrdering);
289 return bracketInstWithFences(AtomicI, FenceOrdering);
291 if (!ShouldInsertFences)
292 return tryInsertTrailingSeqCstFence(AtomicI);
296bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
302 expandAtomicLoadToLibcall(LI);
306 bool MadeChange =
false;
308 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
309 LI = convertAtomicLoadToIntegerType(LI);
313 MadeChange |= tryInsertFencesForAtomic(
316 MadeChange |= tryExpandAtomicLoad(LI);
325 expandAtomicStoreToLibcall(SI);
329 bool MadeChange =
false;
331 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
332 SI = convertAtomicStoreToIntegerType(SI);
336 MadeChange |= tryInsertFencesForAtomic(
339 MadeChange |= tryExpandAtomicStore(SI);
345 expandAtomicRMWToLibcall(RMWI);
349 bool MadeChange =
false;
351 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
352 RMWI = convertAtomicXchgToIntegerType(RMWI);
356 MadeChange |= tryInsertFencesForAtomic(
366 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
367 tryExpandAtomicRMW(RMWI);
373 expandAtomicCASToLibcall(CASI);
379 bool MadeChange =
false;
380 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
383 CASI = convertCmpXchgToIntegerType(CASI);
389 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
400 CASI->setSuccessOrdering(CASOrdering);
401 CASI->setFailureOrdering(CASOrdering);
402 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
404 }
else if (CmpXchgExpansion !=
405 TargetLoweringBase::AtomicExpansionKind::LLSC) {
407 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
410 MadeChange |= tryExpandAtomicCmpXchg(CASI);
417bool AtomicExpandImpl::run(
418 Function &
F,
const LibcallLoweringModuleAnalysisResult &LibcallResult,
419 const TargetMachine *TM) {
421 if (!Subtarget->enableAtomicExpand())
423 TLI = Subtarget->getTargetLowering();
425 DL = &
F.getDataLayout();
427 bool MadeChange =
false;
439 if (processAtomicInstr(&Inst)) {
451bool AtomicExpandLegacy::runOnFunction(Function &
F) {
453 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
456 auto *TM = &TPC->getTM<TargetMachine>();
458 const LibcallLoweringModuleAnalysisResult &LibcallResult =
459 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
461 return AE.run(
F, LibcallResult, TM);
465 return new AtomicExpandLegacy();
475 if (!LibcallResult) {
477 "' analysis required");
483 bool Changed = AE.run(
F, *LibcallResult, TM);
490bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
492 ReplacementIRBuilder Builder(
I, *
DL);
502 return (LeadingFence || TrailingFence);
517LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
519 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
521 ReplacementIRBuilder Builder(LI, *
DL);
525 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
526 NewLI->setAlignment(LI->
getAlign());
529 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
531 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
538AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
543 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
545 ReplacementIRBuilder Builder(RMWI, *
DL);
550 ? Builder.CreatePtrToInt(Val, NewTy)
551 : Builder.CreateBitCast(Val, NewTy);
558 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
561 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
562 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
568bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
570 case TargetLoweringBase::AtomicExpansionKind::None:
572 case TargetLoweringBase::AtomicExpansionKind::LLSC:
573 expandAtomicOpToLLSC(
576 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
578 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
579 return expandAtomicLoadToLL(LI);
580 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
581 return expandAtomicLoadToCmpXchg(LI);
582 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
583 LI->
setAtomic(AtomicOrdering::NotAtomic);
585 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
593bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
595 case TargetLoweringBase::AtomicExpansionKind::None:
597 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
600 case TargetLoweringBase::AtomicExpansionKind::Expand:
601 expandAtomicStoreToXChg(SI);
603 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
604 SI->setAtomic(AtomicOrdering::NotAtomic);
611bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
612 ReplacementIRBuilder Builder(LI, *
DL);
627bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
628 ReplacementIRBuilder Builder(LI, *
DL);
630 if (Order == AtomicOrdering::Unordered)
631 Order = AtomicOrdering::Monotonic;
637 Value *Pair = Builder.CreateAtomicCmpXchg(
638 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
640 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
656StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
657 ReplacementIRBuilder Builder(SI, *
DL);
658 auto *
M =
SI->getModule();
659 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
661 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
663 Value *Addr =
SI->getPointerOperand();
665 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
669 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
670 SI->eraseFromParent();
674void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
681 ReplacementIRBuilder Builder(SI, *
DL);
683 assert(Ordering != AtomicOrdering::NotAtomic);
685 ? AtomicOrdering::Monotonic
687 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
689 SI->getAlign(), RMWOrdering);
690 SI->eraseFromParent();
693 tryExpandAtomicRMW(AI);
708 NewVal = Builder.CreateBitCast(NewVal, IntTy);
709 Loaded = Builder.CreateBitCast(Loaded, IntTy);
713 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
718 Success = Builder.CreateExtractValue(Pair, 1,
"success");
719 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
722 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
725bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
729 case TargetLoweringBase::AtomicExpansionKind::None:
731 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
734 if (ValueSize < MinCASSize) {
735 expandPartwordAtomicRMW(AI,
736 TargetLoweringBase::AtomicExpansionKind::LLSC);
738 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
747 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
750 if (ValueSize < MinCASSize) {
751 expandPartwordAtomicRMW(AI,
752 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
761 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
762 <<
"A compare and swap loop was generated for an atomic "
764 << MemScope <<
" memory scope";
770 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
773 if (ValueSize < MinCASSize) {
778 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
782 expandAtomicRMWToMaskedIntrinsic(AI);
785 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
789 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
793 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
795 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
805struct PartwordMaskValues {
807 Type *WordType =
nullptr;
809 Type *IntValueType =
nullptr;
810 Value *AlignedAddr =
nullptr;
811 Align AlignedAddrAlignment;
813 Value *ShiftAmt =
nullptr;
814 Value *Mask =
nullptr;
815 Value *Inv_Mask =
nullptr;
819raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
820 auto PrintObj = [&
O](
auto *
V) {
827 O <<
"PartwordMaskValues {\n";
829 PrintObj(PMV.WordType);
831 PrintObj(PMV.ValueType);
832 O <<
" AlignedAddr: ";
833 PrintObj(PMV.AlignedAddr);
834 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
836 PrintObj(PMV.ShiftAmt);
840 PrintObj(PMV.Inv_Mask);
866 unsigned MinWordSize) {
867 PartwordMaskValues PMV;
872 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
874 PMV.ValueType = PMV.IntValueType =
ValueType;
879 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
881 if (PMV.ValueType == PMV.WordType) {
882 PMV.AlignedAddr = Addr;
883 PMV.AlignedAddrAlignment = AddrAlign;
884 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
885 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
889 PMV.AlignedAddrAlignment =
Align(MinWordSize);
891 assert(ValueSize < MinWordSize);
894 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
897 if (AddrAlign < MinWordSize) {
898 PMV.AlignedAddr = Builder.CreateIntrinsic(
899 Intrinsic::ptrmask, {PtrTy, IntTy},
901 nullptr,
"AlignedAddr");
903 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
904 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
907 PMV.AlignedAddr = Addr;
911 if (
DL.isLittleEndian()) {
913 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
916 PMV.ShiftAmt = Builder.CreateShl(
917 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
920 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
921 PMV.Mask = Builder.CreateShl(
922 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
925 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
931 const PartwordMaskValues &PMV) {
932 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
933 if (PMV.WordType == PMV.ValueType)
936 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
937 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
938 return Builder.CreateBitCast(Trunc, PMV.ValueType);
942 Value *Updated,
const PartwordMaskValues &PMV) {
943 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
944 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
945 if (PMV.WordType == PMV.ValueType)
948 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
950 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
952 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
953 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
954 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
964 const PartwordMaskValues &PMV) {
970 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
971 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
983 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
984 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
985 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1024void AtomicExpandImpl::expandPartwordAtomicRMW(
1030 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1036 ReplacementIRBuilder Builder(AI, *
DL);
1038 PartwordMaskValues PMV =
1042 Value *ValOperand_Shifted =
nullptr;
1046 ValOperand_Shifted =
1047 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1048 "ValOperand_Shifted");
1051 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1057 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1058 OldResult = insertRMWCmpXchgLoop(
1059 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1062 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1063 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1064 PMV.AlignedAddrAlignment, MemOpOrder,
1074AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1075 ReplacementIRBuilder Builder(AI, *
DL);
1080 "Unable to widen operation");
1082 PartwordMaskValues PMV =
1086 Value *ValOperand_Shifted =
1088 PMV.ShiftAmt,
"ValOperand_Shifted");
1094 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1096 NewOperand = ValOperand_Shifted;
1099 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1110bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1152 ReplacementIRBuilder Builder(CI, *
DL);
1163 std::prev(BB->
end())->eraseFromParent();
1166 PartwordMaskValues PMV =
1171 Value *NewVal_Shifted =
1173 Value *Cmp_Shifted =
1178 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1180 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1185 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1186 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1189 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1190 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1192 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1220 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1235void AtomicExpandImpl::expandAtomicOpToLLSC(
1236 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1238 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1239 ReplacementIRBuilder Builder(
I, *
DL);
1240 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1241 MemOpOrder, PerformOp);
1243 I->replaceAllUsesWith(Loaded);
1244 I->eraseFromParent();
1247void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1248 ReplacementIRBuilder Builder(AI, *
DL);
1250 PartwordMaskValues PMV =
1260 CastOp = Instruction::SExt;
1264 PMV.ShiftAmt,
"ValOperand_Shifted");
1266 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1273void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1274 AtomicCmpXchgInst *CI) {
1275 ReplacementIRBuilder Builder(CI, *
DL);
1288 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1294 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1301Value *AtomicExpandImpl::insertRMWLLSCLoop(
1302 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1304 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1309 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1310 "Expected at least natural alignment at this point.");
1330 std::prev(BB->
end())->eraseFromParent();
1338 Value *NewVal = PerformOp(Builder, Loaded);
1340 Value *StoreSuccess =
1362AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1365 M->getDataLayout());
1367 ReplacementIRBuilder Builder(CI, *
DL);
1379 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1395bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1401 LLVMContext &Ctx =
F->getContext();
1408 ? AtomicOrdering::Monotonic
1420 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1421 SuccessOrder != AtomicOrdering::Monotonic &&
1422 SuccessOrder != AtomicOrdering::Acquire &&
1427 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1481 auto ReleasedLoadBB =
1485 auto ReleasingStoreBB =
1489 ReplacementIRBuilder Builder(CI, *
DL);
1494 std::prev(BB->
end())->eraseFromParent();
1496 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1499 PartwordMaskValues PMV =
1506 Value *UnreleasedLoad =
1507 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1508 Value *UnreleasedLoadExtract =
1515 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1516 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1519 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1524 PHINode *LoadedTryStore =
1525 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1526 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1527 Value *NewValueInsert =
1530 PMV.AlignedAddr, MemOpOrder);
1532 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1533 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1535 CI->
isWeak() ? FailureBB : RetryBB,
1536 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1540 if (HasReleasedLoadBB) {
1542 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1550 ShouldStore, TryStoreBB, NoStoreBB,
1551 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1553 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1560 if (ShouldInsertFencesForAtomic ||
1566 PHINode *LoadedNoStore =
1568 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1569 if (HasReleasedLoadBB)
1570 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1579 PHINode *LoadedFailure =
1581 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1583 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1584 if (ShouldInsertFencesForAtomic)
1593 PHINode *LoadedExit =
1595 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1596 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1603 Value *LoadedFull = LoadedExit;
1611 for (
auto *User : CI->
users()) {
1617 "weird extraction from { iN, i1 }");
1628 for (
auto *EV : PrunedInsts)
1645bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1658 return C->isMinusOne();
1660 return C->isMaxValue(
true);
1662 return C->isMinValue(
true);
1664 return C->isMaxValue(
false);
1666 return C->isMinValue(
false);
1672bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1674 tryExpandAtomicLoad(ResultingLoad);
1680Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1681 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1683 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1684 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1711 std::prev(BB->
end())->eraseFromParent();
1722 Loaded->addIncoming(InitLoaded, BB);
1724 Value *NewVal = PerformOp(Builder, Loaded);
1726 Value *NewLoaded =
nullptr;
1729 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1730 MemOpOrder == AtomicOrdering::Unordered
1731 ? AtomicOrdering::Monotonic
1733 SSID,
Success, NewLoaded, MetadataSrc);
1736 Loaded->addIncoming(NewLoaded, LoopBB);
1749bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1756 case TargetLoweringBase::AtomicExpansionKind::None:
1757 if (ValueSize < MinCASSize)
1758 return expandPartwordCmpXchg(CI);
1760 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1761 return expandAtomicCmpXchg(CI);
1763 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1764 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1766 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1768 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1775bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1776 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1783 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1786 [&](IRBuilderBase &Builder,
Value *Loaded) {
1787 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1788 AI->getValOperand());
1811 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1812 return Alignment >=
Size &&
1814 Size <= LargestSize;
1817void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1818 static const RTLIB::Libcall Libcalls[6] = {
1819 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1820 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1823 bool expanded = expandAtomicOpToLibcall(
1824 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1825 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1827 handleFailure(*
I,
"unsupported atomic load");
1830void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1831 static const RTLIB::Libcall Libcalls[6] = {
1832 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1833 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1836 bool expanded = expandAtomicOpToLibcall(
1837 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1838 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1840 handleFailure(*
I,
"unsupported atomic store");
1843void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1844 static const RTLIB::Libcall Libcalls[6] = {
1845 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1846 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1847 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1850 bool expanded = expandAtomicOpToLibcall(
1851 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1852 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1855 handleFailure(*
I,
"unsupported cmpxchg");
1859 static const RTLIB::Libcall LibcallsXchg[6] = {
1860 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1861 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1862 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1863 static const RTLIB::Libcall LibcallsAdd[6] = {
1864 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1865 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1866 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1867 static const RTLIB::Libcall LibcallsSub[6] = {
1868 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1869 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1870 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1871 static const RTLIB::Libcall LibcallsAnd[6] = {
1872 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1873 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1874 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1875 static const RTLIB::Libcall LibcallsOr[6] = {
1876 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1877 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1878 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1879 static const RTLIB::Libcall LibcallsXor[6] = {
1880 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1881 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1882 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1883 static const RTLIB::Libcall LibcallsNand[6] = {
1884 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1885 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1886 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1927void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1933 if (!Libcalls.
empty())
1934 Success = expandAtomicOpToLibcall(
1935 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1936 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1943 expandAtomicRMWToCmpXchg(
1944 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1947 Instruction *MetadataSrc) {
1950 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1959 expandAtomicCASToLibcall(Pair);
1970bool AtomicExpandImpl::expandAtomicOpToLibcall(
1971 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1976 LLVMContext &Ctx =
I->getContext();
1978 const DataLayout &
DL =
M->getDataLayout();
1980 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1983 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1985 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
1995 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1999 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2001 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2004 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2006 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2008 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2010 RTLIB::Libcall RTLibType;
2011 if (UseSizedLibcall) {
2014 RTLibType = Libcalls[1];
2017 RTLibType = Libcalls[2];
2020 RTLibType = Libcalls[3];
2023 RTLibType = Libcalls[4];
2026 RTLibType = Libcalls[5];
2029 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2030 RTLibType = Libcalls[0];
2037 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2038 if (LibcallImpl == RTLIB::Unsupported) {
2069 AllocaInst *AllocaCASExpected =
nullptr;
2070 AllocaInst *AllocaValue =
nullptr;
2071 AllocaInst *AllocaResult =
nullptr;
2078 if (!UseSizedLibcall) {
2080 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2088 Value *PtrVal = PointerOperand;
2090 Args.push_back(PtrVal);
2094 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2098 Args.push_back(AllocaCASExpected);
2103 if (UseSizedLibcall) {
2106 Args.push_back(IntValue);
2108 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2112 Args.push_back(AllocaValue);
2117 if (!CASExpected && HasResult && !UseSizedLibcall) {
2118 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2121 Args.push_back(AllocaResult);
2125 Args.push_back(OrderingVal);
2129 Args.push_back(Ordering2Val);
2133 ResultTy = Type::getInt1Ty(Ctx);
2134 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2135 }
else if (HasResult && UseSizedLibcall)
2136 ResultTy = SizedIntTy;
2138 ResultTy = Type::getVoidTy(Ctx);
2142 for (
Value *Arg : Args)
2144 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2145 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2153 if (ValueOperand && !UseSizedLibcall)
2159 Type *FinalResultTy =
I->getType();
2162 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2167 }
else if (HasResult) {
2169 if (UseSizedLibcall)
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 *Shifted_Inc, 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 Value * extractMaskedValue(IRBuilderBase &Builder, Value *WideWord, const PartwordMaskValues &PMV)
static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, Value *&Success, Value *&NewLoaded, Instruction *MetadataSrc)
Expand Atomic static false unsigned getAtomicOpSize(LoadInst *LI)
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< 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 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()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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.
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.
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.
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
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.
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)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
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)
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
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.
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.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
Record a mapping from subtarget to LibcallLoweringInfo.
const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const
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.
Align getAlign() const
Return the alignment of the access that is being performed.
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.
void setVolatile(bool V)
Specify whether this is a volatile store or not.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
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.
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.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
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.
iterator_range< user_iterator > users()
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
#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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
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.
bool isReleaseOrStronger(AtomicOrdering AO)
AtomicOrderingCABI toCABI(AtomicOrdering AO)
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...
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 >
FunctionAddr VTableAddr Next
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
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.
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
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.