62#define DEBUG_TYPE "atomic-expand"
66class AtomicExpandImpl {
86 Ctx.
emitError(DiagnosticInst ? DiagnosticInst : &FailedInst,
Msg);
88 if (!FailedInst.getType()->isVoidTy())
90 FailedInst.eraseFromParent();
93 template <
typename Inst>
94 void handleUnsupportedAtomicSize(Inst *
I,
const Twine &AtomicOpName,
98 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
99 template <
typename AtomicInst>
100 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
104 bool tryExpandAtomicLoad(
LoadInst *LI);
105 bool expandAtomicLoadToLL(
LoadInst *LI);
106 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
118 void expandAtomicOpToLLSC(
122 void expandPartwordAtomicRMW(
130 Value *insertRMWCmpXchgLoop(
134 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
146 void expandAtomicLoadToLibcall(
LoadInst *LI);
147 void expandAtomicStoreToLibcall(
StoreInst *LI);
150 const Twine &AtomicOpName =
"cmpxchg",
154 CreateCmpXchgInstFun CreateCmpXchg);
179struct ReplacementIRBuilder
180 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
182 MDNode *PCSectionsMD =
nullptr;
190 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
191 this->setIsFPConstrained(
true);
193 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
194 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
199 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
200 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
206char AtomicExpandLegacy::ID = 0;
211 "Expand Atomic instructions",
false,
false)
220 return DL.getTypeStoreSize(LI->getType());
225 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
242 Source.getAllMetadata(MD);
246 for (
auto [ID,
N] : MD) {
248 case LLVMContext::MD_dbg:
249 case LLVMContext::MD_tbaa:
250 case LLVMContext::MD_tbaa_struct:
251 case LLVMContext::MD_alias_scope:
252 case LLVMContext::MD_mem_cache_hint:
253 case LLVMContext::MD_noalias:
254 case LLVMContext::MD_noalias_addrspace:
255 case LLVMContext::MD_access_group:
256 case LLVMContext::MD_mmra:
260 if (ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
262 else if (ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
272template <
typename Inst>
275 Align Alignment =
I->getAlign();
277 return Alignment >=
Size &&
Size <= MaxSize;
280template <
typename Inst>
284 Align Alignment =
I->getAlign();
285 bool NeedSeparator =
false;
287 if (Alignment <
Size) {
288 OS <<
"instruction alignment " << Alignment.value()
289 <<
" is smaller than the required " <<
Size
290 <<
"-byte alignment for this atomic operation";
291 NeedSeparator =
true;
295 if (
Size > MaxSize) {
298 OS <<
"target supports atomics up to " << MaxSize
299 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
303template <
typename Inst>
304void AtomicExpandImpl::handleUnsupportedAtomicSize(
307 SmallString<128> FailureReason;
308 raw_svector_ostream OS(FailureReason);
310 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
314bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
320 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
321 TrailingFence->moveAfter(AtomicI);
327template <
typename AtomicInst>
328bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
329 bool OrderingRequiresFence,
332 if (OrderingRequiresFence && ShouldInsertFences) {
334 AtomicI->setOrdering(NewOrdering);
335 return bracketInstWithFences(AtomicI, FenceOrdering);
337 if (!ShouldInsertFences)
338 return tryInsertTrailingSeqCstFence(AtomicI);
345bool AtomicExpandImpl::lowerToNonAtomic(Instruction *
I) {
347 FI->eraseFromParent();
358 if (LI->isAtomic()) {
359 LI->setAtomic(AtomicOrdering::NotAtomic);
360 LI->setElementwise(
false);
368 if (
SI->isAtomic()) {
369 SI->setAtomic(AtomicOrdering::NotAtomic);
370 SI->setElementwise(
false);
380bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
382 return lowerToNonAtomic(
I);
389 expandAtomicLoadToLibcall(LI);
393 bool MadeChange =
false;
395 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
396 LI = convertAtomicLoadToIntegerType(LI);
400 MadeChange |= tryInsertFencesForAtomic(
403 MadeChange |= tryExpandAtomicLoad(LI);
412 expandAtomicStoreToLibcall(SI);
416 bool MadeChange =
false;
418 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
419 SI = convertAtomicStoreToIntegerType(SI);
423 MadeChange |= tryInsertFencesForAtomic(
426 MadeChange |= tryExpandAtomicStore(SI);
431 bool IsElementwiseExpand =
432 RMWI->isElementwise() &&
434 TargetLoweringBase::AtomicExpansionKind::Expand;
439 if (!IsElementwiseExpand) {
440 expandAtomicRMWToLibcall(RMWI);
445 bool MadeChange =
false;
446 if (!IsElementwiseExpand &&
448 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
449 RMWI = convertAtomicXchgToIntegerType(RMWI);
453 MadeChange |= tryInsertFencesForAtomic(
461 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
462 tryExpandAtomicRMW(RMWI);
468 expandAtomicCASToLibcall(CASI);
474 bool MadeChange =
false;
475 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
478 CASI = convertCmpXchgToIntegerType(CASI);
484 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
495 CASI->setSuccessOrdering(CASOrdering);
496 CASI->setFailureOrdering(CASOrdering);
497 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
499 }
else if (CmpXchgExpansion !=
500 TargetLoweringBase::AtomicExpansionKind::LLSC) {
502 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
505 MadeChange |= tryExpandAtomicCmpXchg(CASI);
513 const ModuleLibcallLoweringInfo &LibcallResult,
514 const TargetMachine *TM) {
515 SingleThreaded =
F.getParent()->getThreadModel() == ThreadModel::Single;
521 TLI = Subtarget->getTargetLowering();
523 DL = &
F.getDataLayout();
525 bool MadeChange =
false;
537 if (processAtomicInstr(&Inst)) {
549bool AtomicExpandLegacy::runOnFunction(
Function &
F) {
551 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
554 auto *TM = &TPC->getTM<TargetMachine>();
556 const ModuleLibcallLoweringInfo &LibcallResult =
557 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
559 return AE.run(
F, LibcallResult, TM);
563 return new AtomicExpandLegacy();
573 if (!LibcallResult) {
575 "' analysis required");
581 bool Changed = AE.run(
F, *LibcallResult, TM);
588bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
590 ReplacementIRBuilder Builder(
I, *
DL);
600 return (LeadingFence || TrailingFence);
615LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
617 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
619 ReplacementIRBuilder Builder(LI, *
DL);
623 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
624 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
627 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
628 : Builder.CreateBitCast(NewLI, LI->
getType());
635AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
640 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
642 ReplacementIRBuilder Builder(RMWI, *
DL);
646 Value *NewVal = Builder.CreateBitPreservingCastChain(*
DL, Val, NewTy);
653 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
656 Builder.CreateBitPreservingCastChain(*
DL, NewRMWI, RMWI->
getType());
677void AtomicExpandImpl::expandElementwiseAtomicRMW(AtomicRMWInst *AI) {
680 Type *LaneTy = VecTy->getElementType();
681 const unsigned NumLanes = VecTy->getNumElements();
685 ReplacementIRBuilder Builder(AI, *
DL);
690 bool Elementwise) -> AtomicRMWInst * {
692 Builder.CreateAtomicRMW(AI->
getOperation(), HalfPtr, HalfVal,
A,
695 NewAI->setElementwise(Elementwise);
700 Constant *IdxZero = ConstantInt::get(IdxTy, 0);
701 Constant *IdxOne = ConstantInt::get(IdxTy, 1);
706 Value *LaneVal = Builder.CreateExtractElement(Val, IdxZero,
"lane.val");
707 AtomicRMWInst *LaneRMW = CreateRMWInstruction(Ptr, LaneVal, AI->
getAlign(),
710 LaneRMW, IdxZero,
"lane.old");
713 processAtomicInstr(LaneRMW);
720 "elementwise atomicrmw vector length must be a power of two");
721 const unsigned HalfLanes = NumLanes / 2;
723 const uint64_t HalfBytes =
DL->getTypeStoreSize(HalfVecTy).getFixedValue();
725 Value *LoVal = Builder.CreateShuffleVector(
727 Value *HiVal = Builder.CreateShuffleVector(
730 Value *HiPtr = Builder.CreateInBoundsGEP(HalfVecTy, Ptr, IdxOne,
"hi.ptr");
734 AtomicRMWInst *LoRMW =
735 CreateRMWInstruction(Ptr, LoVal, LoAlign,
true);
736 AtomicRMWInst *HiRMW =
737 CreateRMWInstruction(HiPtr, HiVal, HiAlign,
true);
744 processAtomicInstr(LoRMW);
745 processAtomicInstr(HiRMW);
748bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
750 case TargetLoweringBase::AtomicExpansionKind::None:
752 case TargetLoweringBase::AtomicExpansionKind::LLSC:
753 expandAtomicOpToLLSC(
756 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
758 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
759 return expandAtomicLoadToLL(LI);
760 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
761 return expandAtomicLoadToCmpXchg(LI);
762 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
763 LI->
setAtomic(AtomicOrdering::NotAtomic);
765 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
773bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
775 case TargetLoweringBase::AtomicExpansionKind::None:
777 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
780 case TargetLoweringBase::AtomicExpansionKind::Expand:
781 expandAtomicStoreToXChg(SI);
783 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
784 SI->setAtomic(AtomicOrdering::NotAtomic);
791bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
792 ReplacementIRBuilder Builder(LI, *
DL);
807bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
808 ReplacementIRBuilder Builder(LI, *
DL);
810 if (Order == AtomicOrdering::Unordered)
811 Order = AtomicOrdering::Monotonic;
820 Type *CmpXchgTy = Ty;
825 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
826 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
830 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
832 Loaded = Builder.CreateBitCast(Loaded, Ty);
848StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
849 ReplacementIRBuilder Builder(SI, *
DL);
850 auto *
M =
SI->getModule();
851 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
853 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
854 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
855 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
857 Value *Addr =
SI->getPointerOperand();
859 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
861 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
862 SI->eraseFromParent();
866void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
873 ReplacementIRBuilder Builder(SI, *
DL);
875 assert(Ordering != AtomicOrdering::NotAtomic);
877 ? AtomicOrdering::Monotonic
879 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
881 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
883 SI->eraseFromParent();
886 tryExpandAtomicRMW(AI);
901 NewVal = Builder.CreateBitCast(NewVal, IntTy);
902 Loaded = Builder.CreateBitCast(Loaded, IntTy);
906 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
912 Success = Builder.CreateExtractValue(Pair, 1,
"success");
913 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
916 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
919void AtomicExpandImpl::expandAtomicSubToAdd(AtomicRMWInst *AI) {
920 ReplacementIRBuilder Builder(AI, *
DL);
941bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
945 case TargetLoweringBase::AtomicExpansionKind::None:
947 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
950 if (ValueSize < MinCASSize) {
951 expandPartwordAtomicRMW(AI,
952 TargetLoweringBase::AtomicExpansionKind::LLSC);
954 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
963 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
966 if (ValueSize < MinCASSize) {
967 expandPartwordAtomicRMW(AI,
968 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
977 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
978 <<
"A compare and swap loop was generated for an atomic "
986 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
989 if (ValueSize < MinCASSize) {
994 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
998 expandAtomicRMWToMaskedIntrinsic(AI);
1001 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
1005 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
1009 case TargetLoweringBase::AtomicExpansionKind::Expand:
1011 expandElementwiseAtomicRMW(AI);
1014 expandAtomicSubToAdd(AI);
1016 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1018 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
1028struct PartwordMaskValues {
1030 Type *WordType =
nullptr;
1032 Type *IntValueType =
nullptr;
1033 Value *AlignedAddr =
nullptr;
1034 Align AlignedAddrAlignment;
1036 Value *ShiftAmt =
nullptr;
1037 Value *Mask =
nullptr;
1038 Value *Inv_Mask =
nullptr;
1042raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
1043 auto PrintObj = [&
O](
auto *
V) {
1050 O <<
"PartwordMaskValues {\n";
1052 PrintObj(PMV.WordType);
1053 O <<
" ValueType: ";
1054 PrintObj(PMV.ValueType);
1055 O <<
" AlignedAddr: ";
1056 PrintObj(PMV.AlignedAddr);
1057 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
1059 PrintObj(PMV.ShiftAmt);
1063 PrintObj(PMV.Inv_Mask);
1089 unsigned MinWordSize) {
1090 PartwordMaskValues PMV;
1095 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
1097 PMV.ValueType = PMV.IntValueType =
ValueType;
1102 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
1104 if (PMV.ValueType == PMV.WordType) {
1105 PMV.AlignedAddr = Addr;
1106 PMV.AlignedAddrAlignment = AddrAlign;
1107 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
1108 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
1112 PMV.AlignedAddrAlignment =
Align(MinWordSize);
1114 assert(ValueSize < MinWordSize);
1117 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
1120 if (AddrAlign < MinWordSize) {
1121 PMV.AlignedAddr = Builder.CreateIntrinsic(
1122 Intrinsic::ptrmask, {PtrTy, IntTy},
1124 nullptr,
"AlignedAddr");
1126 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
1127 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1130 PMV.AlignedAddr = Addr;
1134 if (
DL.isLittleEndian()) {
1136 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1139 PMV.ShiftAmt = Builder.CreateShl(
1140 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1143 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1144 PMV.Mask = Builder.CreateShl(
1145 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1148 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1154 const PartwordMaskValues &PMV) {
1155 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1156 if (PMV.WordType == PMV.ValueType)
1159 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1160 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1161 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1165 Value *Updated,
const PartwordMaskValues &PMV) {
1166 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1167 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1168 if (PMV.WordType == PMV.ValueType)
1171 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1173 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1175 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1176 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1177 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1187 const PartwordMaskValues &PMV) {
1194 "Or/Xor/And handled by widenPartwordAtomicRMW");
1199 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1202 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1224 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1225 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1226 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1233 assert(!ValOperand_Shifted);
1247void AtomicExpandImpl::expandPartwordAtomicRMW(
1253 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1259 ReplacementIRBuilder Builder(AI, *
DL);
1261 PartwordMaskValues PMV =
1265 Value *ValOperand_Shifted =
nullptr;
1266 bool NeedsShiftedOperand =
1271 if (NeedsShiftedOperand) {
1273 ValOperand_Shifted =
1274 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1275 "ValOperand_Shifted");
1278 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1284 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1285 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1286 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1290 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1291 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1292 PMV.AlignedAddrAlignment, MemOpOrder,
1302AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1303 ReplacementIRBuilder Builder(AI, *
DL);
1308 "Unable to widen operation");
1310 PartwordMaskValues PMV =
1320 Value *ValOperand_Shifted =
1322 "ValOperand_Shifted");
1328 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1330 NewOperand = ValOperand_Shifted;
1333 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1345bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1387 ReplacementIRBuilder Builder(CI, *
DL);
1398 std::prev(BB->
end())->eraseFromParent();
1401 PartwordMaskValues PMV =
1406 Value *NewVal_Shifted =
1408 Value *Cmp_Shifted =
1413 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1414 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1419 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1420 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1433 processAtomicInstr(InitLoaded);
1437 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1438 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1440 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1468 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1483void AtomicExpandImpl::expandAtomicOpToLLSC(
1484 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1486 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1487 ReplacementIRBuilder Builder(
I, *
DL);
1488 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1489 MemOpOrder, PerformOp);
1491 I->replaceAllUsesWith(Loaded);
1492 I->eraseFromParent();
1495void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1496 ReplacementIRBuilder Builder(AI, *
DL);
1498 PartwordMaskValues PMV =
1508 CastOp = Instruction::SExt;
1512 PMV.ShiftAmt,
"ValOperand_Shifted");
1514 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1521void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1522 AtomicCmpXchgInst *CI) {
1523 ReplacementIRBuilder Builder(CI, *
DL);
1536 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1542 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1549Value *AtomicExpandImpl::insertRMWLLSCLoop(
1550 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1552 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1557 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1558 "Expected at least natural alignment at this point.");
1578 std::prev(BB->
end())->eraseFromParent();
1586 Value *NewVal = PerformOp(Builder, Loaded);
1588 Value *StoreSuccess =
1610AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1613 M->getDataLayout());
1615 ReplacementIRBuilder Builder(CI, *
DL);
1627 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1643bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1649 LLVMContext &Ctx =
F->getContext();
1656 ? AtomicOrdering::Monotonic
1668 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1669 SuccessOrder != AtomicOrdering::Monotonic &&
1670 SuccessOrder != AtomicOrdering::Acquire &&
1675 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1729 auto ReleasedLoadBB =
1733 auto ReleasingStoreBB =
1737 ReplacementIRBuilder Builder(CI, *
DL);
1742 std::prev(BB->
end())->eraseFromParent();
1744 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1747 PartwordMaskValues PMV =
1754 Value *UnreleasedLoad =
1755 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1756 Value *UnreleasedLoadExtract =
1763 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1764 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1767 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1772 PHINode *LoadedTryStore =
1773 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1774 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1775 Value *NewValueInsert =
1778 PMV.AlignedAddr, MemOpOrder);
1780 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1781 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1783 CI->
isWeak() ? FailureBB : RetryBB,
1784 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1788 if (HasReleasedLoadBB) {
1790 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1798 ShouldStore, TryStoreBB, NoStoreBB,
1799 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1801 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1808 if (ShouldInsertFencesForAtomic ||
1814 PHINode *LoadedNoStore =
1816 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1817 if (HasReleasedLoadBB)
1818 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1827 PHINode *LoadedFailure =
1829 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1831 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1832 if (ShouldInsertFencesForAtomic)
1841 PHINode *LoadedExit =
1843 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1844 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1851 Value *LoadedFull = LoadedExit;
1859 for (
auto *User : CI->
users()) {
1865 "weird extraction from { iN, i1 }");
1876 for (
auto *EV : PrunedInsts)
1893bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1908 return C->isMinusOne();
1910 return C->isMaxValue(
true);
1912 return C->isMinValue(
true);
1914 return C->isMaxValue(
false);
1916 return C->isMinValue(
false);
1922bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1924 tryExpandAtomicLoad(ResultingLoad);
1930Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1931 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1933 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1934 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1961 std::prev(BB->
end())->eraseFromParent();
1969 Loaded->addIncoming(InitLoaded, BB);
1978 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1982 processAtomicInstr(InitLoaded);
1985 Value *NewVal = PerformOp(Builder, Loaded);
1987 Value *NewLoaded =
nullptr;
1990 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1991 MemOpOrder == AtomicOrdering::Unordered
1992 ? AtomicOrdering::Monotonic
1994 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
1997 Loaded->addIncoming(NewLoaded, LoopBB);
2010bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
2017 case TargetLoweringBase::AtomicExpansionKind::None:
2018 if (ValueSize < MinCASSize)
2019 return expandPartwordCmpXchg(CI);
2021 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
2022 return expandAtomicCmpXchg(CI);
2024 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
2025 expandAtomicCmpXchgToMaskedIntrinsic(CI);
2027 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
2029 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
2036bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
2037 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
2044 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
2047 [&](IRBuilderBase &Builder,
Value *Loaded) {
2048 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
2049 AI->getValOperand());
2072 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
2073 return Alignment >=
Size &&
2075 Size <= LargestSize;
2078void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
2079 static const RTLIB::Libcall Libcalls[6] = {
2080 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
2081 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
2084 bool Expanded = expandAtomicOpToLibcall(
2085 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
2086 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2088 handleUnsupportedAtomicSize(
I,
"atomic load");
2091void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
2092 static const RTLIB::Libcall Libcalls[6] = {
2093 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
2094 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
2097 bool Expanded = expandAtomicOpToLibcall(
2098 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
2099 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2101 handleUnsupportedAtomicSize(
I,
"atomic store");
2104void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
2105 const Twine &AtomicOpName,
2106 Instruction *DiagnosticInst) {
2107 static const RTLIB::Libcall Libcalls[6] = {
2108 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
2109 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
2110 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
2113 bool Expanded = expandAtomicOpToLibcall(
2114 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
2115 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
2118 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
2122 static const RTLIB::Libcall LibcallsXchg[6] = {
2123 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
2124 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
2125 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
2126 static const RTLIB::Libcall LibcallsAdd[6] = {
2127 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2128 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2129 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2130 static const RTLIB::Libcall LibcallsSub[6] = {
2131 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2132 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2133 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2134 static const RTLIB::Libcall LibcallsAnd[6] = {
2135 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2136 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2137 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2138 static const RTLIB::Libcall LibcallsOr[6] = {
2139 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2140 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2141 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2142 static const RTLIB::Libcall LibcallsXor[6] = {
2143 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2144 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2145 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2146 static const RTLIB::Libcall LibcallsNand[6] = {
2147 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2148 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2149 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2190void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2196 if (!Libcalls.
empty())
2197 Success = expandAtomicOpToLibcall(
2198 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2199 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2206 expandAtomicRMWToCmpXchg(
2207 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2210 Value *&NewLoaded, Instruction *MetadataSrc) {
2213 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2223 expandAtomicCASToLibcall(
2237bool AtomicExpandImpl::expandAtomicOpToLibcall(
2238 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2243 LLVMContext &Ctx =
I->getContext();
2245 const DataLayout &
DL =
M->getDataLayout();
2247 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2250 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2252 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2262 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2266 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2268 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2271 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2273 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2275 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2277 RTLIB::Libcall RTLibType;
2278 if (UseSizedLibcall) {
2281 RTLibType = Libcalls[1];
2284 RTLibType = Libcalls[2];
2287 RTLibType = Libcalls[3];
2290 RTLibType = Libcalls[4];
2293 RTLibType = Libcalls[5];
2296 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2297 RTLibType = Libcalls[0];
2304 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2305 if (LibcallImpl == RTLIB::Unsupported) {
2336 AllocaInst *AllocaCASExpected =
nullptr;
2337 AllocaInst *AllocaValue =
nullptr;
2338 AllocaInst *AllocaResult =
nullptr;
2345 if (!UseSizedLibcall) {
2347 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2355 Value *PtrVal = PointerOperand;
2357 Args.push_back(PtrVal);
2361 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2365 Args.push_back(AllocaCASExpected);
2370 if (UseSizedLibcall) {
2373 Args.push_back(IntValue);
2375 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2379 Args.push_back(AllocaValue);
2384 if (!CASExpected && HasResult && !UseSizedLibcall) {
2385 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2388 Args.push_back(AllocaResult);
2392 Args.push_back(OrderingVal);
2396 Args.push_back(Ordering2Val);
2400 ResultTy = Type::getInt1Ty(Ctx);
2401 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2402 }
else if (HasResult && UseSizedLibcall)
2403 ResultTy = SizedIntTy;
2405 ResultTy = Type::getVoidTy(Ctx);
2409 for (
Value *Arg : Args)
2411 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2412 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2420 if (ValueOperand && !UseSizedLibcall)
2426 Type *FinalResultTy =
I->getType();
2429 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2434 }
else if (HasResult) {
2436 if (UseSizedLibcall) {
2440 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2441 unsigned AS = PtrTy->getAddressSpace();
2443 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2452 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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,...
bool isElementwise() const
Return true if this RMW has elementwise vector semantics.
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.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
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.
bool isStrongerThanMonotonic(AtomicOrdering AO)
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
bool isReleaseOrStronger(AtomicOrdering AO)
AtomicOrderingCABI toCABI(AtomicOrdering AO)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
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.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
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 llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
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.