63#define DEBUG_TYPE "atomic-expand"
67class AtomicExpandImpl {
87 Ctx.
emitError(DiagnosticInst ? DiagnosticInst : &FailedInst,
Msg);
89 if (!FailedInst.getType()->isVoidTy())
91 FailedInst.eraseFromParent();
94 template <
typename Inst>
95 void handleUnsupportedAtomicSize(Inst *
I,
const Twine &AtomicOpName,
99 bool tryInsertTrailingSeqCstFence(
Instruction *AtomicI);
100 template <
typename AtomicInst>
101 bool tryInsertFencesForAtomic(AtomicInst *AtomicI,
bool OrderingRequiresFence,
105 bool tryExpandAtomicLoad(
LoadInst *LI);
106 bool expandAtomicLoadToLL(
LoadInst *LI);
107 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
119 void expandAtomicOpToLLSC(
123 void expandPartwordAtomicRMW(
131 Value *insertRMWCmpXchgLoop(
135 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
147 void expandAtomicLoadToLibcall(
LoadInst *LI);
148 void expandAtomicStoreToLibcall(
StoreInst *LI);
151 const Twine &AtomicOpName =
"cmpxchg",
155 CreateCmpXchgInstFun CreateCmpXchg);
180struct ReplacementIRBuilder
181 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
183 MDNode *PCSectionsMD =
nullptr;
191 if (
I->getFunction()->hasFnAttribute(Attribute::StrictFP))
192 this->setIsFPConstrained(
true);
194 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
195 PCSectionsMD =
I->getMetadata(LLVMContext::MD_pcsections);
200 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
201 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
207char AtomicExpandLegacy::ID = 0;
212 "Expand Atomic instructions",
false,
false)
221 return DL.getTypeStoreSize(LI->getType());
226 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
243 Source.getAllMetadata(MD);
247 for (
auto [ID,
N] : MD) {
249 case LLVMContext::MD_dbg:
250 case LLVMContext::MD_tbaa:
251 case LLVMContext::MD_tbaa_struct:
252 case LLVMContext::MD_alias_scope:
253 case LLVMContext::MD_mem_cache_hint:
254 case LLVMContext::MD_noalias:
255 case LLVMContext::MD_noalias_addrspace:
256 case LLVMContext::MD_access_group:
257 case LLVMContext::MD_mmra:
261 if (ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
263 else if (ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
273template <
typename Inst>
276 Align Alignment =
I->getAlign();
281template <
typename Inst>
285 Align Alignment =
I->getAlign();
286 bool NeedSeparator =
false;
289 OS <<
"instruction alignment " << Alignment.value()
290 <<
" is smaller than the required " <<
Size
291 <<
"-byte alignment for this atomic operation";
292 NeedSeparator =
true;
296 if (
Size > MaxSize) {
299 OS <<
"target supports atomics up to " << MaxSize
300 <<
" bytes, but this atomic accesses " <<
Size <<
" bytes";
304template <
typename Inst>
305void AtomicExpandImpl::handleUnsupportedAtomicSize(
308 SmallString<128> FailureReason;
309 raw_svector_ostream OS(FailureReason);
311 handleFailure(*
I, Twine(
"unsupported ") + AtomicOpName +
": " + FailureReason,
315bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
321 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
322 TrailingFence->moveAfter(AtomicI);
328template <
typename AtomicInst>
329bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
330 bool OrderingRequiresFence,
333 if (OrderingRequiresFence && ShouldInsertFences) {
335 AtomicI->setOrdering(NewOrdering);
336 return bracketInstWithFences(AtomicI, FenceOrdering);
338 if (!ShouldInsertFences)
339 return tryInsertTrailingSeqCstFence(AtomicI);
346bool AtomicExpandImpl::lowerToNonAtomic(Instruction *
I) {
348 FI->eraseFromParent();
359 if (LI->isAtomic()) {
360 LI->setAtomic(AtomicOrdering::NotAtomic);
361 LI->setElementwise(
false);
369 if (
SI->isAtomic()) {
370 SI->setAtomic(AtomicOrdering::NotAtomic);
371 SI->setElementwise(
false);
381bool AtomicExpandImpl::processAtomicInstr(Instruction *
I) {
383 return lowerToNonAtomic(
I);
390 expandAtomicLoadToLibcall(LI);
394 bool MadeChange =
false;
396 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
397 LI = convertAtomicLoadToIntegerType(LI);
405 MadeChange |= tryExpandAtomicLoad(LI);
414 expandAtomicStoreToLibcall(SI);
418 bool MadeChange =
false;
420 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
421 SI = convertAtomicStoreToIntegerType(SI);
429 MadeChange |= tryExpandAtomicStore(SI);
434 bool IsElementwiseExpand =
435 RMWI->isElementwise() &&
437 TargetLoweringBase::AtomicExpansionKind::Expand;
442 if (!IsElementwiseExpand) {
443 expandAtomicRMWToLibcall(RMWI);
448 bool MadeChange =
false;
449 if (!IsElementwiseExpand &&
451 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
452 RMWI = convertAtomicXchgToIntegerType(RMWI);
456 MadeChange |= tryInsertFencesForAtomic(
464 MadeChange |= (
isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
465 tryExpandAtomicRMW(RMWI);
471 expandAtomicCASToLibcall(CASI);
477 bool MadeChange =
false;
478 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
481 CASI = convertCmpXchgToIntegerType(CASI);
487 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
498 CASI->setSuccessOrdering(CASOrdering);
499 CASI->setFailureOrdering(CASOrdering);
500 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
502 }
else if (CmpXchgExpansion !=
503 TargetLoweringBase::AtomicExpansionKind::LLSC) {
505 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
508 MadeChange |= tryExpandAtomicCmpXchg(CASI);
516 const ModuleLibcallLoweringInfo &LibcallResult,
517 const TargetMachine *TM) {
518 SingleThreaded =
F.getParent()->getThreadModel() == ThreadModel::Single;
524 TLI = Subtarget->getTargetLowering();
526 DL = &
F.getDataLayout();
528 bool MadeChange =
false;
540 if (processAtomicInstr(&Inst)) {
552bool AtomicExpandLegacy::runOnFunction(
Function &
F) {
554 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
557 auto *TM = &TPC->getTM<TargetMachine>();
559 const ModuleLibcallLoweringInfo &LibcallResult =
560 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
562 return AE.run(
F, LibcallResult, TM);
566 return new AtomicExpandLegacy();
576 if (!LibcallResult) {
578 "' analysis required");
584 bool Changed = AE.run(
F, *LibcallResult, TM);
591bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
593 ReplacementIRBuilder Builder(
I, *
DL);
603 return (LeadingFence || TrailingFence);
618LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
620 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
622 ReplacementIRBuilder Builder(LI, *
DL);
626 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->
getProperties());
627 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
630 ? Builder.CreateIntToPtr(NewLI, LI->
getType())
631 : Builder.CreateBitCast(NewLI, LI->
getType());
638AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
643 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
645 ReplacementIRBuilder Builder(RMWI, *
DL);
649 Value *NewVal = Builder.CreateBitPreservingCastChain(*
DL, Val, NewTy);
656 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
659 Builder.CreateBitPreservingCastChain(*
DL, NewRMWI, RMWI->
getType());
680void AtomicExpandImpl::expandElementwiseAtomicRMW(AtomicRMWInst *AI) {
683 Type *LaneTy = VecTy->getElementType();
684 const unsigned NumLanes = VecTy->getNumElements();
688 ReplacementIRBuilder Builder(AI, *
DL);
693 bool Elementwise) -> AtomicRMWInst * {
695 Builder.CreateAtomicRMW(AI->
getOperation(), HalfPtr, HalfVal,
A,
698 NewAI->setElementwise(Elementwise);
703 Constant *IdxZero = ConstantInt::get(IdxTy, 0);
704 Constant *IdxOne = ConstantInt::get(IdxTy, 1);
709 Value *LaneVal = Builder.CreateExtractElement(Val, IdxZero,
"lane.val");
710 AtomicRMWInst *LaneRMW = CreateRMWInstruction(Ptr, LaneVal, AI->
getAlign(),
713 LaneRMW, IdxZero,
"lane.old");
716 processAtomicInstr(LaneRMW);
723 "elementwise atomicrmw vector length must be a power of two");
724 const unsigned HalfLanes = NumLanes / 2;
726 const uint64_t HalfBytes =
DL->getTypeStoreSize(HalfVecTy).getFixedValue();
728 Value *LoVal = Builder.CreateShuffleVector(
730 Value *HiVal = Builder.CreateShuffleVector(
733 Value *HiPtr = Builder.CreateInBoundsGEP(HalfVecTy, Ptr, IdxOne,
"hi.ptr");
737 AtomicRMWInst *LoRMW =
738 CreateRMWInstruction(Ptr, LoVal, LoAlign,
true);
739 AtomicRMWInst *HiRMW =
740 CreateRMWInstruction(HiPtr, HiVal, HiAlign,
true);
747 processAtomicInstr(LoRMW);
748 processAtomicInstr(HiRMW);
751bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
753 case TargetLoweringBase::AtomicExpansionKind::None:
755 case TargetLoweringBase::AtomicExpansionKind::LLSC:
756 expandAtomicOpToLLSC(
759 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
761 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
762 return expandAtomicLoadToLL(LI);
763 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
764 return expandAtomicLoadToCmpXchg(LI);
765 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
766 LI->
setAtomic(AtomicOrdering::NotAtomic);
768 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
776bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
778 case TargetLoweringBase::AtomicExpansionKind::None:
780 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
783 case TargetLoweringBase::AtomicExpansionKind::Expand:
784 expandAtomicStoreToXChg(SI);
786 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
787 SI->setAtomic(AtomicOrdering::NotAtomic);
794bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
795 ReplacementIRBuilder Builder(LI, *
DL);
810bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
811 ReplacementIRBuilder Builder(LI, *
DL);
813 if (Order == AtomicOrdering::Unordered)
814 Order = AtomicOrdering::Monotonic;
823 Type *CmpXchgTy = Ty;
828 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
829 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
833 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
835 Loaded = Builder.CreateBitCast(Loaded, Ty);
851StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
852 ReplacementIRBuilder Builder(SI, *
DL);
853 auto *
M =
SI->getModule();
854 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
856 Value *NewVal =
SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
857 ? Builder.CreatePtrToInt(
SI->getValueOperand(), NewTy)
858 : Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
860 Value *Addr =
SI->getPointerOperand();
862 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr,
SI->getProperties());
864 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
865 SI->eraseFromParent();
869void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
876 ReplacementIRBuilder Builder(SI, *
DL);
878 assert(Ordering != AtomicOrdering::NotAtomic);
880 ? AtomicOrdering::Monotonic
882 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
884 SI->getAlign(), RMWOrdering,
SI->getSyncScopeID());
886 SI->eraseFromParent();
889 tryExpandAtomicRMW(AI);
904 NewVal = Builder.CreateBitCast(NewVal, IntTy);
905 Loaded = Builder.CreateBitCast(Loaded, IntTy);
909 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
915 Success = Builder.CreateExtractValue(Pair, 1,
"success");
916 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
919 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
922void AtomicExpandImpl::expandAtomicSubToAdd(AtomicRMWInst *AI) {
923 ReplacementIRBuilder Builder(AI, *
DL);
944bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
948 case TargetLoweringBase::AtomicExpansionKind::None:
950 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
953 if (ValueSize < MinCASSize) {
954 expandPartwordAtomicRMW(AI,
955 TargetLoweringBase::AtomicExpansionKind::LLSC);
957 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
966 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
969 if (ValueSize < MinCASSize) {
970 expandPartwordAtomicRMW(AI,
971 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
980 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
981 <<
"A compare and swap loop was generated for an atomic "
989 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
992 if (ValueSize < MinCASSize) {
997 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1001 expandAtomicRMWToMaskedIntrinsic(AI);
1004 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
1008 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
1012 case TargetLoweringBase::AtomicExpansionKind::Expand:
1014 expandElementwiseAtomicRMW(AI);
1017 expandAtomicSubToAdd(AI);
1019 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1021 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
1031struct PartwordMaskValues {
1033 Type *WordType =
nullptr;
1035 Type *IntValueType =
nullptr;
1036 Value *AlignedAddr =
nullptr;
1037 Align AlignedAddrAlignment;
1039 Value *ShiftAmt =
nullptr;
1040 Value *Mask =
nullptr;
1041 Value *Inv_Mask =
nullptr;
1045raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
1046 auto PrintObj = [&
O](
auto *
V) {
1053 O <<
"PartwordMaskValues {\n";
1055 PrintObj(PMV.WordType);
1056 O <<
" ValueType: ";
1057 PrintObj(PMV.ValueType);
1058 O <<
" AlignedAddr: ";
1059 PrintObj(PMV.AlignedAddr);
1060 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
1062 PrintObj(PMV.ShiftAmt);
1066 PrintObj(PMV.Inv_Mask);
1092 unsigned MinWordSize) {
1093 PartwordMaskValues PMV;
1098 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
1100 PMV.ValueType = PMV.IntValueType =
ValueType;
1105 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
1107 if (PMV.ValueType == PMV.WordType) {
1108 PMV.AlignedAddr = Addr;
1109 PMV.AlignedAddrAlignment = AddrAlign;
1110 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
1111 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
1115 PMV.AlignedAddrAlignment =
Align(MinWordSize);
1117 assert(ValueSize < MinWordSize);
1120 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
1123 if (AddrAlign < MinWordSize) {
1124 PMV.AlignedAddr = Builder.CreateIntrinsic(
1125 Intrinsic::ptrmask, {PtrTy, IntTy},
1127 nullptr,
"AlignedAddr");
1129 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
1130 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
1133 PMV.AlignedAddr = Addr;
1137 if (
DL.isLittleEndian()) {
1139 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
1142 PMV.ShiftAmt = Builder.CreateShl(
1143 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
1146 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
1147 PMV.Mask = Builder.CreateShl(
1148 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
1151 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
1157 const PartwordMaskValues &PMV) {
1158 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1159 if (PMV.WordType == PMV.ValueType)
1162 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
1163 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
1164 return Builder.CreateBitCast(Trunc, PMV.ValueType);
1168 Value *Updated,
const PartwordMaskValues &PMV) {
1169 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
1170 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
1171 if (PMV.WordType == PMV.ValueType)
1174 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
1176 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
1178 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
1179 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
1180 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
1190 const PartwordMaskValues &PMV) {
1197 "Or/Xor/And handled by widenPartwordAtomicRMW");
1202 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1205 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, ValOperand_Shifted);
1227 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1228 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1229 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1236 assert(!ValOperand_Shifted);
1250void AtomicExpandImpl::expandPartwordAtomicRMW(
1256 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1262 ReplacementIRBuilder Builder(AI, *
DL);
1264 PartwordMaskValues PMV =
1268 Value *ValOperand_Shifted =
nullptr;
1269 bool NeedsShiftedOperand =
1274 if (NeedsShiftedOperand) {
1276 ValOperand_Shifted =
1277 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1278 "ValOperand_Shifted");
1281 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1287 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1288 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1289 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1293 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1294 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1295 PMV.AlignedAddrAlignment, MemOpOrder,
1305AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1306 ReplacementIRBuilder Builder(AI, *
DL);
1311 "Unable to widen operation");
1313 PartwordMaskValues PMV =
1323 Value *ValOperand_Shifted =
1325 "ValOperand_Shifted");
1331 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1333 NewOperand = ValOperand_Shifted;
1336 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1348bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1390 ReplacementIRBuilder Builder(CI, *
DL);
1401 std::prev(BB->
end())->eraseFromParent();
1404 PartwordMaskValues PMV =
1409 Value *NewVal_Shifted =
1411 Value *Cmp_Shifted =
1416 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1417 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1422 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1423 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1436 processAtomicInstr(InitLoaded);
1440 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1441 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1443 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1471 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1486void AtomicExpandImpl::expandAtomicOpToLLSC(
1487 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1489 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1490 ReplacementIRBuilder Builder(
I, *
DL);
1491 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1492 MemOpOrder, PerformOp);
1494 I->replaceAllUsesWith(Loaded);
1495 I->eraseFromParent();
1498void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1499 ReplacementIRBuilder Builder(AI, *
DL);
1501 PartwordMaskValues PMV =
1511 CastOp = Instruction::SExt;
1515 PMV.ShiftAmt,
"ValOperand_Shifted");
1517 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1524void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1525 AtomicCmpXchgInst *CI) {
1526 ReplacementIRBuilder Builder(CI, *
DL);
1539 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1545 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1552Value *AtomicExpandImpl::insertRMWLLSCLoop(
1553 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1555 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1560 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1561 "Expected at least natural alignment at this point.");
1581 std::prev(BB->
end())->eraseFromParent();
1589 Value *NewVal = PerformOp(Builder, Loaded);
1591 Value *StoreSuccess =
1613AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1616 M->getDataLayout());
1618 ReplacementIRBuilder Builder(CI, *
DL);
1630 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1646bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1652 LLVMContext &Ctx =
F->getContext();
1659 ? AtomicOrdering::Monotonic
1671 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1672 SuccessOrder != AtomicOrdering::Monotonic &&
1673 SuccessOrder != AtomicOrdering::Acquire &&
1678 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1732 auto ReleasedLoadBB =
1736 auto ReleasingStoreBB =
1740 ReplacementIRBuilder Builder(CI, *
DL);
1745 std::prev(BB->
end())->eraseFromParent();
1747 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1750 PartwordMaskValues PMV =
1757 Value *UnreleasedLoad =
1758 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1759 Value *UnreleasedLoadExtract =
1766 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1767 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1770 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1775 PHINode *LoadedTryStore =
1776 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1777 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1778 Value *NewValueInsert =
1781 PMV.AlignedAddr, MemOpOrder);
1783 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1784 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1786 CI->
isWeak() ? FailureBB : RetryBB,
1787 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1791 if (HasReleasedLoadBB) {
1793 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1801 ShouldStore, TryStoreBB, NoStoreBB,
1802 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1804 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1811 if (ShouldInsertFencesForAtomic ||
1817 PHINode *LoadedNoStore =
1819 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1820 if (HasReleasedLoadBB)
1821 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1830 PHINode *LoadedFailure =
1832 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1834 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1835 if (ShouldInsertFencesForAtomic)
1844 PHINode *LoadedExit =
1846 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1847 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1854 Value *LoadedFull = LoadedExit;
1862 for (
auto *User : CI->
users()) {
1868 "weird extraction from { iN, i1 }");
1879 for (
auto *EV : PrunedInsts)
1896bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1911 return C->isMinusOne();
1913 return C->isMaxValue(
true);
1915 return C->isMinValue(
true);
1917 return C->isMaxValue(
false);
1919 return C->isMinValue(
false);
1925bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1927 tryExpandAtomicLoad(ResultingLoad);
1933Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1934 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1936 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1937 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1964 std::prev(BB->
end())->eraseFromParent();
1972 Loaded->addIncoming(InitLoaded, BB);
1981 InitLoaded->
setAtomic(AtomicOrdering::Monotonic, SSID);
1985 processAtomicInstr(InitLoaded);
1988 Value *NewVal = PerformOp(Builder, Loaded);
1990 Value *NewLoaded =
nullptr;
1993 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1994 MemOpOrder == AtomicOrdering::Unordered
1995 ? AtomicOrdering::Monotonic
1997 SSID, IsVolatile,
Success, NewLoaded, MetadataSrc);
2000 Loaded->addIncoming(NewLoaded, LoopBB);
2013bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
2020 case TargetLoweringBase::AtomicExpansionKind::None:
2021 if (ValueSize < MinCASSize)
2022 return expandPartwordCmpXchg(CI);
2024 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
2025 return expandAtomicCmpXchg(CI);
2027 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
2028 expandAtomicCmpXchgToMaskedIntrinsic(CI);
2030 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
2032 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
2039bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
2040 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
2047 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
2050 [&](IRBuilderBase &Builder,
Value *Loaded) {
2051 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
2052 AI->getValOperand());
2075 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
2076 return Alignment >=
Size &&
2078 Size <= LargestSize;
2081void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
2082 static const RTLIB::Libcall Libcalls[6] = {
2083 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
2084 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
2087 bool Expanded = expandAtomicOpToLibcall(
2088 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
2089 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2091 handleUnsupportedAtomicSize(
I,
"atomic load");
2094void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
2095 static const RTLIB::Libcall Libcalls[6] = {
2096 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
2097 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
2100 bool Expanded = expandAtomicOpToLibcall(
2101 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
2102 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2104 handleUnsupportedAtomicSize(
I,
"atomic store");
2107void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I,
2108 const Twine &AtomicOpName,
2109 Instruction *DiagnosticInst) {
2110 static const RTLIB::Libcall Libcalls[6] = {
2111 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
2112 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
2113 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
2116 bool Expanded = expandAtomicOpToLibcall(
2117 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
2118 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
2121 handleUnsupportedAtomicSize(
I, AtomicOpName, DiagnosticInst);
2125 static const RTLIB::Libcall LibcallsXchg[6] = {
2126 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
2127 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
2128 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
2129 static const RTLIB::Libcall LibcallsAdd[6] = {
2130 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
2131 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
2132 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
2133 static const RTLIB::Libcall LibcallsSub[6] = {
2134 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
2135 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
2136 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
2137 static const RTLIB::Libcall LibcallsAnd[6] = {
2138 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
2139 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
2140 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
2141 static const RTLIB::Libcall LibcallsOr[6] = {
2142 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
2143 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
2144 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
2145 static const RTLIB::Libcall LibcallsXor[6] = {
2146 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
2147 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
2148 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
2149 static const RTLIB::Libcall LibcallsNand[6] = {
2150 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
2151 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
2152 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
2193void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
2199 if (!Libcalls.
empty())
2200 Success = expandAtomicOpToLibcall(
2201 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
2202 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2209 expandAtomicRMWToCmpXchg(
2210 I, [
this,
I](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
2213 Value *&NewLoaded, Instruction *MetadataSrc) {
2216 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2226 expandAtomicCASToLibcall(
2240bool AtomicExpandImpl::expandAtomicOpToLibcall(
2241 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
2246 LLVMContext &Ctx =
I->getContext();
2248 const DataLayout &
DL =
M->getDataLayout();
2250 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
2253 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
2255 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
2265 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
2269 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2271 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
2274 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
2276 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
2278 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
2280 RTLIB::Libcall RTLibType;
2281 if (UseSizedLibcall) {
2284 RTLibType = Libcalls[1];
2287 RTLibType = Libcalls[2];
2290 RTLibType = Libcalls[3];
2293 RTLibType = Libcalls[4];
2296 RTLibType = Libcalls[5];
2299 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2300 RTLibType = Libcalls[0];
2307 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2308 if (LibcallImpl == RTLIB::Unsupported) {
2339 AllocaInst *AllocaCASExpected =
nullptr;
2340 AllocaInst *AllocaValue =
nullptr;
2341 AllocaInst *AllocaResult =
nullptr;
2348 if (!UseSizedLibcall) {
2350 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2358 Value *PtrVal = PointerOperand;
2360 Args.push_back(PtrVal);
2364 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2368 Args.push_back(AllocaCASExpected);
2373 if (UseSizedLibcall) {
2376 Args.push_back(IntValue);
2378 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2382 Args.push_back(AllocaValue);
2387 if (!CASExpected && HasResult && !UseSizedLibcall) {
2388 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2391 Args.push_back(AllocaResult);
2397 Attribute::AttrKind OrderingExt =
2398 TargetLibraryInfo::getExtAttrForI32Param(
M->getTargetTriple());
2401 Args.push_back(OrderingVal);
2402 Attr = Attr.maybeAddParamAttribute(Ctx,
Args.size() - 1, OrderingExt);
2406 Args.push_back(Ordering2Val);
2407 Attr = Attr.maybeAddParamAttribute(Ctx,
Args.size() - 1, OrderingExt);
2412 ResultTy = Type::getInt1Ty(Ctx);
2413 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2414 }
else if (HasResult && UseSizedLibcall)
2415 ResultTy = SizedIntTy;
2417 ResultTy = Type::getVoidTy(Ctx);
2421 for (
Value *Arg : Args)
2423 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2424 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2432 if (ValueOperand && !UseSizedLibcall)
2438 Type *FinalResultTy =
I->getType();
2441 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2446 }
else if (HasResult) {
2448 if (UseSizedLibcall) {
2452 if (VTy && PtrTy && !
Result->getType()->isVectorTy()) {
2453 unsigned AS = PtrTy->getAddressSpace();
2455 Result, VTy->getWithNewType(
DL.getIntPtrType(Ctx, AS)));
2464 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 bool isAtomicAlignmentSupported(Align Alignment, uint64_t SizeInBytes) const
Return true if the target supports an atomic access of SizeInBytes bytes at the given Alignment.
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.