60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
84 bool tryExpandAtomicLoad(
LoadInst *LI);
85 bool expandAtomicLoadToLL(
LoadInst *LI);
86 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
96 void expandAtomicOpToLLSC(
100 void expandPartwordAtomicRMW(
108 static Value *insertRMWCmpXchgLoop(
124 void expandAtomicLoadToLibcall(
LoadInst *LI);
125 void expandAtomicStoreToLibcall(
StoreInst *LI);
156struct ReplacementIRBuilder
157 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
167 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
168 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
169 this->setIsFPConstrained(
true);
171 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
176 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
182char AtomicExpandLegacy::ID = 0;
187 "Expand Atomic instructions",
false,
false)
196 return DL.getTypeStoreSize(LI->getType());
201 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
218 Source.getAllMetadata(MD);
222 for (
auto [
ID,
N] : MD) {
224 case LLVMContext::MD_dbg:
225 case LLVMContext::MD_tbaa:
226 case LLVMContext::MD_tbaa_struct:
227 case LLVMContext::MD_alias_scope:
228 case LLVMContext::MD_noalias:
229 case LLVMContext::MD_noalias_addrspace:
230 case LLVMContext::MD_access_group:
231 case LLVMContext::MD_mmra:
235 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
237 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
250template <
typename Inst>
253 Align Alignment =
I->getAlign();
254 return Alignment >=
Size &&
258bool AtomicExpandImpl::processAtomicInstr(
Instruction *
I) {
264 bool MadeChange =
false;
272 expandAtomicLoadToLibcall(LI);
277 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
278 I = LI = convertAtomicLoadToIntegerType(LI);
286 expandAtomicStoreToLibcall(SI);
291 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
292 I =
SI = convertAtomicStoreToIntegerType(SI);
297 expandAtomicRMWToLibcall(RMWI);
302 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
303 I = RMWI = convertAtomicXchgToIntegerType(RMWI);
308 expandAtomicCASToLibcall(CASI);
314 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
317 I = CASI = convertCmpXchgToIntegerType(CASI);
324 auto FenceOrdering = AtomicOrdering::Monotonic;
326 FenceOrdering = LI->getOrdering();
327 LI->setOrdering(AtomicOrdering::Monotonic);
329 FenceOrdering =
SI->getOrdering();
330 SI->setOrdering(AtomicOrdering::Monotonic);
333 FenceOrdering = RMWI->getOrdering();
334 RMWI->setOrdering(AtomicOrdering::Monotonic);
337 TargetLoweringBase::AtomicExpansionKind::None &&
345 FenceOrdering = CASI->getMergedOrdering();
348 CASI->setSuccessOrdering(CASOrdering);
349 CASI->setFailureOrdering(CASOrdering);
352 if (FenceOrdering != AtomicOrdering::Monotonic) {
353 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
357 TargetLoweringBase::AtomicExpansionKind::LLSC)) {
361 Builder,
I, AtomicOrdering::SequentiallyConsistent)) {
362 TrailingFence->moveAfter(
I);
368 MadeChange |= tryExpandAtomicLoad(LI);
370 MadeChange |= tryExpandAtomicStore(SI);
381 MadeChange |= tryExpandAtomicRMW(RMWI);
384 MadeChange |= tryExpandAtomicCmpXchg(CASI);
389bool AtomicExpandImpl::run(
390 Function &
F,
const LibcallLoweringModuleAnalysisResult &LibcallResult,
391 const TargetMachine *TM) {
393 if (!Subtarget->enableAtomicExpand())
395 TLI = Subtarget->getTargetLowering();
397 DL = &
F.getDataLayout();
399 bool MadeChange =
false;
411 if (processAtomicInstr(&Inst)) {
423bool AtomicExpandLegacy::runOnFunction(Function &
F) {
425 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
428 auto *TM = &TPC->getTM<TargetMachine>();
430 const LibcallLoweringModuleAnalysisResult &LibcallResult =
431 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
433 return AE.run(
F, LibcallResult, TM);
437 return new AtomicExpandLegacy();
447 if (!LibcallResult) {
449 "' analysis required");
455 bool Changed = AE.run(
F, *LibcallResult, TM);
462bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
464 ReplacementIRBuilder Builder(
I, *
DL);
474 return (LeadingFence || TrailingFence);
489LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
491 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
493 ReplacementIRBuilder Builder(LI, *
DL);
497 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
498 NewLI->setAlignment(LI->
getAlign());
501 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
503 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
510AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
515 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
517 ReplacementIRBuilder Builder(RMWI, *
DL);
522 ? Builder.CreatePtrToInt(Val, NewTy)
523 : Builder.CreateBitCast(Val, NewTy);
530 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
533 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
534 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
540bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
542 case TargetLoweringBase::AtomicExpansionKind::None:
544 case TargetLoweringBase::AtomicExpansionKind::LLSC:
545 expandAtomicOpToLLSC(
548 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
550 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
551 return expandAtomicLoadToLL(LI);
552 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
553 return expandAtomicLoadToCmpXchg(LI);
554 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
555 LI->
setAtomic(AtomicOrdering::NotAtomic);
557 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
565bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
567 case TargetLoweringBase::AtomicExpansionKind::None:
569 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
572 case TargetLoweringBase::AtomicExpansionKind::Expand:
573 expandAtomicStoreToXChg(SI);
575 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
576 SI->setAtomic(AtomicOrdering::NotAtomic);
583bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
584 ReplacementIRBuilder Builder(LI, *
DL);
599bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
600 ReplacementIRBuilder Builder(LI, *
DL);
602 if (Order == AtomicOrdering::Unordered)
603 Order = AtomicOrdering::Monotonic;
609 Value *Pair = Builder.CreateAtomicCmpXchg(
610 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
612 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
628StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
629 ReplacementIRBuilder Builder(SI, *
DL);
630 auto *
M =
SI->getModule();
631 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
633 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
635 Value *Addr =
SI->getPointerOperand();
637 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
641 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
642 SI->eraseFromParent();
646void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
653 ReplacementIRBuilder Builder(SI, *
DL);
655 assert(Ordering != AtomicOrdering::NotAtomic);
657 ? AtomicOrdering::Monotonic
659 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
661 SI->getAlign(), RMWOrdering);
662 SI->eraseFromParent();
665 tryExpandAtomicRMW(AI);
680 NewVal = Builder.CreateBitCast(NewVal, IntTy);
681 Loaded = Builder.CreateBitCast(Loaded, IntTy);
685 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
690 Success = Builder.CreateExtractValue(Pair, 1,
"success");
691 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
694 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
697bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
701 case TargetLoweringBase::AtomicExpansionKind::None:
703 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
706 if (ValueSize < MinCASSize) {
707 expandPartwordAtomicRMW(AI,
708 TargetLoweringBase::AtomicExpansionKind::LLSC);
710 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
719 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
722 if (ValueSize < MinCASSize) {
723 expandPartwordAtomicRMW(AI,
724 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
733 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
734 <<
"A compare and swap loop was generated for an atomic "
736 << MemScope <<
" memory scope";
742 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
745 if (ValueSize < MinCASSize) {
750 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
754 expandAtomicRMWToMaskedIntrinsic(AI);
757 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
761 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
765 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
767 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
777struct PartwordMaskValues {
779 Type *WordType =
nullptr;
781 Type *IntValueType =
nullptr;
782 Value *AlignedAddr =
nullptr;
783 Align AlignedAddrAlignment;
785 Value *ShiftAmt =
nullptr;
786 Value *Mask =
nullptr;
787 Value *Inv_Mask =
nullptr;
791raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
792 auto PrintObj = [&
O](
auto *
V) {
799 O <<
"PartwordMaskValues {\n";
801 PrintObj(PMV.WordType);
803 PrintObj(PMV.ValueType);
804 O <<
" AlignedAddr: ";
805 PrintObj(PMV.AlignedAddr);
806 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
808 PrintObj(PMV.ShiftAmt);
812 PrintObj(PMV.Inv_Mask);
838 unsigned MinWordSize) {
839 PartwordMaskValues PMV;
844 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
846 PMV.ValueType = PMV.IntValueType =
ValueType;
851 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
853 if (PMV.ValueType == PMV.WordType) {
854 PMV.AlignedAddr = Addr;
855 PMV.AlignedAddrAlignment = AddrAlign;
856 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
857 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
861 PMV.AlignedAddrAlignment =
Align(MinWordSize);
863 assert(ValueSize < MinWordSize);
866 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
869 if (AddrAlign < MinWordSize) {
870 PMV.AlignedAddr = Builder.CreateIntrinsic(
871 Intrinsic::ptrmask, {PtrTy, IntTy},
873 nullptr,
"AlignedAddr");
875 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
876 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
879 PMV.AlignedAddr = Addr;
883 if (
DL.isLittleEndian()) {
885 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
888 PMV.ShiftAmt = Builder.CreateShl(
889 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
892 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
893 PMV.Mask = Builder.CreateShl(
894 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
897 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
903 const PartwordMaskValues &PMV) {
904 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
905 if (PMV.WordType == PMV.ValueType)
908 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
909 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
910 return Builder.CreateBitCast(Trunc, PMV.ValueType);
914 Value *Updated,
const PartwordMaskValues &PMV) {
915 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
916 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
917 if (PMV.WordType == PMV.ValueType)
920 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
922 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
924 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
925 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
926 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
936 const PartwordMaskValues &PMV) {
942 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
943 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
955 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
956 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
957 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
994void AtomicExpandImpl::expandPartwordAtomicRMW(
1000 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1006 ReplacementIRBuilder Builder(AI, *
DL);
1008 PartwordMaskValues PMV =
1012 Value *ValOperand_Shifted =
nullptr;
1016 ValOperand_Shifted =
1017 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1018 "ValOperand_Shifted");
1021 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1027 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1028 OldResult = insertRMWCmpXchgLoop(
1029 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1032 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1033 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1034 PMV.AlignedAddrAlignment, MemOpOrder,
1044AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1045 ReplacementIRBuilder Builder(AI, *
DL);
1050 "Unable to widen operation");
1052 PartwordMaskValues PMV =
1056 Value *ValOperand_Shifted =
1058 PMV.ShiftAmt,
"ValOperand_Shifted");
1064 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1066 NewOperand = ValOperand_Shifted;
1069 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1080bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1122 ReplacementIRBuilder Builder(CI, *
DL);
1133 std::prev(BB->
end())->eraseFromParent();
1136 PartwordMaskValues PMV =
1141 Value *NewVal_Shifted =
1143 Value *Cmp_Shifted =
1148 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1150 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1155 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1156 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1159 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1160 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1162 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1190 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1205void AtomicExpandImpl::expandAtomicOpToLLSC(
1206 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1208 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1209 ReplacementIRBuilder Builder(
I, *
DL);
1210 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1211 MemOpOrder, PerformOp);
1213 I->replaceAllUsesWith(Loaded);
1214 I->eraseFromParent();
1217void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1218 ReplacementIRBuilder Builder(AI, *
DL);
1220 PartwordMaskValues PMV =
1230 CastOp = Instruction::SExt;
1234 PMV.ShiftAmt,
"ValOperand_Shifted");
1236 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1243void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1244 AtomicCmpXchgInst *CI) {
1245 ReplacementIRBuilder Builder(CI, *
DL);
1258 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1264 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1271Value *AtomicExpandImpl::insertRMWLLSCLoop(
1272 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1274 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1279 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1280 "Expected at least natural alignment at this point.");
1300 std::prev(BB->
end())->eraseFromParent();
1308 Value *NewVal = PerformOp(Builder, Loaded);
1310 Value *StoreSuccess =
1332AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1335 M->getDataLayout());
1337 ReplacementIRBuilder Builder(CI, *
DL);
1349 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1365bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1371 LLVMContext &Ctx =
F->getContext();
1378 ? AtomicOrdering::Monotonic
1390 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1391 SuccessOrder != AtomicOrdering::Monotonic &&
1392 SuccessOrder != AtomicOrdering::Acquire &&
1397 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1451 auto ReleasedLoadBB =
1455 auto ReleasingStoreBB =
1459 ReplacementIRBuilder Builder(CI, *
DL);
1464 std::prev(BB->
end())->eraseFromParent();
1466 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1469 PartwordMaskValues PMV =
1476 Value *UnreleasedLoad =
1477 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1478 Value *UnreleasedLoadExtract =
1485 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1486 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1489 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1494 PHINode *LoadedTryStore =
1495 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1496 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1497 Value *NewValueInsert =
1500 PMV.AlignedAddr, MemOpOrder);
1502 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1503 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1505 CI->
isWeak() ? FailureBB : RetryBB,
1506 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1510 if (HasReleasedLoadBB) {
1512 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1520 ShouldStore, TryStoreBB, NoStoreBB,
1521 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1523 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1530 if (ShouldInsertFencesForAtomic ||
1536 PHINode *LoadedNoStore =
1538 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1539 if (HasReleasedLoadBB)
1540 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1549 PHINode *LoadedFailure =
1551 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1553 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1554 if (ShouldInsertFencesForAtomic)
1563 PHINode *LoadedExit =
1565 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1566 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1573 Value *LoadedFull = LoadedExit;
1581 for (
auto *User : CI->
users()) {
1587 "weird extraction from { iN, i1 }");
1598 for (
auto *EV : PrunedInsts)
1615bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1628 return C->isMinusOne();
1630 return C->isMaxValue(
true);
1632 return C->isMinValue(
true);
1634 return C->isMaxValue(
false);
1636 return C->isMinValue(
false);
1642bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1644 tryExpandAtomicLoad(ResultingLoad);
1650Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1651 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1653 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1681 std::prev(BB->
end())->eraseFromParent();
1689 Loaded->addIncoming(InitLoaded, BB);
1691 Value *NewVal = PerformOp(Builder, Loaded);
1693 Value *NewLoaded =
nullptr;
1696 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1697 MemOpOrder == AtomicOrdering::Unordered
1698 ? AtomicOrdering::Monotonic
1700 SSID,
Success, NewLoaded, MetadataSrc);
1703 Loaded->addIncoming(NewLoaded, LoopBB);
1716bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1723 case TargetLoweringBase::AtomicExpansionKind::None:
1724 if (ValueSize < MinCASSize)
1725 return expandPartwordCmpXchg(CI);
1727 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1728 return expandAtomicCmpXchg(CI);
1730 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1731 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1733 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1735 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1746 Builder.setIsFPConstrained(
1751 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1755 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1756 AI->getValOperand());
1779 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1780 return Alignment >=
Size &&
1782 Size <= LargestSize;
1785void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1786 static const RTLIB::Libcall Libcalls[6] = {
1787 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1788 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1791 bool expanded = expandAtomicOpToLibcall(
1792 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1793 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1795 handleFailure(*
I,
"unsupported atomic load");
1798void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1799 static const RTLIB::Libcall Libcalls[6] = {
1800 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1801 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1804 bool expanded = expandAtomicOpToLibcall(
1805 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1806 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1808 handleFailure(*
I,
"unsupported atomic store");
1811void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1812 static const RTLIB::Libcall Libcalls[6] = {
1813 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1814 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1815 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1818 bool expanded = expandAtomicOpToLibcall(
1819 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1820 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1823 handleFailure(*
I,
"unsupported cmpxchg");
1827 static const RTLIB::Libcall LibcallsXchg[6] = {
1828 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1829 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1830 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1831 static const RTLIB::Libcall LibcallsAdd[6] = {
1832 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1833 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1834 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1835 static const RTLIB::Libcall LibcallsSub[6] = {
1836 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1837 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1838 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1839 static const RTLIB::Libcall LibcallsAnd[6] = {
1840 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1841 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1842 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1843 static const RTLIB::Libcall LibcallsOr[6] = {
1844 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1845 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1846 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1847 static const RTLIB::Libcall LibcallsXor[6] = {
1848 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1849 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1850 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1851 static const RTLIB::Libcall LibcallsNand[6] = {
1852 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1853 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1854 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1893void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1899 if (!Libcalls.
empty())
1900 Success = expandAtomicOpToLibcall(
1901 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1902 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1910 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1913 Instruction *MetadataSrc) {
1916 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1925 expandAtomicCASToLibcall(Pair);
1936bool AtomicExpandImpl::expandAtomicOpToLibcall(
1937 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1942 LLVMContext &Ctx =
I->getContext();
1944 const DataLayout &
DL =
M->getDataLayout();
1946 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1949 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1951 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1955 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1957 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1960 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1962 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1964 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1966 RTLIB::Libcall RTLibType;
1967 if (UseSizedLibcall) {
1970 RTLibType = Libcalls[1];
1973 RTLibType = Libcalls[2];
1976 RTLibType = Libcalls[3];
1979 RTLibType = Libcalls[4];
1982 RTLibType = Libcalls[5];
1985 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1986 RTLibType = Libcalls[0];
1993 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
1994 if (LibcallImpl == RTLIB::Unsupported) {
2025 AllocaInst *AllocaCASExpected =
nullptr;
2026 AllocaInst *AllocaValue =
nullptr;
2027 AllocaInst *AllocaResult =
nullptr;
2034 if (!UseSizedLibcall) {
2036 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2044 Value *PtrVal = PointerOperand;
2046 Args.push_back(PtrVal);
2050 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2054 Args.push_back(AllocaCASExpected);
2059 if (UseSizedLibcall) {
2062 Args.push_back(IntValue);
2064 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2068 Args.push_back(AllocaValue);
2073 if (!CASExpected && HasResult && !UseSizedLibcall) {
2074 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2077 Args.push_back(AllocaResult);
2081 Args.push_back(OrderingVal);
2085 Args.push_back(Ordering2Val);
2089 ResultTy = Type::getInt1Ty(Ctx);
2090 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2091 }
else if (HasResult && UseSizedLibcall)
2092 ResultTy = SizedIntTy;
2094 ResultTy = Type::getVoidTy(Ctx);
2098 for (
Value *Arg : Args)
2100 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2101 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2109 if (ValueOperand && !UseSizedLibcall)
2115 Type *FinalResultTy =
I->getType();
2118 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2123 }
else if (HasResult) {
2125 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
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
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.
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
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.
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)
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="")
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="")
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
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)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
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.
function_ref< void( IRBuilderBase &, Value *, Value *, Value *, Align, AtomicOrdering, SyncScope::ID, Value *&, Value *&, Instruction *)> CreateCmpXchgInstFun
Parameters (see the expansion example below): (the builder, addr, loaded, new_val,...
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 >
bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg)
Expand an atomic RMW instruction into a loop utilizing cmpxchg.
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.