60#define DEBUG_TYPE "atomic-expand"
64class AtomicExpandImpl {
84 Ctx.
emitError(DiagnosticInst ? DiagnosticInst : &FailedInst,
Msg);
86 if (!FailedInst.getType()->isVoidTy())
88 FailedInst.eraseFromParent();
91 template <
typename Inst>
92 void handleUnsupportedAtomicSize(Inst *
I,
const Twine &AtomicOpName,
96 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
97 template <
typename AtomicInst>
98 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
102 bool tryExpandAtomicLoad(
LoadInst *LI);
103 bool expandAtomicLoadToLL(
LoadInst *LI);
104 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
115 void expandAtomicOpToLLSC(
119 void expandPartwordAtomicRMW(
127 Value *insertRMWCmpXchgLoop(
131 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
143 void expandAtomicLoadToLibcall(
LoadInst *LI);
144 void expandAtomicStoreToLibcall(
StoreInst *LI);
147 const Twine &AtomicOpName =
"cmpxchg",
151 CreateCmpXchgInstFun CreateCmpXchg);
176struct ReplacementIRBuilder
177 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
179 MDNode *PCSectionsMD =
nullptr;
188 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
189 this->setIsFPConstrained(
true);
191 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
192 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
197 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
198 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
204char AtomicExpandLegacy::ID = 0;
209 "Expand Atomic instructions",
false,
false)
218 return DL.getTypeStoreSize(LI->getType());
223 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
240 Source.getAllMetadata(MD);
244 for (
auto [ID,
N] : MD) {
246 case LLVMContext::MD_dbg:
247 case LLVMContext::MD_tbaa:
248 case LLVMContext::MD_tbaa_struct:
249 case LLVMContext::MD_alias_scope:
250 case LLVMContext::MD_mem_cache_hint:
251 case LLVMContext::MD_noalias:
252 case LLVMContext::MD_noalias_addrspace:
253 case LLVMContext::MD_access_group:
254 case LLVMContext::MD_mmra:
258 if (ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
260 else if (ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
270template <
typename Inst>
273 Align Alignment =
I->getAlign();
275 return Alignment >=
Size &&
Size <= MaxSize;
278template <
typename Inst>
282 Align Alignment =
I->getAlign();
283 bool NeedSeparator =
false;
285 if (Alignment <
Size) {
286 OS <<
"instruction alignment " << Alignment.value()
287 <<
" is smaller than the required " <<
Size
288 <<
"-byte alignment for this atomic operation";
289 NeedSeparator =
true;
293 if (
Size > MaxSize) {
296 OS <<
"target supports atomics up to " << MaxSize
297 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
301template <
typename Inst>
302void AtomicExpandImpl::handleUnsupportedAtomicSize(
305 SmallString<128> FailureReason;
306 raw_svector_ostream OS(FailureReason);
308 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
312bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
318 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
319 TrailingFence->moveAfter(AtomicI);
325template <
typename AtomicInst>
326bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
327 bool OrderingRequiresFence,
330 if (OrderingRequiresFence && ShouldInsertFences) {
332 AtomicI->setOrdering(NewOrdering);
333 return bracketInstWithFences(AtomicI, FenceOrdering);
335 if (!ShouldInsertFences)
336 return tryInsertTrailingSeqCstFence(AtomicI);
343bool AtomicExpandImpl::lowerToNonAtomic(Instruction *
I) {
345 FI->eraseFromParent();
356 if (LI->isAtomic()) {
357 LI->setAtomic(AtomicOrdering::NotAtomic);
358 LI->setElementwise(
false);
366 if (
SI->isAtomic()) {
367 SI->setAtomic(AtomicOrdering::NotAtomic);
368 SI->setElementwise(
false);
378bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
380 return lowerToNonAtomic(
I);
387 expandAtomicLoadToLibcall(LI);
391 bool MadeChange =
false;
393 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
394 LI = convertAtomicLoadToIntegerType(LI);
398 MadeChange |= tryInsertFencesForAtomic(
401 MadeChange |= tryExpandAtomicLoad(LI);
410 expandAtomicStoreToLibcall(SI);
414 bool MadeChange =
false;
416 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
417 SI = convertAtomicStoreToIntegerType(SI);
421 MadeChange |= tryInsertFencesForAtomic(
424 MadeChange |= tryExpandAtomicStore(SI);
430 expandAtomicRMWToLibcall(RMWI);
434 bool MadeChange =
false;
436 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
437 RMWI = convertAtomicXchgToIntegerType(RMWI);
441 MadeChange |= tryInsertFencesForAtomic(
451 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
452 tryExpandAtomicRMW(RMWI);
458 expandAtomicCASToLibcall(CASI);
464 bool MadeChange =
false;
465 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
468 CASI = convertCmpXchgToIntegerType(CASI);
474 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
485 CASI->setSuccessOrdering(CASOrdering);
486 CASI->setFailureOrdering(CASOrdering);
487 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
489 }
else if (CmpXchgExpansion !=
490 TargetLoweringBase::AtomicExpansionKind::LLSC) {
492 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
495 MadeChange |= tryExpandAtomicCmpXchg(CASI);
503 const ModuleLibcallLoweringInfo &LibcallResult,
504 const TargetMachine *TM) {
505 SingleThreaded =
F.getParent()->getThreadModel() == ThreadModel::Single;
511 TLI = Subtarget->getTargetLowering();
513 DL = &
F.getDataLayout();
515 bool MadeChange =
false;
527 if (processAtomicInstr(&Inst)) {
539bool AtomicExpandLegacy::runOnFunction(
Function &
F) {
541 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
544 auto *TM = &TPC->getTM<TargetMachine>();
546 const ModuleLibcallLoweringInfo &LibcallResult =
547 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
549 return AE.run(
F, LibcallResult, TM);
553 return new AtomicExpandLegacy();
563 if (!LibcallResult) {
565 "' analysis required");
571 bool Changed = AE.run(
F, *LibcallResult, TM);
578bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
580 ReplacementIRBuilder Builder(
I, *
DL);
590 return (LeadingFence || TrailingFence);
605LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
607 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
609 ReplacementIRBuilder Builder(LI, *
DL);
613 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
614 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
617 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
618 : Builder.CreateBitCast(NewLI, LI->
getType());
625AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
630 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
632 ReplacementIRBuilder Builder(RMWI, *
DL);
636 Value *NewVal = Builder.CreateBitPreservingCastChain(*
DL, Val, NewTy);
643 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
646 Builder.CreateBitPreservingCastChain(*
DL, NewRMWI, RMWI->
getType());
652bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
654 case TargetLoweringBase::AtomicExpansionKind::None:
656 case TargetLoweringBase::AtomicExpansionKind::LLSC:
657 expandAtomicOpToLLSC(
660 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
662 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
663 return expandAtomicLoadToLL(LI);
664 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
665 return expandAtomicLoadToCmpXchg(LI);
666 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
667 LI->
setAtomic(AtomicOrdering::NotAtomic);
669 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
677bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
679 case TargetLoweringBase::AtomicExpansionKind::None:
681 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
684 case TargetLoweringBase::AtomicExpansionKind::Expand:
685 expandAtomicStoreToXChg(SI);
687 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
688 SI->setAtomic(AtomicOrdering::NotAtomic);
695bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
696 ReplacementIRBuilder Builder(LI, *
DL);
711bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
712 ReplacementIRBuilder Builder(LI, *
DL);
714 if (Order == AtomicOrdering::Unordered)
715 Order = AtomicOrdering::Monotonic;
724 Type *CmpXchgTy = Ty;
729 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
730 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
734 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
736 Loaded = Builder.CreateBitCast(Loaded, Ty);
752StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
753 ReplacementIRBuilder Builder(SI, *
DL);
754 auto *
M =
SI->getModule();
755 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
757 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
758 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
759 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
761 Value *Addr =
SI->getPointerOperand();
763 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
765 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
766 SI->eraseFromParent();
770void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
777 ReplacementIRBuilder Builder(SI, *
DL);
779 assert(Ordering != AtomicOrdering::NotAtomic);
781 ? AtomicOrdering::Monotonic
783 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
785 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
787 SI->eraseFromParent();
790 tryExpandAtomicRMW(AI);
805 NewVal = Builder.CreateBitCast(NewVal, IntTy);
806 Loaded = Builder.CreateBitCast(Loaded, IntTy);
810 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
816 Success = Builder.CreateExtractValue(Pair, 1,
"success");
817 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
820 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
823void AtomicExpandImpl::expandAtomicSubToAdd(AtomicRMWInst *AI) {
824 ReplacementIRBuilder Builder(AI, *
DL);
845bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
849 case TargetLoweringBase::AtomicExpansionKind::None:
851 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
854 if (ValueSize < MinCASSize) {
855 expandPartwordAtomicRMW(AI,
856 TargetLoweringBase::AtomicExpansionKind::LLSC);
858 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
867 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
870 if (ValueSize < MinCASSize) {
871 expandPartwordAtomicRMW(AI,
872 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
881 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
882 <<
"A compare and swap loop was generated for an atomic "
890 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
893 if (ValueSize < MinCASSize) {
898 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
902 expandAtomicRMWToMaskedIntrinsic(AI);
905 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
909 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
913 case TargetLoweringBase::AtomicExpansionKind::Expand:
914 expandAtomicSubToAdd(AI);
916 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
918 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
928struct PartwordMaskValues {
930 Type *WordType =
nullptr;
932 Type *IntValueType =
nullptr;
933 Value *AlignedAddr =
nullptr;
934 Align AlignedAddrAlignment;
936 Value *ShiftAmt =
nullptr;
937 Value *Mask =
nullptr;
938 Value *Inv_Mask =
nullptr;
942raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
943 auto PrintObj = [&
O](
auto *
V) {
950 O <<
"PartwordMaskValues {\n";
952 PrintObj(PMV.WordType);
954 PrintObj(PMV.ValueType);
955 O <<
" AlignedAddr: ";
956 PrintObj(PMV.AlignedAddr);
957 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
959 PrintObj(PMV.ShiftAmt);
963 PrintObj(PMV.Inv_Mask);
989 unsigned MinWordSize) {
990 PartwordMaskValues PMV;
995 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
997 PMV.ValueType = PMV.IntValueType =
ValueType;
1002 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
1004 if (PMV.ValueType == PMV.WordType) {
1005 PMV.AlignedAddr = Addr;
1006 PMV.AlignedAddrAlignment = AddrAlign;
1007 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
1008 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
1012 PMV.AlignedAddrAlignment =
Align(MinWordSize);
1014 assert(ValueSize < MinWordSize);
1017 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
1020 if (AddrAlign < MinWordSize) {
1021 PMV.AlignedAddr = Builder.CreateIntrinsic(
1022 Intrinsic::ptrmask, {PtrTy, IntTy},
1024 nullptr,
"AlignedAddr");
1026 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
1027 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1030 PMV.AlignedAddr = Addr;
1034 if (
DL.isLittleEndian()) {
1036 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1039 PMV.ShiftAmt = Builder.CreateShl(
1040 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1043 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1044 PMV.Mask = Builder.CreateShl(
1045 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1048 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1054 const PartwordMaskValues &PMV) {
1055 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1056 if (PMV.WordType == PMV.ValueType)
1059 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1060 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1061 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1065 Value *Updated,
const PartwordMaskValues &PMV) {
1066 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1067 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1068 if (PMV.WordType == PMV.ValueType)
1071 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1073 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1075 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1076 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1077 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1087 const PartwordMaskValues &PMV) {
1094 "Or/Xor/And handled by widenPartwordAtomicRMW");
1099 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1102 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1124 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1125 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1126 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1133 assert(!ValOperand_Shifted);
1147void AtomicExpandImpl::expandPartwordAtomicRMW(
1153 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1159 ReplacementIRBuilder Builder(AI, *
DL);
1161 PartwordMaskValues PMV =
1165 Value *ValOperand_Shifted =
nullptr;
1166 bool NeedsShiftedOperand =
1171 if (NeedsShiftedOperand) {
1173 ValOperand_Shifted =
1174 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1175 "ValOperand_Shifted");
1178 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1184 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1185 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1186 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1190 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1191 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1192 PMV.AlignedAddrAlignment, MemOpOrder,
1202AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1203 ReplacementIRBuilder Builder(AI, *
DL);
1208 "Unable to widen operation");
1210 PartwordMaskValues PMV =
1220 Value *ValOperand_Shifted =
1222 "ValOperand_Shifted");
1228 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1230 NewOperand = ValOperand_Shifted;
1233 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1245bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1287 ReplacementIRBuilder Builder(CI, *
DL);
1298 std::prev(BB->
end())->eraseFromParent();
1301 PartwordMaskValues PMV =
1306 Value *NewVal_Shifted =
1308 Value *Cmp_Shifted =
1313 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1314 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1319 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1320 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1333 processAtomicInstr(InitLoaded);
1337 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1338 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1340 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1368 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1383void AtomicExpandImpl::expandAtomicOpToLLSC(
1384 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1386 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1387 ReplacementIRBuilder Builder(
I, *
DL);
1388 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1389 MemOpOrder, PerformOp);
1391 I->replaceAllUsesWith(Loaded);
1392 I->eraseFromParent();
1395void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1396 ReplacementIRBuilder Builder(AI, *
DL);
1398 PartwordMaskValues PMV =
1408 CastOp = Instruction::SExt;
1412 PMV.ShiftAmt,
"ValOperand_Shifted");
1414 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1421void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1422 AtomicCmpXchgInst *CI) {
1423 ReplacementIRBuilder Builder(CI, *
DL);
1436 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1442 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1449Value *AtomicExpandImpl::insertRMWLLSCLoop(
1450 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1452 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1457 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1458 "Expected at least natural alignment at this point.");
1478 std::prev(BB->
end())->eraseFromParent();
1486 Value *NewVal = PerformOp(Builder, Loaded);
1488 Value *StoreSuccess =
1510AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1513 M->getDataLayout());
1515 ReplacementIRBuilder Builder(CI, *
DL);
1527 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1543bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1549 LLVMContext &Ctx =
F->getContext();
1556 ? AtomicOrdering::Monotonic
1568 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1569 SuccessOrder != AtomicOrdering::Monotonic &&
1570 SuccessOrder != AtomicOrdering::Acquire &&
1575 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1629 auto ReleasedLoadBB =
1633 auto ReleasingStoreBB =
1637 ReplacementIRBuilder Builder(CI, *
DL);
1642 std::prev(BB->
end())->eraseFromParent();
1644 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1647 PartwordMaskValues PMV =
1654 Value *UnreleasedLoad =
1655 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1656 Value *UnreleasedLoadExtract =
1663 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1664 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1667 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1672 PHINode *LoadedTryStore =
1673 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1674 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1675 Value *NewValueInsert =
1678 PMV.AlignedAddr, MemOpOrder);
1680 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1681 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1683 CI->
isWeak() ? FailureBB : RetryBB,
1684 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1688 if (HasReleasedLoadBB) {
1690 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1698 ShouldStore, TryStoreBB, NoStoreBB,
1699 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1701 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1708 if (ShouldInsertFencesForAtomic ||
1714 PHINode *LoadedNoStore =
1716 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1717 if (HasReleasedLoadBB)
1718 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1727 PHINode *LoadedFailure =
1729 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1731 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1732 if (ShouldInsertFencesForAtomic)
1741 PHINode *LoadedExit =
1743 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1744 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1751 Value *LoadedFull = LoadedExit;
1759 for (
auto *User : CI->
users()) {
1765 "weird extraction from { iN, i1 }");
1776 for (
auto *EV : PrunedInsts)
1793bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1808 return C->isMinusOne();
1810 return C->isMaxValue(
true);
1812 return C->isMinValue(
true);
1814 return C->isMaxValue(
false);
1816 return C->isMinValue(
false);
1822bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1824 tryExpandAtomicLoad(ResultingLoad);
1830Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1831 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1833 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1834 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1861 std::prev(BB->
end())->eraseFromParent();
1869 Loaded->addIncoming(InitLoaded, BB);
1878 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1882 processAtomicInstr(InitLoaded);
1885 Value *NewVal = PerformOp(Builder, Loaded);
1887 Value *NewLoaded =
nullptr;
1890 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1891 MemOpOrder == AtomicOrdering::Unordered
1892 ? AtomicOrdering::Monotonic
1894 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1897 Loaded->addIncoming(NewLoaded, LoopBB);
1910bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1917 case TargetLoweringBase::AtomicExpansionKind::None:
1918 if (ValueSize < MinCASSize)
1919 return expandPartwordCmpXchg(CI);
1921 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1922 return expandAtomicCmpXchg(CI);
1924 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1925 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1927 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1929 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1936bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1937 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1944 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1947 [&](IRBuilderBase &Builder,
Value *Loaded) {
1948 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1949 AI->getValOperand());
1972 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1973 return Alignment >=
Size &&
1975 Size <= LargestSize;
1978void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1979 static const RTLIB::Libcall Libcalls[6] = {
1980 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1981 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1984 bool Expanded = expandAtomicOpToLibcall(
1985 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1986 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1988 handleUnsupportedAtomicSize(
I,
"atomic load");
1991void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1992 static const RTLIB::Libcall Libcalls[6] = {
1993 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1994 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1997 bool Expanded = expandAtomicOpToLibcall(
1998 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1999 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2001 handleUnsupportedAtomicSize(
I,
"atomic store");
2004void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
2005 const Twine &AtomicOpName,
2006 Instruction *DiagnosticInst) {
2007 static const RTLIB::Libcall Libcalls[6] = {
2008 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
2009 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
2010 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
2013 bool Expanded = expandAtomicOpToLibcall(
2014 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
2015 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
2018 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
2022 static const RTLIB::Libcall LibcallsXchg[6] = {
2023 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
2024 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
2025 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
2026 static const RTLIB::Libcall LibcallsAdd[6] = {
2027 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2028 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2029 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2030 static const RTLIB::Libcall LibcallsSub[6] = {
2031 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2032 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2033 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2034 static const RTLIB::Libcall LibcallsAnd[6] = {
2035 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2036 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2037 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2038 static const RTLIB::Libcall LibcallsOr[6] = {
2039 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2040 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2041 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2042 static const RTLIB::Libcall LibcallsXor[6] = {
2043 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2044 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2045 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2046 static const RTLIB::Libcall LibcallsNand[6] = {
2047 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2048 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2049 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2090void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2096 if (!Libcalls.
empty())
2097 Success = expandAtomicOpToLibcall(
2098 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2099 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2106 expandAtomicRMWToCmpXchg(
2107 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2110 Value *&NewLoaded, Instruction *MetadataSrc) {
2113 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2123 expandAtomicCASToLibcall(
2137bool AtomicExpandImpl::expandAtomicOpToLibcall(
2138 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2143 LLVMContext &Ctx =
I->getContext();
2145 const DataLayout &
DL =
M->getDataLayout();
2147 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2150 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2152 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2162 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2166 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2168 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2171 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2173 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2175 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2177 RTLIB::Libcall RTLibType;
2178 if (UseSizedLibcall) {
2181 RTLibType = Libcalls[1];
2184 RTLibType = Libcalls[2];
2187 RTLibType = Libcalls[3];
2190 RTLibType = Libcalls[4];
2193 RTLibType = Libcalls[5];
2196 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2197 RTLibType = Libcalls[0];
2204 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2205 if (LibcallImpl == RTLIB::Unsupported) {
2236 AllocaInst *AllocaCASExpected =
nullptr;
2237 AllocaInst *AllocaValue =
nullptr;
2238 AllocaInst *AllocaResult =
nullptr;
2245 if (!UseSizedLibcall) {
2247 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2255 Value *PtrVal = PointerOperand;
2257 Args.push_back(PtrVal);
2261 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2265 Args.push_back(AllocaCASExpected);
2270 if (UseSizedLibcall) {
2273 Args.push_back(IntValue);
2275 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2279 Args.push_back(AllocaValue);
2284 if (!CASExpected && HasResult && !UseSizedLibcall) {
2285 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2288 Args.push_back(AllocaResult);
2292 Args.push_back(OrderingVal);
2296 Args.push_back(Ordering2Val);
2300 ResultTy = Type::getInt1Ty(Ctx);
2301 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2302 }
else if (HasResult && UseSizedLibcall)
2303 ResultTy = SizedIntTy;
2305 ResultTy = Type::getVoidTy(Ctx);
2309 for (
Value *Arg : Args)
2311 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2312 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2320 if (ValueOperand && !UseSizedLibcall)
2326 Type *FinalResultTy =
I->getType();
2329 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2334 }
else if (HasResult) {
2336 if (UseSizedLibcall) {
2340 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2341 unsigned AS = PtrTy->getAddressSpace();
2343 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2352 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 *ValOperand_Shifted, 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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()
void setOperation(BinOp Operation)
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.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNull=false)
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)
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.
iterator_range< user_iterator > users()
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 or function.
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.
Records a mapping from an opaque lowering context to its LibcallLoweringInfo.
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)
void setOperand(unsigned i, Value *Val)
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.
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.
@ 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 const LibcallLoweringInfo & getLibcallLowering(const ModuleLibcallLoweringInfo &ModuleInfo, const TargetSubtargetInfo &Subtarget)
Resolve the LibcallLoweringInfo for Subtarget from the module-level ModuleInfo, applying the subtarge...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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.
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.