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);
114 void expandAtomicOpToLLSC(
118 void expandPartwordAtomicRMW(
126 Value *insertRMWCmpXchgLoop(
130 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
142 void expandAtomicLoadToLibcall(
LoadInst *LI);
143 void expandAtomicStoreToLibcall(
StoreInst *LI);
146 const Twine &AtomicOpName =
"cmpxchg",
150 CreateCmpXchgInstFun CreateCmpXchg);
175struct ReplacementIRBuilder
176 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
178 MDNode *PCSectionsMD =
nullptr;
187 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
188 this->setIsFPConstrained(
true);
190 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
191 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
196 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
197 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
203char AtomicExpandLegacy::ID = 0;
208 "Expand Atomic instructions",
false,
false)
217 return DL.getTypeStoreSize(LI->getType());
222 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
239 Source.getAllMetadata(MD);
243 for (
auto [ID,
N] : MD) {
245 case LLVMContext::MD_dbg:
246 case LLVMContext::MD_tbaa:
247 case LLVMContext::MD_tbaa_struct:
248 case LLVMContext::MD_alias_scope:
249 case LLVMContext::MD_noalias:
250 case LLVMContext::MD_noalias_addrspace:
251 case LLVMContext::MD_access_group:
252 case LLVMContext::MD_mmra:
256 if (ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
258 else if (ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
268template <
typename Inst>
271 Align Alignment =
I->getAlign();
273 return Alignment >=
Size &&
Size <= MaxSize;
276template <
typename Inst>
280 Align Alignment =
I->getAlign();
281 bool NeedSeparator =
false;
283 if (Alignment <
Size) {
284 OS <<
"instruction alignment " << Alignment.value()
285 <<
" is smaller than the required " <<
Size
286 <<
"-byte alignment for this atomic operation";
287 NeedSeparator =
true;
291 if (
Size > MaxSize) {
294 OS <<
"target supports atomics up to " << MaxSize
295 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
299template <
typename Inst>
300void AtomicExpandImpl::handleUnsupportedAtomicSize(
303 SmallString<128> FailureReason;
304 raw_svector_ostream OS(FailureReason);
306 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
310bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
316 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
317 TrailingFence->moveAfter(AtomicI);
323template <
typename AtomicInst>
324bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
325 bool OrderingRequiresFence,
328 if (OrderingRequiresFence && ShouldInsertFences) {
330 AtomicI->setOrdering(NewOrdering);
331 return bracketInstWithFences(AtomicI, FenceOrdering);
333 if (!ShouldInsertFences)
334 return tryInsertTrailingSeqCstFence(AtomicI);
341bool AtomicExpandImpl::lowerToNonAtomic(Instruction *
I) {
343 FI->eraseFromParent();
354 if (LI->isAtomic()) {
355 LI->setAtomic(AtomicOrdering::NotAtomic);
356 LI->setElementwise(
false);
364 if (
SI->isAtomic()) {
365 SI->setAtomic(AtomicOrdering::NotAtomic);
366 SI->setElementwise(
false);
376bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
378 return lowerToNonAtomic(
I);
385 expandAtomicLoadToLibcall(LI);
389 bool MadeChange =
false;
391 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
392 LI = convertAtomicLoadToIntegerType(LI);
396 MadeChange |= tryInsertFencesForAtomic(
399 MadeChange |= tryExpandAtomicLoad(LI);
408 expandAtomicStoreToLibcall(SI);
412 bool MadeChange =
false;
414 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
415 SI = convertAtomicStoreToIntegerType(SI);
419 MadeChange |= tryInsertFencesForAtomic(
422 MadeChange |= tryExpandAtomicStore(SI);
428 expandAtomicRMWToLibcall(RMWI);
432 bool MadeChange =
false;
434 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
435 RMWI = convertAtomicXchgToIntegerType(RMWI);
439 MadeChange |= tryInsertFencesForAtomic(
449 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
450 tryExpandAtomicRMW(RMWI);
456 expandAtomicCASToLibcall(CASI);
462 bool MadeChange =
false;
463 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
466 CASI = convertCmpXchgToIntegerType(CASI);
472 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
483 CASI->setSuccessOrdering(CASOrdering);
484 CASI->setFailureOrdering(CASOrdering);
485 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
487 }
else if (CmpXchgExpansion !=
488 TargetLoweringBase::AtomicExpansionKind::LLSC) {
490 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
493 MadeChange |= tryExpandAtomicCmpXchg(CASI);
501 const ModuleLibcallLoweringInfo &LibcallResult,
502 const TargetMachine *TM) {
503 SingleThreaded =
F.getParent()->getThreadModel() == ThreadModel::Single;
509 TLI = Subtarget->getTargetLowering();
511 DL = &
F.getDataLayout();
513 bool MadeChange =
false;
525 if (processAtomicInstr(&Inst)) {
537bool AtomicExpandLegacy::runOnFunction(
Function &
F) {
539 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
542 auto *TM = &TPC->getTM<TargetMachine>();
544 const ModuleLibcallLoweringInfo &LibcallResult =
545 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
547 return AE.run(
F, LibcallResult, TM);
551 return new AtomicExpandLegacy();
561 if (!LibcallResult) {
563 "' analysis required");
569 bool Changed = AE.run(
F, *LibcallResult, TM);
576bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
578 ReplacementIRBuilder Builder(
I, *
DL);
588 return (LeadingFence || TrailingFence);
603LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
605 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
607 ReplacementIRBuilder Builder(LI, *
DL);
611 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
612 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
615 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
616 : Builder.CreateBitCast(NewLI, LI->
getType());
623AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
628 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
630 ReplacementIRBuilder Builder(RMWI, *
DL);
634 Value *NewVal = Builder.CreateBitPreservingCastChain(*
DL, Val, NewTy);
641 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
644 Builder.CreateBitPreservingCastChain(*
DL, NewRMWI, RMWI->
getType());
650bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
652 case TargetLoweringBase::AtomicExpansionKind::None:
654 case TargetLoweringBase::AtomicExpansionKind::LLSC:
655 expandAtomicOpToLLSC(
658 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
660 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
661 return expandAtomicLoadToLL(LI);
662 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
663 return expandAtomicLoadToCmpXchg(LI);
664 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
665 LI->
setAtomic(AtomicOrdering::NotAtomic);
667 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
675bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
677 case TargetLoweringBase::AtomicExpansionKind::None:
679 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
682 case TargetLoweringBase::AtomicExpansionKind::Expand:
683 expandAtomicStoreToXChg(SI);
685 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
686 SI->setAtomic(AtomicOrdering::NotAtomic);
693bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
694 ReplacementIRBuilder Builder(LI, *
DL);
709bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
710 ReplacementIRBuilder Builder(LI, *
DL);
712 if (Order == AtomicOrdering::Unordered)
713 Order = AtomicOrdering::Monotonic;
722 Type *CmpXchgTy = Ty;
727 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
728 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
732 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
734 Loaded = Builder.CreateBitCast(Loaded, Ty);
750StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
751 ReplacementIRBuilder Builder(SI, *
DL);
752 auto *
M =
SI->getModule();
753 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
755 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
756 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
757 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
759 Value *Addr =
SI->getPointerOperand();
761 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
762 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
763 SI->eraseFromParent();
767void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
774 ReplacementIRBuilder Builder(SI, *
DL);
776 assert(Ordering != AtomicOrdering::NotAtomic);
778 ? AtomicOrdering::Monotonic
780 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
782 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
784 SI->eraseFromParent();
787 tryExpandAtomicRMW(AI);
802 NewVal = Builder.CreateBitCast(NewVal, IntTy);
803 Loaded = Builder.CreateBitCast(Loaded, IntTy);
807 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
813 Success = Builder.CreateExtractValue(Pair, 1,
"success");
814 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
817 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
820bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
824 case TargetLoweringBase::AtomicExpansionKind::None:
826 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
829 if (ValueSize < MinCASSize) {
830 expandPartwordAtomicRMW(AI,
831 TargetLoweringBase::AtomicExpansionKind::LLSC);
833 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
842 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
845 if (ValueSize < MinCASSize) {
846 expandPartwordAtomicRMW(AI,
847 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
856 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
857 <<
"A compare and swap loop was generated for an atomic "
865 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
868 if (ValueSize < MinCASSize) {
873 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
877 expandAtomicRMWToMaskedIntrinsic(AI);
880 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
884 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
888 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
890 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
900struct PartwordMaskValues {
902 Type *WordType =
nullptr;
904 Type *IntValueType =
nullptr;
905 Value *AlignedAddr =
nullptr;
906 Align AlignedAddrAlignment;
908 Value *ShiftAmt =
nullptr;
909 Value *Mask =
nullptr;
910 Value *Inv_Mask =
nullptr;
914raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
915 auto PrintObj = [&
O](
auto *
V) {
922 O <<
"PartwordMaskValues {\n";
924 PrintObj(PMV.WordType);
926 PrintObj(PMV.ValueType);
927 O <<
" AlignedAddr: ";
928 PrintObj(PMV.AlignedAddr);
929 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
931 PrintObj(PMV.ShiftAmt);
935 PrintObj(PMV.Inv_Mask);
961 unsigned MinWordSize) {
962 PartwordMaskValues PMV;
967 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
969 PMV.ValueType = PMV.IntValueType =
ValueType;
974 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
976 if (PMV.ValueType == PMV.WordType) {
977 PMV.AlignedAddr = Addr;
978 PMV.AlignedAddrAlignment = AddrAlign;
979 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
980 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
984 PMV.AlignedAddrAlignment =
Align(MinWordSize);
986 assert(ValueSize < MinWordSize);
989 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
992 if (AddrAlign < MinWordSize) {
993 PMV.AlignedAddr = Builder.CreateIntrinsic(
994 Intrinsic::ptrmask, {PtrTy, IntTy},
996 nullptr,
"AlignedAddr");
998 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
999 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1002 PMV.AlignedAddr = Addr;
1006 if (
DL.isLittleEndian()) {
1008 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1011 PMV.ShiftAmt = Builder.CreateShl(
1012 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1015 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1016 PMV.Mask = Builder.CreateShl(
1017 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1020 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1026 const PartwordMaskValues &PMV) {
1027 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1028 if (PMV.WordType == PMV.ValueType)
1031 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1032 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1033 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1037 Value *Updated,
const PartwordMaskValues &PMV) {
1038 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1039 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1040 if (PMV.WordType == PMV.ValueType)
1043 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1045 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1047 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1048 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1049 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1059 const PartwordMaskValues &PMV) {
1066 "Or/Xor/And handled by widenPartwordAtomicRMW");
1071 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1074 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1096 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1097 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1098 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1105 assert(!ValOperand_Shifted);
1119void AtomicExpandImpl::expandPartwordAtomicRMW(
1125 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1131 ReplacementIRBuilder Builder(AI, *
DL);
1133 PartwordMaskValues PMV =
1137 Value *ValOperand_Shifted =
nullptr;
1138 bool NeedsShiftedOperand =
1143 if (NeedsShiftedOperand) {
1145 ValOperand_Shifted =
1146 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1147 "ValOperand_Shifted");
1150 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1156 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1157 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1158 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1162 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1163 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1164 PMV.AlignedAddrAlignment, MemOpOrder,
1174AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1175 ReplacementIRBuilder Builder(AI, *
DL);
1180 "Unable to widen operation");
1182 PartwordMaskValues PMV =
1192 Value *ValOperand_Shifted =
1194 "ValOperand_Shifted");
1200 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1202 NewOperand = ValOperand_Shifted;
1205 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1217bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1259 ReplacementIRBuilder Builder(CI, *
DL);
1270 std::prev(BB->
end())->eraseFromParent();
1273 PartwordMaskValues PMV =
1278 Value *NewVal_Shifted =
1280 Value *Cmp_Shifted =
1285 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1286 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1291 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1292 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1305 processAtomicInstr(InitLoaded);
1309 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1310 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1312 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1340 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1355void AtomicExpandImpl::expandAtomicOpToLLSC(
1356 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1358 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1359 ReplacementIRBuilder Builder(
I, *
DL);
1360 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1361 MemOpOrder, PerformOp);
1363 I->replaceAllUsesWith(Loaded);
1364 I->eraseFromParent();
1367void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1368 ReplacementIRBuilder Builder(AI, *
DL);
1370 PartwordMaskValues PMV =
1380 CastOp = Instruction::SExt;
1384 PMV.ShiftAmt,
"ValOperand_Shifted");
1386 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1393void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1394 AtomicCmpXchgInst *CI) {
1395 ReplacementIRBuilder Builder(CI, *
DL);
1408 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1414 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1421Value *AtomicExpandImpl::insertRMWLLSCLoop(
1422 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1424 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1429 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1430 "Expected at least natural alignment at this point.");
1450 std::prev(BB->
end())->eraseFromParent();
1458 Value *NewVal = PerformOp(Builder, Loaded);
1460 Value *StoreSuccess =
1482AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1485 M->getDataLayout());
1487 ReplacementIRBuilder Builder(CI, *
DL);
1499 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1515bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1521 LLVMContext &Ctx =
F->getContext();
1528 ? AtomicOrdering::Monotonic
1540 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1541 SuccessOrder != AtomicOrdering::Monotonic &&
1542 SuccessOrder != AtomicOrdering::Acquire &&
1547 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1601 auto ReleasedLoadBB =
1605 auto ReleasingStoreBB =
1609 ReplacementIRBuilder Builder(CI, *
DL);
1614 std::prev(BB->
end())->eraseFromParent();
1616 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1619 PartwordMaskValues PMV =
1626 Value *UnreleasedLoad =
1627 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1628 Value *UnreleasedLoadExtract =
1635 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1636 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1639 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1644 PHINode *LoadedTryStore =
1645 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1646 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1647 Value *NewValueInsert =
1650 PMV.AlignedAddr, MemOpOrder);
1652 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1653 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1655 CI->
isWeak() ? FailureBB : RetryBB,
1656 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1660 if (HasReleasedLoadBB) {
1662 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1670 ShouldStore, TryStoreBB, NoStoreBB,
1671 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1673 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1680 if (ShouldInsertFencesForAtomic ||
1686 PHINode *LoadedNoStore =
1688 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1689 if (HasReleasedLoadBB)
1690 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1699 PHINode *LoadedFailure =
1701 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1703 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1704 if (ShouldInsertFencesForAtomic)
1713 PHINode *LoadedExit =
1715 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1716 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1723 Value *LoadedFull = LoadedExit;
1731 for (
auto *User : CI->
users()) {
1737 "weird extraction from { iN, i1 }");
1748 for (
auto *EV : PrunedInsts)
1765bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1780 return C->isMinusOne();
1782 return C->isMaxValue(
true);
1784 return C->isMinValue(
true);
1786 return C->isMaxValue(
false);
1788 return C->isMinValue(
false);
1794bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1796 tryExpandAtomicLoad(ResultingLoad);
1802Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1803 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1805 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1806 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1833 std::prev(BB->
end())->eraseFromParent();
1841 Loaded->addIncoming(InitLoaded, BB);
1850 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1854 processAtomicInstr(InitLoaded);
1857 Value *NewVal = PerformOp(Builder, Loaded);
1859 Value *NewLoaded =
nullptr;
1862 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1863 MemOpOrder == AtomicOrdering::Unordered
1864 ? AtomicOrdering::Monotonic
1866 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1869 Loaded->addIncoming(NewLoaded, LoopBB);
1882bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1889 case TargetLoweringBase::AtomicExpansionKind::None:
1890 if (ValueSize < MinCASSize)
1891 return expandPartwordCmpXchg(CI);
1893 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1894 return expandAtomicCmpXchg(CI);
1896 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1897 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1899 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1901 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1908bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1909 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1916 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1919 [&](IRBuilderBase &Builder,
Value *Loaded) {
1920 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1921 AI->getValOperand());
1944 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1945 return Alignment >=
Size &&
1947 Size <= LargestSize;
1950void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1951 static const RTLIB::Libcall Libcalls[6] = {
1952 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1953 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1956 bool Expanded = expandAtomicOpToLibcall(
1957 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1958 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1960 handleUnsupportedAtomicSize(
I,
"atomic load");
1963void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1964 static const RTLIB::Libcall Libcalls[6] = {
1965 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1966 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1969 bool Expanded = expandAtomicOpToLibcall(
1970 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1971 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1973 handleUnsupportedAtomicSize(
I,
"atomic store");
1976void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
1977 const Twine &AtomicOpName,
1978 Instruction *DiagnosticInst) {
1979 static const RTLIB::Libcall Libcalls[6] = {
1980 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1981 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1982 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1985 bool Expanded = expandAtomicOpToLibcall(
1986 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1987 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1990 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
1994 static const RTLIB::Libcall LibcallsXchg[6] = {
1995 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1996 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1997 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1998 static const RTLIB::Libcall LibcallsAdd[6] = {
1999 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2000 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2001 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2002 static const RTLIB::Libcall LibcallsSub[6] = {
2003 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2004 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2005 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2006 static const RTLIB::Libcall LibcallsAnd[6] = {
2007 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2008 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2009 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2010 static const RTLIB::Libcall LibcallsOr[6] = {
2011 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2012 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2013 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2014 static const RTLIB::Libcall LibcallsXor[6] = {
2015 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2016 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2017 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2018 static const RTLIB::Libcall LibcallsNand[6] = {
2019 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2020 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2021 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2062void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2068 if (!Libcalls.
empty())
2069 Success = expandAtomicOpToLibcall(
2070 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2071 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2078 expandAtomicRMWToCmpXchg(
2079 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2082 Value *&NewLoaded, Instruction *MetadataSrc) {
2085 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2095 expandAtomicCASToLibcall(
2109bool AtomicExpandImpl::expandAtomicOpToLibcall(
2110 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2115 LLVMContext &Ctx =
I->getContext();
2117 const DataLayout &
DL =
M->getDataLayout();
2119 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2122 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2124 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2134 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2138 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2140 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2143 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2145 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2147 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2149 RTLIB::Libcall RTLibType;
2150 if (UseSizedLibcall) {
2153 RTLibType = Libcalls[1];
2156 RTLibType = Libcalls[2];
2159 RTLibType = Libcalls[3];
2162 RTLibType = Libcalls[4];
2165 RTLibType = Libcalls[5];
2168 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2169 RTLibType = Libcalls[0];
2176 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2177 if (LibcallImpl == RTLIB::Unsupported) {
2208 AllocaInst *AllocaCASExpected =
nullptr;
2209 AllocaInst *AllocaValue =
nullptr;
2210 AllocaInst *AllocaResult =
nullptr;
2217 if (!UseSizedLibcall) {
2219 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2227 Value *PtrVal = PointerOperand;
2229 Args.push_back(PtrVal);
2233 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2237 Args.push_back(AllocaCASExpected);
2242 if (UseSizedLibcall) {
2245 Args.push_back(IntValue);
2247 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2251 Args.push_back(AllocaValue);
2256 if (!CASExpected && HasResult && !UseSizedLibcall) {
2257 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2260 Args.push_back(AllocaResult);
2264 Args.push_back(OrderingVal);
2268 Args.push_back(Ordering2Val);
2272 ResultTy = Type::getInt1Ty(Ctx);
2273 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2274 }
else if (HasResult && UseSizedLibcall)
2275 ResultTy = SizedIntTy;
2277 ResultTy = Type::getVoidTy(Ctx);
2281 for (
Value *Arg : Args)
2283 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2284 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2292 if (ValueOperand && !UseSizedLibcall)
2298 Type *FinalResultTy =
I->getType();
2301 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2306 }
else if (HasResult) {
2308 if (UseSizedLibcall) {
2312 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2313 unsigned AS = PtrTy->getAddressSpace();
2315 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2324 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()
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)
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.
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.