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);
348 }
else if (
I->hasAtomicStore() &&
350 auto FenceOrdering = AtomicOrdering::Monotonic;
352 FenceOrdering =
SI->getOrdering();
354 FenceOrdering = RMWI->getOrdering();
356 TargetLoweringBase::AtomicExpansionKind::LLSC)
358 FenceOrdering = CASI->getSuccessOrdering();
361 if (
auto TrailingFence =
363 TrailingFence->moveAfter(
I);
369 MadeChange |= tryExpandAtomicLoad(LI);
371 MadeChange |= tryExpandAtomicStore(SI);
382 MadeChange |= tryExpandAtomicRMW(RMWI);
385 MadeChange |= tryExpandAtomicCmpXchg(CASI);
390bool AtomicExpandImpl::run(Function &
F,
const TargetMachine *TM) {
391 const auto *Subtarget =
TM->getSubtargetImpl(
F);
392 if (!Subtarget->enableAtomicExpand())
394 TLI = Subtarget->getTargetLowering();
395 DL = &
F.getDataLayout();
397 bool MadeChange =
false;
409 if (processAtomicInstr(&Inst)) {
421bool AtomicExpandLegacy::runOnFunction(Function &
F) {
423 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
426 auto *
TM = &TPC->getTM<TargetMachine>();
428 return AE.run(
F, TM);
432 return new AtomicExpandLegacy();
446bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
448 ReplacementIRBuilder Builder(
I, *
DL);
458 return (LeadingFence || TrailingFence);
473LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
475 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
477 ReplacementIRBuilder Builder(LI, *
DL);
481 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
482 NewLI->setAlignment(LI->
getAlign());
485 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
487 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
494AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
499 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
501 ReplacementIRBuilder Builder(RMWI, *
DL);
506 ? Builder.CreatePtrToInt(Val, NewTy)
507 : Builder.CreateBitCast(Val, NewTy);
514 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
517 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
518 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
524bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
526 case TargetLoweringBase::AtomicExpansionKind::None:
528 case TargetLoweringBase::AtomicExpansionKind::LLSC:
529 expandAtomicOpToLLSC(
532 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
534 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
535 return expandAtomicLoadToLL(LI);
536 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
537 return expandAtomicLoadToCmpXchg(LI);
538 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
539 LI->
setAtomic(AtomicOrdering::NotAtomic);
541 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
549bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
551 case TargetLoweringBase::AtomicExpansionKind::None:
553 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
556 case TargetLoweringBase::AtomicExpansionKind::Expand:
557 expandAtomicStoreToXChg(SI);
559 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
560 SI->setAtomic(AtomicOrdering::NotAtomic);
567bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
568 ReplacementIRBuilder Builder(LI, *
DL);
583bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
584 ReplacementIRBuilder Builder(LI, *
DL);
586 if (Order == AtomicOrdering::Unordered)
587 Order = AtomicOrdering::Monotonic;
593 Value *Pair = Builder.CreateAtomicCmpXchg(
594 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
596 Value *Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
612StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
613 ReplacementIRBuilder Builder(SI, *
DL);
614 auto *
M =
SI->getModule();
615 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
617 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
619 Value *Addr =
SI->getPointerOperand();
621 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
625 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
626 SI->eraseFromParent();
630void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
637 ReplacementIRBuilder Builder(SI, *
DL);
639 assert(Ordering != AtomicOrdering::NotAtomic);
641 ? AtomicOrdering::Monotonic
643 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
645 SI->getAlign(), RMWOrdering);
646 SI->eraseFromParent();
649 tryExpandAtomicRMW(AI);
664 NewVal = Builder.CreateBitCast(NewVal, IntTy);
665 Loaded = Builder.CreateBitCast(Loaded, IntTy);
669 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
674 Success = Builder.CreateExtractValue(Pair, 1,
"success");
675 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
678 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
681bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
685 case TargetLoweringBase::AtomicExpansionKind::None:
687 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
690 if (ValueSize < MinCASSize) {
691 expandPartwordAtomicRMW(AI,
692 TargetLoweringBase::AtomicExpansionKind::LLSC);
694 auto PerformOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
703 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
706 if (ValueSize < MinCASSize) {
707 expandPartwordAtomicRMW(AI,
708 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
717 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
718 <<
"A compare and swap loop was generated for an atomic "
720 << MemScope <<
" memory scope";
726 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
729 if (ValueSize < MinCASSize) {
734 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
738 expandAtomicRMWToMaskedIntrinsic(AI);
741 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
745 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
749 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
751 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
761struct PartwordMaskValues {
763 Type *WordType =
nullptr;
765 Type *IntValueType =
nullptr;
766 Value *AlignedAddr =
nullptr;
767 Align AlignedAddrAlignment;
769 Value *ShiftAmt =
nullptr;
770 Value *Mask =
nullptr;
771 Value *Inv_Mask =
nullptr;
775raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
776 auto PrintObj = [&
O](
auto *
V) {
783 O <<
"PartwordMaskValues {\n";
785 PrintObj(PMV.WordType);
787 PrintObj(PMV.ValueType);
788 O <<
" AlignedAddr: ";
789 PrintObj(PMV.AlignedAddr);
790 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
792 PrintObj(PMV.ShiftAmt);
796 PrintObj(PMV.Inv_Mask);
822 unsigned MinWordSize) {
823 PartwordMaskValues PMV;
828 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
830 PMV.ValueType = PMV.IntValueType =
ValueType;
835 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
837 if (PMV.ValueType == PMV.WordType) {
838 PMV.AlignedAddr = Addr;
839 PMV.AlignedAddrAlignment = AddrAlign;
840 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
841 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
845 PMV.AlignedAddrAlignment =
Align(MinWordSize);
847 assert(ValueSize < MinWordSize);
850 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
853 if (AddrAlign < MinWordSize) {
854 PMV.AlignedAddr = Builder.CreateIntrinsic(
855 Intrinsic::ptrmask, {PtrTy, IntTy},
856 {Addr, ConstantInt::get(IntTy, ~(
uint64_t)(MinWordSize - 1))},
nullptr,
859 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
860 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
863 PMV.AlignedAddr = Addr;
867 if (
DL.isLittleEndian()) {
869 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
872 PMV.ShiftAmt = Builder.CreateShl(
873 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
876 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
877 PMV.Mask = Builder.CreateShl(
878 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
881 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
887 const PartwordMaskValues &PMV) {
888 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
889 if (PMV.WordType == PMV.ValueType)
892 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
893 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
894 return Builder.CreateBitCast(Trunc, PMV.ValueType);
898 Value *Updated,
const PartwordMaskValues &PMV) {
899 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
900 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
901 if (PMV.WordType == PMV.ValueType)
904 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
906 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
908 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
909 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
910 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
920 const PartwordMaskValues &PMV) {
926 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
927 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
939 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
940 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
941 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
978void AtomicExpandImpl::expandPartwordAtomicRMW(
984 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
990 ReplacementIRBuilder Builder(AI, *
DL);
992 PartwordMaskValues PMV =
996 Value *ValOperand_Shifted =
nullptr;
1000 ValOperand_Shifted =
1001 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1002 "ValOperand_Shifted");
1005 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *Loaded) {
1011 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1012 OldResult = insertRMWCmpXchgLoop(
1013 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1016 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1017 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1018 PMV.AlignedAddrAlignment, MemOpOrder,
1028AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1029 ReplacementIRBuilder Builder(AI, *
DL);
1034 "Unable to widen operation");
1036 PartwordMaskValues PMV =
1040 Value *ValOperand_Shifted =
1042 PMV.ShiftAmt,
"ValOperand_Shifted");
1048 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1050 NewOperand = ValOperand_Shifted;
1053 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1064bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1106 ReplacementIRBuilder Builder(CI, *
DL);
1117 std::prev(BB->
end())->eraseFromParent();
1120 PartwordMaskValues PMV =
1125 Value *NewVal_Shifted =
1127 Value *Cmp_Shifted =
1132 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1134 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1139 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1140 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1143 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1144 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1146 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1174 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1189void AtomicExpandImpl::expandAtomicOpToLLSC(
1190 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1192 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1193 ReplacementIRBuilder Builder(
I, *
DL);
1194 Value *Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1195 MemOpOrder, PerformOp);
1197 I->replaceAllUsesWith(Loaded);
1198 I->eraseFromParent();
1201void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1202 ReplacementIRBuilder Builder(AI, *
DL);
1204 PartwordMaskValues PMV =
1214 CastOp = Instruction::SExt;
1218 PMV.ShiftAmt,
"ValOperand_Shifted");
1220 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1227void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1228 AtomicCmpXchgInst *CI) {
1229 ReplacementIRBuilder Builder(CI, *
DL);
1242 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1248 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1255Value *AtomicExpandImpl::insertRMWLLSCLoop(
1256 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1258 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1263 assert(AddrAlign >=
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 =
1316AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1319 M->getDataLayout());
1321 ReplacementIRBuilder Builder(CI, *
DL);
1333 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1349bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1355 LLVMContext &Ctx =
F->getContext();
1362 ? AtomicOrdering::Monotonic
1374 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1375 SuccessOrder != AtomicOrdering::Monotonic &&
1376 SuccessOrder != AtomicOrdering::Acquire &&
1381 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1435 auto ReleasedLoadBB =
1439 auto ReleasingStoreBB =
1443 ReplacementIRBuilder Builder(CI, *
DL);
1448 std::prev(BB->
end())->eraseFromParent();
1450 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1453 PartwordMaskValues PMV =
1460 Value *UnreleasedLoad =
1461 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1462 Value *UnreleasedLoadExtract =
1469 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1470 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1473 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1478 PHINode *LoadedTryStore =
1479 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1480 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1481 Value *NewValueInsert =
1484 PMV.AlignedAddr, MemOpOrder);
1486 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1487 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1489 CI->
isWeak() ? FailureBB : RetryBB,
1490 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1494 if (HasReleasedLoadBB) {
1496 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1504 ShouldStore, TryStoreBB, NoStoreBB,
1505 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1507 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1514 if (ShouldInsertFencesForAtomic ||
1520 PHINode *LoadedNoStore =
1522 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1523 if (HasReleasedLoadBB)
1524 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1533 PHINode *LoadedFailure =
1535 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1537 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1538 if (ShouldInsertFencesForAtomic)
1547 PHINode *LoadedExit =
1549 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1550 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1557 Value *LoadedFull = LoadedExit;
1565 for (
auto *User : CI->
users()) {
1571 "weird extraction from { iN, i1 }");
1582 for (
auto *EV : PrunedInsts)
1599bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1612 return C->isMinusOne();
1614 return C->isMaxValue(
true);
1616 return C->isMinValue(
true);
1618 return C->isMaxValue(
false);
1620 return C->isMinValue(
false);
1626bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1628 tryExpandAtomicLoad(ResultingLoad);
1634Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1635 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1637 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1665 std::prev(BB->
end())->eraseFromParent();
1672 PHINode *Loaded = Builder.
CreatePHI(ResultTy, 2,
"loaded");
1675 Value *NewVal = PerformOp(Builder, Loaded);
1677 Value *NewLoaded =
nullptr;
1680 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1681 MemOpOrder == AtomicOrdering::Unordered
1682 ? AtomicOrdering::Monotonic
1684 SSID,
Success, NewLoaded, MetadataSrc);
1700bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1707 case TargetLoweringBase::AtomicExpansionKind::None:
1708 if (ValueSize < MinCASSize)
1709 return expandPartwordCmpXchg(CI);
1711 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1712 return expandAtomicCmpXchg(CI);
1714 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1715 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1717 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1719 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1730 Builder.setIsFPConstrained(
1735 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1739 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1740 AI->getValOperand());
1763 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1764 return Alignment >=
Size &&
1766 Size <= LargestSize;
1769void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1770 static const RTLIB::Libcall Libcalls[6] = {
1771 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1772 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1775 bool expanded = expandAtomicOpToLibcall(
1776 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1777 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1779 handleFailure(*
I,
"unsupported atomic load");
1782void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1783 static const RTLIB::Libcall Libcalls[6] = {
1784 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1785 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1788 bool expanded = expandAtomicOpToLibcall(
1789 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1790 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1792 handleFailure(*
I,
"unsupported atomic store");
1795void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1796 static const RTLIB::Libcall Libcalls[6] = {
1797 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1798 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1799 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1802 bool expanded = expandAtomicOpToLibcall(
1803 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1804 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1807 handleFailure(*
I,
"unsupported cmpxchg");
1811 static const RTLIB::Libcall LibcallsXchg[6] = {
1812 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1813 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1814 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1815 static const RTLIB::Libcall LibcallsAdd[6] = {
1816 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1817 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1818 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1819 static const RTLIB::Libcall LibcallsSub[6] = {
1820 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1821 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1822 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1823 static const RTLIB::Libcall LibcallsAnd[6] = {
1824 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1825 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1826 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1827 static const RTLIB::Libcall LibcallsOr[6] = {
1828 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1829 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1830 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1831 static const RTLIB::Libcall LibcallsXor[6] = {
1832 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1833 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1834 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1835 static const RTLIB::Libcall LibcallsNand[6] = {
1836 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1837 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1838 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1877void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1883 if (!Libcalls.
empty())
1884 Success = expandAtomicOpToLibcall(
1885 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1886 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1894 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1897 Instruction *MetadataSrc) {
1900 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1909 expandAtomicCASToLibcall(Pair);
1920bool AtomicExpandImpl::expandAtomicOpToLibcall(
1921 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1926 LLVMContext &Ctx =
I->getContext();
1928 const DataLayout &
DL =
M->getDataLayout();
1930 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1933 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1935 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1939 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1941 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1944 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1946 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1948 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1950 RTLIB::Libcall RTLibType;
1951 if (UseSizedLibcall) {
1954 RTLibType = Libcalls[1];
1957 RTLibType = Libcalls[2];
1960 RTLibType = Libcalls[3];
1963 RTLibType = Libcalls[4];
1966 RTLibType = Libcalls[5];
1969 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1970 RTLibType = Libcalls[0];
2008 AllocaInst *AllocaCASExpected =
nullptr;
2009 AllocaInst *AllocaValue =
nullptr;
2010 AllocaInst *AllocaResult =
nullptr;
2017 if (!UseSizedLibcall) {
2019 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2027 Value *PtrVal = PointerOperand;
2029 Args.push_back(PtrVal);
2033 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2037 Args.push_back(AllocaCASExpected);
2042 if (UseSizedLibcall) {
2045 Args.push_back(IntValue);
2047 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2051 Args.push_back(AllocaValue);
2056 if (!CASExpected && HasResult && !UseSizedLibcall) {
2057 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2060 Args.push_back(AllocaResult);
2064 Args.push_back(OrderingVal);
2068 Args.push_back(Ordering2Val);
2072 ResultTy = Type::getInt1Ty(Ctx);
2073 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2074 }
else if (HasResult && UseSizedLibcall)
2075 ResultTy = SizedIntTy;
2077 ResultTy = Type::getVoidTy(Ctx);
2081 for (
Value *Arg : Args)
2083 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2084 FunctionCallee LibcallFn =
2091 if (ValueOperand && !UseSizedLibcall)
2097 Type *FinalResultTy =
I->getType();
2100 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2105 }
else if (HasResult) {
2107 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 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)
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.