55 #define DEBUG_TYPE "atomic-expand" 75 bool tryExpandAtomicLoad(
LoadInst *LI);
76 bool expandAtomicLoadToLL(
LoadInst *LI);
77 bool expandAtomicLoadToCmpXchg(
LoadInst *LI);
85 void expandAtomicOpToLLSC(
88 void expandPartwordAtomicRMW(
97 static Value *insertRMWCmpXchgLoop(
113 void expandAtomicLoadToLibcall(
LoadInst *LI);
114 void expandAtomicStoreToLibcall(
StoreInst *LI);
161 assert(Align != 0 &&
"An atomic LoadInst always has an explicit alignment");
170 assert(Align != 0 &&
"An atomic StoreInst always has an explicit alignment");
191 template <
typename Inst>
199 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
204 if (!
TM.getSubtargetImpl(F)->enableAtomicExpand())
206 TLI =
TM.getSubtargetImpl(F)->getTargetLowering();
218 bool MadeChange =
false;
219 for (
auto I : AtomicInsts) {
224 assert((LI || SI || RMWI || CASI) &&
"Unknown atomic instruction");
229 expandAtomicLoadToLibcall(LI);
235 expandAtomicStoreToLibcall(SI);
241 expandAtomicRMWToLibcall(RMWI);
247 expandAtomicCASToLibcall(CASI);
253 if (TLI->shouldInsertFencesForAtomic(
I)) {
256 FenceOrdering = LI->getOrdering();
259 FenceOrdering = SI->getOrdering();
263 FenceOrdering = RMWI->getOrdering();
266 TLI->shouldExpandAtomicCmpXchgInIR(CASI) ==
274 FenceOrdering = CASI->getSuccessOrdering();
280 MadeChange |= bracketInstWithFences(
I, FenceOrdering);
285 if (LI->getType()->isFloatingPointTy()) {
288 LI = convertAtomicLoadToIntegerType(LI);
289 assert(LI->getType()->isIntegerTy() &&
"invariant broken");
293 MadeChange |= tryExpandAtomicLoad(LI);
295 if (SI->getValueOperand()->getType()->isFloatingPointTy()) {
298 SI = convertAtomicStoreToIntegerType(SI);
299 assert(SI->getValueOperand()->getType()->isIntegerTy() &&
304 if (TLI->shouldExpandAtomicStoreInIR(SI))
305 MadeChange |= expandAtomicStore(SI);
312 if (isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) {
315 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
318 if (ValueSize < MinCASSize &&
321 RMWI = widenPartwordAtomicRMW(RMWI);
325 MadeChange |= tryExpandAtomicRMW(RMWI);
330 assert(!CASI->getCompareOperand()->getType()->isFloatingPointTy() &&
331 "unimplemented - floating point not legal at IR level");
332 if (CASI->getCompareOperand()->getType()->isPointerTy() ) {
335 CASI = convertCmpXchgToIntegerType(CASI);
336 assert(CASI->getCompareOperand()->getType()->isIntegerTy() &&
341 MadeChange |= tryExpandAtomicCmpXchg(CASI);
350 auto LeadingFence = TLI->emitLeadingFence(Builder, I, Order);
352 auto TrailingFence = TLI->emitTrailingFence(Builder, I, Order);
356 TrailingFence->moveAfter(I);
358 return (LeadingFence || TrailingFence);
364 EVT VT = TLI->getValueType(DL, T);
375 Type *NewTy = getCorrespondingIntegerType(LI->
getType(),
383 Value *NewAddr = Builder.CreateBitCast(Addr, PT);
385 auto *NewLI = Builder.CreateLoad(NewAddr);
389 LLVM_DEBUG(
dbgs() <<
"Replaced " << *LI <<
" with " << *NewLI <<
"\n");
391 Value *NewVal = Builder.CreateBitCast(NewLI, LI->
getType());
397 bool AtomicExpand::tryExpandAtomicLoad(
LoadInst *LI) {
398 switch (TLI->shouldExpandAtomicLoadInIR(LI)) {
402 expandAtomicOpToLLSC(
407 return expandAtomicLoadToLL(LI);
409 return expandAtomicLoadToCmpXchg(LI);
415 bool AtomicExpand::expandAtomicLoadToLL(
LoadInst *LI) {
423 TLI->emitAtomicCmpXchgNoStoreLLBalance(Builder);
431 bool AtomicExpand::expandAtomicLoadToCmpXchg(
LoadInst *LI) {
435 Type *Ty = cast<PointerType>(Addr->
getType())->getElementType();
439 Addr, DummyVal, DummyVal, Order,
473 LLVM_DEBUG(
dbgs() <<
"Replaced " << *SI <<
" with " << *NewSI <<
"\n");
478 bool AtomicExpand::expandAtomicStore(
StoreInst *SI) {
492 return tryExpandAtomicRMW(AI);
500 Addr, Loaded, NewVal, MemOpOrder,
515 return Builder.
CreateAdd(Loaded, Inc,
"new");
517 return Builder.
CreateSub(Loaded, Inc,
"new");
519 return Builder.
CreateAnd(Loaded, Inc,
"new");
523 return Builder.
CreateOr(Loaded, Inc,
"new");
525 return Builder.
CreateXor(Loaded, Inc,
"new");
528 return Builder.
CreateSelect(NewVal, Loaded, Inc,
"new");
531 return Builder.
CreateSelect(NewVal, Loaded, Inc,
"new");
534 return Builder.
CreateSelect(NewVal, Loaded, Inc,
"new");
537 return Builder.
CreateSelect(NewVal, Loaded, Inc,
"new");
544 switch (TLI->shouldExpandAtomicRMWInIR(AI)) {
548 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
550 if (ValueSize < MinCASSize) {
552 "MinCmpXchgSizeInBits not yet supported for LL/SC architectures.");
564 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
566 if (ValueSize < MinCASSize) {
567 expandPartwordAtomicRMW(AI,
575 expandAtomicRMWToMaskedIntrinsic(AI);
586 struct PartwordMaskValues {
616 PartwordMaskValues
Ret;
627 assert(ValueSize < WordSize);
637 Builder.
CreateAnd(AddrInt, ~(uint64_t)(WordSize - 1)), WordPtrType,
640 Value *PtrLSB = Builder.
CreateAnd(AddrInt, WordSize - 1,
"PtrLSB");
643 Ret.ShiftAmt = Builder.
CreateShl(PtrLSB, 3);
650 Ret.ShiftAmt = Builder.
CreateTrunc(Ret.ShiftAmt, Ret.WordType,
"ShiftAmt");
654 Ret.Inv_Mask = Builder.
CreateNot(Ret.Mask,
"Inv_Mask");
665 const PartwordMaskValues &PMV) {
672 Value *FinalVal = Builder.
CreateOr(Loaded_MaskOut, Shifted_Inc);
686 Value *FinalVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Masked);
697 Builder.
CreateLShr(Loaded, PMV.ShiftAmt), PMV.ValueType);
700 Builder.
CreateZExt(NewVal, PMV.WordType), PMV.ShiftAmt);
702 Value *FinalVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shiftup);
717 void AtomicExpand::expandPartwordAtomicRMW(
725 PartwordMaskValues PMV =
727 TLI->getMinCmpXchgSizeInBits() / 8);
729 Value *ValOperand_Shifted =
731 PMV.ShiftAmt,
"ValOperand_Shifted");
741 insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder,
744 Builder.
CreateLShr(OldResult, PMV.ShiftAmt), PMV.ValueType);
756 "Unable to widen operation");
758 PartwordMaskValues PMV =
760 TLI->getMinCmpXchgSizeInBits() / 8);
762 Value *ValOperand_Shifted =
764 PMV.ShiftAmt,
"ValOperand_Shifted");
770 Builder.
CreateOr(PMV.Inv_Mask, ValOperand_Shifted,
"AndOperand");
772 NewOperand = ValOperand_Shifted;
778 Builder.
CreateLShr(NewAI, PMV.ShiftAmt), PMV.ValueType);
829 const int WordSize = TLI->getMinCmpXchgSizeInBits() / 8;
839 std::prev(BB->
end())->eraseFromParent();
846 Value *NewVal_Shifted =
855 Value *InitLoaded_MaskOut = Builder.
CreateAnd(InitLoaded, PMV.Inv_Mask);
861 Loaded_MaskOut->
addIncoming(InitLoaded_MaskOut, BB);
864 Value *FullWord_NewVal = Builder.
CreateOr(Loaded_MaskOut, NewVal_Shifted);
865 Value *FullWord_Cmp = Builder.
CreateOr(Loaded_MaskOut, Cmp_Shifted);
895 Loaded_MaskOut->
addIncoming(OldVal_MaskOut, FailureBB);
901 Builder.
CreateLShr(OldVal, PMV.ShiftAmt), PMV.ValueType);
910 void AtomicExpand::expandAtomicOpToLLSC(
915 insertRMWLLSCLoop(Builder, ResultType, Addr, MemOpOrder, PerformOp);
921 void AtomicExpand::expandAtomicRMWToMaskedIntrinsic(
AtomicRMWInst *AI) {
924 PartwordMaskValues PMV =
926 TLI->getMinCmpXchgSizeInBits() / 8);
934 CastOp = Instruction::SExt;
938 PMV.ShiftAmt,
"ValOperand_Shifted");
939 Value *OldResult = TLI->emitMaskedAtomicRMWIntrinsic(
940 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
943 Builder.
CreateLShr(OldResult, PMV.ShiftAmt), PMV.ValueType);
953 TLI->getMinCmpXchgSizeInBits() / 8);
961 Value *OldVal = TLI->emitMaskedAtomicCmpXchgIntrinsic(
962 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
965 Builder.
CreateLShr(OldVal, PMV.ShiftAmt), PMV.ValueType);
970 CmpVal_Shifted, Builder.
CreateAnd(OldVal, PMV.Mask),
"Success");
977 Value *AtomicExpand::insertRMWLLSCLoop(
1003 std::prev(BB->
end())->eraseFromParent();
1009 Value *Loaded = TLI->emitLoadLinked(Builder, Addr, MemOpOrder);
1011 Value *NewVal = PerformOp(Builder, Loaded);
1013 Value *StoreSuccess =
1014 TLI->emitStoreConditional(Builder, NewVal, Addr, MemOpOrder);
1031 M->getDataLayout());
1038 Value *NewAddr = Builder.CreateBitCast(Addr, PT);
1044 auto *NewCI = Builder.CreateAtomicCmpXchg(NewAddr, NewCmp, NewNewVal,
1049 NewCI->setWeak(CI->
isWeak());
1050 LLVM_DEBUG(
dbgs() <<
"Replaced " << *CI <<
" with " << *NewCI <<
"\n");
1052 Value *OldVal = Builder.CreateExtractValue(NewCI, 0);
1053 Value *Succ = Builder.CreateExtractValue(NewCI, 1);
1058 Res = Builder.CreateInsertValue(Res, OldVal, 0);
1059 Res = Builder.CreateInsertValue(Res, Succ, 1);
1077 bool ShouldInsertFencesForAtomic = TLI->shouldInsertFencesForAtomic(CI);
1090 bool HasReleasedLoadBB = !CI->
isWeak() && ShouldInsertFencesForAtomic &&
1146 auto ReleasedLoadBB =
1150 auto ReleasingStoreBB =
1160 std::prev(BB->
end())->eraseFromParent();
1162 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1163 TLI->emitLeadingFence(Builder, CI, SuccessOrder);
1168 Value *UnreleasedLoad = TLI->emitLoadLinked(Builder, Addr, MemOpOrder);
1174 Builder.
CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB);
1177 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1178 TLI->emitLeadingFence(Builder, CI, SuccessOrder);
1182 Value *StoreSuccess = TLI->emitStoreConditional(
1186 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1188 CI->
isWeak() ? FailureBB : RetryBB);
1192 if (HasReleasedLoadBB) {
1193 SecondLoad = TLI->emitLoadLinked(Builder, Addr, MemOpOrder);
1199 Builder.
CreateCondBr(ShouldStore, TryStoreBB, NoStoreBB);
1206 if (ShouldInsertFencesForAtomic)
1207 TLI->emitTrailingFence(Builder, CI, SuccessOrder);
1214 TLI->emitAtomicCmpXchgNoStoreLLBalance(Builder);
1218 if (ShouldInsertFencesForAtomic)
1219 TLI->emitTrailingFence(Builder, CI, FailureOrder);
1233 if (!HasReleasedLoadBB)
1234 Loaded = UnreleasedLoad;
1238 TryStoreLoaded->
addIncoming(UnreleasedLoad, ReleasingStoreBB);
1239 TryStoreLoaded->
addIncoming(SecondLoad, ReleasedLoadBB);
1243 NoStoreLoaded->
addIncoming(UnreleasedLoad, StartBB);
1244 NoStoreLoaded->
addIncoming(SecondLoad, ReleasedLoadBB);
1248 ExitLoaded->
addIncoming(TryStoreLoaded, SuccessBB);
1249 ExitLoaded->
addIncoming(NoStoreLoaded, FailureBB);
1251 Loaded = ExitLoaded;
1263 "weird extraction from { iN, i1 }");
1274 for (
auto EV : PrunedInsts)
1275 EV->eraseFromParent();
1304 return C->isMinusOne();
1311 bool AtomicExpand::simplifyIdempotentRMW(
AtomicRMWInst* RMWI) {
1312 if (
auto ResultingLoad = TLI->lowerIdempotentRMWIntoFencedLoad(RMWI)) {
1313 tryExpandAtomicLoad(ResultingLoad);
1319 Value *AtomicExpand::insertRMWCmpXchgLoop(
1350 std::prev(BB->
end())->eraseFromParent();
1362 Value *NewVal = PerformOp(Builder, Loaded);
1364 Value *NewLoaded =
nullptr;
1367 CreateCmpXchg(Builder, Addr, Loaded, NewVal,
1371 Success, NewLoaded);
1372 assert(Success && NewLoaded);
1383 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
1386 switch (TLI->shouldExpandAtomicCmpXchgInIR(CI)) {
1390 if (ValueSize < MinCASSize)
1391 expandPartwordCmpXchg(CI);
1394 assert(ValueSize >= MinCASSize &&
1395 "MinCmpXchgSizeInBits not yet supported for LL/SC expansions.");
1396 return expandAtomicCmpXchg(CI);
1399 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1408 Value *Loaded = AtomicExpand::insertRMWCmpXchgLoop(
1436 return Align >= Size &&
1437 (Size == 1 || Size == 2 || Size == 4 || Size == 8 || Size == 16) &&
1438 Size <= LargestSize;
1441 void AtomicExpand::expandAtomicLoadToLibcall(
LoadInst *I) {
1444 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1448 bool expanded = expandAtomicOpToLibcall(
1452 assert(expanded &&
"expandAtomicOpToLibcall shouldn't fail tor Load");
1455 void AtomicExpand::expandAtomicStoreToLibcall(
StoreInst *I) {
1458 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1462 bool expanded = expandAtomicOpToLibcall(
1466 assert(expanded &&
"expandAtomicOpToLibcall shouldn't fail tor Store");
1471 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1472 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1473 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1477 bool expanded = expandAtomicOpToLibcall(
1482 assert(expanded &&
"expandAtomicOpToLibcall shouldn't fail tor CAS");
1487 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1488 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1489 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1491 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1492 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1493 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1495 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1496 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1497 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1499 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1500 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1501 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1503 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1504 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1505 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1507 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1508 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1509 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1511 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1512 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1513 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1542 void AtomicExpand::expandAtomicRMWToLibcall(
AtomicRMWInst *I) {
1549 if (!Libcalls.
empty())
1550 Success = expandAtomicOpToLibcall(
1565 Addr, Loaded, NewVal, MemOpOrder,
1571 expandAtomicCASToLibcall(Pair);
1582 bool AtomicExpand::expandAtomicOpToLibcall(
1614 if (UseSizedLibcall) {
1616 case 1: RTLibType = Libcalls[1];
break;
1617 case 2: RTLibType = Libcalls[2];
break;
1618 case 4: RTLibType = Libcalls[3];
break;
1619 case 8: RTLibType = Libcalls[4];
break;
1620 case 16: RTLibType = Libcalls[5];
break;
1622 }
else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
1623 RTLibType = Libcalls[0];
1657 Value *AllocaCASExpected_i8 =
nullptr;
1659 Value *AllocaValue_i8 =
nullptr;
1661 Value *AllocaResult_i8 =
nullptr;
1668 if (!UseSizedLibcall) {
1680 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->
getType());
1682 AllocaCASExpected_i8 =
1691 if (UseSizedLibcall) {
1696 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->
getType());
1707 if (!CASExpected && HasResult && !UseSizedLibcall) {
1708 AllocaResult = AllocaBuilder.CreateAlloca(I->
getType());
1727 }
else if (HasResult && UseSizedLibcall)
1728 ResultTy = SizedIntTy;
1741 Value *Result = Call;
1744 if (ValueOperand && !UseSizedLibcall)
1752 Value *ExpectedOut =
1758 }
else if (HasResult) {
1760 if (UseSizedLibcall)
Value * getValueOperand()
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A parsed version of the target data layout string in and methods for querying it. ...
static ConstantInt * getFalse(LLVMContext &Context)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
static IntegerType * getInt1Ty(LLVMContext &C)
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
*p = old <signed v ? old : v
LLVMContext & getContext() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Atomic ordering constants.
This class represents lattice values for constants.
bool isAtomic() const
Return true if this instruction has an AtomicOrdering of unordered or higher.
static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I)
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
A Module instance is used to store all the information related to an LLVM module. ...
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, unsigned Align, const char *Name)
Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' correctly, instead of converting the strin...
void setAlignment(unsigned Align)
an instruction that atomically checks whether a specified value is in a memory location, and, if it is, stores a new value there.
void push_back(const T &Elt)
This class represents a function call, abstracting a target machine's calling convention.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit...
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space...
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this store instruction.
static PartwordMaskValues createMaskInstrs(IRBuilder<> &Builder, Instruction *I, Type *ValueType, Value *Addr, unsigned WordSize)
This is a helper function which builds instructions to provide values necessary for partword atomic o...
*p = old <unsigned v ? old : v
An efficient, type-erasing, non-owning reference to a callable.
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
*p = old >unsigned v ? old : v
LLVMContext & getContext() const
All values hold a context through their type.
Value * getNewValOperand()
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
char & AtomicExpandID
AtomicExpandID – Lowers atomic operations in terms of either cmpxchg load-linked/store-conditional l...
An instruction for reading from memory.
static IntegerType * getInt64Ty(LLVMContext &C)
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
Value * CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name="")
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
*p = old >signed v ? old : v
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, bool isVolatile=false)
iterator begin()
Instruction iterator methods.
Value * CreateNot(Value *V, const Twine &Name="")
bool isVolatile() const
Return true if this is a load from a volatile memory location.
inst_iterator inst_begin(Function *F)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
BinOp getOperation() const
bool isWeak() const
Return true if this cmpxchg may spuriously fail.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This file contains the simple types necessary to represent the attributes associated with functions a...
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
bool isVolatile() const
Return true if this is a cmpxchg from a volatile memory location.
Value * CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name="")
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
AtomicOrdering
Atomic ordering for LLVM's memory model.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg)
Expand an atomic RMW instruction into a loop utilizing cmpxchg.
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * getPointerOperand()
Class to represent function types.
unsigned getSizeInBits() const
Return the size of the specified value type in bits.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Type * getType() const
All values are typed, get the type of this value.
static bool canUseSizedAtomicCall(unsigned Size, unsigned Align, const DataLayout &DL)
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
BinOp
This enumeration lists the possible modifications atomicrmw can make.
AtomicOrdering getSuccessOrdering() const
Returns the success ordering constraint of this cmpxchg instruction.
static void createCmpXchgInstFun(IRBuilder<> &Builder, Value *Addr, Value *Loaded, Value *NewVal, AtomicOrdering MemOpOrder, Value *&Success, Value *&NewLoaded)
BasicBlock * GetInsertBlock() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
bool isLittleEndian() const
Layout endianness...
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
const BasicBlock & getEntryBlock() const
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
static bool runOnFunction(Function &F, bool PostInlining)
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
UnreachableInst * CreateUnreachable()
size_t size() const
size - Get the array size.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Value * getCompareOperand()
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
const Instruction & front() const
bool isAcquireOrStronger(AtomicOrdering ao)
unsigned getPrefTypeAlignment(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
static Type * getVoidTy(LLVMContext &C)
unsigned getLargestLegalIntTypeSizeInBits() const
Returns the size of largest legal integer type size, or 0 if none are set.
static unsigned getAtomicOpSize(LoadInst *LI)
void initializeAtomicExpandPass(PassRegistry &)
FunctionPass class - This class is used to implement most global optimizations.
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Value * getPointerOperand()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
self_iterator getIterator()
Class to represent integer types.
const Function * getFunction() const
Return the function this instruction belongs to.
void setAlignment(unsigned Align)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
INITIALIZE_PASS(AtomicExpand, DEBUG_TYPE, "Expand Atomic instructions", false, false) FunctionPass *llvm
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this cmpxchg instruction.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
unsigned getMaxAtomicSizeInBitsSupported() const
Returns the maximum atomic operation size (in bits) supported by the backend.
static Value * performAtomicOp(AtomicRMWInst::BinOp Op, IRBuilder<> &Builder, Value *Loaded, Value *Inc)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value...
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success...
bool isReleaseOrStronger(AtomicOrdering ao)
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
CallInst * CreateLifetimeEnd(Value *Ptr, ConstantInt *Size=nullptr)
Create a lifetime.end intrinsic.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
unsigned getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
This is the shared class of boolean and integer constants.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * getTrue(LLVMContext &Context)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void setVolatile(bool V)
Specify whether this is a volatile store or not.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
void setWeak(bool IsWeak)
iterator_range< user_iterator > users()
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
amdgpu Simplify well known AMD library false Value Value * Arg
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
LLVM_NODISCARD AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
bool isVolatile() const
Return true if this is a store to a volatile memory location.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
static IntegerType * getInt32Ty(LLVMContext &C)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this store instruction.
Value * getPointerOperand()
const Function * getParent() const
Return the enclosing method, or null if none.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this load instruction.
bool optForMinSize() const
Optimize this function for minimum size (-Oz).
static unsigned getAtomicOpAlign(LoadInst *LI)
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
AtomicOrderingCABI toCABI(AtomicOrdering ao)
unsigned getAlignment() const
Return the alignment of the access that is being performed.
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM Value Representation.
void setAlignment(unsigned Align)
uint64_t getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
static ArrayRef< RTLIB::Libcall > GetRMWLibcall(AtomicRMWInst::BinOp Op)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
BasicBlock::iterator GetInsertPoint() const
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Primary interface to the complete machine description for the target machine.
static Value * performMaskedAtomicOp(AtomicRMWInst::BinOp Op, IRBuilder<> &Builder, Value *Loaded, Value *Shifted_Inc, Value *Inc, const PartwordMaskValues &PMV)
Emit IR to implement a masked version of a given atomicrmw operation.
CallInst * CreateLifetimeStart(Value *Ptr, ConstantInt *Size=nullptr)
Create a lifetime.start intrinsic.
inst_iterator inst_end(Function *F)
OUTCHAIN = ATOMIC_STORE(INCHAIN, ptr, val) This corresponds to "store atomic" instruction.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
FunctionPass * createAtomicExpandPass()
void setVolatile(bool V)
Specify whether this is a volatile load or not.
Value * CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name="")
Value * getPointerOperand()
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
bool empty() const
empty - Check if the array is empty.
This file describes how to lower LLVM code to machine code.
const BasicBlock * getParent() const
an instruction to allocate memory on the stack
A discriminated union of two pointer types, with the discriminator in the low bit of the pointer...