60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
83 Ctx.
emitError(DiagnosticInst ? DiagnosticInst : &FailedInst,
Msg);
85 if (!FailedInst.getType()->isVoidTy())
87 FailedInst.eraseFromParent();
90 template <
typename Inst>
91 void handleUnsupportedAtomicSize(Inst *
I,
const Twine &AtomicOpName,
95 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
96 template <
typename AtomicInst>
97 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
101 bool tryExpandAtomicLoad(
LoadInst *LI);
102 bool expandAtomicLoadToLL(
LoadInst *LI);
103 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
113 void expandAtomicOpToLLSC(
117 void expandPartwordAtomicRMW(
125 Value *insertRMWCmpXchgLoop(
129 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
141 void expandAtomicLoadToLibcall(
LoadInst *LI);
142 void expandAtomicStoreToLibcall(
StoreInst *LI);
145 const Twine &AtomicOpName =
"cmpxchg",
149 CreateCmpXchgInstFun CreateCmpXchg);
174struct ReplacementIRBuilder
175 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
177 MDNode *PCSectionsMD =
nullptr;
186 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
187 this->setIsFPConstrained(
true);
189 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
190 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
195 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
196 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
202char AtomicExpandLegacy::ID = 0;
207 "Expand Atomic instructions",
false,
false)
216 return DL.getTypeStoreSize(LI->getType());
221 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
238 Source.getAllMetadata(MD);
242 for (
auto [
ID,
N] : MD) {
244 case LLVMContext::MD_dbg:
245 case LLVMContext::MD_tbaa:
246 case LLVMContext::MD_tbaa_struct:
247 case LLVMContext::MD_alias_scope:
248 case LLVMContext::MD_noalias:
249 case LLVMContext::MD_noalias_addrspace:
250 case LLVMContext::MD_access_group:
251 case LLVMContext::MD_mmra:
255 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
257 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
267template <
typename Inst>
270 Align Alignment =
I->getAlign();
272 return Alignment >=
Size &&
Size <= MaxSize;
275template <
typename Inst>
279 Align Alignment =
I->getAlign();
280 bool NeedSeparator =
false;
282 if (Alignment <
Size) {
283 OS <<
"instruction alignment " << Alignment.
value()
284 <<
" is smaller than the required " <<
Size
285 <<
"-byte alignment for this atomic operation";
286 NeedSeparator =
true;
290 if (
Size > MaxSize) {
293 OS <<
"target supports atomics up to " << MaxSize
294 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
298template <
typename Inst>
299void AtomicExpandImpl::handleUnsupportedAtomicSize(
302 SmallString<128> FailureReason;
303 raw_svector_ostream OS(FailureReason);
305 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
309bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
315 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
316 TrailingFence->moveAfter(AtomicI);
322template <
typename AtomicInst>
323bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
324 bool OrderingRequiresFence,
327 if (OrderingRequiresFence && ShouldInsertFences) {
329 AtomicI->setOrdering(NewOrdering);
330 return bracketInstWithFences(AtomicI, FenceOrdering);
332 if (!ShouldInsertFences)
333 return tryInsertTrailingSeqCstFence(AtomicI);
337bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
343 expandAtomicLoadToLibcall(LI);
347 bool MadeChange =
false;
349 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
350 LI = convertAtomicLoadToIntegerType(LI);
354 MadeChange |= tryInsertFencesForAtomic(
357 MadeChange |= tryExpandAtomicLoad(LI);
366 expandAtomicStoreToLibcall(SI);
370 bool MadeChange =
false;
372 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
373 SI = convertAtomicStoreToIntegerType(SI);
377 MadeChange |= tryInsertFencesForAtomic(
380 MadeChange |= tryExpandAtomicStore(SI);
386 expandAtomicRMWToLibcall(RMWI);
390 bool MadeChange =
false;
392 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
393 RMWI = convertAtomicXchgToIntegerType(RMWI);
397 MadeChange |= tryInsertFencesForAtomic(
407 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
408 tryExpandAtomicRMW(RMWI);
414 expandAtomicCASToLibcall(CASI);
420 bool MadeChange =
false;
421 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
424 CASI = convertCmpXchgToIntegerType(CASI);
430 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
441 CASI->setSuccessOrdering(CASOrdering);
442 CASI->setFailureOrdering(CASOrdering);
443 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
445 }
else if (CmpXchgExpansion !=
446 TargetLoweringBase::AtomicExpansionKind::LLSC) {
448 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
451 MadeChange |= tryExpandAtomicCmpXchg(CASI);
458bool AtomicExpandImpl::run(
459 Function &
F,
const LibcallLoweringModuleAnalysisResult &LibcallResult,
460 const TargetMachine *TM) {
462 if (!Subtarget->enableAtomicExpand())
464 TLI = Subtarget->getTargetLowering();
466 DL = &
F.getDataLayout();
468 bool MadeChange =
false;
480 if (processAtomicInstr(&Inst)) {
492bool AtomicExpandLegacy::runOnFunction(Function &
F) {
494 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
497 auto *TM = &TPC->getTM<TargetMachine>();
499 const LibcallLoweringModuleAnalysisResult &LibcallResult =
500 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
502 return AE.run(
F, LibcallResult, TM);
506 return new AtomicExpandLegacy();
516 if (!LibcallResult) {
518 "' analysis required");
524 bool Changed = AE.run(
F, *LibcallResult, TM);
531bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
533 ReplacementIRBuilder Builder(
I, *
DL);
543 return (LeadingFence || TrailingFence);
558LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
560 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
562 ReplacementIRBuilder Builder(LI, *
DL);
566 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
567 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
570 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
571 : Builder.CreateBitCast(NewLI, LI->
getType());
578AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
583 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
585 ReplacementIRBuilder Builder(RMWI, *
DL);
590 ? Builder.CreatePtrToInt(Val, NewTy)
591 : Builder.CreateBitCast(Val, NewTy);
598 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
601 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
602 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
608bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
610 case TargetLoweringBase::AtomicExpansionKind::None:
612 case TargetLoweringBase::AtomicExpansionKind::LLSC:
613 expandAtomicOpToLLSC(
616 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
618 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
619 return expandAtomicLoadToLL(LI);
620 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
621 return expandAtomicLoadToCmpXchg(LI);
622 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
623 LI->
setAtomic(AtomicOrdering::NotAtomic);
625 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
633bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
635 case TargetLoweringBase::AtomicExpansionKind::None:
637 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
640 case TargetLoweringBase::AtomicExpansionKind::Expand:
641 expandAtomicStoreToXChg(SI);
643 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
644 SI->setAtomic(AtomicOrdering::NotAtomic);
651bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
652 ReplacementIRBuilder Builder(LI, *
DL);
667bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
668 ReplacementIRBuilder Builder(LI, *
DL);
670 if (Order == AtomicOrdering::Unordered)
671 Order = AtomicOrdering::Monotonic;
680 Type *CmpXchgTy = Ty;
685 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
686 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
690 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
692 Loaded = Builder.CreateBitCast(Loaded, Ty);
708StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
709 ReplacementIRBuilder Builder(SI, *
DL);
710 auto *
M =
SI->getModule();
711 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
713 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
714 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
715 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
717 Value *Addr =
SI->getPointerOperand();
719 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
720 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
721 SI->eraseFromParent();
725void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
732 ReplacementIRBuilder Builder(SI, *
DL);
734 assert(Ordering != AtomicOrdering::NotAtomic);
736 ? AtomicOrdering::Monotonic
738 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
740 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
742 SI->eraseFromParent();
745 tryExpandAtomicRMW(AI);
760 NewVal = Builder.CreateBitCast(NewVal, IntTy);
761 Loaded = Builder.CreateBitCast(Loaded, IntTy);
765 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
771 Success = Builder.CreateExtractValue(Pair, 1,
"success");
772 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
775 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
778bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
782 case TargetLoweringBase::AtomicExpansionKind::None:
784 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
787 if (ValueSize < MinCASSize) {
788 expandPartwordAtomicRMW(AI,
789 TargetLoweringBase::AtomicExpansionKind::LLSC);
791 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
800 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
803 if (ValueSize < MinCASSize) {
804 expandPartwordAtomicRMW(AI,
805 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
814 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
815 <<
"A compare and swap loop was generated for an atomic "
817 << MemScope <<
" memory scope";
823 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
826 if (ValueSize < MinCASSize) {
831 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
835 expandAtomicRMWToMaskedIntrinsic(AI);
838 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
842 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
846 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
848 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
858struct PartwordMaskValues {
860 Type *WordType =
nullptr;
862 Type *IntValueType =
nullptr;
863 Value *AlignedAddr =
nullptr;
864 Align AlignedAddrAlignment;
866 Value *ShiftAmt =
nullptr;
867 Value *Mask =
nullptr;
868 Value *Inv_Mask =
nullptr;
872raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
873 auto PrintObj = [&
O](
auto *
V) {
880 O <<
"PartwordMaskValues {\n";
882 PrintObj(PMV.WordType);
884 PrintObj(PMV.ValueType);
885 O <<
" AlignedAddr: ";
886 PrintObj(PMV.AlignedAddr);
887 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
889 PrintObj(PMV.ShiftAmt);
893 PrintObj(PMV.Inv_Mask);
919 unsigned MinWordSize) {
920 PartwordMaskValues PMV;
925 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
927 PMV.ValueType = PMV.IntValueType =
ValueType;
932 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
934 if (PMV.ValueType == PMV.WordType) {
935 PMV.AlignedAddr = Addr;
936 PMV.AlignedAddrAlignment = AddrAlign;
937 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
938 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
942 PMV.AlignedAddrAlignment =
Align(MinWordSize);
944 assert(ValueSize < MinWordSize);
947 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
950 if (AddrAlign < MinWordSize) {
951 PMV.AlignedAddr = Builder.CreateIntrinsic(
952 Intrinsic::ptrmask, {PtrTy, IntTy},
954 nullptr,
"AlignedAddr");
956 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
957 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
960 PMV.AlignedAddr = Addr;
964 if (
DL.isLittleEndian()) {
966 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
969 PMV.ShiftAmt = Builder.CreateShl(
970 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
973 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
974 PMV.Mask = Builder.CreateShl(
975 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
978 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
984 const PartwordMaskValues &PMV) {
985 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
986 if (PMV.WordType == PMV.ValueType)
989 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
990 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
991 return Builder.CreateBitCast(Trunc, PMV.ValueType);
995 Value *Updated,
const PartwordMaskValues &PMV) {
996 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
997 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
998 if (PMV.WordType == PMV.ValueType)
1001 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1003 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1005 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1006 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1007 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1017 const PartwordMaskValues &PMV) {
1023 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1024 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
1036 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1037 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1038 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1077void AtomicExpandImpl::expandPartwordAtomicRMW(
1083 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1089 ReplacementIRBuilder Builder(AI, *
DL);
1091 PartwordMaskValues PMV =
1095 Value *ValOperand_Shifted =
nullptr;
1099 ValOperand_Shifted =
1100 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1101 "ValOperand_Shifted");
1104 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1110 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1111 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1112 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1116 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1117 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1118 PMV.AlignedAddrAlignment, MemOpOrder,
1128AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1129 ReplacementIRBuilder Builder(AI, *
DL);
1134 "Unable to widen operation");
1136 PartwordMaskValues PMV =
1140 Value *ValOperand_Shifted =
1142 PMV.ShiftAmt,
"ValOperand_Shifted");
1148 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1150 NewOperand = ValOperand_Shifted;
1153 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1165bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1207 ReplacementIRBuilder Builder(CI, *
DL);
1218 std::prev(BB->
end())->eraseFromParent();
1221 PartwordMaskValues PMV =
1226 Value *NewVal_Shifted =
1228 Value *Cmp_Shifted =
1233 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1234 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1239 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1240 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1253 processAtomicInstr(InitLoaded);
1257 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1258 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1260 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1288 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1303void AtomicExpandImpl::expandAtomicOpToLLSC(
1304 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1306 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1307 ReplacementIRBuilder Builder(
I, *
DL);
1308 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1309 MemOpOrder, PerformOp);
1311 I->replaceAllUsesWith(Loaded);
1312 I->eraseFromParent();
1315void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1316 ReplacementIRBuilder Builder(AI, *
DL);
1318 PartwordMaskValues PMV =
1328 CastOp = Instruction::SExt;
1332 PMV.ShiftAmt,
"ValOperand_Shifted");
1334 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1341void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1342 AtomicCmpXchgInst *CI) {
1343 ReplacementIRBuilder Builder(CI, *
DL);
1356 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1362 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1369Value *AtomicExpandImpl::insertRMWLLSCLoop(
1370 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1372 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1377 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1378 "Expected at least natural alignment at this point.");
1398 std::prev(BB->
end())->eraseFromParent();
1406 Value *NewVal = PerformOp(Builder, Loaded);
1408 Value *StoreSuccess =
1430AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1433 M->getDataLayout());
1435 ReplacementIRBuilder Builder(CI, *
DL);
1447 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1463bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1469 LLVMContext &Ctx =
F->getContext();
1476 ? AtomicOrdering::Monotonic
1488 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1489 SuccessOrder != AtomicOrdering::Monotonic &&
1490 SuccessOrder != AtomicOrdering::Acquire &&
1495 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1549 auto ReleasedLoadBB =
1553 auto ReleasingStoreBB =
1557 ReplacementIRBuilder Builder(CI, *
DL);
1562 std::prev(BB->
end())->eraseFromParent();
1564 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1567 PartwordMaskValues PMV =
1574 Value *UnreleasedLoad =
1575 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1576 Value *UnreleasedLoadExtract =
1583 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1584 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1587 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1592 PHINode *LoadedTryStore =
1593 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1594 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1595 Value *NewValueInsert =
1598 PMV.AlignedAddr, MemOpOrder);
1600 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1601 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1603 CI->
isWeak() ? FailureBB : RetryBB,
1604 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1608 if (HasReleasedLoadBB) {
1610 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1618 ShouldStore, TryStoreBB, NoStoreBB,
1619 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1621 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1628 if (ShouldInsertFencesForAtomic ||
1634 PHINode *LoadedNoStore =
1636 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1637 if (HasReleasedLoadBB)
1638 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1647 PHINode *LoadedFailure =
1649 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1651 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1652 if (ShouldInsertFencesForAtomic)
1661 PHINode *LoadedExit =
1663 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1664 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1671 Value *LoadedFull = LoadedExit;
1679 for (
auto *User : CI->
users()) {
1685 "weird extraction from { iN, i1 }");
1696 for (
auto *EV : PrunedInsts)
1713bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1728 return C->isMinusOne();
1730 return C->isMaxValue(
true);
1732 return C->isMinValue(
true);
1734 return C->isMaxValue(
false);
1736 return C->isMinValue(
false);
1742bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1744 tryExpandAtomicLoad(ResultingLoad);
1750Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1751 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1753 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1754 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1781 std::prev(BB->
end())->eraseFromParent();
1789 Loaded->addIncoming(InitLoaded, BB);
1798 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1802 processAtomicInstr(InitLoaded);
1805 Value *NewVal = PerformOp(Builder, Loaded);
1807 Value *NewLoaded =
nullptr;
1810 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1811 MemOpOrder == AtomicOrdering::Unordered
1812 ? AtomicOrdering::Monotonic
1814 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1817 Loaded->addIncoming(NewLoaded, LoopBB);
1830bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1837 case TargetLoweringBase::AtomicExpansionKind::None:
1838 if (ValueSize < MinCASSize)
1839 return expandPartwordCmpXchg(CI);
1841 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1842 return expandAtomicCmpXchg(CI);
1844 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1845 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1847 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1849 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1856bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1857 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1864 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1867 [&](IRBuilderBase &Builder,
Value *Loaded) {
1868 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1869 AI->getValOperand());
1892 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1893 return Alignment >=
Size &&
1895 Size <= LargestSize;
1898void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1899 static const RTLIB::Libcall Libcalls[6] = {
1900 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1901 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1904 bool Expanded = expandAtomicOpToLibcall(
1905 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1906 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1908 handleUnsupportedAtomicSize(
I,
"atomic load");
1911void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1912 static const RTLIB::Libcall Libcalls[6] = {
1913 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1914 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1917 bool Expanded = expandAtomicOpToLibcall(
1918 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1919 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1921 handleUnsupportedAtomicSize(
I,
"atomic store");
1924void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
1925 const Twine &AtomicOpName,
1926 Instruction *DiagnosticInst) {
1927 static const RTLIB::Libcall Libcalls[6] = {
1928 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1929 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1930 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1933 bool Expanded = expandAtomicOpToLibcall(
1934 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1935 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1938 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
1942 static const RTLIB::Libcall LibcallsXchg[6] = {
1943 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1944 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1945 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1946 static const RTLIB::Libcall LibcallsAdd[6] = {
1947 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1948 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1949 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1950 static const RTLIB::Libcall LibcallsSub[6] = {
1951 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1952 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1953 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1954 static const RTLIB::Libcall LibcallsAnd[6] = {
1955 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1956 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1957 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1958 static const RTLIB::Libcall LibcallsOr[6] = {
1959 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1960 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1961 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1962 static const RTLIB::Libcall LibcallsXor[6] = {
1963 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1964 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1965 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1966 static const RTLIB::Libcall LibcallsNand[6] = {
1967 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1968 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1969 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2010void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2016 if (!Libcalls.
empty())
2017 Success = expandAtomicOpToLibcall(
2018 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2019 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2026 expandAtomicRMWToCmpXchg(
2027 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2030 Value *&NewLoaded, Instruction *MetadataSrc) {
2033 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2043 expandAtomicCASToLibcall(
2057bool AtomicExpandImpl::expandAtomicOpToLibcall(
2058 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2063 LLVMContext &Ctx =
I->getContext();
2065 const DataLayout &
DL =
M->getDataLayout();
2067 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2070 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2072 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2082 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2086 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2088 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2091 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2093 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2095 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2097 RTLIB::Libcall RTLibType;
2098 if (UseSizedLibcall) {
2101 RTLibType = Libcalls[1];
2104 RTLibType = Libcalls[2];
2107 RTLibType = Libcalls[3];
2110 RTLibType = Libcalls[4];
2113 RTLibType = Libcalls[5];
2116 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2117 RTLibType = Libcalls[0];
2124 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2125 if (LibcallImpl == RTLIB::Unsupported) {
2156 AllocaInst *AllocaCASExpected =
nullptr;
2157 AllocaInst *AllocaValue =
nullptr;
2158 AllocaInst *AllocaResult =
nullptr;
2165 if (!UseSizedLibcall) {
2167 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2175 Value *PtrVal = PointerOperand;
2177 Args.push_back(PtrVal);
2181 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2185 Args.push_back(AllocaCASExpected);
2190 if (UseSizedLibcall) {
2193 Args.push_back(IntValue);
2195 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2199 Args.push_back(AllocaValue);
2204 if (!CASExpected && HasResult && !UseSizedLibcall) {
2205 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2208 Args.push_back(AllocaResult);
2212 Args.push_back(OrderingVal);
2216 Args.push_back(Ordering2Val);
2220 ResultTy = Type::getInt1Ty(Ctx);
2221 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2222 }
else if (HasResult && UseSizedLibcall)
2223 ResultTy = SizedIntTy;
2225 ResultTy = Type::getVoidTy(Ctx);
2229 for (
Value *Arg : Args)
2231 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2232 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2240 if (ValueOperand && !UseSizedLibcall)
2246 Type *FinalResultTy =
I->getType();
2249 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2254 }
else if (HasResult) {
2256 if (UseSizedLibcall) {
2260 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2261 unsigned AS = PtrTy->getAddressSpace();
2263 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2272 I->replaceAllUsesWith(V);
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 void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, bool IsVolatile, Value *&Success, Value *&NewLoaded, Instruction *MetadataSrc)
static Value * extractMaskedValue(IRBuilderBase &Builder, Value *WideWord, const PartwordMaskValues &PMV)
Expand Atomic static false unsigned getAtomicOpSize(LoadInst *LI)
static void writeUnsupportedAtomicSizeReason(const TargetLowering *TLI, Inst *I, raw_ostream &OS)
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 SmallString class.
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()
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
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.
LLVM_ABI 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.
void setVolatile(bool V)
Specify whether this is a volatile RMW or not.
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
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
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.
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.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
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)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
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
LLVM_ABI Value * CreateBitPreservingCastChain(const DataLayout &DL, Value *V, Type *NewTy)
Create a chain of casts to convert V to NewTy, preserving the bit pattern of V.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
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="")
void setIsFPConstrained(bool IsCon)
Enable/Disable use of constrained floating point math.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
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)
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="")
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, bool Elementwise=false)
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.
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.
LoadStoreInstProperties getProperties() const
Returns the properties of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
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.
virtual bool shouldIssueAtomicLoadForAtomicEmulationLoop(void) const
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.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI 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 >
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
LLVM_ABI 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.
LLVM_ABI 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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
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.