60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
83 bool tryExpandAtomicLoad(
LoadInst *LI);
84 bool expandAtomicLoadToLL(
LoadInst *LI);
85 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
95 void expandAtomicOpToLLSC(
99 void expandPartwordAtomicRMW(
107 static Value *insertRMWCmpXchgLoop(
123 void expandAtomicLoadToLibcall(
LoadInst *LI);
124 void expandAtomicStoreToLibcall(
StoreInst *LI);
150struct ReplacementIRBuilder
151 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
161 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
162 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
163 this->setIsFPConstrained(
true);
165 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
170 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
176char AtomicExpandLegacy::ID = 0;
181 "Expand Atomic instructions",
false,
false)
189 return DL.getTypeStoreSize(LI->getType());
194 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
211 Source.getAllMetadata(MD);
215 for (
auto [
ID,
N] : MD) {
217 case LLVMContext::MD_dbg:
218 case LLVMContext::MD_tbaa:
219 case LLVMContext::MD_tbaa_struct:
220 case LLVMContext::MD_alias_scope:
221 case LLVMContext::MD_noalias:
222 case LLVMContext::MD_noalias_addrspace:
223 case LLVMContext::MD_access_group:
224 case LLVMContext::MD_mmra:
228 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
230 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
243template <
typename Inst>
246 Align Alignment =
I->getAlign();
247 return Alignment >=
Size &&
251bool AtomicExpandImpl::processAtomicInstr(
Instruction *
I) {
257 bool MadeChange =
false;
265 expandAtomicLoadToLibcall(LI);
270 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
271 I = LI = convertAtomicLoadToIntegerType(LI);
279 expandAtomicStoreToLibcall(SI);
284 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
285 I =
SI = convertAtomicStoreToIntegerType(SI);
290 expandAtomicRMWToLibcall(RMWI);
295 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
296 I = RMWI = convertAtomicXchgToIntegerType(RMWI);
301 expandAtomicCASToLibcall(CASI);
307 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
310 I = CASI = convertCmpXchgToIntegerType(CASI);
317 auto FenceOrdering = AtomicOrdering::Monotonic;
319 FenceOrdering = LI->getOrdering();
320 LI->setOrdering(AtomicOrdering::Monotonic);
322 FenceOrdering =
SI->getOrdering();
323 SI->setOrdering(AtomicOrdering::Monotonic);
326 FenceOrdering = RMWI->getOrdering();
327 RMWI->setOrdering(AtomicOrdering::Monotonic);
330 TargetLoweringBase::AtomicExpansionKind::None &&
338 FenceOrdering = CASI->getMergedOrdering();
341 CASI->setSuccessOrdering(CASOrdering);
342 CASI->setFailureOrdering(CASOrdering);
345 if (FenceOrdering != AtomicOrdering::Monotonic) {
346 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
350 TargetLoweringBase::AtomicExpansionKind::LLSC)) {
354 Builder,
I, AtomicOrdering::SequentiallyConsistent)) {
355 TrailingFence->moveAfter(
I);
361 MadeChange |= tryExpandAtomicLoad(LI);
363 MadeChange |= tryExpandAtomicStore(SI);
374 MadeChange |= tryExpandAtomicRMW(RMWI);
377 MadeChange |= tryExpandAtomicCmpXchg(CASI);
382bool AtomicExpandImpl::run(Function &
F,
const TargetMachine *TM) {
384 if (!Subtarget->enableAtomicExpand())
386 TLI = Subtarget->getTargetLowering();
387 DL = &
F.getDataLayout();
389 bool MadeChange =
false;
401 if (processAtomicInstr(&Inst)) {
413bool AtomicExpandLegacy::runOnFunction(Function &
F) {
415 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
418 auto *TM = &TPC->getTM<TargetMachine>();
420 return AE.run(
F, TM);
424 return new AtomicExpandLegacy();
438bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
440 ReplacementIRBuilder Builder(
I, *
DL);
450 return (LeadingFence || TrailingFence);
465LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
467 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
469 ReplacementIRBuilder Builder(LI, *
DL);
473 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
474 NewLI->setAlignment(LI->
getAlign());
477 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
479 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
486AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
491 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
493 ReplacementIRBuilder Builder(RMWI, *
DL);
498 ? Builder.CreatePtrToInt(Val, NewTy)
499 : Builder.CreateBitCast(Val, NewTy);
506 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
509 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
510 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
516bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
518 case TargetLoweringBase::AtomicExpansionKind::None:
520 case TargetLoweringBase::AtomicExpansionKind::LLSC:
521 expandAtomicOpToLLSC(
524 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
526 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
527 return expandAtomicLoadToLL(LI);
528 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
529 return expandAtomicLoadToCmpXchg(LI);
530 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
531 LI->
setAtomic(AtomicOrdering::NotAtomic);
533 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
541bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
543 case TargetLoweringBase::AtomicExpansionKind::None:
545 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
548 case TargetLoweringBase::AtomicExpansionKind::Expand:
549 expandAtomicStoreToXChg(SI);
551 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
552 SI->setAtomic(AtomicOrdering::NotAtomic);
559bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
560 ReplacementIRBuilder Builder(LI, *
DL);
575bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
576 ReplacementIRBuilder Builder(LI, *
DL);
578 if (Order == AtomicOrdering::Unordered)
579 Order = AtomicOrdering::Monotonic;
585 Value *Pair = Builder.CreateAtomicCmpXchg(
586 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
588 Value *Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
604StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
605 ReplacementIRBuilder Builder(SI, *
DL);
606 auto *
M =
SI->getModule();
607 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
609 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
611 Value *Addr =
SI->getPointerOperand();
613 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
617 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
618 SI->eraseFromParent();
622void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
629 ReplacementIRBuilder Builder(SI, *
DL);
631 assert(Ordering != AtomicOrdering::NotAtomic);
633 ? AtomicOrdering::Monotonic
635 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
637 SI->getAlign(), RMWOrdering);
638 SI->eraseFromParent();
641 tryExpandAtomicRMW(AI);
656 NewVal = Builder.CreateBitCast(NewVal, IntTy);
657 Loaded = Builder.CreateBitCast(Loaded, IntTy);
661 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
666 Success = Builder.CreateExtractValue(Pair, 1,
"success");
667 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
670 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
673bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
677 case TargetLoweringBase::AtomicExpansionKind::None:
679 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
682 if (ValueSize < MinCASSize) {
683 expandPartwordAtomicRMW(AI,
684 TargetLoweringBase::AtomicExpansionKind::LLSC);
686 auto PerformOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
695 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
698 if (ValueSize < MinCASSize) {
699 expandPartwordAtomicRMW(AI,
700 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
709 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
710 <<
"A compare and swap loop was generated for an atomic "
712 << MemScope <<
" memory scope";
718 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
721 if (ValueSize < MinCASSize) {
726 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
730 expandAtomicRMWToMaskedIntrinsic(AI);
733 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
737 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
741 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
743 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
753struct PartwordMaskValues {
755 Type *WordType =
nullptr;
757 Type *IntValueType =
nullptr;
758 Value *AlignedAddr =
nullptr;
759 Align AlignedAddrAlignment;
761 Value *ShiftAmt =
nullptr;
762 Value *Mask =
nullptr;
763 Value *Inv_Mask =
nullptr;
767raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
768 auto PrintObj = [&
O](
auto *
V) {
775 O <<
"PartwordMaskValues {\n";
777 PrintObj(PMV.WordType);
779 PrintObj(PMV.ValueType);
780 O <<
" AlignedAddr: ";
781 PrintObj(PMV.AlignedAddr);
782 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
784 PrintObj(PMV.ShiftAmt);
788 PrintObj(PMV.Inv_Mask);
814 unsigned MinWordSize) {
815 PartwordMaskValues PMV;
820 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
822 PMV.ValueType = PMV.IntValueType =
ValueType;
827 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
829 if (PMV.ValueType == PMV.WordType) {
830 PMV.AlignedAddr = Addr;
831 PMV.AlignedAddrAlignment = AddrAlign;
832 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
833 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
837 PMV.AlignedAddrAlignment =
Align(MinWordSize);
839 assert(ValueSize < MinWordSize);
842 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
845 if (AddrAlign < MinWordSize) {
846 PMV.AlignedAddr = Builder.CreateIntrinsic(
847 Intrinsic::ptrmask, {PtrTy, IntTy},
849 nullptr,
"AlignedAddr");
851 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
852 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
855 PMV.AlignedAddr = Addr;
859 if (
DL.isLittleEndian()) {
861 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
864 PMV.ShiftAmt = Builder.CreateShl(
865 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
868 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
869 PMV.Mask = Builder.CreateShl(
870 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
873 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
879 const PartwordMaskValues &PMV) {
880 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
881 if (PMV.WordType == PMV.ValueType)
884 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
885 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
886 return Builder.CreateBitCast(Trunc, PMV.ValueType);
890 Value *Updated,
const PartwordMaskValues &PMV) {
891 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
892 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
893 if (PMV.WordType == PMV.ValueType)
896 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
898 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
900 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
901 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
902 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
912 const PartwordMaskValues &PMV) {
918 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
919 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
931 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
932 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
933 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
970void AtomicExpandImpl::expandPartwordAtomicRMW(
976 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
982 ReplacementIRBuilder Builder(AI, *
DL);
984 PartwordMaskValues PMV =
988 Value *ValOperand_Shifted =
nullptr;
993 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
994 "ValOperand_Shifted");
997 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
1003 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1004 OldResult = insertRMWCmpXchgLoop(
1005 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1008 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1009 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1010 PMV.AlignedAddrAlignment, MemOpOrder,
1020AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1021 ReplacementIRBuilder Builder(AI, *
DL);
1026 "Unable to widen operation");
1028 PartwordMaskValues PMV =
1032 Value *ValOperand_Shifted =
1034 PMV.ShiftAmt,
"ValOperand_Shifted");
1040 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1042 NewOperand = ValOperand_Shifted;
1045 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1056bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1098 ReplacementIRBuilder Builder(CI, *
DL);
1109 std::prev(BB->
end())->eraseFromParent();
1112 PartwordMaskValues PMV =
1117 Value *NewVal_Shifted =
1119 Value *Cmp_Shifted =
1124 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1126 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1131 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1132 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1135 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1136 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1138 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1166 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1181void AtomicExpandImpl::expandAtomicOpToLLSC(
1182 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1184 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1185 ReplacementIRBuilder Builder(
I, *
DL);
1186 Value *Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1187 MemOpOrder, PerformOp);
1189 I->replaceAllUsesWith(Loaded);
1190 I->eraseFromParent();
1193void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1194 ReplacementIRBuilder Builder(AI, *
DL);
1196 PartwordMaskValues PMV =
1206 CastOp = Instruction::SExt;
1210 PMV.ShiftAmt,
"ValOperand_Shifted");
1212 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1219void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1220 AtomicCmpXchgInst *CI) {
1221 ReplacementIRBuilder Builder(CI, *
DL);
1234 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1240 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1247Value *AtomicExpandImpl::insertRMWLLSCLoop(
1248 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1250 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1255 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1256 "Expected at least natural alignment at this point.");
1276 std::prev(BB->
end())->eraseFromParent();
1284 Value *NewVal = PerformOp(Builder, Loaded);
1286 Value *StoreSuccess =
1308AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1311 M->getDataLayout());
1313 ReplacementIRBuilder Builder(CI, *
DL);
1325 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1341bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1347 LLVMContext &Ctx =
F->getContext();
1354 ? AtomicOrdering::Monotonic
1366 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1367 SuccessOrder != AtomicOrdering::Monotonic &&
1368 SuccessOrder != AtomicOrdering::Acquire &&
1373 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1427 auto ReleasedLoadBB =
1431 auto ReleasingStoreBB =
1435 ReplacementIRBuilder Builder(CI, *
DL);
1440 std::prev(BB->
end())->eraseFromParent();
1442 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1445 PartwordMaskValues PMV =
1452 Value *UnreleasedLoad =
1453 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1454 Value *UnreleasedLoadExtract =
1461 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1462 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1465 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1470 PHINode *LoadedTryStore =
1471 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1472 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1473 Value *NewValueInsert =
1476 PMV.AlignedAddr, MemOpOrder);
1478 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1479 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1481 CI->
isWeak() ? FailureBB : RetryBB,
1482 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1486 if (HasReleasedLoadBB) {
1488 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1496 ShouldStore, TryStoreBB, NoStoreBB,
1497 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1499 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1506 if (ShouldInsertFencesForAtomic ||
1512 PHINode *LoadedNoStore =
1514 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1515 if (HasReleasedLoadBB)
1516 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1525 PHINode *LoadedFailure =
1527 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1529 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1530 if (ShouldInsertFencesForAtomic)
1539 PHINode *LoadedExit =
1541 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1542 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1549 Value *LoadedFull = LoadedExit;
1557 for (
auto *User : CI->
users()) {
1563 "weird extraction from { iN, i1 }");
1574 for (
auto *EV : PrunedInsts)
1591bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1604 return C->isMinusOne();
1606 return C->isMaxValue(
true);
1608 return C->isMinValue(
true);
1610 return C->isMaxValue(
false);
1612 return C->isMinValue(
false);
1618bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1620 tryExpandAtomicLoad(ResultingLoad);
1626Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1627 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1629 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1657 std::prev(BB->
end())->eraseFromParent();
1664 PHINode *Loaded = Builder.
CreatePHI(ResultTy, 2,
"loaded");
1667 Value *NewVal = PerformOp(Builder, Loaded);
1669 Value *NewLoaded =
nullptr;
1672 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1673 MemOpOrder == AtomicOrdering::Unordered
1674 ? AtomicOrdering::Monotonic
1676 SSID,
Success, NewLoaded, MetadataSrc);
1692bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1699 case TargetLoweringBase::AtomicExpansionKind::None:
1700 if (ValueSize < MinCASSize)
1701 return expandPartwordCmpXchg(CI);
1703 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1704 return expandAtomicCmpXchg(CI);
1706 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1707 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1709 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1711 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1722 Builder.setIsFPConstrained(
1727 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1731 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1732 AI->getValOperand());
1755 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1756 return Alignment >=
Size &&
1758 Size <= LargestSize;
1761void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1762 static const RTLIB::Libcall Libcalls[6] = {
1763 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1764 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1767 bool expanded = expandAtomicOpToLibcall(
1768 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1769 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1771 handleFailure(*
I,
"unsupported atomic load");
1774void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1775 static const RTLIB::Libcall Libcalls[6] = {
1776 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1777 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1780 bool expanded = expandAtomicOpToLibcall(
1781 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1782 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1784 handleFailure(*
I,
"unsupported atomic store");
1787void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1788 static const RTLIB::Libcall Libcalls[6] = {
1789 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1790 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1791 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1794 bool expanded = expandAtomicOpToLibcall(
1795 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1796 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1799 handleFailure(*
I,
"unsupported cmpxchg");
1803 static const RTLIB::Libcall LibcallsXchg[6] = {
1804 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1805 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1806 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1807 static const RTLIB::Libcall LibcallsAdd[6] = {
1808 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1809 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1810 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1811 static const RTLIB::Libcall LibcallsSub[6] = {
1812 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1813 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1814 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1815 static const RTLIB::Libcall LibcallsAnd[6] = {
1816 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1817 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1818 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1819 static const RTLIB::Libcall LibcallsOr[6] = {
1820 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1821 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1822 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1823 static const RTLIB::Libcall LibcallsXor[6] = {
1824 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1825 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1826 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1827 static const RTLIB::Libcall LibcallsNand[6] = {
1828 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1829 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1830 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1869void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1875 if (!Libcalls.
empty())
1876 Success = expandAtomicOpToLibcall(
1877 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1878 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1886 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1889 Instruction *MetadataSrc) {
1892 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1901 expandAtomicCASToLibcall(Pair);
1912bool AtomicExpandImpl::expandAtomicOpToLibcall(
1913 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1918 LLVMContext &Ctx =
I->getContext();
1920 const DataLayout &
DL =
M->getDataLayout();
1922 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1925 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1927 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1931 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1933 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1936 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1938 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1940 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1942 RTLIB::Libcall RTLibType;
1943 if (UseSizedLibcall) {
1946 RTLibType = Libcalls[1];
1949 RTLibType = Libcalls[2];
1952 RTLibType = Libcalls[3];
1955 RTLibType = Libcalls[4];
1958 RTLibType = Libcalls[5];
1961 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1962 RTLibType = Libcalls[0];
2000 AllocaInst *AllocaCASExpected =
nullptr;
2001 AllocaInst *AllocaValue =
nullptr;
2002 AllocaInst *AllocaResult =
nullptr;
2009 if (!UseSizedLibcall) {
2011 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2019 Value *PtrVal = PointerOperand;
2021 Args.push_back(PtrVal);
2025 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2029 Args.push_back(AllocaCASExpected);
2034 if (UseSizedLibcall) {
2037 Args.push_back(IntValue);
2039 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2043 Args.push_back(AllocaValue);
2048 if (!CASExpected && HasResult && !UseSizedLibcall) {
2049 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2052 Args.push_back(AllocaResult);
2056 Args.push_back(OrderingVal);
2060 Args.push_back(Ordering2Val);
2064 ResultTy = Type::getInt1Ty(Ctx);
2065 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2066 }
else if (HasResult && UseSizedLibcall)
2067 ResultTy = SizedIntTy;
2069 ResultTy = Type::getVoidTy(Ctx);
2073 for (
Value *Arg : Args)
2075 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2076 FunctionCallee LibcallFn =
2083 if (ValueOperand && !UseSizedLibcall)
2089 Type *FinalResultTy =
I->getType();
2092 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2097 }
else if (HasResult) {
2099 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).
#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)
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)
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...
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.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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 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 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 AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const
Returns how the given atomic cmpxchg should be expanded 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 AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
virtual void emitCmpArithAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a atomicrmw which the result is only used by comparison, using a target-specific intrinsic.
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
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.
iterator_range< user_iterator > users()
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
#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.
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.
LLVM_ABI void initializeAtomicExpandLegacyPass(PassRegistry &)
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.