59#define DEBUG_TYPE "atomic-expand"
63class AtomicExpandImpl {
91 bool tryExpandAtomicLoad(
LoadInst *LI);
92 bool expandAtomicLoadToLL(
LoadInst *LI);
93 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
103 void expandAtomicOpToLLSC(
107 void expandPartwordAtomicRMW(
115 static Value *insertRMWCmpXchgLoop(
119 CreateCmpXchgInstFun CreateCmpXchg,
Instruction *MetadataSrc);
131 void expandAtomicLoadToLibcall(
LoadInst *LI);
132 void expandAtomicStoreToLibcall(
StoreInst *LI);
137 CreateCmpXchgInstFun CreateCmpXchg);
162struct ReplacementIRBuilder
163 :
IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
173 this->CollectMetadataToCopy(
I, {LLVMContext::MD_pcsections});
174 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
175 this->setIsFPConstrained(
true);
177 MMRAMD =
I->getMetadata(LLVMContext::MD_mmra);
182 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
188char AtomicExpandLegacy::ID = 0;
193 "Expand Atomic instructions",
false,
false)
202 return DL.getTypeStoreSize(LI->getType());
207 return DL.getTypeStoreSize(
SI->getValueOperand()->getType());
224 Source.getAllMetadata(MD);
228 for (
auto [
ID,
N] : MD) {
230 case LLVMContext::MD_dbg:
231 case LLVMContext::MD_tbaa:
232 case LLVMContext::MD_tbaa_struct:
233 case LLVMContext::MD_alias_scope:
234 case LLVMContext::MD_noalias:
235 case LLVMContext::MD_noalias_addrspace:
236 case LLVMContext::MD_access_group:
237 case LLVMContext::MD_mmra:
241 if (
ID == Ctx.getMDKindID(
"amdgpu.no.remote.memory"))
243 else if (
ID == Ctx.getMDKindID(
"amdgpu.no.fine.grained.memory"))
256template <
typename Inst>
259 Align Alignment =
I->getAlign();
260 return Alignment >=
Size &&
264bool AtomicExpandImpl::processAtomicInstr(
Instruction *
I) {
270 bool MadeChange =
false;
278 expandAtomicLoadToLibcall(LI);
283 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
284 I = LI = convertAtomicLoadToIntegerType(LI);
292 expandAtomicStoreToLibcall(SI);
297 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
298 I =
SI = convertAtomicStoreToIntegerType(SI);
303 expandAtomicRMWToLibcall(RMWI);
308 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
309 I = RMWI = convertAtomicXchgToIntegerType(RMWI);
314 expandAtomicCASToLibcall(CASI);
320 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
323 I = CASI = convertCmpXchgToIntegerType(CASI);
330 auto FenceOrdering = AtomicOrdering::Monotonic;
332 FenceOrdering = LI->getOrdering();
333 LI->setOrdering(AtomicOrdering::Monotonic);
335 FenceOrdering =
SI->getOrdering();
336 SI->setOrdering(AtomicOrdering::Monotonic);
339 FenceOrdering = RMWI->getOrdering();
343 TargetLoweringBase::AtomicExpansionKind::None &&
351 FenceOrdering = CASI->getMergedOrdering();
354 CASI->setSuccessOrdering(CASOrdering);
355 CASI->setFailureOrdering(CASOrdering);
358 if (FenceOrdering != AtomicOrdering::Monotonic) {
359 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
363 TargetLoweringBase::AtomicExpansionKind::LLSC)) {
367 Builder,
I, AtomicOrdering::SequentiallyConsistent)) {
368 TrailingFence->moveAfter(
I);
374 MadeChange |= tryExpandAtomicLoad(LI);
376 MadeChange |= tryExpandAtomicStore(SI);
387 MadeChange |= tryExpandAtomicRMW(RMWI);
390 MadeChange |= tryExpandAtomicCmpXchg(CASI);
395bool AtomicExpandImpl::run(
396 Function &
F,
const LibcallLoweringModuleAnalysisResult &LibcallResult,
397 const TargetMachine *TM) {
399 if (!Subtarget->enableAtomicExpand())
401 TLI = Subtarget->getTargetLowering();
403 DL = &
F.getDataLayout();
405 bool MadeChange =
false;
417 if (processAtomicInstr(&Inst)) {
429bool AtomicExpandLegacy::runOnFunction(Function &
F) {
431 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
434 auto *TM = &TPC->getTM<TargetMachine>();
436 const LibcallLoweringModuleAnalysisResult &LibcallResult =
437 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*
F.getParent());
439 return AE.run(
F, LibcallResult, TM);
443 return new AtomicExpandLegacy();
453 if (!LibcallResult) {
455 "' analysis required");
461 bool Changed = AE.run(
F, *LibcallResult, TM);
468bool AtomicExpandImpl::bracketInstWithFences(
Instruction *
I,
470 ReplacementIRBuilder Builder(
I, *
DL);
480 return (LeadingFence || TrailingFence);
495LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
497 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
M->getDataLayout());
499 ReplacementIRBuilder Builder(LI, *
DL);
503 auto *NewLI = Builder.CreateLoad(NewTy, Addr);
504 NewLI->setAlignment(LI->
getAlign());
507 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
509 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
516AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
521 getCorrespondingIntegerType(RMWI->
getType(),
M->getDataLayout());
523 ReplacementIRBuilder Builder(RMWI, *
DL);
528 ? Builder.CreatePtrToInt(Val, NewTy)
529 : Builder.CreateBitCast(Val, NewTy);
536 LLVM_DEBUG(
dbgs() <<
"Replaced " << *RMWI <<
" with " << *NewRMWI <<
"\n");
539 ? Builder.CreateIntToPtr(NewRMWI, RMWI->
getType())
540 : Builder.CreateBitCast(NewRMWI, RMWI->
getType());
546bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
548 case TargetLoweringBase::AtomicExpansionKind::None:
550 case TargetLoweringBase::AtomicExpansionKind::LLSC:
551 expandAtomicOpToLLSC(
554 [](IRBuilderBase &Builder,
Value *Loaded) { return Loaded; });
556 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
557 return expandAtomicLoadToLL(LI);
558 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
559 return expandAtomicLoadToCmpXchg(LI);
560 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
561 LI->
setAtomic(AtomicOrdering::NotAtomic);
563 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
571bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
573 case TargetLoweringBase::AtomicExpansionKind::None:
575 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
578 case TargetLoweringBase::AtomicExpansionKind::Expand:
579 expandAtomicStoreToXChg(SI);
581 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
582 SI->setAtomic(AtomicOrdering::NotAtomic);
589bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
590 ReplacementIRBuilder Builder(LI, *
DL);
605bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
606 ReplacementIRBuilder Builder(LI, *
DL);
608 if (Order == AtomicOrdering::Unordered)
609 Order = AtomicOrdering::Monotonic;
615 Value *Pair = Builder.CreateAtomicCmpXchg(
616 Addr, DummyVal, DummyVal, LI->
getAlign(), Order,
618 Value *
Loaded = Builder.CreateExtractValue(Pair, 0,
"loaded");
634StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
635 ReplacementIRBuilder Builder(SI, *
DL);
636 auto *
M =
SI->getModule();
637 Type *NewTy = getCorrespondingIntegerType(
SI->getValueOperand()->getType(),
639 Value *NewVal = Builder.CreateBitCast(
SI->getValueOperand(), NewTy);
641 Value *Addr =
SI->getPointerOperand();
643 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr);
647 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
648 SI->eraseFromParent();
652void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
659 ReplacementIRBuilder Builder(SI, *
DL);
661 assert(Ordering != AtomicOrdering::NotAtomic);
663 ? AtomicOrdering::Monotonic
665 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
667 SI->getAlign(), RMWOrdering);
668 SI->eraseFromParent();
671 tryExpandAtomicRMW(AI);
686 NewVal = Builder.CreateBitCast(NewVal, IntTy);
687 Loaded = Builder.CreateBitCast(Loaded, IntTy);
691 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
696 Success = Builder.CreateExtractValue(Pair, 1,
"success");
697 NewLoaded = Builder.CreateExtractValue(Pair, 0,
"newloaded");
700 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
703bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
707 case TargetLoweringBase::AtomicExpansionKind::None:
709 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
712 if (ValueSize < MinCASSize) {
713 expandPartwordAtomicRMW(AI,
714 TargetLoweringBase::AtomicExpansionKind::LLSC);
716 auto PerformOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
725 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
728 if (ValueSize < MinCASSize) {
729 expandPartwordAtomicRMW(AI,
730 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
739 return OptimizationRemark(
DEBUG_TYPE,
"Passed", AI)
740 <<
"A compare and swap loop was generated for an atomic "
742 << MemScope <<
" memory scope";
748 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
751 if (ValueSize < MinCASSize) {
756 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
760 expandAtomicRMWToMaskedIntrinsic(AI);
763 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
767 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
771 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
773 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
783struct PartwordMaskValues {
785 Type *WordType =
nullptr;
787 Type *IntValueType =
nullptr;
788 Value *AlignedAddr =
nullptr;
789 Align AlignedAddrAlignment;
791 Value *ShiftAmt =
nullptr;
792 Value *Mask =
nullptr;
793 Value *Inv_Mask =
nullptr;
797raw_ostream &
operator<<(raw_ostream &O,
const PartwordMaskValues &PMV) {
798 auto PrintObj = [&
O](
auto *
V) {
805 O <<
"PartwordMaskValues {\n";
807 PrintObj(PMV.WordType);
809 PrintObj(PMV.ValueType);
810 O <<
" AlignedAddr: ";
811 PrintObj(PMV.AlignedAddr);
812 O <<
" AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.
value() <<
'\n';
814 PrintObj(PMV.ShiftAmt);
818 PrintObj(PMV.Inv_Mask);
844 unsigned MinWordSize) {
845 PartwordMaskValues PMV;
850 unsigned ValueSize =
DL.getTypeStoreSize(
ValueType);
852 PMV.ValueType = PMV.IntValueType =
ValueType;
857 PMV.WordType = MinWordSize > ValueSize ?
Type::getIntNTy(Ctx, MinWordSize * 8)
859 if (PMV.ValueType == PMV.WordType) {
860 PMV.AlignedAddr = Addr;
861 PMV.AlignedAddrAlignment = AddrAlign;
862 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
863 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0,
true);
867 PMV.AlignedAddrAlignment =
Align(MinWordSize);
869 assert(ValueSize < MinWordSize);
872 IntegerType *IntTy =
DL.getIndexType(Ctx, PtrTy->getAddressSpace());
875 if (AddrAlign < MinWordSize) {
876 PMV.AlignedAddr = Builder.CreateIntrinsic(
877 Intrinsic::ptrmask, {PtrTy, IntTy},
879 nullptr,
"AlignedAddr");
881 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
882 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1,
"PtrLSB");
885 PMV.AlignedAddr = Addr;
889 if (
DL.isLittleEndian()) {
891 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
894 PMV.ShiftAmt = Builder.CreateShl(
895 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
898 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType,
"ShiftAmt");
899 PMV.Mask = Builder.CreateShl(
900 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
903 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask,
"Inv_Mask");
909 const PartwordMaskValues &PMV) {
910 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
911 if (PMV.WordType == PMV.ValueType)
914 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt,
"shifted");
915 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType,
"extracted");
916 return Builder.CreateBitCast(Trunc, PMV.ValueType);
920 Value *Updated,
const PartwordMaskValues &PMV) {
921 assert(WideWord->
getType() == PMV.WordType &&
"Widened type mismatch");
922 assert(Updated->
getType() == PMV.ValueType &&
"Value type mismatch");
923 if (PMV.WordType == PMV.ValueType)
926 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
928 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType,
"extended");
930 Builder.CreateShl(ZExt, PMV.ShiftAmt,
"shifted",
true);
931 Value *
And = Builder.CreateAnd(WideWord, PMV.Inv_Mask,
"unmasked");
932 Value *
Or = Builder.CreateOr(
And, Shift,
"inserted");
942 const PartwordMaskValues &PMV) {
948 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
949 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
961 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
962 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
963 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1002void AtomicExpandImpl::expandPartwordAtomicRMW(
1008 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1014 ReplacementIRBuilder Builder(AI, *
DL);
1016 PartwordMaskValues PMV =
1020 Value *ValOperand_Shifted =
nullptr;
1024 ValOperand_Shifted =
1025 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1026 "ValOperand_Shifted");
1029 auto PerformPartwordOp = [&](IRBuilderBase &Builder,
Value *
Loaded) {
1035 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1036 OldResult = insertRMWCmpXchgLoop(
1037 Builder, PMV.WordType, PMV.AlignedAddr, PMV.AlignedAddrAlignment,
1040 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1041 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1042 PMV.AlignedAddrAlignment, MemOpOrder,
1052AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1053 ReplacementIRBuilder Builder(AI, *
DL);
1058 "Unable to widen operation");
1060 PartwordMaskValues PMV =
1064 Value *ValOperand_Shifted =
1066 PMV.ShiftAmt,
"ValOperand_Shifted");
1072 Builder.
CreateOr(ValOperand_Shifted, PMV.Inv_Mask,
"AndOperand");
1074 NewOperand = ValOperand_Shifted;
1077 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1088bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1130 ReplacementIRBuilder Builder(CI, *
DL);
1141 std::prev(BB->
end())->eraseFromParent();
1144 PartwordMaskValues PMV =
1149 Value *NewVal_Shifted =
1151 Value *Cmp_Shifted =
1156 LoadInst *InitLoaded = Builder.
CreateLoad(PMV.WordType, PMV.AlignedAddr);
1158 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
1163 PHINode *Loaded_MaskOut = Builder.
CreatePHI(PMV.WordType, 2);
1164 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
1167 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
1168 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
1170 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1198 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
1213void AtomicExpandImpl::expandAtomicOpToLLSC(
1214 Instruction *
I,
Type *ResultType,
Value *Addr, Align AddrAlign,
1216 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1217 ReplacementIRBuilder Builder(
I, *
DL);
1218 Value *
Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1219 MemOpOrder, PerformOp);
1221 I->replaceAllUsesWith(Loaded);
1222 I->eraseFromParent();
1225void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1226 ReplacementIRBuilder Builder(AI, *
DL);
1228 PartwordMaskValues PMV =
1238 CastOp = Instruction::SExt;
1242 PMV.ShiftAmt,
"ValOperand_Shifted");
1244 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1251void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1252 AtomicCmpXchgInst *CI) {
1253 ReplacementIRBuilder Builder(CI, *
DL);
1266 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1272 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
1279Value *AtomicExpandImpl::insertRMWLLSCLoop(
1280 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1282 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp) {
1287 assert(AddrAlign >=
F->getDataLayout().getTypeStoreSize(ResultTy) &&
1288 "Expected at least natural alignment at this point.");
1308 std::prev(BB->
end())->eraseFromParent();
1316 Value *NewVal = PerformOp(Builder, Loaded);
1318 Value *StoreSuccess =
1340AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1343 M->getDataLayout());
1345 ReplacementIRBuilder Builder(CI, *
DL);
1357 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1373bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1379 LLVMContext &Ctx =
F->getContext();
1386 ? AtomicOrdering::Monotonic
1398 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1399 SuccessOrder != AtomicOrdering::Monotonic &&
1400 SuccessOrder != AtomicOrdering::Acquire &&
1405 bool UseUnconditionalReleaseBarrier =
F->hasMinSize() && !CI->
isWeak();
1459 auto ReleasedLoadBB =
1463 auto ReleasingStoreBB =
1467 ReplacementIRBuilder Builder(CI, *
DL);
1472 std::prev(BB->
end())->eraseFromParent();
1474 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1477 PartwordMaskValues PMV =
1484 Value *UnreleasedLoad =
1485 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1486 Value *UnreleasedLoadExtract =
1493 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1494 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1497 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1502 PHINode *LoadedTryStore =
1503 Builder.
CreatePHI(PMV.WordType, 2,
"loaded.trystore");
1504 LoadedTryStore->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1505 Value *NewValueInsert =
1508 PMV.AlignedAddr, MemOpOrder);
1510 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0),
"success");
1511 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1513 CI->
isWeak() ? FailureBB : RetryBB,
1514 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1518 if (HasReleasedLoadBB) {
1520 TLI->
emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1528 ShouldStore, TryStoreBB, NoStoreBB,
1529 MDBuilder(
F->getContext()).createLikelyBranchWeights());
1531 LoadedTryStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1538 if (ShouldInsertFencesForAtomic ||
1544 PHINode *LoadedNoStore =
1546 LoadedNoStore->
addIncoming(UnreleasedLoad, StartBB);
1547 if (HasReleasedLoadBB)
1548 LoadedNoStore->
addIncoming(SecondLoad, ReleasedLoadBB);
1557 PHINode *LoadedFailure =
1559 LoadedFailure->
addIncoming(LoadedNoStore, NoStoreBB);
1561 LoadedFailure->
addIncoming(LoadedTryStore, TryStoreBB);
1562 if (ShouldInsertFencesForAtomic)
1571 PHINode *LoadedExit =
1573 LoadedExit->
addIncoming(LoadedTryStore, SuccessBB);
1574 LoadedExit->
addIncoming(LoadedFailure, FailureBB);
1581 Value *LoadedFull = LoadedExit;
1589 for (
auto *User : CI->
users()) {
1595 "weird extraction from { iN, i1 }");
1606 for (
auto *EV : PrunedInsts)
1623bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1636 return C->isMinusOne();
1638 return C->isMaxValue(
true);
1640 return C->isMinValue(
true);
1642 return C->isMaxValue(
false);
1644 return C->isMinValue(
false);
1650bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1652 tryExpandAtomicLoad(ResultingLoad);
1658Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1659 IRBuilderBase &Builder,
Type *ResultTy,
Value *Addr, Align AddrAlign,
1661 function_ref<
Value *(IRBuilderBase &,
Value *)> PerformOp,
1662 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1689 std::prev(BB->
end())->eraseFromParent();
1700 Loaded->addIncoming(InitLoaded, BB);
1702 Value *NewVal = PerformOp(Builder, Loaded);
1704 Value *NewLoaded =
nullptr;
1707 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1708 MemOpOrder == AtomicOrdering::Unordered
1709 ? AtomicOrdering::Monotonic
1711 SSID,
Success, NewLoaded, MetadataSrc);
1714 Loaded->addIncoming(NewLoaded, LoopBB);
1727bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1734 case TargetLoweringBase::AtomicExpansionKind::None:
1735 if (ValueSize < MinCASSize)
1736 return expandPartwordCmpXchg(CI);
1738 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1739 return expandAtomicCmpXchg(CI);
1741 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1742 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1744 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1746 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1753bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1754 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1761 Value *
Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1764 [&](IRBuilderBase &Builder,
Value *Loaded) {
1765 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1766 AI->getValOperand());
1789 unsigned LargestSize =
DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1790 return Alignment >=
Size &&
1792 Size <= LargestSize;
1795void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *
I) {
1796 static const RTLIB::Libcall Libcalls[6] = {
1797 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1798 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1801 bool expanded = expandAtomicOpToLibcall(
1802 I,
Size,
I->getAlign(),
I->getPointerOperand(),
nullptr,
nullptr,
1803 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1805 handleFailure(*
I,
"unsupported atomic load");
1808void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *
I) {
1809 static const RTLIB::Libcall Libcalls[6] = {
1810 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1811 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1814 bool expanded = expandAtomicOpToLibcall(
1815 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValueOperand(),
1816 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1818 handleFailure(*
I,
"unsupported atomic store");
1821void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *
I) {
1822 static const RTLIB::Libcall Libcalls[6] = {
1823 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1824 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1825 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1828 bool expanded = expandAtomicOpToLibcall(
1829 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getNewValOperand(),
1830 I->getCompareOperand(),
I->getSuccessOrdering(),
I->getFailureOrdering(),
1833 handleFailure(*
I,
"unsupported cmpxchg");
1837 static const RTLIB::Libcall LibcallsXchg[6] = {
1838 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1839 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1840 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1841 static const RTLIB::Libcall LibcallsAdd[6] = {
1842 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1843 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1844 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1845 static const RTLIB::Libcall LibcallsSub[6] = {
1846 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1847 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1848 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1849 static const RTLIB::Libcall LibcallsAnd[6] = {
1850 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1851 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1852 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1853 static const RTLIB::Libcall LibcallsOr[6] = {
1854 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1855 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1856 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1857 static const RTLIB::Libcall LibcallsXor[6] = {
1858 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1859 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1860 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1861 static const RTLIB::Libcall LibcallsNand[6] = {
1862 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1863 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1864 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1905void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *
I) {
1911 if (!Libcalls.
empty())
1912 Success = expandAtomicOpToLibcall(
1913 I,
Size,
I->getAlign(),
I->getPointerOperand(),
I->getValOperand(),
1914 nullptr,
I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1921 expandAtomicRMWToCmpXchg(
1922 I, [
this](IRBuilderBase &Builder,
Value *Addr,
Value *Loaded,
1925 Instruction *MetadataSrc) {
1928 Addr, Loaded, NewVal, Alignment, MemOpOrder,
1937 expandAtomicCASToLibcall(Pair);
1948bool AtomicExpandImpl::expandAtomicOpToLibcall(
1949 Instruction *
I,
unsigned Size, Align Alignment,
Value *PointerOperand,
1954 LLVMContext &Ctx =
I->getContext();
1956 const DataLayout &
DL =
M->getDataLayout();
1958 IRBuilder<> AllocaBuilder(&
I->getFunction()->getEntryBlock().front());
1961 Type *SizedIntTy = Type::getIntNTy(Ctx,
Size * 8);
1963 if (
M->getTargetTriple().isOSWindows() &&
M->getTargetTriple().isX86_64() &&
1973 const Align AllocaAlignment =
DL.getPrefTypeAlign(SizedIntTy);
1977 assert(Ordering != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1979 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering));
1982 assert(Ordering2 != AtomicOrdering::NotAtomic &&
"expect atomic MO");
1984 ConstantInt::get(Type::getInt32Ty(Ctx), (
int)
toCABI(Ordering2));
1986 bool HasResult =
I->getType() != Type::getVoidTy(Ctx);
1988 RTLIB::Libcall RTLibType;
1989 if (UseSizedLibcall) {
1992 RTLibType = Libcalls[1];
1995 RTLibType = Libcalls[2];
1998 RTLibType = Libcalls[3];
2001 RTLibType = Libcalls[4];
2004 RTLibType = Libcalls[5];
2007 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2008 RTLibType = Libcalls[0];
2015 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->
getLibcallImpl(RTLibType);
2016 if (LibcallImpl == RTLIB::Unsupported) {
2047 AllocaInst *AllocaCASExpected =
nullptr;
2048 AllocaInst *AllocaValue =
nullptr;
2049 AllocaInst *AllocaResult =
nullptr;
2056 if (!UseSizedLibcall) {
2058 Args.push_back(ConstantInt::get(
DL.getIntPtrType(Ctx),
Size));
2066 Value *PtrVal = PointerOperand;
2068 Args.push_back(PtrVal);
2072 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
2076 Args.push_back(AllocaCASExpected);
2081 if (UseSizedLibcall) {
2084 Args.push_back(IntValue);
2086 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
2090 Args.push_back(AllocaValue);
2095 if (!CASExpected && HasResult && !UseSizedLibcall) {
2096 AllocaResult = AllocaBuilder.CreateAlloca(
I->getType());
2099 Args.push_back(AllocaResult);
2103 Args.push_back(OrderingVal);
2107 Args.push_back(Ordering2Val);
2111 ResultTy = Type::getInt1Ty(Ctx);
2112 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2113 }
else if (HasResult && UseSizedLibcall)
2114 ResultTy = SizedIntTy;
2116 ResultTy = Type::getVoidTy(Ctx);
2120 for (
Value *Arg : Args)
2122 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys,
false);
2123 FunctionCallee LibcallFn =
M->getOrInsertFunction(
2131 if (ValueOperand && !UseSizedLibcall)
2137 Type *FinalResultTy =
I->getType();
2140 CASExpected->
getType(), AllocaCASExpected, AllocaAlignment);
2145 }
else if (HasResult) {
2147 if (UseSizedLibcall)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static Value * performMaskedAtomicOp(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Shifted_Inc, Value *Inc, const PartwordMaskValues &PMV)
Emit IR to implement a masked version of a given atomicrmw operation.
static PartwordMaskValues createMaskInstrs(IRBuilderBase &Builder, Instruction *I, Type *ValueType, Value *Addr, Align AddrAlign, unsigned MinWordSize)
This is a helper function which builds instructions to provide values necessary for partword atomic o...
static bool canUseSizedAtomicCall(unsigned Size, Align Alignment, const DataLayout &DL)
static Value * extractMaskedValue(IRBuilderBase &Builder, Value *WideWord, const PartwordMaskValues &PMV)
static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr, Value *Loaded, Value *NewVal, Align AddrAlign, AtomicOrdering MemOpOrder, SyncScope::ID SSID, Value *&Success, Value *&NewLoaded, Instruction *MetadataSrc)
Expand Atomic static false unsigned getAtomicOpSize(LoadInst *LI)
static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I)
static Value * insertMaskedValue(IRBuilderBase &Builder, Value *WideWord, Value *Updated, const PartwordMaskValues &PMV)
static void copyMetadataForAtomic(Instruction &Dest, const Instruction &Source)
Copy metadata that's safe to preserve when widening atomics.
static ArrayRef< RTLIB::Libcall > GetRMWLibcall(AtomicRMWInst::BinOp Op)
Atomic ordering constants.
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
static bool isIdempotentRMW(AtomicRMWInst &RMWI)
Return true if and only if the given instruction does not modify the memory location referenced.
Machine Check Debug Module
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file contains the declarations for profiling metadata utility functions.
This file defines the 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()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - 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.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
Value * getPointerOperand()
BinOp getOperation() const
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
static LLVM_ABI StringRef getOperationName(BinOp Op)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
iterator begin()
Instruction iterator methods.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::reverse_iterator reverse_iterator
void setAttributes(AttributeList A)
Set the attributes for this call.
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
BasicBlockListType::iterator iterator
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Common base class shared among various IRBuilders.
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI CallInst * CreateLifetimeStart(Value *Ptr)
Create a lifetime.start intrinsic.
LLVM_ABI CallInst * CreateLifetimeEnd(Value *Ptr)
Create a lifetime.end intrinsic.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
UnreachableInst * CreateUnreachable()
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
BasicBlock * GetInsertBlock() const
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.
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)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void moveAfter(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
LLVM_ABI void getSyncScopeNames(SmallVectorImpl< StringRef > &SSNs) const
getSyncScopeNames - Populates client supplied SmallVector with synchronization scope names registered...
Tracks which library functions to use for a particular subtarget.
LLVM_ABI RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const
Return the lowering's selection of implementation call for Call.
Record a mapping from subtarget to LibcallLoweringInfo.
const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const
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.
Align getAlign() const
Return the alignment of the access that is being performed.
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.
void setVolatile(bool V)
Specify whether this is a volatile store or not.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
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.
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.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI bool canInstructionHaveMMRAs(const Instruction &I)
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
bool isReleaseOrStronger(AtomicOrdering AO)
AtomicOrderingCABI toCABI(AtomicOrdering AO)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
FunctionAddr VTableAddr Next
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
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.
bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI FunctionPass * createAtomicExpandLegacyPass()
AtomicExpandPass - At IR level this pass replace atomic instructions with __atomic_* library calls,...
LLVM_ABI char & AtomicExpandID
AtomicExpandID – Lowers atomic operations in terms of either cmpxchg load-linked/store-conditional lo...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.