59#define DEBUG_TYPE "atomic-expand"
63class AtomicExpandImpl {
82 bool tryExpandAtomicLoad(
LoadInst *LI);
83 bool expandAtomicLoadToLL(
LoadInst *LI);
84 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
94 void expandAtomicOpToLLSC(
98 void expandPartwordAtomicRMW(
106 static Value *insertRMWCmpXchgLoop(
122 void expandAtomicLoadToLibcall(
LoadInst *LI);
123 void expandAtomicStoreToLibcall(
StoreInst *LI);
149struct ReplacementIRBuilder
150 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
160 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
161 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
162 this->setIsFPConstrained(
true);
164 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
169 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
175char AtomicExpandLegacy::ID = 0;
180 "Expand Atomic instructions",
false,
false)
188 return DL.getTypeStoreSize(LI->getType());
193 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
210 Source.getAllMetadata(MD);
214 for (
auto [
ID,
N] : MD) {
216 case LLVMContext::MD_dbg:
217 case LLVMContext::MD_tbaa:
218 case LLVMContext::MD_tbaa_struct:
219 case LLVMContext::MD_alias_scope:
220 case LLVMContext::MD_noalias:
221 case LLVMContext::MD_noalias_addrspace:
222 case LLVMContext::MD_access_group:
223 case LLVMContext::MD_mmra:
227 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
229 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
242template <
typename Inst>
245 Align Alignment =
I->getAlign();
246 return Alignment >=
Size &&
250bool AtomicExpandImpl::processAtomicInstr(
Instruction *
I) {
256 bool MadeChange =
false;
264 expandAtomicLoadToLibcall(LI);
269 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
270 I = LI = convertAtomicLoadToIntegerType(LI);
278 expandAtomicStoreToLibcall(SI);
283 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
284 I =
SI = convertAtomicStoreToIntegerType(SI);
289 expandAtomicRMWToLibcall(RMWI);
294 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
295 I = RMWI = convertAtomicXchgToIntegerType(RMWI);
300 expandAtomicCASToLibcall(CASI);
306 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
309 I = CASI = convertCmpXchgToIntegerType(CASI);
316 auto FenceOrdering = AtomicOrdering::Monotonic;
318 FenceOrdering = LI->getOrdering();
319 LI->setOrdering(AtomicOrdering::Monotonic);
321 FenceOrdering =
SI->getOrdering();
322 SI->setOrdering(AtomicOrdering::Monotonic);
325 FenceOrdering = RMWI->getOrdering();
326 RMWI->setOrdering(AtomicOrdering::Monotonic);
329 TargetLoweringBase::AtomicExpansionKind::None &&
337 FenceOrdering = CASI->getMergedOrdering();
340 CASI->setSuccessOrdering(CASOrdering);
341 CASI->setFailureOrdering(CASOrdering);
344 if (FenceOrdering != AtomicOrdering::Monotonic) {
345 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
347 }
else if (
I->hasAtomicStore() &&
349 auto FenceOrdering = AtomicOrdering::Monotonic;
351 FenceOrdering =
SI->getOrdering();
353 FenceOrdering = RMWI->getOrdering();
355 TargetLoweringBase::AtomicExpansionKind::LLSC)
357 FenceOrdering = CASI->getSuccessOrdering();
360 if (
auto TrailingFence =
362 TrailingFence->moveAfter(
I);
368 MadeChange |= tryExpandAtomicLoad(LI);
370 MadeChange |= tryExpandAtomicStore(SI);
377 if (isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) {
381 MadeChange |= tryExpandAtomicRMW(RMWI);
384 MadeChange |= tryExpandAtomicCmpXchg(CASI);
389bool AtomicExpandImpl::run(Function &
F,
const TargetMachine *TM) {
390 const auto *Subtarget =
TM->getSubtargetImpl(
F);
391 if (!Subtarget->enableAtomicExpand())
393 TLI = Subtarget->getTargetLowering();
394 DL = &
F.getDataLayout();
396 bool MadeChange =
false;
408 if (processAtomicInstr(&Inst)) {
420bool AtomicExpandLegacy::runOnFunction(Function &
F) {
422 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
425 auto *
TM = &TPC->getTM<TargetMachine>();
427 return AE.run(
F, TM);
431 return new AtomicExpandLegacy();
445bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
447 ReplacementIRBuilder Builder(
I, *
DL);
457 return (LeadingFence || TrailingFence);
472LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
474 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
476 ReplacementIRBuilder Builder(LI, *
DL);
480 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
481 NewLI->setAlignment(LI->
getAlign());
484 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
486 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
493AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
498 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
500 ReplacementIRBuilder Builder(RMWI, *
DL);
505 ? Builder.CreatePtrToInt(Val, NewTy)
506 : Builder.CreateBitCast(Val, NewTy);
513 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
516 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
517 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
523bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
525 case TargetLoweringBase::AtomicExpansionKind::None:
527 case TargetLoweringBase::AtomicExpansionKind::LLSC:
528 expandAtomicOpToLLSC(
531 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
533 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
534 return expandAtomicLoadToLL(LI);
535 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
536 return expandAtomicLoadToCmpXchg(LI);
537 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
538 LI->
setAtomic(AtomicOrdering::NotAtomic);
540 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
548bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
550 case TargetLoweringBase::AtomicExpansionKind::None:
552 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
555 case TargetLoweringBase::AtomicExpansionKind::Expand:
556 expandAtomicStoreToXChg(SI);
558 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
559 SI->setAtomic(AtomicOrdering::NotAtomic);
566bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
567 ReplacementIRBuilder Builder(LI, *
DL);
582bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
583 ReplacementIRBuilder Builder(LI, *
DL);
585 if (Order == AtomicOrdering::Unordered)
586 Order = AtomicOrdering::Monotonic;
592 Value *Pair = Builder.CreateAtomicCmpXchg(
593 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
595 Value *Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
611StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
612 ReplacementIRBuilder Builder(SI, *
DL);
613 auto *
M =
SI->getModule();
614 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
616 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
618 Value *Addr =
SI->getPointerOperand();
620 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
624 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
625 SI->eraseFromParent();
629void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
636 ReplacementIRBuilder Builder(SI, *
DL);
638 assert(Ordering != AtomicOrdering::NotAtomic);
640 ? AtomicOrdering::Monotonic
642 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
644 SI->getAlign(), RMWOrdering);
645 SI->eraseFromParent();
648 tryExpandAtomicRMW(AI);
663 NewVal = Builder.CreateBitCast(NewVal, IntTy);
664 Loaded = Builder.CreateBitCast(Loaded, IntTy);
668 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
673 Success = Builder.CreateExtractValue(Pair, 1,
"success");
674 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
677 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
680bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
684 case TargetLoweringBase::AtomicExpansionKind::None:
686 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
689 if (ValueSize < MinCASSize) {
690 expandPartwordAtomicRMW(AI,
691 TargetLoweringBase::AtomicExpansionKind::LLSC);
693 auto PerformOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
702 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
705 if (ValueSize < MinCASSize) {
706 expandPartwordAtomicRMW(AI,
707 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
716 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
717 <<
"A compare and swap loop was generated for an atomic "
719 << MemScope <<
" memory scope";
725 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
728 if (ValueSize < MinCASSize) {
733 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
737 expandAtomicRMWToMaskedIntrinsic(AI);
740 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
744 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
748 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
750 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
760struct PartwordMaskValues {
762 Type *WordType =
nullptr;
764 Type *IntValueType =
nullptr;
765 Value *AlignedAddr =
nullptr;
766 Align AlignedAddrAlignment;
768 Value *ShiftAmt =
nullptr;
769 Value *Mask =
nullptr;
770 Value *Inv_Mask =
nullptr;
774raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
775 auto PrintObj = [&
O](
auto *
V) {
782 O <<
"PartwordMaskValues {\n";
784 PrintObj(PMV.WordType);
786 PrintObj(PMV.ValueType);
787 O <<
" AlignedAddr: ";
788 PrintObj(PMV.AlignedAddr);
789 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
791 PrintObj(PMV.ShiftAmt);
795 PrintObj(PMV.Inv_Mask);
821 unsigned MinWordSize) {
822 PartwordMaskValues PMV;
827 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
829 PMV.ValueType = PMV.IntValueType =
ValueType;
834 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
836 if (PMV.ValueType == PMV.WordType) {
837 PMV.AlignedAddr = Addr;
838 PMV.AlignedAddrAlignment = AddrAlign;
839 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
840 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
844 PMV.AlignedAddrAlignment =
Align(MinWordSize);
846 assert(ValueSize < MinWordSize);
849 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
852 if (AddrAlign < MinWordSize) {
853 PMV.AlignedAddr = Builder.CreateIntrinsic(
854 Intrinsic::ptrmask, {PtrTy, IntTy},
855 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
858 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
859 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
862 PMV.AlignedAddr = Addr;
866 if (
DL.isLittleEndian()) {
868 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
871 PMV.ShiftAmt = Builder.CreateShl(
872 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
875 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
876 PMV.Mask = Builder.CreateShl(
877 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
880 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
886 const PartwordMaskValues &PMV) {
887 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
888 if (PMV.WordType == PMV.ValueType)
891 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
892 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
893 return Builder.CreateBitCast(Trunc, PMV.ValueType);
897 Value *Updated,
const PartwordMaskValues &PMV) {
898 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
899 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
900 if (PMV.WordType == PMV.ValueType)
903 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
905 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
907 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
908 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
909 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
919 const PartwordMaskValues &PMV) {
925 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
926 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
938 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
939 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
940 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
977void AtomicExpandImpl::expandPartwordAtomicRMW(
983 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
989 ReplacementIRBuilder Builder(AI, *
DL);
991 PartwordMaskValues PMV =
995 Value *ValOperand_Shifted =
nullptr;
1000 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1001 "ValOperand_Shifted");
1004 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
1010 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1011 OldResult = insertRMWCmpXchgLoop(
1012 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1015 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1016 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1017 PMV.AlignedAddrAlignment, MemOpOrder,
1027AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1028 ReplacementIRBuilder Builder(AI, *
DL);
1033 "Unable to widen operation");
1035 PartwordMaskValues PMV =
1039 Value *ValOperand_Shifted =
1041 PMV.ShiftAmt,
"ValOperand_Shifted");
1047 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1049 NewOperand = ValOperand_Shifted;
1052 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1063bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1105 ReplacementIRBuilder Builder(CI, *
DL);
1116 std::prev(BB->
end())->eraseFromParent();
1119 PartwordMaskValues PMV =
1124 Value *NewVal_Shifted =
1126 Value *Cmp_Shifted =
1131 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1133 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1138 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1139 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1142 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1143 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1145 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1173 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1188void AtomicExpandImpl::expandAtomicOpToLLSC(
1189 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1191 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1192 ReplacementIRBuilder Builder(
I, *
DL);
1193 Value *Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1194 MemOpOrder, PerformOp);
1196 I->replaceAllUsesWith(Loaded);
1197 I->eraseFromParent();
1200void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1201 ReplacementIRBuilder Builder(AI, *
DL);
1203 PartwordMaskValues PMV =
1213 CastOp = Instruction::SExt;
1217 PMV.ShiftAmt,
"ValOperand_Shifted");
1219 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1226void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1227 AtomicCmpXchgInst *CI) {
1228 ReplacementIRBuilder Builder(CI, *
DL);
1241 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1247 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1254Value *AtomicExpandImpl::insertRMWLLSCLoop(
1255 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1257 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1263 F->getDataLayout().getTypeStoreSize(ResultTy) &&
1264 "Expected at least natural alignment at this point.");
1284 std::prev(BB->
end())->eraseFromParent();
1292 Value *NewVal = PerformOp(Builder, Loaded);
1294 Value *StoreSuccess =
1310AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1313 M->getDataLayout());
1315 ReplacementIRBuilder Builder(CI, *
DL);
1327 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1343bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1349 LLVMContext &Ctx =
F->getContext();
1356 ? AtomicOrdering::Monotonic
1368 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1369 SuccessOrder != AtomicOrdering::Monotonic &&
1370 SuccessOrder != AtomicOrdering::Acquire &&
1375 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1429 auto ReleasedLoadBB =
1433 auto ReleasingStoreBB =
1437 ReplacementIRBuilder Builder(CI, *
DL);
1442 std::prev(BB->
end())->eraseFromParent();
1444 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1447 PartwordMaskValues PMV =
1454 Value *UnreleasedLoad =
1455 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1456 Value *UnreleasedLoadExtract =
1463 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1464 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1467 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1472 PHINode *LoadedTryStore =
1473 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1474 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1475 Value *NewValueInsert =
1478 PMV.AlignedAddr, MemOpOrder);
1480 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1481 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1483 CI->
isWeak() ? FailureBB : RetryBB,
1484 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1488 if (HasReleasedLoadBB) {
1490 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1498 ShouldStore, TryStoreBB, NoStoreBB,
1499 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1501 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1508 if (ShouldInsertFencesForAtomic ||
1514 PHINode *LoadedNoStore =
1516 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1517 if (HasReleasedLoadBB)
1518 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1527 PHINode *LoadedFailure =
1529 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1531 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1532 if (ShouldInsertFencesForAtomic)
1541 PHINode *LoadedExit =
1543 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1544 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1551 Value *LoadedFull = LoadedExit;
1559 for (
auto *User : CI->
users()) {
1565 "weird extraction from { iN, i1 }");
1576 for (
auto *EV : PrunedInsts)
1593bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1606 return C->isMinusOne();
1608 return C->isMaxValue(
true);
1610 return C->isMinValue(
true);
1612 return C->isMaxValue(
false);
1614 return C->isMinValue(
false);
1620bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1622 tryExpandAtomicLoad(ResultingLoad);
1628Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1629 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1631 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1659 std::prev(BB->
end())->eraseFromParent();
1666 PHINode *Loaded = Builder.
CreatePHI(ResultTy, 2,
"loaded");
1669 Value *NewVal = PerformOp(Builder, Loaded);
1671 Value *NewLoaded =
nullptr;
1674 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1675 MemOpOrder == AtomicOrdering::Unordered
1676 ? AtomicOrdering::Monotonic
1678 SSID,
Success, NewLoaded, MetadataSrc);
1689bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1696 case TargetLoweringBase::AtomicExpansionKind::None:
1697 if (ValueSize < MinCASSize)
1698 return expandPartwordCmpXchg(CI);
1700 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1701 return expandAtomicCmpXchg(CI);
1703 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1704 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1706 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1708 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1719 Builder.setIsFPConstrained(
1724 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1728 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1729 AI->getValOperand());
1752 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1753 return Alignment >=
Size &&
1755 Size <= LargestSize;
1758void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1759 static const RTLIB::Libcall Libcalls[6] = {
1760 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1761 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1764 bool expanded = expandAtomicOpToLibcall(
1765 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1766 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1768 handleFailure(*
I,
"unsupported atomic load");
1771void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1772 static const RTLIB::Libcall Libcalls[6] = {
1773 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1774 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1777 bool expanded = expandAtomicOpToLibcall(
1778 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1779 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1781 handleFailure(*
I,
"unsupported atomic store");
1784void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1785 static const RTLIB::Libcall Libcalls[6] = {
1786 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1787 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1788 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1791 bool expanded = expandAtomicOpToLibcall(
1792 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1793 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1796 handleFailure(*
I,
"unsupported cmpxchg");
1800 static const RTLIB::Libcall LibcallsXchg[6] = {
1801 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1802 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1803 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1804 static const RTLIB::Libcall LibcallsAdd[6] = {
1805 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1806 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1807 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1808 static const RTLIB::Libcall LibcallsSub[6] = {
1809 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1810 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1811 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1812 static const RTLIB::Libcall LibcallsAnd[6] = {
1813 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1814 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1815 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1816 static const RTLIB::Libcall LibcallsOr[6] = {
1817 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1818 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1819 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1820 static const RTLIB::Libcall LibcallsXor[6] = {
1821 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1822 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1823 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1824 static const RTLIB::Libcall LibcallsNand[6] = {
1825 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1826 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1827 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1866void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1872 if (!Libcalls.
empty())
1873 Success = expandAtomicOpToLibcall(
1874 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1875 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1883 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1886 Instruction *MetadataSrc) {
1889 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1898 expandAtomicCASToLibcall(Pair);
1909bool AtomicExpandImpl::expandAtomicOpToLibcall(
1910 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1915 LLVMContext &Ctx =
I->getContext();
1917 const DataLayout &
DL =
M->getDataLayout();
1919 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1922 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1924 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1928 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1930 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1933 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1935 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1937 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1939 RTLIB::Libcall RTLibType;
1940 if (UseSizedLibcall) {
1943 RTLibType = Libcalls[1];
1946 RTLibType = Libcalls[2];
1949 RTLibType = Libcalls[3];
1952 RTLibType = Libcalls[4];
1955 RTLibType = Libcalls[5];
1958 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1959 RTLibType = Libcalls[0];
1997 AllocaInst *AllocaCASExpected =
nullptr;
1998 AllocaInst *AllocaValue =
nullptr;
1999 AllocaInst *AllocaResult =
nullptr;
2006 if (!UseSizedLibcall) {
2008 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2016 Value *PtrVal = PointerOperand;
2018 Args.push_back(PtrVal);
2022 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2026 Args.push_back(AllocaCASExpected);
2031 if (UseSizedLibcall) {
2034 Args.push_back(IntValue);
2036 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2040 Args.push_back(AllocaValue);
2045 if (!CASExpected && HasResult && !UseSizedLibcall) {
2046 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2049 Args.push_back(AllocaResult);
2053 Args.push_back(OrderingVal);
2057 Args.push_back(Ordering2Val);
2061 ResultTy = Type::getInt1Ty(Ctx);
2062 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2063 }
else if (HasResult && UseSizedLibcall)
2064 ResultTy = SizedIntTy;
2066 ResultTy = Type::getVoidTy(Ctx);
2070 for (
Value *Arg : Args)
2072 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2073 FunctionCallee LibcallFn =
2080 if (ValueOperand && !UseSizedLibcall)
2086 Type *FinalResultTy =
I->getType();
2089 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2094 }
else if (HasResult) {
2096 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")
#define LLVM_ATTRIBUTE_UNUSED
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.
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 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 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 shouldInsertTrailingFenceForAtomicStore(const Instruction *I) const
Whether AtomicExpandPass should automatically insert a trailing fence without reducing the ordering f...
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.
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)
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.
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.