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);
173struct ReplacementIRBuilder
174 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
176 MDNode *PCSectionsMD =
nullptr;
185 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
186 this->setIsFPConstrained(
true);
188 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
189 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
194 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
195 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
201char AtomicExpandLegacy::ID = 0;
206 "Expand Atomic instructions",
false,
false)
215 return DL.getTypeStoreSize(LI->getType());
220 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
237 Source.getAllMetadata(MD);
241 for (
auto [
ID,
N] : MD) {
243 case LLVMContext::MD_dbg:
244 case LLVMContext::MD_tbaa:
245 case LLVMContext::MD_tbaa_struct:
246 case LLVMContext::MD_alias_scope:
247 case LLVMContext::MD_noalias:
248 case LLVMContext::MD_noalias_addrspace:
249 case LLVMContext::MD_access_group:
250 case LLVMContext::MD_mmra:
254 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
256 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
266template <
typename Inst>
269 Align Alignment =
I->getAlign();
271 return Alignment >=
Size &&
Size <= MaxSize;
274template <
typename Inst>
278 Align Alignment =
I->getAlign();
279 bool NeedSeparator =
false;
281 if (Alignment <
Size) {
282 OS <<
"instruction alignment " << Alignment.
value()
283 <<
" is smaller than the required " <<
Size
284 <<
"-byte alignment for this atomic operation";
285 NeedSeparator =
true;
289 if (
Size > MaxSize) {
292 OS <<
"target supports atomics up to " << MaxSize
293 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
297template <
typename Inst>
298void AtomicExpandImpl::handleUnsupportedAtomicSize(
301 SmallString<128> FailureReason;
302 raw_svector_ostream OS(FailureReason);
304 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
308bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
314 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
315 TrailingFence->moveAfter(AtomicI);
321template <
typename AtomicInst>
322bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
323 bool OrderingRequiresFence,
326 if (OrderingRequiresFence && ShouldInsertFences) {
328 AtomicI->setOrdering(NewOrdering);
329 return bracketInstWithFences(AtomicI, FenceOrdering);
331 if (!ShouldInsertFences)
332 return tryInsertTrailingSeqCstFence(AtomicI);
336bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
342 expandAtomicLoadToLibcall(LI);
346 bool MadeChange =
false;
348 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
349 LI = convertAtomicLoadToIntegerType(LI);
353 MadeChange |= tryInsertFencesForAtomic(
356 MadeChange |= tryExpandAtomicLoad(LI);
365 expandAtomicStoreToLibcall(SI);
369 bool MadeChange =
false;
371 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
372 SI = convertAtomicStoreToIntegerType(SI);
376 MadeChange |= tryInsertFencesForAtomic(
379 MadeChange |= tryExpandAtomicStore(SI);
385 expandAtomicRMWToLibcall(RMWI);
389 bool MadeChange =
false;
391 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
392 RMWI = convertAtomicXchgToIntegerType(RMWI);
396 MadeChange |= tryInsertFencesForAtomic(
406 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
407 tryExpandAtomicRMW(RMWI);
413 expandAtomicCASToLibcall(CASI);
419 bool MadeChange =
false;
420 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
423 CASI = convertCmpXchgToIntegerType(CASI);
429 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
440 CASI->setSuccessOrdering(CASOrdering);
441 CASI->setFailureOrdering(CASOrdering);
442 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
444 }
else if (CmpXchgExpansion !=
445 TargetLoweringBase::AtomicExpansionKind::LLSC) {
447 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
450 MadeChange |= tryExpandAtomicCmpXchg(CASI);
457bool AtomicExpandImpl::run(Function &
F,
458 const ModuleLibcallLoweringInfo &LibcallResult,
459 const TargetMachine *TM) {
461 if (!Subtarget->enableAtomicExpand())
463 TLI = Subtarget->getTargetLowering();
465 DL = &
F.getDataLayout();
467 bool MadeChange =
false;
479 if (processAtomicInstr(&Inst)) {
491bool AtomicExpandLegacy::runOnFunction(Function &
F) {
493 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
496 auto *TM = &TPC->getTM<TargetMachine>();
498 const ModuleLibcallLoweringInfo &LibcallResult =
499 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
501 return AE.run(
F, LibcallResult, TM);
505 return new AtomicExpandLegacy();
515 if (!LibcallResult) {
517 "' analysis required");
523 bool Changed = AE.run(
F, *LibcallResult, TM);
530bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
532 ReplacementIRBuilder Builder(
I, *
DL);
542 return (LeadingFence || TrailingFence);
557LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
559 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
561 ReplacementIRBuilder Builder(LI, *
DL);
565 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
566 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
569 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
570 : Builder.CreateBitCast(NewLI, LI->
getType());
577AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
582 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
584 ReplacementIRBuilder Builder(RMWI, *
DL);
589 ? Builder.CreatePtrToInt(Val, NewTy)
590 : Builder.CreateBitCast(Val, NewTy);
597 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
600 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
601 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
607bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
609 case TargetLoweringBase::AtomicExpansionKind::None:
611 case TargetLoweringBase::AtomicExpansionKind::LLSC:
612 expandAtomicOpToLLSC(
615 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
617 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
618 return expandAtomicLoadToLL(LI);
619 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
620 return expandAtomicLoadToCmpXchg(LI);
621 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
622 LI->
setAtomic(AtomicOrdering::NotAtomic);
624 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
632bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
634 case TargetLoweringBase::AtomicExpansionKind::None:
636 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
639 case TargetLoweringBase::AtomicExpansionKind::Expand:
640 expandAtomicStoreToXChg(SI);
642 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
643 SI->setAtomic(AtomicOrdering::NotAtomic);
650bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
651 ReplacementIRBuilder Builder(LI, *
DL);
666bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
667 ReplacementIRBuilder Builder(LI, *
DL);
669 if (Order == AtomicOrdering::Unordered)
670 Order = AtomicOrdering::Monotonic;
679 Type *CmpXchgTy = Ty;
684 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
685 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
689 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
691 Loaded = Builder.CreateBitCast(Loaded, Ty);
707StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
708 ReplacementIRBuilder Builder(SI, *
DL);
709 auto *
M =
SI->getModule();
710 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
712 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
713 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
714 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
716 Value *Addr =
SI->getPointerOperand();
718 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
719 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
720 SI->eraseFromParent();
724void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
731 ReplacementIRBuilder Builder(SI, *
DL);
733 assert(Ordering != AtomicOrdering::NotAtomic);
735 ? AtomicOrdering::Monotonic
737 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
739 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
741 SI->eraseFromParent();
744 tryExpandAtomicRMW(AI);
759 NewVal = Builder.CreateBitCast(NewVal, IntTy);
760 Loaded = Builder.CreateBitCast(Loaded, IntTy);
764 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
770 Success = Builder.CreateExtractValue(Pair, 1,
"success");
771 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
774 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
777bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
781 case TargetLoweringBase::AtomicExpansionKind::None:
783 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
786 if (ValueSize < MinCASSize) {
787 expandPartwordAtomicRMW(AI,
788 TargetLoweringBase::AtomicExpansionKind::LLSC);
790 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
799 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
802 if (ValueSize < MinCASSize) {
803 expandPartwordAtomicRMW(AI,
804 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
813 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
814 <<
"A compare and swap loop was generated for an atomic "
816 << MemScope <<
" memory scope";
822 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
825 if (ValueSize < MinCASSize) {
830 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
834 expandAtomicRMWToMaskedIntrinsic(AI);
837 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
841 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
845 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
847 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
857struct PartwordMaskValues {
859 Type *WordType =
nullptr;
861 Type *IntValueType =
nullptr;
862 Value *AlignedAddr =
nullptr;
863 Align AlignedAddrAlignment;
865 Value *ShiftAmt =
nullptr;
866 Value *Mask =
nullptr;
867 Value *Inv_Mask =
nullptr;
871raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
872 auto PrintObj = [&
O](
auto *
V) {
879 O <<
"PartwordMaskValues {\n";
881 PrintObj(PMV.WordType);
883 PrintObj(PMV.ValueType);
884 O <<
" AlignedAddr: ";
885 PrintObj(PMV.AlignedAddr);
886 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
888 PrintObj(PMV.ShiftAmt);
892 PrintObj(PMV.Inv_Mask);
918 unsigned MinWordSize) {
919 PartwordMaskValues PMV;
924 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
926 PMV.ValueType = PMV.IntValueType =
ValueType;
931 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
933 if (PMV.ValueType == PMV.WordType) {
934 PMV.AlignedAddr = Addr;
935 PMV.AlignedAddrAlignment = AddrAlign;
936 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
937 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
941 PMV.AlignedAddrAlignment =
Align(MinWordSize);
943 assert(ValueSize < MinWordSize);
946 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
949 if (AddrAlign < MinWordSize) {
950 PMV.AlignedAddr = Builder.CreateIntrinsic(
951 Intrinsic::ptrmask, {PtrTy, IntTy},
953 nullptr,
"AlignedAddr");
955 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
956 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
959 PMV.AlignedAddr = Addr;
963 if (
DL.isLittleEndian()) {
965 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
968 PMV.ShiftAmt = Builder.CreateShl(
969 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
972 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
973 PMV.Mask = Builder.CreateShl(
974 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
977 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
983 const PartwordMaskValues &PMV) {
984 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
985 if (PMV.WordType == PMV.ValueType)
988 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
989 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
990 return Builder.CreateBitCast(Trunc, PMV.ValueType);
994 Value *Updated,
const PartwordMaskValues &PMV) {
995 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
996 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
997 if (PMV.WordType == PMV.ValueType)
1000 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1002 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1004 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1005 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1006 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1016 const PartwordMaskValues &PMV) {
1022 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1023 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
1035 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1036 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1037 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1076void AtomicExpandImpl::expandPartwordAtomicRMW(
1082 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1088 ReplacementIRBuilder Builder(AI, *
DL);
1090 PartwordMaskValues PMV =
1094 Value *ValOperand_Shifted =
nullptr;
1098 ValOperand_Shifted =
1099 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1100 "ValOperand_Shifted");
1103 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1109 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1110 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1111 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1115 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1116 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1117 PMV.AlignedAddrAlignment, MemOpOrder,
1127AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1128 ReplacementIRBuilder Builder(AI, *
DL);
1133 "Unable to widen operation");
1135 PartwordMaskValues PMV =
1139 Value *ValOperand_Shifted =
1141 PMV.ShiftAmt,
"ValOperand_Shifted");
1147 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1149 NewOperand = ValOperand_Shifted;
1152 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1164bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1206 ReplacementIRBuilder Builder(CI, *
DL);
1217 std::prev(BB->
end())->eraseFromParent();
1220 PartwordMaskValues PMV =
1225 Value *NewVal_Shifted =
1227 Value *Cmp_Shifted =
1232 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1233 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1238 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1239 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1252 processAtomicInstr(InitLoaded);
1256 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1257 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1259 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1287 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1302void AtomicExpandImpl::expandAtomicOpToLLSC(
1303 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1305 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1306 ReplacementIRBuilder Builder(
I, *
DL);
1307 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1308 MemOpOrder, PerformOp);
1310 I->replaceAllUsesWith(Loaded);
1311 I->eraseFromParent();
1314void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1315 ReplacementIRBuilder Builder(AI, *
DL);
1317 PartwordMaskValues PMV =
1327 CastOp = Instruction::SExt;
1331 PMV.ShiftAmt,
"ValOperand_Shifted");
1333 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1340void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1341 AtomicCmpXchgInst *CI) {
1342 ReplacementIRBuilder Builder(CI, *
DL);
1355 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1361 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1368Value *AtomicExpandImpl::insertRMWLLSCLoop(
1369 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1371 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1376 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1377 "Expected at least natural alignment at this point.");
1397 std::prev(BB->
end())->eraseFromParent();
1405 Value *NewVal = PerformOp(Builder, Loaded);
1407 Value *StoreSuccess =
1429AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1432 M->getDataLayout());
1434 ReplacementIRBuilder Builder(CI, *
DL);
1446 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1462bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1468 LLVMContext &Ctx =
F->getContext();
1475 ? AtomicOrdering::Monotonic
1487 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1488 SuccessOrder != AtomicOrdering::Monotonic &&
1489 SuccessOrder != AtomicOrdering::Acquire &&
1494 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1548 auto ReleasedLoadBB =
1552 auto ReleasingStoreBB =
1556 ReplacementIRBuilder Builder(CI, *
DL);
1561 std::prev(BB->
end())->eraseFromParent();
1563 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1566 PartwordMaskValues PMV =
1573 Value *UnreleasedLoad =
1574 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1575 Value *UnreleasedLoadExtract =
1582 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1583 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1586 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1591 PHINode *LoadedTryStore =
1592 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1593 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1594 Value *NewValueInsert =
1597 PMV.AlignedAddr, MemOpOrder);
1599 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1600 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1602 CI->
isWeak() ? FailureBB : RetryBB,
1603 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1607 if (HasReleasedLoadBB) {
1609 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1617 ShouldStore, TryStoreBB, NoStoreBB,
1618 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1620 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1627 if (ShouldInsertFencesForAtomic ||
1633 PHINode *LoadedNoStore =
1635 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1636 if (HasReleasedLoadBB)
1637 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1646 PHINode *LoadedFailure =
1648 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1650 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1651 if (ShouldInsertFencesForAtomic)
1660 PHINode *LoadedExit =
1662 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1663 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1670 Value *LoadedFull = LoadedExit;
1678 for (
auto *User : CI->
users()) {
1684 "weird extraction from { iN, i1 }");
1695 for (
auto *EV : PrunedInsts)
1712bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1727 return C->isMinusOne();
1729 return C->isMaxValue(
true);
1731 return C->isMinValue(
true);
1733 return C->isMaxValue(
false);
1735 return C->isMinValue(
false);
1741bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1743 tryExpandAtomicLoad(ResultingLoad);
1749Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1750 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1752 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1753 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1780 std::prev(BB->
end())->eraseFromParent();
1788 Loaded->addIncoming(InitLoaded, BB);
1797 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1801 processAtomicInstr(InitLoaded);
1804 Value *NewVal = PerformOp(Builder, Loaded);
1806 Value *NewLoaded =
nullptr;
1809 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1810 MemOpOrder == AtomicOrdering::Unordered
1811 ? AtomicOrdering::Monotonic
1813 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1816 Loaded->addIncoming(NewLoaded, LoopBB);
1829bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1836 case TargetLoweringBase::AtomicExpansionKind::None:
1837 if (ValueSize < MinCASSize)
1838 return expandPartwordCmpXchg(CI);
1840 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1841 return expandAtomicCmpXchg(CI);
1843 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1844 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1846 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1848 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1855bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1856 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1863 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1866 [&](IRBuilderBase &Builder,
Value *Loaded) {
1867 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1868 AI->getValOperand());
1891 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1892 return Alignment >=
Size &&
1894 Size <= LargestSize;
1897void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1898 static const RTLIB::Libcall Libcalls[6] = {
1899 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1900 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1903 bool Expanded = expandAtomicOpToLibcall(
1904 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1905 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1907 handleUnsupportedAtomicSize(
I,
"atomic load");
1910void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1911 static const RTLIB::Libcall Libcalls[6] = {
1912 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1913 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1916 bool Expanded = expandAtomicOpToLibcall(
1917 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1918 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1920 handleUnsupportedAtomicSize(
I,
"atomic store");
1923void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
1924 const Twine &AtomicOpName,
1925 Instruction *DiagnosticInst) {
1926 static const RTLIB::Libcall Libcalls[6] = {
1927 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1928 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1929 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1932 bool Expanded = expandAtomicOpToLibcall(
1933 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1934 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1937 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
1941 static const RTLIB::Libcall LibcallsXchg[6] = {
1942 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1943 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1944 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1945 static const RTLIB::Libcall LibcallsAdd[6] = {
1946 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1947 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1948 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1949 static const RTLIB::Libcall LibcallsSub[6] = {
1950 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1951 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1952 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1953 static const RTLIB::Libcall LibcallsAnd[6] = {
1954 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1955 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1956 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1957 static const RTLIB::Libcall LibcallsOr[6] = {
1958 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1959 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1960 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1961 static const RTLIB::Libcall LibcallsXor[6] = {
1962 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1963 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1964 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1965 static const RTLIB::Libcall LibcallsNand[6] = {
1966 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1967 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1968 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2009void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2015 if (!Libcalls.
empty())
2016 Success = expandAtomicOpToLibcall(
2017 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2018 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2025 expandAtomicRMWToCmpXchg(
2026 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2029 Value *&NewLoaded, Instruction *MetadataSrc) {
2032 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2042 expandAtomicCASToLibcall(
2056bool AtomicExpandImpl::expandAtomicOpToLibcall(
2057 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2062 LLVMContext &Ctx =
I->getContext();
2064 const DataLayout &
DL =
M->getDataLayout();
2066 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2069 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2071 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2081 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2085 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2087 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2090 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2092 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2094 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2096 RTLIB::Libcall RTLibType;
2097 if (UseSizedLibcall) {
2100 RTLibType = Libcalls[1];
2103 RTLibType = Libcalls[2];
2106 RTLibType = Libcalls[3];
2109 RTLibType = Libcalls[4];
2112 RTLibType = Libcalls[5];
2115 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2116 RTLibType = Libcalls[0];
2123 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2124 if (LibcallImpl == RTLIB::Unsupported) {
2155 AllocaInst *AllocaCASExpected =
nullptr;
2156 AllocaInst *AllocaValue =
nullptr;
2157 AllocaInst *AllocaResult =
nullptr;
2164 if (!UseSizedLibcall) {
2166 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2174 Value *PtrVal = PointerOperand;
2176 Args.push_back(PtrVal);
2180 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2184 Args.push_back(AllocaCASExpected);
2189 if (UseSizedLibcall) {
2192 Args.push_back(IntValue);
2194 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2198 Args.push_back(AllocaValue);
2203 if (!CASExpected && HasResult && !UseSizedLibcall) {
2204 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2207 Args.push_back(AllocaResult);
2211 Args.push_back(OrderingVal);
2215 Args.push_back(Ordering2Val);
2219 ResultTy = Type::getInt1Ty(Ctx);
2220 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2221 }
else if (HasResult && UseSizedLibcall)
2222 ResultTy = SizedIntTy;
2224 ResultTy = Type::getVoidTy(Ctx);
2228 for (
Value *Arg : Args)
2230 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2231 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2239 if (ValueOperand && !UseSizedLibcall)
2245 Type *FinalResultTy =
I->getType();
2248 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2253 }
else if (HasResult) {
2255 if (UseSizedLibcall) {
2259 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2260 unsigned AS = PtrTy->getAddressSpace();
2262 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2271 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.
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.
Record a mapping from subtarget to LibcallLoweringInfo.
const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const
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.