60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
84 bool tryExpandAtomicLoad(
LoadInst *LI);
85 bool expandAtomicLoadToLL(
LoadInst *LI);
86 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
96 void expandAtomicOpToLLSC(
100 void expandPartwordAtomicRMW(
108 static Value *insertRMWCmpXchgLoop(
124 void expandAtomicLoadToLibcall(
LoadInst *LI);
125 void expandAtomicStoreToLibcall(
StoreInst *LI);
158struct ReplacementIRBuilder
159 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
169 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
170 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
171 this->setIsFPConstrained(
true);
173 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
178 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
184char AtomicExpandLegacy::ID = 0;
189 "Expand Atomic instructions",
false,
false)
198 return DL.getTypeStoreSize(LI->getType());
203 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
220 Source.getAllMetadata(MD);
224 for (
auto [
ID,
N] : MD) {
226 case LLVMContext::MD_dbg:
227 case LLVMContext::MD_tbaa:
228 case LLVMContext::MD_tbaa_struct:
229 case LLVMContext::MD_alias_scope:
230 case LLVMContext::MD_noalias:
231 case LLVMContext::MD_noalias_addrspace:
232 case LLVMContext::MD_access_group:
233 case LLVMContext::MD_mmra:
237 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
239 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
252template <
typename Inst>
255 Align Alignment =
I->getAlign();
256 return Alignment >=
Size &&
260bool AtomicExpandImpl::processAtomicInstr(
Instruction *
I) {
266 bool MadeChange =
false;
274 expandAtomicLoadToLibcall(LI);
279 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
280 I = LI = convertAtomicLoadToIntegerType(LI);
288 expandAtomicStoreToLibcall(SI);
293 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
294 I =
SI = convertAtomicStoreToIntegerType(SI);
299 expandAtomicRMWToLibcall(RMWI);
304 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
305 I = RMWI = convertAtomicXchgToIntegerType(RMWI);
310 expandAtomicCASToLibcall(CASI);
316 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
319 I = CASI = convertCmpXchgToIntegerType(CASI);
326 auto FenceOrdering = AtomicOrdering::Monotonic;
328 FenceOrdering = LI->getOrdering();
329 LI->setOrdering(AtomicOrdering::Monotonic);
331 FenceOrdering =
SI->getOrdering();
332 SI->setOrdering(AtomicOrdering::Monotonic);
335 FenceOrdering = RMWI->getOrdering();
336 RMWI->setOrdering(AtomicOrdering::Monotonic);
339 TargetLoweringBase::AtomicExpansionKind::None &&
347 FenceOrdering = CASI->getMergedOrdering();
350 CASI->setSuccessOrdering(CASOrdering);
351 CASI->setFailureOrdering(CASOrdering);
354 if (FenceOrdering != AtomicOrdering::Monotonic) {
355 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
359 TargetLoweringBase::AtomicExpansionKind::LLSC)) {
363 Builder,
I, AtomicOrdering::SequentiallyConsistent)) {
364 TrailingFence->moveAfter(
I);
370 MadeChange |= tryExpandAtomicLoad(LI);
372 MadeChange |= tryExpandAtomicStore(SI);
383 MadeChange |= tryExpandAtomicRMW(RMWI);
386 MadeChange |= tryExpandAtomicCmpXchg(CASI);
391bool AtomicExpandImpl::run(
392 Function &
F,
const LibcallLoweringModuleAnalysisResult &LibcallResult,
393 const TargetMachine *TM) {
395 if (!Subtarget->enableAtomicExpand())
397 TLI = Subtarget->getTargetLowering();
399 DL = &
F.getDataLayout();
401 bool MadeChange =
false;
413 if (processAtomicInstr(&Inst)) {
425bool AtomicExpandLegacy::runOnFunction(Function &
F) {
427 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
430 auto *TM = &TPC->getTM<TargetMachine>();
432 const LibcallLoweringModuleAnalysisResult &LibcallResult =
433 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
435 return AE.run(
F, LibcallResult, TM);
439 return new AtomicExpandLegacy();
449 if (!LibcallResult) {
451 "' analysis required");
457 bool Changed = AE.run(
F, *LibcallResult, TM);
464bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
466 ReplacementIRBuilder Builder(
I, *
DL);
476 return (LeadingFence || TrailingFence);
491LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
493 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
495 ReplacementIRBuilder Builder(LI, *
DL);
499 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
500 NewLI->setAlignment(LI->
getAlign());
503 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
505 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
512AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
517 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
519 ReplacementIRBuilder Builder(RMWI, *
DL);
524 ? Builder.CreatePtrToInt(Val, NewTy)
525 : Builder.CreateBitCast(Val, NewTy);
532 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
535 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
536 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
542bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
544 case TargetLoweringBase::AtomicExpansionKind::None:
546 case TargetLoweringBase::AtomicExpansionKind::LLSC:
547 expandAtomicOpToLLSC(
550 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
552 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
553 return expandAtomicLoadToLL(LI);
554 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
555 return expandAtomicLoadToCmpXchg(LI);
556 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
557 LI->
setAtomic(AtomicOrdering::NotAtomic);
559 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
567bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
569 case TargetLoweringBase::AtomicExpansionKind::None:
571 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
574 case TargetLoweringBase::AtomicExpansionKind::Expand:
575 expandAtomicStoreToXChg(SI);
577 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
578 SI->setAtomic(AtomicOrdering::NotAtomic);
585bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
586 ReplacementIRBuilder Builder(LI, *
DL);
601bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
602 ReplacementIRBuilder Builder(LI, *
DL);
604 if (Order == AtomicOrdering::Unordered)
605 Order = AtomicOrdering::Monotonic;
611 Value *Pair = Builder.CreateAtomicCmpXchg(
612 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
614 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
630StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
631 ReplacementIRBuilder Builder(SI, *
DL);
632 auto *
M =
SI->getModule();
633 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
635 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
637 Value *Addr =
SI->getPointerOperand();
639 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
643 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
644 SI->eraseFromParent();
648void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
655 ReplacementIRBuilder Builder(SI, *
DL);
657 assert(Ordering != AtomicOrdering::NotAtomic);
659 ? AtomicOrdering::Monotonic
661 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
663 SI->getAlign(), RMWOrdering);
664 SI->eraseFromParent();
667 tryExpandAtomicRMW(AI);
682 NewVal = Builder.CreateBitCast(NewVal, IntTy);
683 Loaded = Builder.CreateBitCast(Loaded, IntTy);
687 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
692 Success = Builder.CreateExtractValue(Pair, 1,
"success");
693 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
696 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
699bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
703 case TargetLoweringBase::AtomicExpansionKind::None:
705 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
708 if (ValueSize < MinCASSize) {
709 expandPartwordAtomicRMW(AI,
710 TargetLoweringBase::AtomicExpansionKind::LLSC);
712 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
721 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
724 if (ValueSize < MinCASSize) {
725 expandPartwordAtomicRMW(AI,
726 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
735 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
736 <<
"A compare and swap loop was generated for an atomic "
738 << MemScope <<
" memory scope";
744 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
747 if (ValueSize < MinCASSize) {
752 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
756 expandAtomicRMWToMaskedIntrinsic(AI);
759 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
763 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
767 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
769 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
779struct PartwordMaskValues {
781 Type *WordType =
nullptr;
783 Type *IntValueType =
nullptr;
784 Value *AlignedAddr =
nullptr;
785 Align AlignedAddrAlignment;
787 Value *ShiftAmt =
nullptr;
788 Value *Mask =
nullptr;
789 Value *Inv_Mask =
nullptr;
793raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
794 auto PrintObj = [&
O](
auto *
V) {
801 O <<
"PartwordMaskValues {\n";
803 PrintObj(PMV.WordType);
805 PrintObj(PMV.ValueType);
806 O <<
" AlignedAddr: ";
807 PrintObj(PMV.AlignedAddr);
808 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
810 PrintObj(PMV.ShiftAmt);
814 PrintObj(PMV.Inv_Mask);
840 unsigned MinWordSize) {
841 PartwordMaskValues PMV;
846 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
848 PMV.ValueType = PMV.IntValueType =
ValueType;
853 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
855 if (PMV.ValueType == PMV.WordType) {
856 PMV.AlignedAddr = Addr;
857 PMV.AlignedAddrAlignment = AddrAlign;
858 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
859 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
863 PMV.AlignedAddrAlignment =
Align(MinWordSize);
865 assert(ValueSize < MinWordSize);
868 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
871 if (AddrAlign < MinWordSize) {
872 PMV.AlignedAddr = Builder.CreateIntrinsic(
873 Intrinsic::ptrmask, {PtrTy, IntTy},
875 nullptr,
"AlignedAddr");
877 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
878 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
881 PMV.AlignedAddr = Addr;
885 if (
DL.isLittleEndian()) {
887 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
890 PMV.ShiftAmt = Builder.CreateShl(
891 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
894 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
895 PMV.Mask = Builder.CreateShl(
896 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
899 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
905 const PartwordMaskValues &PMV) {
906 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
907 if (PMV.WordType == PMV.ValueType)
910 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
911 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
912 return Builder.CreateBitCast(Trunc, PMV.ValueType);
916 Value *Updated,
const PartwordMaskValues &PMV) {
917 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
918 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
919 if (PMV.WordType == PMV.ValueType)
922 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
924 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
926 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
927 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
928 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
938 const PartwordMaskValues &PMV) {
944 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
945 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
957 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
958 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
959 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
996void AtomicExpandImpl::expandPartwordAtomicRMW(
1002 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1008 ReplacementIRBuilder Builder(AI, *
DL);
1010 PartwordMaskValues PMV =
1014 Value *ValOperand_Shifted =
nullptr;
1018 ValOperand_Shifted =
1019 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1020 "ValOperand_Shifted");
1023 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1029 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1030 OldResult = insertRMWCmpXchgLoop(
1031 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1034 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1035 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1036 PMV.AlignedAddrAlignment, MemOpOrder,
1046AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1047 ReplacementIRBuilder Builder(AI, *
DL);
1052 "Unable to widen operation");
1054 PartwordMaskValues PMV =
1058 Value *ValOperand_Shifted =
1060 PMV.ShiftAmt,
"ValOperand_Shifted");
1066 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1068 NewOperand = ValOperand_Shifted;
1071 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1082bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1124 ReplacementIRBuilder Builder(CI, *
DL);
1135 std::prev(BB->
end())->eraseFromParent();
1138 PartwordMaskValues PMV =
1143 Value *NewVal_Shifted =
1145 Value *Cmp_Shifted =
1150 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1152 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1157 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1158 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1161 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1162 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1164 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1192 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1207void AtomicExpandImpl::expandAtomicOpToLLSC(
1208 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1210 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1211 ReplacementIRBuilder Builder(
I, *
DL);
1212 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1213 MemOpOrder, PerformOp);
1215 I->replaceAllUsesWith(Loaded);
1216 I->eraseFromParent();
1219void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1220 ReplacementIRBuilder Builder(AI, *
DL);
1222 PartwordMaskValues PMV =
1232 CastOp = Instruction::SExt;
1236 PMV.ShiftAmt,
"ValOperand_Shifted");
1238 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1245void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1246 AtomicCmpXchgInst *CI) {
1247 ReplacementIRBuilder Builder(CI, *
DL);
1260 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1266 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1273Value *AtomicExpandImpl::insertRMWLLSCLoop(
1274 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1276 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1281 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1282 "Expected at least natural alignment at this point.");
1302 std::prev(BB->
end())->eraseFromParent();
1310 Value *NewVal = PerformOp(Builder, Loaded);
1312 Value *StoreSuccess =
1334AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1337 M->getDataLayout());
1339 ReplacementIRBuilder Builder(CI, *
DL);
1351 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1367bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1373 LLVMContext &Ctx =
F->getContext();
1380 ? AtomicOrdering::Monotonic
1392 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1393 SuccessOrder != AtomicOrdering::Monotonic &&
1394 SuccessOrder != AtomicOrdering::Acquire &&
1399 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1453 auto ReleasedLoadBB =
1457 auto ReleasingStoreBB =
1461 ReplacementIRBuilder Builder(CI, *
DL);
1466 std::prev(BB->
end())->eraseFromParent();
1468 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1471 PartwordMaskValues PMV =
1478 Value *UnreleasedLoad =
1479 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1480 Value *UnreleasedLoadExtract =
1487 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1488 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1491 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1496 PHINode *LoadedTryStore =
1497 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1498 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1499 Value *NewValueInsert =
1502 PMV.AlignedAddr, MemOpOrder);
1504 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1505 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1507 CI->
isWeak() ? FailureBB : RetryBB,
1508 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1512 if (HasReleasedLoadBB) {
1514 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1522 ShouldStore, TryStoreBB, NoStoreBB,
1523 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1525 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1532 if (ShouldInsertFencesForAtomic ||
1538 PHINode *LoadedNoStore =
1540 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1541 if (HasReleasedLoadBB)
1542 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1551 PHINode *LoadedFailure =
1553 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1555 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1556 if (ShouldInsertFencesForAtomic)
1565 PHINode *LoadedExit =
1567 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1568 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1575 Value *LoadedFull = LoadedExit;
1583 for (
auto *User : CI->
users()) {
1589 "weird extraction from { iN, i1 }");
1600 for (
auto *EV : PrunedInsts)
1617bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1630 return C->isMinusOne();
1632 return C->isMaxValue(
true);
1634 return C->isMinValue(
true);
1636 return C->isMaxValue(
false);
1638 return C->isMinValue(
false);
1644bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1646 tryExpandAtomicLoad(ResultingLoad);
1652Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1653 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1655 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1683 std::prev(BB->
end())->eraseFromParent();
1691 Loaded->addIncoming(InitLoaded, BB);
1693 Value *NewVal = PerformOp(Builder, Loaded);
1695 Value *NewLoaded =
nullptr;
1698 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1699 MemOpOrder == AtomicOrdering::Unordered
1700 ? AtomicOrdering::Monotonic
1702 SSID,
Success, NewLoaded, MetadataSrc);
1705 Loaded->addIncoming(NewLoaded, LoopBB);
1718bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1725 case TargetLoweringBase::AtomicExpansionKind::None:
1726 if (ValueSize < MinCASSize)
1727 return expandPartwordCmpXchg(CI);
1729 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1730 return expandAtomicCmpXchg(CI);
1732 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1733 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1735 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1737 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1748 Builder.setIsFPConstrained(
1753 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1757 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1758 AI->getValOperand());
1781 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1782 return Alignment >=
Size &&
1784 Size <= LargestSize;
1787void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1788 static const RTLIB::Libcall Libcalls[6] = {
1789 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1790 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1793 bool expanded = expandAtomicOpToLibcall(
1794 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1795 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1797 handleFailure(*
I,
"unsupported atomic load");
1800void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1801 static const RTLIB::Libcall Libcalls[6] = {
1802 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1803 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1806 bool expanded = expandAtomicOpToLibcall(
1807 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1808 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1810 handleFailure(*
I,
"unsupported atomic store");
1813void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1814 static const RTLIB::Libcall Libcalls[6] = {
1815 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1816 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1817 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1820 bool expanded = expandAtomicOpToLibcall(
1821 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1822 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1825 handleFailure(*
I,
"unsupported cmpxchg");
1829 static const RTLIB::Libcall LibcallsXchg[6] = {
1830 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1831 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1832 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1833 static const RTLIB::Libcall LibcallsAdd[6] = {
1834 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1835 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1836 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1837 static const RTLIB::Libcall LibcallsSub[6] = {
1838 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1839 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1840 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1841 static const RTLIB::Libcall LibcallsAnd[6] = {
1842 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1843 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1844 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1845 static const RTLIB::Libcall LibcallsOr[6] = {
1846 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1847 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1848 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1849 static const RTLIB::Libcall LibcallsXor[6] = {
1850 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1851 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1852 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1853 static const RTLIB::Libcall LibcallsNand[6] = {
1854 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1855 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1856 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1895void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1901 if (!Libcalls.
empty())
1902 Success = expandAtomicOpToLibcall(
1903 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1904 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1912 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1915 Instruction *MetadataSrc) {
1918 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1927 expandAtomicCASToLibcall(Pair);
1938bool AtomicExpandImpl::expandAtomicOpToLibcall(
1939 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1944 LLVMContext &Ctx =
I->getContext();
1946 const DataLayout &
DL =
M->getDataLayout();
1948 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1951 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1953 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1957 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1959 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1962 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1964 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1966 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1968 RTLIB::Libcall RTLibType;
1969 if (UseSizedLibcall) {
1972 RTLibType = Libcalls[1];
1975 RTLibType = Libcalls[2];
1978 RTLibType = Libcalls[3];
1981 RTLibType = Libcalls[4];
1984 RTLibType = Libcalls[5];
1987 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1988 RTLibType = Libcalls[0];
1995 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
1996 if (LibcallImpl == RTLIB::Unsupported) {
2027 AllocaInst *AllocaCASExpected =
nullptr;
2028 AllocaInst *AllocaValue =
nullptr;
2029 AllocaInst *AllocaResult =
nullptr;
2036 if (!UseSizedLibcall) {
2038 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2046 Value *PtrVal = PointerOperand;
2048 Args.push_back(PtrVal);
2052 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2056 Args.push_back(AllocaCASExpected);
2061 if (UseSizedLibcall) {
2064 Args.push_back(IntValue);
2066 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2070 Args.push_back(AllocaValue);
2075 if (!CASExpected && HasResult && !UseSizedLibcall) {
2076 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2079 Args.push_back(AllocaResult);
2083 Args.push_back(OrderingVal);
2087 Args.push_back(Ordering2Val);
2091 ResultTy = Type::getInt1Ty(Ctx);
2092 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2093 }
else if (HasResult && UseSizedLibcall)
2094 ResultTy = SizedIntTy;
2096 ResultTy = Type::getVoidTy(Ctx);
2100 for (
Value *Arg : Args)
2102 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2103 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2111 if (ValueOperand && !UseSizedLibcall)
2117 Type *FinalResultTy =
I->getType();
2120 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2125 }
else if (HasResult) {
2127 if (UseSizedLibcall)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static Value * performMaskedAtomicOp(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Shifted_Inc, Value *Inc, const PartwordMaskValues &PMV)
Emit IR to implement a masked version of a given atomicrmw operation.
static PartwordMaskValues createMaskInstrs(IRBuilderBase &Builder, Instruction *I, Type *ValueType, Value *Addr, Align AddrAlign, unsigned MinWordSize)
This is a helper function which builds instructions to provide values necessary for partword atomic o...
static bool canUseSizedAtomicCall(unsigned Size, Align Alignment, const DataLayout &DL)
static Value * extractMaskedValue(IRBuilderBase &Builder, Value *WideWord, const PartwordMaskValues &PMV)
static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, Value *&Success, Value *&NewLoaded, Instruction *MetadataSrc)
Expand Atomic static false unsigned getAtomicOpSize(LoadInst *LI)
static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I)
static Value * insertMaskedValue(IRBuilderBase &Builder, Value *WideWord, Value *Updated, const PartwordMaskValues &PMV)
static void copyMetadataForAtomic(Instruction &Dest, const Instruction &Source)
Copy metadata that's safe to preserve when widening atomics.
static ArrayRef< RTLIB::Libcall > GetRMWLibcall(AtomicRMWInst::BinOp Op)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
static bool isIdempotentRMW(AtomicRMWInst &RMWI)
Return true if and only if the given instruction does not modify the memory location referenced.
Machine Check Debug Module
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
This file defines the SmallVector class.
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
void setAlignment(Align Align)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
AtomicOrdering getMergedOrdering() const
Returns a single ordering which is at least as strong as both the success and failure orderings for t...
void setWeak(bool IsWeak)
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
Value * getCompareOperand()
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
Value * getPointerOperand()
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isWeak() const
Return true if this cmpxchg may spuriously fail.
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
AtomicOrdering getSuccessOrdering() const
Returns the success ordering constraint of this cmpxchg instruction.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this cmpxchg instruction.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
Value * getPointerOperand()
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
InstListType::reverse_iterator reverse_iterator
void setAttributes(AttributeList A)
Set the attributes for this call.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
BasicBlockListType::iterator iterator
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateLifetimeStart(Value *Ptr)
Create a lifetime.start intrinsic.
LLVM_ABI CallInst * CreateLifetimeEnd(Value *Ptr)
Create a lifetime.end intrinsic.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
UnreachableInst * CreateUnreachable()
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
BasicBlock * GetInsertBlock() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void moveAfter(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void getSyncScopeNames(SmallVectorImpl< StringRef > &SSNs) const
getSyncScopeNames - Populates client supplied SmallVector with synchronization scope names registered...
Tracks which library functions to use for a particular subtarget.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
Record a mapping from subtarget to LibcallLoweringInfo.
const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const
An instruction for reading from memory.
Value * getPointerOperand()
bool isVolatile() const
Return true if this is a load from a volatile memory location.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
void setVolatile(bool V)
Specify whether this is a volatile load or not.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setVolatile(bool V)
Specify whether this is a volatile store or not.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
virtual Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const
Perform a store-conditional operation to Addr.
EVT getMemValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
virtual void emitBitTestAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a bit test atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
virtual bool shouldInsertFencesForAtomic(const Instruction *I) const
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
virtual AtomicOrdering atomicOperationOrderAfterFenceSplit(const Instruction *I) const
virtual void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const
Perform a cmpxchg expansion using a target-specific method.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const
Perform a masked atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
virtual void emitExpandAtomicRMW(AtomicRMWInst *AI) const
Perform a atomicrmw expansion using a target-specific way.
virtual void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const
virtual void emitExpandAtomicStore(StoreInst *SI) const
Perform a atomic store using a target-specific way.
virtual AtomicExpansionKind shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const
Returns how the given atomic atomicrmw should be cast by the IR-level AtomicExpand pass.
virtual bool shouldInsertTrailingSeqCstFenceForAtomicStore(const Instruction *I) const
Whether AtomicExpandPass should automatically insert a seq_cst trailing fence without reducing the or...
virtual AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const
Perform a masked cmpxchg using a target-specific intrinsic.
unsigned getMaxAtomicSizeInBitsSupported() const
Returns the maximum atomic operation size (in bits) supported by the backend.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual void emitExpandAtomicLoad(LoadInst *LI) const
Perform a atomic load using a target-specific way.
virtual AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
virtual void emitCmpArithAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a atomicrmw which the result is only used by comparison, using a target-specific intrinsic.
virtual AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be cast by the IR-level AtomicExpand pass into.
virtual Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
virtual AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be cast by the IR-level AtomicExpand pass.
virtual Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
Inserts in the IR a target-specific intrinsic specifying a fence.
virtual LoadInst * lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const
On some platforms, an AtomicRMW that never actually modifies the value (such as fetch_add of 0) can b...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
bool isReleaseOrStronger(AtomicOrdering AO)
AtomicOrderingCABI toCABI(AtomicOrdering AO)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.