LLVM 24.0.0git
AtomicExpandPass.cpp
Go to the documentation of this file.
1//===- AtomicExpandPass.cpp - Expand atomic instructions ------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a pass (at IR level) to replace atomic instructions with
10// __atomic_* library calls, or target specific instruction which implement the
11// same semantics in a way which better fits the target backend. This can
12// include the use of (intrinsic-based) load-linked/store-conditional loops,
13// AtomicCmpXchg, or type coercions.
14//
15//===----------------------------------------------------------------------===//
16
17#include "llvm/ADT/ArrayRef.h"
28#include "llvm/IR/Attributes.h"
29#include "llvm/IR/BasicBlock.h"
30#include "llvm/IR/Constant.h"
31#include "llvm/IR/Constants.h"
32#include "llvm/IR/DataLayout.h"
34#include "llvm/IR/Function.h"
35#include "llvm/IR/IRBuilder.h"
36#include "llvm/IR/Instruction.h"
38#include "llvm/IR/MDBuilder.h"
40#include "llvm/IR/Module.h"
42#include "llvm/IR/Type.h"
43#include "llvm/IR/User.h"
44#include "llvm/IR/Value.h"
46#include "llvm/Pass.h"
49#include "llvm/Support/Debug.h"
54#include <cassert>
55#include <cstdint>
56#include <iterator>
57
58using namespace llvm;
59
60#define DEBUG_TYPE "atomic-expand"
61
62namespace {
63
64class AtomicExpandImpl {
65 const TargetLowering *TLI = nullptr;
66 const LibcallLoweringInfo *LibcallLowering = nullptr;
67 const DataLayout *DL = nullptr;
68
69private:
70 /// Callback type for emitting a cmpxchg instruction during RMW expansion.
71 /// Parameters: (Builder, Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
72 /// SSID, IsVolatile, /* OUT */ Success, /* OUT */ NewLoaded,
73 /// MetadataSrc)
74 using CreateCmpXchgInstFun = function_ref<void(
76 SyncScope::ID, bool, Value *&, Value *&, Instruction *)>;
77
78 void handleFailure(Instruction &FailedInst, const Twine &Msg,
79 Instruction *DiagnosticInst = nullptr) const {
80 LLVMContext &Ctx = FailedInst.getContext();
81
82 // TODO: Do not use generic error type.
83 Ctx.emitError(DiagnosticInst ? DiagnosticInst : &FailedInst, Msg);
84
85 if (!FailedInst.getType()->isVoidTy())
86 FailedInst.replaceAllUsesWith(PoisonValue::get(FailedInst.getType()));
87 FailedInst.eraseFromParent();
88 }
89
90 template <typename Inst>
91 void handleUnsupportedAtomicSize(Inst *I, const Twine &AtomicOpName,
92 Instruction *DiagnosticInst = nullptr) const;
93
94 bool bracketInstWithFences(Instruction *I, AtomicOrdering Order);
95 bool tryInsertTrailingSeqCstFence(Instruction *AtomicI);
96 template <typename AtomicInst>
97 bool tryInsertFencesForAtomic(AtomicInst *AtomicI, bool OrderingRequiresFence,
98 AtomicOrdering NewOrdering);
99 IntegerType *getCorrespondingIntegerType(Type *T, const DataLayout &DL);
100 LoadInst *convertAtomicLoadToIntegerType(LoadInst *LI);
101 bool tryExpandAtomicLoad(LoadInst *LI);
102 bool expandAtomicLoadToLL(LoadInst *LI);
103 bool expandAtomicLoadToCmpXchg(LoadInst *LI);
104 StoreInst *convertAtomicStoreToIntegerType(StoreInst *SI);
105 bool tryExpandAtomicStore(StoreInst *SI);
106 void expandAtomicStoreToXChg(StoreInst *SI);
107 bool tryExpandAtomicRMW(AtomicRMWInst *AI);
108 AtomicRMWInst *convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI);
109 Value *
110 insertRMWLLSCLoop(IRBuilderBase &Builder, Type *ResultTy, Value *Addr,
111 Align AddrAlign, AtomicOrdering MemOpOrder,
112 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp);
113 void expandAtomicOpToLLSC(
114 Instruction *I, Type *ResultTy, Value *Addr, Align AddrAlign,
115 AtomicOrdering MemOpOrder,
116 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp);
117 void expandPartwordAtomicRMW(
119 AtomicRMWInst *widenPartwordAtomicRMW(AtomicRMWInst *AI);
120 bool expandPartwordCmpXchg(AtomicCmpXchgInst *I);
121 void expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI);
122 void expandAtomicCmpXchgToMaskedIntrinsic(AtomicCmpXchgInst *CI);
123
124 AtomicCmpXchgInst *convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI);
125 Value *insertRMWCmpXchgLoop(
126 IRBuilderBase &Builder, Type *ResultType, Value *Addr, Align AddrAlign,
127 AtomicOrdering MemOpOrder, SyncScope::ID SSID, bool IsVolatile,
128 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp,
129 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc);
130 bool tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI);
131
132 bool expandAtomicCmpXchg(AtomicCmpXchgInst *CI);
133 bool isIdempotentRMW(AtomicRMWInst *RMWI);
134 bool simplifyIdempotentRMW(AtomicRMWInst *RMWI);
135
136 bool expandAtomicOpToLibcall(Instruction *I, unsigned Size, Align Alignment,
137 Value *PointerOperand, Value *ValueOperand,
138 Value *CASExpected, AtomicOrdering Ordering,
139 AtomicOrdering Ordering2,
140 ArrayRef<RTLIB::Libcall> Libcalls);
141 void expandAtomicLoadToLibcall(LoadInst *LI);
142 void expandAtomicStoreToLibcall(StoreInst *LI);
143 void expandAtomicRMWToLibcall(AtomicRMWInst *I);
144 void expandAtomicCASToLibcall(AtomicCmpXchgInst *I,
145 const Twine &AtomicOpName = "cmpxchg",
146 Instruction *DiagnosticInst = nullptr);
147
148 bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI,
149 CreateCmpXchgInstFun CreateCmpXchg);
150
151 bool processAtomicInstr(Instruction *I);
152
153public:
154 bool run(Function &F, const ModuleLibcallLoweringInfo &LibcallResult,
155 const TargetMachine *TM);
156};
157
158class AtomicExpandLegacy : public FunctionPass {
159public:
160 static char ID; // Pass identification, replacement for typeid
161
162 AtomicExpandLegacy() : FunctionPass(ID) {}
163
164 void getAnalysisUsage(AnalysisUsage &AU) const override {
167 }
168
169 bool runOnFunction(Function &F) override;
170};
171
172// IRBuilder to be used for replacement atomic instructions.
173struct ReplacementIRBuilder
174 : IRBuilder<InstSimplifyFolder, IRBuilderCallbackInserter> {
175 MDNode *MMRAMD = nullptr;
176 MDNode *PCSectionsMD = nullptr;
177
178 // Preserves the DebugLoc from I, and preserves still valid metadata.
179 // Enable StrictFP builder mode when appropriate.
180 explicit ReplacementIRBuilder(Instruction *I, const DataLayout &DL)
181 : IRBuilder(
182 I->getContext(), InstSimplifyFolder(DL),
183 IRBuilderCallbackInserter([this](Instruction *I) { addMD(I); })) {
184 SetInsertPoint(I);
185 if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP))
186 this->setIsFPConstrained(true);
187
188 MMRAMD = I->getMetadata(LLVMContext::MD_mmra);
189 PCSectionsMD = I->getMetadata(LLVMContext::MD_pcsections);
190 }
191
192 void addMD(Instruction *I) {
194 I->setMetadata(LLVMContext::MD_mmra, MMRAMD);
195 I->setMetadata(LLVMContext::MD_pcsections, PCSectionsMD);
196 }
197};
198
199} // end anonymous namespace
200
201char AtomicExpandLegacy::ID = 0;
202
203char &llvm::AtomicExpandID = AtomicExpandLegacy::ID;
204
206 "Expand Atomic instructions", false, false)
209INITIALIZE_PASS_END(AtomicExpandLegacy, DEBUG_TYPE,
210 "Expand Atomic instructions", false, false)
211
212// Helper functions to retrieve the size of atomic instructions.
213static unsigned getAtomicOpSize(LoadInst *LI) {
214 const DataLayout &DL = LI->getDataLayout();
215 return DL.getTypeStoreSize(LI->getType());
216}
217
218static unsigned getAtomicOpSize(StoreInst *SI) {
219 const DataLayout &DL = SI->getDataLayout();
220 return DL.getTypeStoreSize(SI->getValueOperand()->getType());
221}
222
223static unsigned getAtomicOpSize(AtomicRMWInst *RMWI) {
224 const DataLayout &DL = RMWI->getDataLayout();
225 return DL.getTypeStoreSize(RMWI->getValOperand()->getType());
226}
227
228static unsigned getAtomicOpSize(AtomicCmpXchgInst *CASI) {
229 const DataLayout &DL = CASI->getDataLayout();
230 return DL.getTypeStoreSize(CASI->getCompareOperand()->getType());
231}
232
233/// Copy metadata that's safe to preserve when widening atomics.
235 const Instruction &Source) {
237 Source.getAllMetadata(MD);
238 LLVMContext &Ctx = Dest.getContext();
239 MDBuilder MDB(Ctx);
240
241 for (auto [ID, N] : MD) {
242 switch (ID) {
243 case LLVMContext::MD_dbg:
244 case LLVMContext::MD_tbaa:
245 case LLVMContext::MD_tbaa_struct:
246 case LLVMContext::MD_alias_scope:
247 case LLVMContext::MD_noalias:
248 case LLVMContext::MD_noalias_addrspace:
249 case LLVMContext::MD_access_group:
250 case LLVMContext::MD_mmra:
251 Dest.setMetadata(ID, N);
252 break;
253 default:
254 if (ID == Ctx.getMDKindID("amdgpu.no.remote.memory"))
255 Dest.setMetadata(ID, N);
256 else if (ID == Ctx.getMDKindID("amdgpu.no.fine.grained.memory"))
257 Dest.setMetadata(ID, N);
258
259 // Losing amdgpu.ignore.denormal.mode, but it doesn't matter for current
260 // uses.
261 break;
262 }
263 }
264}
265
266template <typename Inst>
267static bool atomicSizeSupported(const TargetLowering *TLI, Inst *I) {
268 unsigned Size = getAtomicOpSize(I);
269 Align Alignment = I->getAlign();
270 unsigned MaxSize = TLI->getMaxAtomicSizeInBitsSupported() / 8;
271 return Alignment >= Size && Size <= MaxSize;
272}
273
274template <typename Inst>
276 raw_ostream &OS) {
277 unsigned Size = getAtomicOpSize(I);
278 Align Alignment = I->getAlign();
279 bool NeedSeparator = false;
280
281 if (Alignment < Size) {
282 OS << "instruction alignment " << Alignment.value()
283 << " is smaller than the required " << Size
284 << "-byte alignment for this atomic operation";
285 NeedSeparator = true;
286 }
287
288 unsigned MaxSize = TLI->getMaxAtomicSizeInBitsSupported() / 8;
289 if (Size > MaxSize) {
290 if (NeedSeparator)
291 OS << "; ";
292 OS << "target supports atomics up to " << MaxSize
293 << " bytes, but this atomic accesses " << Size << " bytes";
294 }
295}
296
297template <typename Inst>
298void AtomicExpandImpl::handleUnsupportedAtomicSize(
299 Inst *I, const Twine &AtomicOpName, Instruction *DiagnosticInst) const {
300 assert(!atomicSizeSupported(TLI, I) && "expected unsupported atomic size");
301 SmallString<128> FailureReason;
302 raw_svector_ostream OS(FailureReason);
304 handleFailure(*I, Twine("unsupported ") + AtomicOpName + ": " + FailureReason,
305 DiagnosticInst);
306}
307
308bool AtomicExpandImpl::tryInsertTrailingSeqCstFence(Instruction *AtomicI) {
310 return false;
311
312 IRBuilder Builder(AtomicI);
313 if (auto *TrailingFence = TLI->emitTrailingFence(
314 Builder, AtomicI, AtomicOrdering::SequentiallyConsistent)) {
315 TrailingFence->moveAfter(AtomicI);
316 return true;
317 }
318 return false;
319}
320
321template <typename AtomicInst>
322bool AtomicExpandImpl::tryInsertFencesForAtomic(AtomicInst *AtomicI,
323 bool OrderingRequiresFence,
324 AtomicOrdering NewOrdering) {
325 bool ShouldInsertFences = TLI->shouldInsertFencesForAtomic(AtomicI);
326 if (OrderingRequiresFence && ShouldInsertFences) {
327 AtomicOrdering FenceOrdering = AtomicI->getOrdering();
328 AtomicI->setOrdering(NewOrdering);
329 return bracketInstWithFences(AtomicI, FenceOrdering);
330 }
331 if (!ShouldInsertFences)
332 return tryInsertTrailingSeqCstFence(AtomicI);
333 return false;
334}
335
336bool AtomicExpandImpl::processAtomicInstr(Instruction *I) {
337 if (auto *LI = dyn_cast<LoadInst>(I)) {
338 if (!LI->isAtomic())
339 return false;
340
341 if (!atomicSizeSupported(TLI, LI)) {
342 expandAtomicLoadToLibcall(LI);
343 return true;
344 }
345
346 bool MadeChange = false;
347 if (TLI->shouldCastAtomicLoadInIR(LI) ==
348 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
349 LI = convertAtomicLoadToIntegerType(LI);
350 MadeChange = true;
351 }
352
353 MadeChange |= tryInsertFencesForAtomic(
354 LI, isAcquireOrStronger(LI->getOrdering()), AtomicOrdering::Monotonic);
355
356 MadeChange |= tryExpandAtomicLoad(LI);
357 return MadeChange;
358 }
359
360 if (auto *SI = dyn_cast<StoreInst>(I)) {
361 if (!SI->isAtomic())
362 return false;
363
364 if (!atomicSizeSupported(TLI, SI)) {
365 expandAtomicStoreToLibcall(SI);
366 return true;
367 }
368
369 bool MadeChange = false;
370 if (TLI->shouldCastAtomicStoreInIR(SI) ==
371 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
372 SI = convertAtomicStoreToIntegerType(SI);
373 MadeChange = true;
374 }
375
376 MadeChange |= tryInsertFencesForAtomic(
377 SI, isReleaseOrStronger(SI->getOrdering()), AtomicOrdering::Monotonic);
378
379 MadeChange |= tryExpandAtomicStore(SI);
380 return MadeChange;
381 }
382
383 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
384 if (!atomicSizeSupported(TLI, RMWI)) {
385 expandAtomicRMWToLibcall(RMWI);
386 return true;
387 }
388
389 bool MadeChange = false;
390 if (TLI->shouldCastAtomicRMWIInIR(RMWI) ==
391 TargetLoweringBase::AtomicExpansionKind::CastToInteger) {
392 RMWI = convertAtomicXchgToIntegerType(RMWI);
393 MadeChange = true;
394 }
395
396 MadeChange |= tryInsertFencesForAtomic(
397 RMWI,
398 isReleaseOrStronger(RMWI->getOrdering()) ||
399 isAcquireOrStronger(RMWI->getOrdering()),
401
402 // There are two different ways of expanding RMW instructions:
403 // - into a load if it is idempotent
404 // - into a Cmpxchg/LL-SC loop otherwise
405 // we try them in that order.
406 MadeChange |= (isIdempotentRMW(RMWI) && simplifyIdempotentRMW(RMWI)) ||
407 tryExpandAtomicRMW(RMWI);
408 return MadeChange;
409 }
410
411 if (auto *CASI = dyn_cast<AtomicCmpXchgInst>(I)) {
412 if (!atomicSizeSupported(TLI, CASI)) {
413 expandAtomicCASToLibcall(CASI);
414 return true;
415 }
416
417 // TODO: when we're ready to make the change at the IR level, we can
418 // extend convertCmpXchgToInteger for floating point too.
419 bool MadeChange = false;
420 if (CASI->getCompareOperand()->getType()->isPointerTy()) {
421 // TODO: add a TLI hook to control this so that each target can
422 // convert to lowering the original type one at a time.
423 CASI = convertCmpXchgToIntegerType(CASI);
424 MadeChange = true;
425 }
426
427 auto CmpXchgExpansion = TLI->shouldExpandAtomicCmpXchgInIR(CASI);
428 if (TLI->shouldInsertFencesForAtomic(CASI)) {
429 if (CmpXchgExpansion == TargetLoweringBase::AtomicExpansionKind::None &&
430 (isReleaseOrStronger(CASI->getSuccessOrdering()) ||
431 isAcquireOrStronger(CASI->getSuccessOrdering()) ||
432 isAcquireOrStronger(CASI->getFailureOrdering()))) {
433 // If a compare and swap is lowered to LL/SC, we can do smarter fence
434 // insertion, with a stronger one on the success path than on the
435 // failure path. As a result, fence insertion is directly done by
436 // expandAtomicCmpXchg in that case.
437 AtomicOrdering FenceOrdering = CASI->getMergedOrdering();
438 AtomicOrdering CASOrdering =
440 CASI->setSuccessOrdering(CASOrdering);
441 CASI->setFailureOrdering(CASOrdering);
442 MadeChange |= bracketInstWithFences(CASI, FenceOrdering);
443 }
444 } else if (CmpXchgExpansion !=
445 TargetLoweringBase::AtomicExpansionKind::LLSC) {
446 // CmpXchg LLSC is handled in expandAtomicCmpXchg().
447 MadeChange |= tryInsertTrailingSeqCstFence(CASI);
448 }
449
450 MadeChange |= tryExpandAtomicCmpXchg(CASI);
451 return MadeChange;
452 }
453
454 return false;
455}
456
457bool AtomicExpandImpl::run(Function &F,
458 const ModuleLibcallLoweringInfo &LibcallResult,
459 const TargetMachine *TM) {
460 const auto *Subtarget = TM->getSubtargetImpl(F);
461 if (!Subtarget->enableAtomicExpand())
462 return false;
463 TLI = Subtarget->getTargetLowering();
464 LibcallLowering = &LibcallResult.getLibcallLowering(*Subtarget);
465 DL = &F.getDataLayout();
466
467 bool MadeChange = false;
468
469 for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
470 BasicBlock *BB = &*BBI;
471
473
474 for (BasicBlock::reverse_iterator I = BB->rbegin(), E = BB->rend(); I != E;
475 I = Next) {
476 Instruction &Inst = *I;
477 Next = std::next(I);
478
479 if (processAtomicInstr(&Inst)) {
480 MadeChange = true;
481
482 // New blocks may have been inserted.
483 BBE = F.end();
484 }
485 }
486 }
487
488 return MadeChange;
489}
490
491bool AtomicExpandLegacy::runOnFunction(Function &F) {
492
493 auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
494 if (!TPC)
495 return false;
496 auto *TM = &TPC->getTM<TargetMachine>();
497
498 const ModuleLibcallLoweringInfo &LibcallResult =
499 getAnalysis<LibcallLoweringInfoWrapper>().getResult(*F.getParent());
500 AtomicExpandImpl AE;
501 return AE.run(F, LibcallResult, TM);
502}
503
505 return new AtomicExpandLegacy();
506}
507
510 auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
511
512 const ModuleLibcallLoweringInfo *LibcallResult =
513 MAMProxy.getCachedResult<LibcallLoweringModuleAnalysis>(*F.getParent());
514
515 if (!LibcallResult) {
516 F.getContext().emitError("'" + LibcallLoweringModuleAnalysis::name() +
517 "' analysis required");
518 return PreservedAnalyses::all();
519 }
520
521 AtomicExpandImpl AE;
522
523 bool Changed = AE.run(F, *LibcallResult, TM);
524 if (!Changed)
525 return PreservedAnalyses::all();
526
528}
529
530bool AtomicExpandImpl::bracketInstWithFences(Instruction *I,
531 AtomicOrdering Order) {
532 ReplacementIRBuilder Builder(I, *DL);
533
534 auto LeadingFence = TLI->emitLeadingFence(Builder, I, Order);
535
536 auto TrailingFence = TLI->emitTrailingFence(Builder, I, Order);
537 // We have a guard here because not every atomic operation generates a
538 // trailing fence.
539 if (TrailingFence)
540 TrailingFence->moveAfter(I);
541
542 return (LeadingFence || TrailingFence);
543}
544
545/// Get the iX type with the same bitwidth as T.
547AtomicExpandImpl::getCorrespondingIntegerType(Type *T, const DataLayout &DL) {
548 EVT VT = TLI->getMemValueType(DL, T);
549 unsigned BitWidth = VT.getStoreSizeInBits();
550 assert(BitWidth == VT.getSizeInBits() && "must be a power of two");
551 return IntegerType::get(T->getContext(), BitWidth);
552}
553
554/// Convert an atomic load of a non-integral type to an integer load of the
555/// equivalent bitwidth. See the function comment on
556/// convertAtomicStoreToIntegerType for background.
557LoadInst *AtomicExpandImpl::convertAtomicLoadToIntegerType(LoadInst *LI) {
558 auto *M = LI->getModule();
559 Type *NewTy = getCorrespondingIntegerType(LI->getType(), M->getDataLayout());
560
561 ReplacementIRBuilder Builder(LI, *DL);
562
563 Value *Addr = LI->getPointerOperand();
564
565 auto *NewLI = Builder.CreateLoad(NewTy, Addr, LI->getProperties());
566 LLVM_DEBUG(dbgs() << "Replaced " << *LI << " with " << *NewLI << "\n");
567
568 Value *NewVal = LI->getType()->isPtrOrPtrVectorTy()
569 ? Builder.CreateIntToPtr(NewLI, LI->getType())
570 : Builder.CreateBitCast(NewLI, LI->getType());
571 LI->replaceAllUsesWith(NewVal);
572 LI->eraseFromParent();
573 return NewLI;
574}
575
576AtomicRMWInst *
577AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
579
580 auto *M = RMWI->getModule();
581 Type *NewTy =
582 getCorrespondingIntegerType(RMWI->getType(), M->getDataLayout());
583
584 ReplacementIRBuilder Builder(RMWI, *DL);
585
586 Value *Addr = RMWI->getPointerOperand();
587 Value *Val = RMWI->getValOperand();
588 Value *NewVal = Builder.CreateBitPreservingCastChain(*DL, Val, NewTy);
589
590 auto *NewRMWI = Builder.CreateAtomicRMW(AtomicRMWInst::Xchg, Addr, NewVal,
591 RMWI->getAlign(), RMWI->getOrdering(),
592 RMWI->getSyncScopeID());
593 NewRMWI->setVolatile(RMWI->isVolatile());
594 copyMetadataForAtomic(*NewRMWI, *RMWI);
595 LLVM_DEBUG(dbgs() << "Replaced " << *RMWI << " with " << *NewRMWI << "\n");
596
597 Value *NewRVal =
598 Builder.CreateBitPreservingCastChain(*DL, NewRMWI, RMWI->getType());
599 RMWI->replaceAllUsesWith(NewRVal);
600 RMWI->eraseFromParent();
601 return NewRMWI;
602}
603
604bool AtomicExpandImpl::tryExpandAtomicLoad(LoadInst *LI) {
605 switch (TLI->shouldExpandAtomicLoadInIR(LI)) {
606 case TargetLoweringBase::AtomicExpansionKind::None:
607 return false;
608 case TargetLoweringBase::AtomicExpansionKind::LLSC:
609 expandAtomicOpToLLSC(
610 LI, LI->getType(), LI->getPointerOperand(), LI->getAlign(),
611 LI->getOrdering(),
612 [](IRBuilderBase &Builder, Value *Loaded) { return Loaded; });
613 return true;
614 case TargetLoweringBase::AtomicExpansionKind::LLOnly:
615 return expandAtomicLoadToLL(LI);
616 case TargetLoweringBase::AtomicExpansionKind::CmpXChg:
617 return expandAtomicLoadToCmpXchg(LI);
618 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
619 LI->setAtomic(AtomicOrdering::NotAtomic);
620 return true;
621 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
622 TLI->emitExpandAtomicLoad(LI);
623 return true;
624 default:
625 llvm_unreachable("Unhandled case in tryExpandAtomicLoad");
626 }
627}
628
629bool AtomicExpandImpl::tryExpandAtomicStore(StoreInst *SI) {
630 switch (TLI->shouldExpandAtomicStoreInIR(SI)) {
631 case TargetLoweringBase::AtomicExpansionKind::None:
632 return false;
633 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
634 TLI->emitExpandAtomicStore(SI);
635 return true;
636 case TargetLoweringBase::AtomicExpansionKind::Expand:
637 expandAtomicStoreToXChg(SI);
638 return true;
639 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
640 SI->setAtomic(AtomicOrdering::NotAtomic);
641 return true;
642 default:
643 llvm_unreachable("Unhandled case in tryExpandAtomicStore");
644 }
645}
646
647bool AtomicExpandImpl::expandAtomicLoadToLL(LoadInst *LI) {
648 ReplacementIRBuilder Builder(LI, *DL);
649
650 // On some architectures, load-linked instructions are atomic for larger
651 // sizes than normal loads. For example, the only 64-bit load guaranteed
652 // to be single-copy atomic by ARM is an ldrexd (A3.5.3).
653 Value *Val = TLI->emitLoadLinked(Builder, LI->getType(),
654 LI->getPointerOperand(), LI->getOrdering());
656
657 LI->replaceAllUsesWith(Val);
658 LI->eraseFromParent();
659
660 return true;
661}
662
663bool AtomicExpandImpl::expandAtomicLoadToCmpXchg(LoadInst *LI) {
664 ReplacementIRBuilder Builder(LI, *DL);
665 AtomicOrdering Order = LI->getOrdering();
666 if (Order == AtomicOrdering::Unordered)
667 Order = AtomicOrdering::Monotonic;
668
669 Value *Addr = LI->getPointerOperand();
670 Type *Ty = LI->getType();
671
672 // cmpxchg supports only integer and pointer operands. If the load type is
673 // FP or vector, run the cmpxchg on the same-sized integer and bitcast the
674 // result back; mirrors createCmpXchgInstFun.
675 bool NeedBitcast = Ty->isFloatingPointTy() || Ty->isVectorTy();
676 Type *CmpXchgTy = Ty;
677 if (NeedBitcast)
678 CmpXchgTy = Builder.getIntNTy(Ty->getPrimitiveSizeInBits());
679 Constant *DummyVal = Constant::getNullValue(CmpXchgTy);
680
681 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
682 Addr, DummyVal, DummyVal, LI->getAlign(), Order,
684 LI->getSyncScopeID());
685 Pair->setVolatile(LI->isVolatile());
686 Value *Loaded = Builder.CreateExtractValue(Pair, 0, "loaded");
687 if (NeedBitcast)
688 Loaded = Builder.CreateBitCast(Loaded, Ty);
689
690 LI->replaceAllUsesWith(Loaded);
691 LI->eraseFromParent();
692
693 return true;
694}
695
696/// Convert an atomic store of a non-integral type to an integer store of the
697/// equivalent bitwidth. We used to not support floating point or vector
698/// atomics in the IR at all. The backends learned to deal with the bitcast
699/// idiom because that was the only way of expressing the notion of a atomic
700/// float or vector store. The long term plan is to teach each backend to
701/// instruction select from the original atomic store, but as a migration
702/// mechanism, we convert back to the old format which the backends understand.
703/// Each backend will need individual work to recognize the new format.
704StoreInst *AtomicExpandImpl::convertAtomicStoreToIntegerType(StoreInst *SI) {
705 ReplacementIRBuilder Builder(SI, *DL);
706 auto *M = SI->getModule();
707 Type *NewTy = getCorrespondingIntegerType(SI->getValueOperand()->getType(),
708 M->getDataLayout());
709 Value *NewVal = SI->getValueOperand()->getType()->isPtrOrPtrVectorTy()
710 ? Builder.CreatePtrToInt(SI->getValueOperand(), NewTy)
711 : Builder.CreateBitCast(SI->getValueOperand(), NewTy);
712
713 Value *Addr = SI->getPointerOperand();
714
715 StoreInst *NewSI = Builder.CreateStore(NewVal, Addr, SI->getProperties());
716 LLVM_DEBUG(dbgs() << "Replaced " << *SI << " with " << *NewSI << "\n");
717 SI->eraseFromParent();
718 return NewSI;
719}
720
721void AtomicExpandImpl::expandAtomicStoreToXChg(StoreInst *SI) {
722 // This function is only called on atomic stores that are too large to be
723 // atomic if implemented as a native store. So we replace them by an
724 // atomic swap, that can be implemented for example as a ldrex/strex on ARM
725 // or lock cmpxchg8/16b on X86, as these are atomic for larger sizes.
726 // It is the responsibility of the target to only signal expansion via
727 // shouldExpandAtomicRMW in cases where this is required and possible.
728 ReplacementIRBuilder Builder(SI, *DL);
729 AtomicOrdering Ordering = SI->getOrdering();
730 assert(Ordering != AtomicOrdering::NotAtomic);
731 AtomicOrdering RMWOrdering = Ordering == AtomicOrdering::Unordered
732 ? AtomicOrdering::Monotonic
733 : Ordering;
734 AtomicRMWInst *AI = Builder.CreateAtomicRMW(
735 AtomicRMWInst::Xchg, SI->getPointerOperand(), SI->getValueOperand(),
736 SI->getAlign(), RMWOrdering, SI->getSyncScopeID());
737 AI->setVolatile(SI->isVolatile());
738 SI->eraseFromParent();
739
740 // Now we have an appropriate swap instruction, lower it as usual.
741 tryExpandAtomicRMW(AI);
742}
743
744static void createCmpXchgInstFun(IRBuilderBase &Builder, Value *Addr,
745 Value *Loaded, Value *NewVal, Align AddrAlign,
746 AtomicOrdering MemOpOrder, SyncScope::ID SSID,
747 bool IsVolatile, Value *&Success,
748 Value *&NewLoaded, Instruction *MetadataSrc) {
749 Type *OrigTy = NewVal->getType();
750
751 // This code can go away when cmpxchg supports FP and vector types.
752 assert(!OrigTy->isPointerTy());
753 bool NeedBitcast = OrigTy->isFloatingPointTy() || OrigTy->isVectorTy();
754 if (NeedBitcast) {
755 IntegerType *IntTy = Builder.getIntNTy(OrigTy->getPrimitiveSizeInBits());
756 NewVal = Builder.CreateBitCast(NewVal, IntTy);
757 Loaded = Builder.CreateBitCast(Loaded, IntTy);
758 }
759
760 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
761 Addr, Loaded, NewVal, AddrAlign, MemOpOrder,
763 Pair->setVolatile(IsVolatile);
764 if (MetadataSrc)
765 copyMetadataForAtomic(*Pair, *MetadataSrc);
766
767 Success = Builder.CreateExtractValue(Pair, 1, "success");
768 NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded");
769
770 if (NeedBitcast)
771 NewLoaded = Builder.CreateBitCast(NewLoaded, OrigTy);
772}
773
774bool AtomicExpandImpl::tryExpandAtomicRMW(AtomicRMWInst *AI) {
775 LLVMContext &Ctx = AI->getModule()->getContext();
776 TargetLowering::AtomicExpansionKind Kind = TLI->shouldExpandAtomicRMWInIR(AI);
777 switch (Kind) {
778 case TargetLoweringBase::AtomicExpansionKind::None:
779 return false;
780 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
781 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
782 unsigned ValueSize = getAtomicOpSize(AI);
783 if (ValueSize < MinCASSize) {
784 expandPartwordAtomicRMW(AI,
785 TargetLoweringBase::AtomicExpansionKind::LLSC);
786 } else {
787 auto PerformOp = [&](IRBuilderBase &Builder, Value *Loaded) {
788 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
789 AI->getValOperand());
790 };
791 expandAtomicOpToLLSC(AI, AI->getType(), AI->getPointerOperand(),
792 AI->getAlign(), AI->getOrdering(), PerformOp);
793 }
794 return true;
795 }
796 case TargetLoweringBase::AtomicExpansionKind::CmpXChg: {
797 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
798 unsigned ValueSize = getAtomicOpSize(AI);
799 if (ValueSize < MinCASSize) {
800 expandPartwordAtomicRMW(AI,
801 TargetLoweringBase::AtomicExpansionKind::CmpXChg);
802 } else {
804 Ctx.getSyncScopeNames(SSNs);
805 auto MemScope = SSNs[AI->getSyncScopeID()].empty()
806 ? "system"
807 : SSNs[AI->getSyncScopeID()];
808 OptimizationRemarkEmitter ORE(AI->getFunction());
809 ORE.emit([&]() {
810 return OptimizationRemark(DEBUG_TYPE, "Passed", AI)
811 << "A compare and swap loop was generated for an atomic "
812 << AI->getOperationName(AI->getOperation()) << " operation at "
813 << MemScope << " memory scope";
814 });
815 expandAtomicRMWToCmpXchg(AI, createCmpXchgInstFun);
816 }
817 return true;
818 }
819 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic: {
820 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
821 unsigned ValueSize = getAtomicOpSize(AI);
822 if (ValueSize < MinCASSize) {
824 // Widen And/Or/Xor and give the target another chance at expanding it.
827 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
828 return true;
829 }
830 }
831 expandAtomicRMWToMaskedIntrinsic(AI);
832 return true;
833 }
834 case TargetLoweringBase::AtomicExpansionKind::BitTestIntrinsic: {
836 return true;
837 }
838 case TargetLoweringBase::AtomicExpansionKind::CmpArithIntrinsic: {
840 return true;
841 }
842 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
843 return lowerAtomicRMWInst(AI);
844 case TargetLoweringBase::AtomicExpansionKind::CustomExpand:
845 TLI->emitExpandAtomicRMW(AI);
846 return true;
847 default:
848 llvm_unreachable("Unhandled case in tryExpandAtomicRMW");
849 }
850}
851
852namespace {
853
854struct PartwordMaskValues {
855 // These three fields are guaranteed to be set by createMaskInstrs.
856 Type *WordType = nullptr;
857 Type *ValueType = nullptr;
858 Type *IntValueType = nullptr;
859 Value *AlignedAddr = nullptr;
860 Align AlignedAddrAlignment;
861 // The remaining fields can be null.
862 Value *ShiftAmt = nullptr;
863 Value *Mask = nullptr;
864 Value *Inv_Mask = nullptr;
865};
866
867[[maybe_unused]]
868raw_ostream &operator<<(raw_ostream &O, const PartwordMaskValues &PMV) {
869 auto PrintObj = [&O](auto *V) {
870 if (V)
871 O << *V;
872 else
873 O << "nullptr";
874 O << '\n';
875 };
876 O << "PartwordMaskValues {\n";
877 O << " WordType: ";
878 PrintObj(PMV.WordType);
879 O << " ValueType: ";
880 PrintObj(PMV.ValueType);
881 O << " AlignedAddr: ";
882 PrintObj(PMV.AlignedAddr);
883 O << " AlignedAddrAlignment: " << PMV.AlignedAddrAlignment.value() << '\n';
884 O << " ShiftAmt: ";
885 PrintObj(PMV.ShiftAmt);
886 O << " Mask: ";
887 PrintObj(PMV.Mask);
888 O << " Inv_Mask: ";
889 PrintObj(PMV.Inv_Mask);
890 O << "}\n";
891 return O;
892}
893
894} // end anonymous namespace
895
896/// This is a helper function which builds instructions to provide
897/// values necessary for partword atomic operations. It takes an
898/// incoming address, Addr, and ValueType, and constructs the address,
899/// shift-amounts and masks needed to work with a larger value of size
900/// WordSize.
901///
902/// AlignedAddr: Addr rounded down to a multiple of WordSize
903///
904/// ShiftAmt: Number of bits to right-shift a WordSize value loaded
905/// from AlignAddr for it to have the same value as if
906/// ValueType was loaded from Addr.
907///
908/// Mask: Value to mask with the value loaded from AlignAddr to
909/// include only the part that would've been loaded from Addr.
910///
911/// Inv_Mask: The inverse of Mask.
912static PartwordMaskValues createMaskInstrs(IRBuilderBase &Builder,
914 Value *Addr, Align AddrAlign,
915 unsigned MinWordSize) {
916 PartwordMaskValues PMV;
917
918 Module *M = I->getModule();
919 LLVMContext &Ctx = M->getContext();
920 const DataLayout &DL = M->getDataLayout();
921 unsigned ValueSize = DL.getTypeStoreSize(ValueType);
922
923 PMV.ValueType = PMV.IntValueType = ValueType;
924 if (PMV.ValueType->isFloatingPointTy() || PMV.ValueType->isVectorTy())
925 PMV.IntValueType =
926 Type::getIntNTy(Ctx, ValueType->getPrimitiveSizeInBits());
927
928 PMV.WordType = MinWordSize > ValueSize ? Type::getIntNTy(Ctx, MinWordSize * 8)
929 : ValueType;
930 if (PMV.ValueType == PMV.WordType) {
931 PMV.AlignedAddr = Addr;
932 PMV.AlignedAddrAlignment = AddrAlign;
933 PMV.ShiftAmt = ConstantInt::get(PMV.ValueType, 0);
934 PMV.Mask = ConstantInt::get(PMV.ValueType, ~0, /*isSigned*/ true);
935 return PMV;
936 }
937
938 PMV.AlignedAddrAlignment = Align(MinWordSize);
939
940 assert(ValueSize < MinWordSize);
941
942 PointerType *PtrTy = cast<PointerType>(Addr->getType());
943 IntegerType *IntTy = DL.getIndexType(Ctx, PtrTy->getAddressSpace());
944 Value *PtrLSB;
945
946 if (AddrAlign < MinWordSize) {
947 PMV.AlignedAddr = Builder.CreateIntrinsic(
948 Intrinsic::ptrmask, {PtrTy, IntTy},
949 {Addr, ConstantInt::getSigned(IntTy, ~(uint64_t)(MinWordSize - 1))},
950 nullptr, "AlignedAddr");
951
952 Value *AddrInt = Builder.CreatePtrToInt(Addr, IntTy);
953 PtrLSB = Builder.CreateAnd(AddrInt, MinWordSize - 1, "PtrLSB");
954 } else {
955 // If the alignment is high enough, the LSB are known 0.
956 PMV.AlignedAddr = Addr;
957 PtrLSB = ConstantInt::getNullValue(IntTy);
958 }
959
960 if (DL.isLittleEndian()) {
961 // turn bytes into bits
962 PMV.ShiftAmt = Builder.CreateShl(PtrLSB, 3);
963 } else {
964 // turn bytes into bits, and count from the other side.
965 PMV.ShiftAmt = Builder.CreateShl(
966 Builder.CreateXor(PtrLSB, MinWordSize - ValueSize), 3);
967 }
968
969 PMV.ShiftAmt = Builder.CreateTrunc(PMV.ShiftAmt, PMV.WordType, "ShiftAmt");
970 PMV.Mask = Builder.CreateShl(
971 ConstantInt::get(PMV.WordType, (1 << (ValueSize * 8)) - 1), PMV.ShiftAmt,
972 "Mask");
973
974 PMV.Inv_Mask = Builder.CreateNot(PMV.Mask, "Inv_Mask");
975
976 return PMV;
977}
978
979static Value *extractMaskedValue(IRBuilderBase &Builder, Value *WideWord,
980 const PartwordMaskValues &PMV) {
981 assert(WideWord->getType() == PMV.WordType && "Widened type mismatch");
982 if (PMV.WordType == PMV.ValueType)
983 return WideWord;
984
985 Value *Shift = Builder.CreateLShr(WideWord, PMV.ShiftAmt, "shifted");
986 Value *Trunc = Builder.CreateTrunc(Shift, PMV.IntValueType, "extracted");
987 return Builder.CreateBitCast(Trunc, PMV.ValueType);
988}
989
990static Value *insertMaskedValue(IRBuilderBase &Builder, Value *WideWord,
991 Value *Updated, const PartwordMaskValues &PMV) {
992 assert(WideWord->getType() == PMV.WordType && "Widened type mismatch");
993 assert(Updated->getType() == PMV.ValueType && "Value type mismatch");
994 if (PMV.WordType == PMV.ValueType)
995 return Updated;
996
997 Updated = Builder.CreateBitCast(Updated, PMV.IntValueType);
998
999 Value *ZExt = Builder.CreateZExt(Updated, PMV.WordType, "extended");
1000 Value *Shift =
1001 Builder.CreateShl(ZExt, PMV.ShiftAmt, "shifted", /*HasNUW*/ true);
1002 Value *And = Builder.CreateAnd(WideWord, PMV.Inv_Mask, "unmasked");
1003 Value *Or = Builder.CreateOr(And, Shift, "inserted");
1004 return Or;
1005}
1006
1007/// Emit IR to implement a masked version of a given atomicrmw
1008/// operation. (That is, only the bits under the Mask should be
1009/// affected by the operation)
1011 IRBuilderBase &Builder, Value *Loaded,
1012 Value *Shifted_Inc, Value *Inc,
1013 const PartwordMaskValues &PMV) {
1014 // TODO: update to use
1015 // https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge in order
1016 // to merge bits from two values without requiring PMV.Inv_Mask.
1017 switch (Op) {
1018 case AtomicRMWInst::Xchg: {
1019 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1020 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, Shifted_Inc);
1021 return FinalVal;
1022 }
1023 case AtomicRMWInst::Or:
1024 case AtomicRMWInst::Xor:
1025 case AtomicRMWInst::And:
1026 llvm_unreachable("Or/Xor/And handled by widenPartwordAtomicRMW");
1027 case AtomicRMWInst::Add:
1028 case AtomicRMWInst::Sub:
1029 case AtomicRMWInst::Nand: {
1030 // The other arithmetic ops need to be masked into place.
1031 Value *NewVal = buildAtomicRMWValue(Op, Builder, Loaded, Shifted_Inc);
1032 Value *NewVal_Masked = Builder.CreateAnd(NewVal, PMV.Mask);
1033 Value *Loaded_MaskOut = Builder.CreateAnd(Loaded, PMV.Inv_Mask);
1034 Value *FinalVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Masked);
1035 return FinalVal;
1036 }
1037 case AtomicRMWInst::Max:
1038 case AtomicRMWInst::Min:
1053 // Finally, other ops will operate on the full value, so truncate down to
1054 // the original size, and expand out again after doing the
1055 // operation. Bitcasts will be inserted for FP values.
1056 Value *Loaded_Extract = extractMaskedValue(Builder, Loaded, PMV);
1057 Value *NewVal = buildAtomicRMWValue(Op, Builder, Loaded_Extract, Inc);
1058 Value *FinalVal = insertMaskedValue(Builder, Loaded, NewVal, PMV);
1059 return FinalVal;
1060 }
1061 default:
1062 llvm_unreachable("Unknown atomic op");
1063 }
1064}
1065
1066/// Expand a sub-word atomicrmw operation into an appropriate
1067/// word-sized operation.
1068///
1069/// It will create an LL/SC or cmpxchg loop, as appropriate, the same
1070/// way as a typical atomicrmw expansion. The only difference here is
1071/// that the operation inside of the loop may operate upon only a
1072/// part of the value.
1073void AtomicExpandImpl::expandPartwordAtomicRMW(
1074 AtomicRMWInst *AI, TargetLoweringBase::AtomicExpansionKind ExpansionKind) {
1075 // Widen And/Or/Xor and give the target another chance at expanding it.
1079 tryExpandAtomicRMW(widenPartwordAtomicRMW(AI));
1080 return;
1081 }
1082 AtomicOrdering MemOpOrder = AI->getOrdering();
1083 SyncScope::ID SSID = AI->getSyncScopeID();
1084
1085 ReplacementIRBuilder Builder(AI, *DL);
1086
1087 PartwordMaskValues PMV =
1088 createMaskInstrs(Builder, AI, AI->getType(), AI->getPointerOperand(),
1089 AI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1090
1091 Value *ValOperand_Shifted = nullptr;
1094 Value *ValOp = Builder.CreateBitCast(AI->getValOperand(), PMV.IntValueType);
1095 ValOperand_Shifted =
1096 Builder.CreateShl(Builder.CreateZExt(ValOp, PMV.WordType), PMV.ShiftAmt,
1097 "ValOperand_Shifted");
1098 }
1099
1100 auto PerformPartwordOp = [&](IRBuilderBase &Builder, Value *Loaded) {
1101 return performMaskedAtomicOp(Op, Builder, Loaded, ValOperand_Shifted,
1102 AI->getValOperand(), PMV);
1103 };
1104
1105 Value *OldResult;
1106 if (ExpansionKind == TargetLoweringBase::AtomicExpansionKind::CmpXChg) {
1107 OldResult = insertRMWCmpXchgLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1108 PMV.AlignedAddrAlignment, MemOpOrder, SSID,
1109 AI->isVolatile(), PerformPartwordOp,
1111 } else {
1112 assert(ExpansionKind == TargetLoweringBase::AtomicExpansionKind::LLSC);
1113 OldResult = insertRMWLLSCLoop(Builder, PMV.WordType, PMV.AlignedAddr,
1114 PMV.AlignedAddrAlignment, MemOpOrder,
1115 PerformPartwordOp);
1116 }
1117
1118 Value *FinalOldResult = extractMaskedValue(Builder, OldResult, PMV);
1119 AI->replaceAllUsesWith(FinalOldResult);
1120 AI->eraseFromParent();
1121}
1122
1123// Widen the bitwise atomicrmw (or/xor/and) to the minimum supported width.
1124AtomicRMWInst *AtomicExpandImpl::widenPartwordAtomicRMW(AtomicRMWInst *AI) {
1125 ReplacementIRBuilder Builder(AI, *DL);
1127
1129 Op == AtomicRMWInst::And) &&
1130 "Unable to widen operation");
1131
1132 PartwordMaskValues PMV =
1133 createMaskInstrs(Builder, AI, AI->getType(), AI->getPointerOperand(),
1134 AI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1135
1136 Value *ValOperand_Shifted =
1137 Builder.CreateShl(Builder.CreateZExt(AI->getValOperand(), PMV.WordType),
1138 PMV.ShiftAmt, "ValOperand_Shifted");
1139
1140 Value *NewOperand;
1141
1142 if (Op == AtomicRMWInst::And)
1143 NewOperand =
1144 Builder.CreateOr(ValOperand_Shifted, PMV.Inv_Mask, "AndOperand");
1145 else
1146 NewOperand = ValOperand_Shifted;
1147
1148 AtomicRMWInst *NewAI = Builder.CreateAtomicRMW(
1149 Op, PMV.AlignedAddr, NewOperand, PMV.AlignedAddrAlignment,
1150 AI->getOrdering(), AI->getSyncScopeID());
1151
1152 NewAI->setVolatile(AI->isVolatile());
1153 copyMetadataForAtomic(*NewAI, *AI);
1154
1155 Value *FinalOldResult = extractMaskedValue(Builder, NewAI, PMV);
1156 AI->replaceAllUsesWith(FinalOldResult);
1157 AI->eraseFromParent();
1158 return NewAI;
1159}
1160
1161bool AtomicExpandImpl::expandPartwordCmpXchg(AtomicCmpXchgInst *CI) {
1162 // The basic idea here is that we're expanding a cmpxchg of a
1163 // smaller memory size up to a word-sized cmpxchg. To do this, we
1164 // need to add a retry-loop for strong cmpxchg, so that
1165 // modifications to other parts of the word don't cause a spurious
1166 // failure.
1167
1168 // This generates code like the following:
1169 // [[Setup mask values PMV.*]]
1170 // %NewVal_Shifted = shl i32 %NewVal, %PMV.ShiftAmt
1171 // %Cmp_Shifted = shl i32 %Cmp, %PMV.ShiftAmt
1172 // %InitLoaded = load i32* %addr
1173 // %InitLoaded_MaskOut = and i32 %InitLoaded, %PMV.Inv_Mask
1174 // br partword.cmpxchg.loop
1175 // partword.cmpxchg.loop:
1176 // %Loaded_MaskOut = phi i32 [ %InitLoaded_MaskOut, %entry ],
1177 // [ %OldVal_MaskOut, %partword.cmpxchg.failure ]
1178 // %FullWord_NewVal = or i32 %Loaded_MaskOut, %NewVal_Shifted
1179 // %FullWord_Cmp = or i32 %Loaded_MaskOut, %Cmp_Shifted
1180 // %NewCI = cmpxchg i32* %PMV.AlignedAddr, i32 %FullWord_Cmp,
1181 // i32 %FullWord_NewVal success_ordering failure_ordering
1182 // %OldVal = extractvalue { i32, i1 } %NewCI, 0
1183 // %Success = extractvalue { i32, i1 } %NewCI, 1
1184 // br i1 %Success, label %partword.cmpxchg.end,
1185 // label %partword.cmpxchg.failure
1186 // partword.cmpxchg.failure:
1187 // %OldVal_MaskOut = and i32 %OldVal, %PMV.Inv_Mask
1188 // %ShouldContinue = icmp ne i32 %Loaded_MaskOut, %OldVal_MaskOut
1189 // br i1 %ShouldContinue, label %partword.cmpxchg.loop,
1190 // label %partword.cmpxchg.end
1191 // partword.cmpxchg.end:
1192 // %tmp1 = lshr i32 %OldVal, %PMV.ShiftAmt
1193 // %FinalOldVal = trunc i32 %tmp1 to i8
1194 // %tmp2 = insertvalue { i8, i1 } undef, i8 %FinalOldVal, 0
1195 // %Res = insertvalue { i8, i1 } %25, i1 %Success, 1
1196
1197 Value *Addr = CI->getPointerOperand();
1198 Value *Cmp = CI->getCompareOperand();
1199 Value *NewVal = CI->getNewValOperand();
1200
1201 BasicBlock *BB = CI->getParent();
1202 Function *F = BB->getParent();
1203 ReplacementIRBuilder Builder(CI, *DL);
1204 LLVMContext &Ctx = Builder.getContext();
1205
1206 BasicBlock *EndBB =
1207 BB->splitBasicBlock(CI->getIterator(), "partword.cmpxchg.end");
1208 auto FailureBB =
1209 BasicBlock::Create(Ctx, "partword.cmpxchg.failure", F, EndBB);
1210 auto LoopBB = BasicBlock::Create(Ctx, "partword.cmpxchg.loop", F, FailureBB);
1211
1212 // The split call above "helpfully" added a branch at the end of BB
1213 // (to the wrong place).
1214 std::prev(BB->end())->eraseFromParent();
1215 Builder.SetInsertPoint(BB);
1216
1217 PartwordMaskValues PMV =
1218 createMaskInstrs(Builder, CI, CI->getCompareOperand()->getType(), Addr,
1219 CI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1220
1221 // Shift the incoming values over, into the right location in the word.
1222 Value *NewVal_Shifted =
1223 Builder.CreateShl(Builder.CreateZExt(NewVal, PMV.WordType), PMV.ShiftAmt);
1224 Value *Cmp_Shifted =
1225 Builder.CreateShl(Builder.CreateZExt(Cmp, PMV.WordType), PMV.ShiftAmt);
1226
1227 // Load the entire current word, and mask into place the expected and new
1228 // values
1229 LoadInst *InitLoaded = Builder.CreateLoad(PMV.WordType, PMV.AlignedAddr);
1230 Value *InitLoaded_MaskOut = Builder.CreateAnd(InitLoaded, PMV.Inv_Mask);
1231 Builder.CreateBr(LoopBB);
1232
1233 // partword.cmpxchg.loop:
1234 Builder.SetInsertPoint(LoopBB);
1235 PHINode *Loaded_MaskOut = Builder.CreatePHI(PMV.WordType, 2);
1236 Loaded_MaskOut->addIncoming(InitLoaded_MaskOut, BB);
1237
1238 // The initial load must be atomic with the same synchronization scope
1239 // to avoid a data race with concurrent stores. If the instruction being
1240 // emulated is volatile, issue a volatile load.
1241 // addIncoming is done first so that any replaceAllUsesWith calls during
1242 // normalization correctly update the PHI incoming value.
1243 InitLoaded->setVolatile(CI->isVolatile());
1245 InitLoaded->setAtomic(AtomicOrdering::Monotonic, CI->getSyncScopeID());
1246 // The newly created load might need to be lowered further. Because it is
1247 // created in the same block as the atomicrmw, the AtomicExpand loop will
1248 // not process it again.
1249 processAtomicInstr(InitLoaded);
1250 }
1251
1252 // Mask/Or the expected and new values into place in the loaded word.
1253 Value *FullWord_NewVal = Builder.CreateOr(Loaded_MaskOut, NewVal_Shifted);
1254 Value *FullWord_Cmp = Builder.CreateOr(Loaded_MaskOut, Cmp_Shifted);
1255 AtomicCmpXchgInst *NewCI = Builder.CreateAtomicCmpXchg(
1256 PMV.AlignedAddr, FullWord_Cmp, FullWord_NewVal, PMV.AlignedAddrAlignment,
1258 NewCI->setVolatile(CI->isVolatile());
1259 // When we're building a strong cmpxchg, we need a loop, so you
1260 // might think we could use a weak cmpxchg inside. But, using strong
1261 // allows the below comparison for ShouldContinue, and we're
1262 // expecting the underlying cmpxchg to be a machine instruction,
1263 // which is strong anyways.
1264 NewCI->setWeak(CI->isWeak());
1265
1266 Value *OldVal = Builder.CreateExtractValue(NewCI, 0);
1267 Value *Success = Builder.CreateExtractValue(NewCI, 1);
1268
1269 if (CI->isWeak())
1270 Builder.CreateBr(EndBB);
1271 else
1272 Builder.CreateCondBr(Success, EndBB, FailureBB);
1273
1274 // partword.cmpxchg.failure:
1275 Builder.SetInsertPoint(FailureBB);
1276 // Upon failure, verify that the masked-out part of the loaded value
1277 // has been modified. If it didn't, abort the cmpxchg, since the
1278 // masked-in part must've.
1279 Value *OldVal_MaskOut = Builder.CreateAnd(OldVal, PMV.Inv_Mask);
1280 Value *ShouldContinue = Builder.CreateICmpNE(Loaded_MaskOut, OldVal_MaskOut);
1281 Builder.CreateCondBr(ShouldContinue, LoopBB, EndBB);
1282
1283 // Add the second value to the phi from above
1284 Loaded_MaskOut->addIncoming(OldVal_MaskOut, FailureBB);
1285
1286 // partword.cmpxchg.end:
1287 Builder.SetInsertPoint(CI);
1288
1289 Value *FinalOldVal = extractMaskedValue(Builder, OldVal, PMV);
1290 Value *Res = PoisonValue::get(CI->getType());
1291 Res = Builder.CreateInsertValue(Res, FinalOldVal, 0);
1292 Res = Builder.CreateInsertValue(Res, Success, 1);
1293
1294 CI->replaceAllUsesWith(Res);
1295 CI->eraseFromParent();
1296 return true;
1297}
1298
1299void AtomicExpandImpl::expandAtomicOpToLLSC(
1300 Instruction *I, Type *ResultType, Value *Addr, Align AddrAlign,
1301 AtomicOrdering MemOpOrder,
1302 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp) {
1303 ReplacementIRBuilder Builder(I, *DL);
1304 Value *Loaded = insertRMWLLSCLoop(Builder, ResultType, Addr, AddrAlign,
1305 MemOpOrder, PerformOp);
1306
1307 I->replaceAllUsesWith(Loaded);
1308 I->eraseFromParent();
1309}
1310
1311void AtomicExpandImpl::expandAtomicRMWToMaskedIntrinsic(AtomicRMWInst *AI) {
1312 ReplacementIRBuilder Builder(AI, *DL);
1313
1314 PartwordMaskValues PMV =
1315 createMaskInstrs(Builder, AI, AI->getType(), AI->getPointerOperand(),
1316 AI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1317
1318 // The value operand must be sign-extended for signed min/max so that the
1319 // target's signed comparison instructions can be used. Otherwise, just
1320 // zero-ext.
1321 Instruction::CastOps CastOp = Instruction::ZExt;
1322 AtomicRMWInst::BinOp RMWOp = AI->getOperation();
1323 if (RMWOp == AtomicRMWInst::Max || RMWOp == AtomicRMWInst::Min)
1324 CastOp = Instruction::SExt;
1325
1326 Value *ValOperand_Shifted = Builder.CreateShl(
1327 Builder.CreateCast(CastOp, AI->getValOperand(), PMV.WordType),
1328 PMV.ShiftAmt, "ValOperand_Shifted");
1329 Value *OldResult = TLI->emitMaskedAtomicRMWIntrinsic(
1330 Builder, AI, PMV.AlignedAddr, ValOperand_Shifted, PMV.Mask, PMV.ShiftAmt,
1331 AI->getOrdering());
1332 Value *FinalOldResult = extractMaskedValue(Builder, OldResult, PMV);
1333 AI->replaceAllUsesWith(FinalOldResult);
1334 AI->eraseFromParent();
1335}
1336
1337void AtomicExpandImpl::expandAtomicCmpXchgToMaskedIntrinsic(
1338 AtomicCmpXchgInst *CI) {
1339 ReplacementIRBuilder Builder(CI, *DL);
1340
1341 PartwordMaskValues PMV = createMaskInstrs(
1342 Builder, CI, CI->getCompareOperand()->getType(), CI->getPointerOperand(),
1343 CI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1344
1345 Value *CmpVal_Shifted = Builder.CreateShl(
1346 Builder.CreateZExt(CI->getCompareOperand(), PMV.WordType), PMV.ShiftAmt,
1347 "CmpVal_Shifted");
1348 Value *NewVal_Shifted = Builder.CreateShl(
1349 Builder.CreateZExt(CI->getNewValOperand(), PMV.WordType), PMV.ShiftAmt,
1350 "NewVal_Shifted");
1352 Builder, CI, PMV.AlignedAddr, CmpVal_Shifted, NewVal_Shifted, PMV.Mask,
1353 CI->getMergedOrdering());
1354 Value *FinalOldVal = extractMaskedValue(Builder, OldVal, PMV);
1355 Value *Res = PoisonValue::get(CI->getType());
1356 Res = Builder.CreateInsertValue(Res, FinalOldVal, 0);
1357 Value *Success = Builder.CreateICmpEQ(
1358 CmpVal_Shifted, Builder.CreateAnd(OldVal, PMV.Mask), "Success");
1359 Res = Builder.CreateInsertValue(Res, Success, 1);
1360
1361 CI->replaceAllUsesWith(Res);
1362 CI->eraseFromParent();
1363}
1364
1365Value *AtomicExpandImpl::insertRMWLLSCLoop(
1366 IRBuilderBase &Builder, Type *ResultTy, Value *Addr, Align AddrAlign,
1367 AtomicOrdering MemOpOrder,
1368 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp) {
1369 LLVMContext &Ctx = Builder.getContext();
1370 BasicBlock *BB = Builder.GetInsertBlock();
1371 Function *F = BB->getParent();
1372
1373 assert(AddrAlign >= F->getDataLayout().getTypeStoreSize(ResultTy) &&
1374 "Expected at least natural alignment at this point.");
1375
1376 // Given: atomicrmw some_op iN* %addr, iN %incr ordering
1377 //
1378 // The standard expansion we produce is:
1379 // [...]
1380 // atomicrmw.start:
1381 // %loaded = @load.linked(%addr)
1382 // %new = some_op iN %loaded, %incr
1383 // %stored = @store_conditional(%new, %addr)
1384 // %try_again = icmp i32 ne %stored, 0
1385 // br i1 %try_again, label %loop, label %atomicrmw.end
1386 // atomicrmw.end:
1387 // [...]
1388 BasicBlock *ExitBB =
1389 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
1390 BasicBlock *LoopBB = BasicBlock::Create(Ctx, "atomicrmw.start", F, ExitBB);
1391
1392 // The split call above "helpfully" added a branch at the end of BB (to the
1393 // wrong place).
1394 std::prev(BB->end())->eraseFromParent();
1395 Builder.SetInsertPoint(BB);
1396 Builder.CreateBr(LoopBB);
1397
1398 // Start the main loop block now that we've taken care of the preliminaries.
1399 Builder.SetInsertPoint(LoopBB);
1400 Value *Loaded = TLI->emitLoadLinked(Builder, ResultTy, Addr, MemOpOrder);
1401
1402 Value *NewVal = PerformOp(Builder, Loaded);
1403
1404 Value *StoreSuccess =
1405 TLI->emitStoreConditional(Builder, NewVal, Addr, MemOpOrder);
1406 Value *TryAgain = Builder.CreateICmpNE(
1407 StoreSuccess, ConstantInt::get(IntegerType::get(Ctx, 32), 0), "tryagain");
1408
1409 Instruction *CondBr = Builder.CreateCondBr(TryAgain, LoopBB, ExitBB);
1410
1411 // Atomic RMW expands to a Load-linked / Store-Conditional loop, because it is
1412 // hard to predict precise branch weigths we mark the branch as "unknown"
1413 // (50/50) to prevent misleading optimizations.
1415
1416 Builder.SetInsertPoint(ExitBB, ExitBB->begin());
1417 return Loaded;
1418}
1419
1420/// Convert an atomic cmpxchg of a non-integral type to an integer cmpxchg of
1421/// the equivalent bitwidth. We used to not support pointer cmpxchg in the
1422/// IR. As a migration step, we convert back to what use to be the standard
1423/// way to represent a pointer cmpxchg so that we can update backends one by
1424/// one.
1425AtomicCmpXchgInst *
1426AtomicExpandImpl::convertCmpXchgToIntegerType(AtomicCmpXchgInst *CI) {
1427 auto *M = CI->getModule();
1428 Type *NewTy = getCorrespondingIntegerType(CI->getCompareOperand()->getType(),
1429 M->getDataLayout());
1430
1431 ReplacementIRBuilder Builder(CI, *DL);
1432
1433 Value *Addr = CI->getPointerOperand();
1434
1435 Value *NewCmp = Builder.CreatePtrToInt(CI->getCompareOperand(), NewTy);
1436 Value *NewNewVal = Builder.CreatePtrToInt(CI->getNewValOperand(), NewTy);
1437
1438 auto *NewCI = Builder.CreateAtomicCmpXchg(
1439 Addr, NewCmp, NewNewVal, CI->getAlign(), CI->getSuccessOrdering(),
1440 CI->getFailureOrdering(), CI->getSyncScopeID());
1441 NewCI->setVolatile(CI->isVolatile());
1442 NewCI->setWeak(CI->isWeak());
1443 LLVM_DEBUG(dbgs() << "Replaced " << *CI << " with " << *NewCI << "\n");
1444
1445 Value *OldVal = Builder.CreateExtractValue(NewCI, 0);
1446 Value *Succ = Builder.CreateExtractValue(NewCI, 1);
1447
1448 OldVal = Builder.CreateIntToPtr(OldVal, CI->getCompareOperand()->getType());
1449
1450 Value *Res = PoisonValue::get(CI->getType());
1451 Res = Builder.CreateInsertValue(Res, OldVal, 0);
1452 Res = Builder.CreateInsertValue(Res, Succ, 1);
1453
1454 CI->replaceAllUsesWith(Res);
1455 CI->eraseFromParent();
1456 return NewCI;
1457}
1458
1459bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1460 AtomicOrdering SuccessOrder = CI->getSuccessOrdering();
1461 AtomicOrdering FailureOrder = CI->getFailureOrdering();
1462 Value *Addr = CI->getPointerOperand();
1463 BasicBlock *BB = CI->getParent();
1464 Function *F = BB->getParent();
1465 LLVMContext &Ctx = F->getContext();
1466 // If shouldInsertFencesForAtomic() returns true, then the target does not
1467 // want to deal with memory orders, and emitLeading/TrailingFence should take
1468 // care of everything. Otherwise, emitLeading/TrailingFence are no-op and we
1469 // should preserve the ordering.
1470 bool ShouldInsertFencesForAtomic = TLI->shouldInsertFencesForAtomic(CI);
1471 AtomicOrdering MemOpOrder = ShouldInsertFencesForAtomic
1472 ? AtomicOrdering::Monotonic
1473 : CI->getMergedOrdering();
1474
1475 // In implementations which use a barrier to achieve release semantics, we can
1476 // delay emitting this barrier until we know a store is actually going to be
1477 // attempted. The cost of this delay is that we need 2 copies of the block
1478 // emitting the load-linked, affecting code size.
1479 //
1480 // Ideally, this logic would be unconditional except for the minsize check
1481 // since in other cases the extra blocks naturally collapse down to the
1482 // minimal loop. Unfortunately, this puts too much stress on later
1483 // optimisations so we avoid emitting the extra logic in those cases too.
1484 bool HasReleasedLoadBB = !CI->isWeak() && ShouldInsertFencesForAtomic &&
1485 SuccessOrder != AtomicOrdering::Monotonic &&
1486 SuccessOrder != AtomicOrdering::Acquire &&
1487 !F->hasMinSize();
1488
1489 // There's no overhead for sinking the release barrier in a weak cmpxchg, so
1490 // do it even on minsize.
1491 bool UseUnconditionalReleaseBarrier = F->hasMinSize() && !CI->isWeak();
1492
1493 // Given: cmpxchg some_op iN* %addr, iN %desired, iN %new success_ord fail_ord
1494 //
1495 // The full expansion we produce is:
1496 // [...]
1497 // %aligned.addr = ...
1498 // cmpxchg.start:
1499 // %unreleasedload = @load.linked(%aligned.addr)
1500 // %unreleasedload.extract = extract value from %unreleasedload
1501 // %should_store = icmp eq %unreleasedload.extract, %desired
1502 // br i1 %should_store, label %cmpxchg.releasingstore,
1503 // label %cmpxchg.nostore
1504 // cmpxchg.releasingstore:
1505 // fence?
1506 // br label cmpxchg.trystore
1507 // cmpxchg.trystore:
1508 // %loaded.trystore = phi [%unreleasedload, %cmpxchg.releasingstore],
1509 // [%releasedload, %cmpxchg.releasedload]
1510 // %updated.new = insert %new into %loaded.trystore
1511 // %stored = @store_conditional(%updated.new, %aligned.addr)
1512 // %success = icmp eq i32 %stored, 0
1513 // br i1 %success, label %cmpxchg.success,
1514 // label %cmpxchg.releasedload/%cmpxchg.failure
1515 // cmpxchg.releasedload:
1516 // %releasedload = @load.linked(%aligned.addr)
1517 // %releasedload.extract = extract value from %releasedload
1518 // %should_store = icmp eq %releasedload.extract, %desired
1519 // br i1 %should_store, label %cmpxchg.trystore,
1520 // label %cmpxchg.failure
1521 // cmpxchg.success:
1522 // fence?
1523 // br label %cmpxchg.end
1524 // cmpxchg.nostore:
1525 // %loaded.nostore = phi [%unreleasedload, %cmpxchg.start],
1526 // [%releasedload,
1527 // %cmpxchg.releasedload/%cmpxchg.trystore]
1528 // @load_linked_fail_balance()?
1529 // br label %cmpxchg.failure
1530 // cmpxchg.failure:
1531 // fence?
1532 // br label %cmpxchg.end
1533 // cmpxchg.end:
1534 // %loaded.exit = phi [%loaded.nostore, %cmpxchg.failure],
1535 // [%loaded.trystore, %cmpxchg.trystore]
1536 // %success = phi i1 [true, %cmpxchg.success], [false, %cmpxchg.failure]
1537 // %loaded = extract value from %loaded.exit
1538 // %restmp = insertvalue { iN, i1 } undef, iN %loaded, 0
1539 // %res = insertvalue { iN, i1 } %restmp, i1 %success, 1
1540 // [...]
1541 BasicBlock *ExitBB = BB->splitBasicBlock(CI->getIterator(), "cmpxchg.end");
1542 auto FailureBB = BasicBlock::Create(Ctx, "cmpxchg.failure", F, ExitBB);
1543 auto NoStoreBB = BasicBlock::Create(Ctx, "cmpxchg.nostore", F, FailureBB);
1544 auto SuccessBB = BasicBlock::Create(Ctx, "cmpxchg.success", F, NoStoreBB);
1545 auto ReleasedLoadBB =
1546 BasicBlock::Create(Ctx, "cmpxchg.releasedload", F, SuccessBB);
1547 auto TryStoreBB =
1548 BasicBlock::Create(Ctx, "cmpxchg.trystore", F, ReleasedLoadBB);
1549 auto ReleasingStoreBB =
1550 BasicBlock::Create(Ctx, "cmpxchg.fencedstore", F, TryStoreBB);
1551 auto StartBB = BasicBlock::Create(Ctx, "cmpxchg.start", F, ReleasingStoreBB);
1552
1553 ReplacementIRBuilder Builder(CI, *DL);
1554
1555 // The split call above "helpfully" added a branch at the end of BB (to the
1556 // wrong place), but we might want a fence too. It's easiest to just remove
1557 // the branch entirely.
1558 std::prev(BB->end())->eraseFromParent();
1559 Builder.SetInsertPoint(BB);
1560 if (ShouldInsertFencesForAtomic && UseUnconditionalReleaseBarrier)
1561 TLI->emitLeadingFence(Builder, CI, SuccessOrder);
1562
1563 PartwordMaskValues PMV =
1564 createMaskInstrs(Builder, CI, CI->getCompareOperand()->getType(), Addr,
1565 CI->getAlign(), TLI->getMinCmpXchgSizeInBits() / 8);
1566 Builder.CreateBr(StartBB);
1567
1568 // Start the main loop block now that we've taken care of the preliminaries.
1569 Builder.SetInsertPoint(StartBB);
1570 Value *UnreleasedLoad =
1571 TLI->emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1572 Value *UnreleasedLoadExtract =
1573 extractMaskedValue(Builder, UnreleasedLoad, PMV);
1574 Value *ShouldStore = Builder.CreateICmpEQ(
1575 UnreleasedLoadExtract, CI->getCompareOperand(), "should_store");
1576
1577 // If the cmpxchg doesn't actually need any ordering when it fails, we can
1578 // jump straight past that fence instruction (if it exists).
1579 Builder.CreateCondBr(ShouldStore, ReleasingStoreBB, NoStoreBB,
1580 MDBuilder(F->getContext()).createLikelyBranchWeights());
1581
1582 Builder.SetInsertPoint(ReleasingStoreBB);
1583 if (ShouldInsertFencesForAtomic && !UseUnconditionalReleaseBarrier)
1584 TLI->emitLeadingFence(Builder, CI, SuccessOrder);
1585 Builder.CreateBr(TryStoreBB);
1586
1587 Builder.SetInsertPoint(TryStoreBB);
1588 PHINode *LoadedTryStore =
1589 Builder.CreatePHI(PMV.WordType, 2, "loaded.trystore");
1590 LoadedTryStore->addIncoming(UnreleasedLoad, ReleasingStoreBB);
1591 Value *NewValueInsert =
1592 insertMaskedValue(Builder, LoadedTryStore, CI->getNewValOperand(), PMV);
1593 Value *StoreSuccess = TLI->emitStoreConditional(Builder, NewValueInsert,
1594 PMV.AlignedAddr, MemOpOrder);
1595 StoreSuccess = Builder.CreateICmpEQ(
1596 StoreSuccess, ConstantInt::get(Type::getInt32Ty(Ctx), 0), "success");
1597 BasicBlock *RetryBB = HasReleasedLoadBB ? ReleasedLoadBB : StartBB;
1598 Builder.CreateCondBr(StoreSuccess, SuccessBB,
1599 CI->isWeak() ? FailureBB : RetryBB,
1600 MDBuilder(F->getContext()).createLikelyBranchWeights());
1601
1602 Builder.SetInsertPoint(ReleasedLoadBB);
1603 Value *SecondLoad;
1604 if (HasReleasedLoadBB) {
1605 SecondLoad =
1606 TLI->emitLoadLinked(Builder, PMV.WordType, PMV.AlignedAddr, MemOpOrder);
1607 Value *SecondLoadExtract = extractMaskedValue(Builder, SecondLoad, PMV);
1608 ShouldStore = Builder.CreateICmpEQ(SecondLoadExtract,
1609 CI->getCompareOperand(), "should_store");
1610
1611 // If the cmpxchg doesn't actually need any ordering when it fails, we can
1612 // jump straight past that fence instruction (if it exists).
1613 Builder.CreateCondBr(
1614 ShouldStore, TryStoreBB, NoStoreBB,
1615 MDBuilder(F->getContext()).createLikelyBranchWeights());
1616 // Update PHI node in TryStoreBB.
1617 LoadedTryStore->addIncoming(SecondLoad, ReleasedLoadBB);
1618 } else
1619 Builder.CreateUnreachable();
1620
1621 // Make sure later instructions don't get reordered with a fence if
1622 // necessary.
1623 Builder.SetInsertPoint(SuccessBB);
1624 if (ShouldInsertFencesForAtomic ||
1626 TLI->emitTrailingFence(Builder, CI, SuccessOrder);
1627 Builder.CreateBr(ExitBB);
1628
1629 Builder.SetInsertPoint(NoStoreBB);
1630 PHINode *LoadedNoStore =
1631 Builder.CreatePHI(UnreleasedLoad->getType(), 2, "loaded.nostore");
1632 LoadedNoStore->addIncoming(UnreleasedLoad, StartBB);
1633 if (HasReleasedLoadBB)
1634 LoadedNoStore->addIncoming(SecondLoad, ReleasedLoadBB);
1635
1636 // In the failing case, where we don't execute the store-conditional, the
1637 // target might want to balance out the load-linked with a dedicated
1638 // instruction (e.g., on ARM, clearing the exclusive monitor).
1640 Builder.CreateBr(FailureBB);
1641
1642 Builder.SetInsertPoint(FailureBB);
1643 PHINode *LoadedFailure =
1644 Builder.CreatePHI(UnreleasedLoad->getType(), 2, "loaded.failure");
1645 LoadedFailure->addIncoming(LoadedNoStore, NoStoreBB);
1646 if (CI->isWeak())
1647 LoadedFailure->addIncoming(LoadedTryStore, TryStoreBB);
1648 if (ShouldInsertFencesForAtomic)
1649 TLI->emitTrailingFence(Builder, CI, FailureOrder);
1650 Builder.CreateBr(ExitBB);
1651
1652 // Finally, we have control-flow based knowledge of whether the cmpxchg
1653 // succeeded or not. We expose this to later passes by converting any
1654 // subsequent "icmp eq/ne %loaded, %oldval" into a use of an appropriate
1655 // PHI.
1656 Builder.SetInsertPoint(ExitBB, ExitBB->begin());
1657 PHINode *LoadedExit =
1658 Builder.CreatePHI(UnreleasedLoad->getType(), 2, "loaded.exit");
1659 LoadedExit->addIncoming(LoadedTryStore, SuccessBB);
1660 LoadedExit->addIncoming(LoadedFailure, FailureBB);
1661 PHINode *Success = Builder.CreatePHI(Type::getInt1Ty(Ctx), 2, "success");
1662 Success->addIncoming(ConstantInt::getTrue(Ctx), SuccessBB);
1663 Success->addIncoming(ConstantInt::getFalse(Ctx), FailureBB);
1664
1665 // This is the "exit value" from the cmpxchg expansion. It may be of
1666 // a type wider than the one in the cmpxchg instruction.
1667 Value *LoadedFull = LoadedExit;
1668
1669 Builder.SetInsertPoint(ExitBB, std::next(Success->getIterator()));
1670 Value *Loaded = extractMaskedValue(Builder, LoadedFull, PMV);
1671
1672 // Look for any users of the cmpxchg that are just comparing the loaded value
1673 // against the desired one, and replace them with the CFG-derived version.
1675 for (auto *User : CI->users()) {
1676 ExtractValueInst *EV = dyn_cast<ExtractValueInst>(User);
1677 if (!EV)
1678 continue;
1679
1680 assert(EV->getNumIndices() == 1 && EV->getIndices()[0] <= 1 &&
1681 "weird extraction from { iN, i1 }");
1682
1683 if (EV->getIndices()[0] == 0)
1684 EV->replaceAllUsesWith(Loaded);
1685 else
1687
1688 PrunedInsts.push_back(EV);
1689 }
1690
1691 // We can remove the instructions now we're no longer iterating through them.
1692 for (auto *EV : PrunedInsts)
1693 EV->eraseFromParent();
1694
1695 if (!CI->use_empty()) {
1696 // Some use of the full struct return that we don't understand has happened,
1697 // so we've got to reconstruct it properly.
1698 Value *Res;
1699 Res = Builder.CreateInsertValue(PoisonValue::get(CI->getType()), Loaded, 0);
1700 Res = Builder.CreateInsertValue(Res, Success, 1);
1701
1702 CI->replaceAllUsesWith(Res);
1703 }
1704
1705 CI->eraseFromParent();
1706 return true;
1707}
1708
1709bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) {
1710 if (RMWI->isVolatile())
1711 return false;
1712 // TODO: Add floating point support.
1713 auto C = dyn_cast<ConstantInt>(RMWI->getValOperand());
1714 if (!C)
1715 return false;
1716
1717 switch (RMWI->getOperation()) {
1718 case AtomicRMWInst::Add:
1719 case AtomicRMWInst::Sub:
1720 case AtomicRMWInst::Or:
1721 case AtomicRMWInst::Xor:
1722 return C->isZero();
1723 case AtomicRMWInst::And:
1724 return C->isMinusOne();
1725 case AtomicRMWInst::Min:
1726 return C->isMaxValue(true);
1727 case AtomicRMWInst::Max:
1728 return C->isMinValue(true);
1730 return C->isMaxValue(false);
1732 return C->isMinValue(false);
1733 default:
1734 return false;
1735 }
1736}
1737
1738bool AtomicExpandImpl::simplifyIdempotentRMW(AtomicRMWInst *RMWI) {
1739 if (auto ResultingLoad = TLI->lowerIdempotentRMWIntoFencedLoad(RMWI)) {
1740 tryExpandAtomicLoad(ResultingLoad);
1741 return true;
1742 }
1743 return false;
1744}
1745
1746Value *AtomicExpandImpl::insertRMWCmpXchgLoop(
1747 IRBuilderBase &Builder, Type *ResultTy, Value *Addr, Align AddrAlign,
1748 AtomicOrdering MemOpOrder, SyncScope::ID SSID, bool IsVolatile,
1749 function_ref<Value *(IRBuilderBase &, Value *)> PerformOp,
1750 CreateCmpXchgInstFun CreateCmpXchg, Instruction *MetadataSrc) {
1751 LLVMContext &Ctx = Builder.getContext();
1752 BasicBlock *BB = Builder.GetInsertBlock();
1753 Function *F = BB->getParent();
1754
1755 // Given: atomicrmw some_op iN* %addr, iN %incr ordering
1756 //
1757 // The standard expansion we produce is:
1758 // [...]
1759 // %init_loaded = load atomic iN* %addr
1760 // br label %loop
1761 // loop:
1762 // %loaded = phi iN [ %init_loaded, %entry ], [ %new_loaded, %loop ]
1763 // %new = some_op iN %loaded, %incr
1764 // %pair = cmpxchg iN* %addr, iN %loaded, iN %new
1765 // %new_loaded = extractvalue { iN, i1 } %pair, 0
1766 // %success = extractvalue { iN, i1 } %pair, 1
1767 // br i1 %success, label %atomicrmw.end, label %loop
1768 // atomicrmw.end:
1769 // [...]
1770 BasicBlock *ExitBB =
1771 BB->splitBasicBlock(Builder.GetInsertPoint(), "atomicrmw.end");
1772 BasicBlock *LoopBB = BasicBlock::Create(Ctx, "atomicrmw.start", F, ExitBB);
1773
1774 // The split call above "helpfully" added a branch at the end of BB (to the
1775 // wrong place), but we want a load. It's easiest to just remove
1776 // the branch entirely.
1777 std::prev(BB->end())->eraseFromParent();
1778 Builder.SetInsertPoint(BB);
1779 LoadInst *InitLoaded = Builder.CreateAlignedLoad(ResultTy, Addr, AddrAlign);
1780 Builder.CreateBr(LoopBB);
1781
1782 // Start the main loop block now that we've taken care of the preliminaries.
1783 Builder.SetInsertPoint(LoopBB);
1784 PHINode *Loaded = Builder.CreatePHI(ResultTy, 2, "loaded");
1785 Loaded->addIncoming(InitLoaded, BB);
1786
1787 // The initial load must be atomic with the same synchronization scope
1788 // to avoid a data race with concurrent stores. If the instruction being
1789 // emulated is volatile, issue a volatile load.
1790 // addIncoming is done first so that any replaceAllUsesWith calls during
1791 // normalization correctly update the PHI incoming value.
1792 InitLoaded->setVolatile(IsVolatile);
1794 InitLoaded->setAtomic(AtomicOrdering::Monotonic, SSID);
1795 // The newly created load might need to be lowered further. Because it is
1796 // created in the same block as the atomicrmw, the AtomicExpand loop will
1797 // not process it again.
1798 processAtomicInstr(InitLoaded);
1799 }
1800
1801 Value *NewVal = PerformOp(Builder, Loaded);
1802
1803 Value *NewLoaded = nullptr;
1804 Value *Success = nullptr;
1805
1806 CreateCmpXchg(Builder, Addr, Loaded, NewVal, AddrAlign,
1807 MemOpOrder == AtomicOrdering::Unordered
1808 ? AtomicOrdering::Monotonic
1809 : MemOpOrder,
1810 SSID, IsVolatile, Success, NewLoaded, MetadataSrc);
1811 assert(Success && NewLoaded);
1812
1813 Loaded->addIncoming(NewLoaded, LoopBB);
1814
1815 Instruction *CondBr = Builder.CreateCondBr(Success, ExitBB, LoopBB);
1816
1817 // Atomic RMW expands to a cmpxchg loop, Since precise branch weights
1818 // cannot be easily determined here, we mark the branch as "unknown" (50/50)
1819 // to prevent misleading optimizations.
1821
1822 Builder.SetInsertPoint(ExitBB, ExitBB->begin());
1823 return NewLoaded;
1824}
1825
1826bool AtomicExpandImpl::tryExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) {
1827 unsigned MinCASSize = TLI->getMinCmpXchgSizeInBits() / 8;
1828 unsigned ValueSize = getAtomicOpSize(CI);
1829
1830 switch (TLI->shouldExpandAtomicCmpXchgInIR(CI)) {
1831 default:
1832 llvm_unreachable("Unhandled case in tryExpandAtomicCmpXchg");
1833 case TargetLoweringBase::AtomicExpansionKind::None:
1834 if (ValueSize < MinCASSize)
1835 return expandPartwordCmpXchg(CI);
1836 return false;
1837 case TargetLoweringBase::AtomicExpansionKind::LLSC: {
1838 return expandAtomicCmpXchg(CI);
1839 }
1840 case TargetLoweringBase::AtomicExpansionKind::MaskedIntrinsic:
1841 expandAtomicCmpXchgToMaskedIntrinsic(CI);
1842 return true;
1843 case TargetLoweringBase::AtomicExpansionKind::NotAtomic:
1844 return lowerAtomicCmpXchgInst(CI);
1845 case TargetLoweringBase::AtomicExpansionKind::CustomExpand: {
1846 TLI->emitExpandAtomicCmpXchg(CI);
1847 return true;
1848 }
1849 }
1850}
1851
1852bool AtomicExpandImpl::expandAtomicRMWToCmpXchg(
1853 AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg) {
1854 ReplacementIRBuilder Builder(AI, AI->getDataLayout());
1855 Builder.setIsFPConstrained(
1856 AI->getFunction()->hasFnAttribute(Attribute::StrictFP));
1857
1858 // FIXME: If FP exceptions are observable, we should force them off for the
1859 // loop for the FP atomics.
1860 Value *Loaded = AtomicExpandImpl::insertRMWCmpXchgLoop(
1861 Builder, AI->getType(), AI->getPointerOperand(), AI->getAlign(),
1862 AI->getOrdering(), AI->getSyncScopeID(), AI->isVolatile(),
1863 [&](IRBuilderBase &Builder, Value *Loaded) {
1864 return buildAtomicRMWValue(AI->getOperation(), Builder, Loaded,
1865 AI->getValOperand());
1866 },
1867 CreateCmpXchg, /*MetadataSrc=*/AI);
1868
1869 AI->replaceAllUsesWith(Loaded);
1870 AI->eraseFromParent();
1871 return true;
1872}
1873
1874// In order to use one of the sized library calls such as
1875// __atomic_fetch_add_4, the alignment must be sufficient, the size
1876// must be one of the potentially-specialized sizes, and the value
1877// type must actually exist in C on the target (otherwise, the
1878// function wouldn't actually be defined.)
1879static bool canUseSizedAtomicCall(unsigned Size, Align Alignment,
1880 const DataLayout &DL) {
1881 // TODO: "LargestSize" is an approximation for "largest type that
1882 // you can express in C". It seems to be the case that int128 is
1883 // supported on all 64-bit platforms, otherwise only up to 64-bit
1884 // integers are supported. If we get this wrong, then we'll try to
1885 // call a sized libcall that doesn't actually exist. There should
1886 // really be some more reliable way in LLVM of determining integer
1887 // sizes which are valid in the target's C ABI...
1888 unsigned LargestSize = DL.getLargestLegalIntTypeSizeInBits() >= 64 ? 16 : 8;
1889 return Alignment >= Size &&
1890 (Size == 1 || Size == 2 || Size == 4 || Size == 8 || Size == 16) &&
1891 Size <= LargestSize;
1892}
1893
1894void AtomicExpandImpl::expandAtomicLoadToLibcall(LoadInst *I) {
1895 static const RTLIB::Libcall Libcalls[6] = {
1896 RTLIB::ATOMIC_LOAD, RTLIB::ATOMIC_LOAD_1, RTLIB::ATOMIC_LOAD_2,
1897 RTLIB::ATOMIC_LOAD_4, RTLIB::ATOMIC_LOAD_8, RTLIB::ATOMIC_LOAD_16};
1898 unsigned Size = getAtomicOpSize(I);
1899
1900 bool Expanded = expandAtomicOpToLibcall(
1901 I, Size, I->getAlign(), I->getPointerOperand(), nullptr, nullptr,
1902 I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1903 if (!Expanded)
1904 handleUnsupportedAtomicSize(I, "atomic load");
1905}
1906
1907void AtomicExpandImpl::expandAtomicStoreToLibcall(StoreInst *I) {
1908 static const RTLIB::Libcall Libcalls[6] = {
1909 RTLIB::ATOMIC_STORE, RTLIB::ATOMIC_STORE_1, RTLIB::ATOMIC_STORE_2,
1910 RTLIB::ATOMIC_STORE_4, RTLIB::ATOMIC_STORE_8, RTLIB::ATOMIC_STORE_16};
1911 unsigned Size = getAtomicOpSize(I);
1912
1913 bool Expanded = expandAtomicOpToLibcall(
1914 I, Size, I->getAlign(), I->getPointerOperand(), I->getValueOperand(),
1915 nullptr, I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
1916 if (!Expanded)
1917 handleUnsupportedAtomicSize(I, "atomic store");
1918}
1919
1920void AtomicExpandImpl::expandAtomicCASToLibcall(AtomicCmpXchgInst *I,
1921 const Twine &AtomicOpName,
1922 Instruction *DiagnosticInst) {
1923 static const RTLIB::Libcall Libcalls[6] = {
1924 RTLIB::ATOMIC_COMPARE_EXCHANGE, RTLIB::ATOMIC_COMPARE_EXCHANGE_1,
1925 RTLIB::ATOMIC_COMPARE_EXCHANGE_2, RTLIB::ATOMIC_COMPARE_EXCHANGE_4,
1926 RTLIB::ATOMIC_COMPARE_EXCHANGE_8, RTLIB::ATOMIC_COMPARE_EXCHANGE_16};
1927 unsigned Size = getAtomicOpSize(I);
1928
1929 bool Expanded = expandAtomicOpToLibcall(
1930 I, Size, I->getAlign(), I->getPointerOperand(), I->getNewValOperand(),
1931 I->getCompareOperand(), I->getSuccessOrdering(), I->getFailureOrdering(),
1932 Libcalls);
1933 if (!Expanded)
1934 handleUnsupportedAtomicSize(I, AtomicOpName, DiagnosticInst);
1935}
1936
1938 static const RTLIB::Libcall LibcallsXchg[6] = {
1939 RTLIB::ATOMIC_EXCHANGE, RTLIB::ATOMIC_EXCHANGE_1,
1940 RTLIB::ATOMIC_EXCHANGE_2, RTLIB::ATOMIC_EXCHANGE_4,
1941 RTLIB::ATOMIC_EXCHANGE_8, RTLIB::ATOMIC_EXCHANGE_16};
1942 static const RTLIB::Libcall LibcallsAdd[6] = {
1943 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_ADD_1,
1944 RTLIB::ATOMIC_FETCH_ADD_2, RTLIB::ATOMIC_FETCH_ADD_4,
1945 RTLIB::ATOMIC_FETCH_ADD_8, RTLIB::ATOMIC_FETCH_ADD_16};
1946 static const RTLIB::Libcall LibcallsSub[6] = {
1947 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_SUB_1,
1948 RTLIB::ATOMIC_FETCH_SUB_2, RTLIB::ATOMIC_FETCH_SUB_4,
1949 RTLIB::ATOMIC_FETCH_SUB_8, RTLIB::ATOMIC_FETCH_SUB_16};
1950 static const RTLIB::Libcall LibcallsAnd[6] = {
1951 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_AND_1,
1952 RTLIB::ATOMIC_FETCH_AND_2, RTLIB::ATOMIC_FETCH_AND_4,
1953 RTLIB::ATOMIC_FETCH_AND_8, RTLIB::ATOMIC_FETCH_AND_16};
1954 static const RTLIB::Libcall LibcallsOr[6] = {
1955 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_OR_1,
1956 RTLIB::ATOMIC_FETCH_OR_2, RTLIB::ATOMIC_FETCH_OR_4,
1957 RTLIB::ATOMIC_FETCH_OR_8, RTLIB::ATOMIC_FETCH_OR_16};
1958 static const RTLIB::Libcall LibcallsXor[6] = {
1959 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_XOR_1,
1960 RTLIB::ATOMIC_FETCH_XOR_2, RTLIB::ATOMIC_FETCH_XOR_4,
1961 RTLIB::ATOMIC_FETCH_XOR_8, RTLIB::ATOMIC_FETCH_XOR_16};
1962 static const RTLIB::Libcall LibcallsNand[6] = {
1963 RTLIB::UNKNOWN_LIBCALL, RTLIB::ATOMIC_FETCH_NAND_1,
1964 RTLIB::ATOMIC_FETCH_NAND_2, RTLIB::ATOMIC_FETCH_NAND_4,
1965 RTLIB::ATOMIC_FETCH_NAND_8, RTLIB::ATOMIC_FETCH_NAND_16};
1966
1967 switch (Op) {
1969 llvm_unreachable("Should not have BAD_BINOP.");
1971 return ArrayRef(LibcallsXchg);
1972 case AtomicRMWInst::Add:
1973 return ArrayRef(LibcallsAdd);
1974 case AtomicRMWInst::Sub:
1975 return ArrayRef(LibcallsSub);
1976 case AtomicRMWInst::And:
1977 return ArrayRef(LibcallsAnd);
1978 case AtomicRMWInst::Or:
1979 return ArrayRef(LibcallsOr);
1980 case AtomicRMWInst::Xor:
1981 return ArrayRef(LibcallsXor);
1983 return ArrayRef(LibcallsNand);
1984 case AtomicRMWInst::Max:
1985 case AtomicRMWInst::Min:
2000 // No atomic libcalls are available for these.
2001 return {};
2002 }
2003 llvm_unreachable("Unexpected AtomicRMW operation.");
2004}
2005
2006void AtomicExpandImpl::expandAtomicRMWToLibcall(AtomicRMWInst *I) {
2007 ArrayRef<RTLIB::Libcall> Libcalls = GetRMWLibcall(I->getOperation());
2008
2009 unsigned Size = getAtomicOpSize(I);
2010
2011 bool Success = false;
2012 if (!Libcalls.empty())
2013 Success = expandAtomicOpToLibcall(
2014 I, Size, I->getAlign(), I->getPointerOperand(), I->getValOperand(),
2015 nullptr, I->getOrdering(), AtomicOrdering::NotAtomic, Libcalls);
2016
2017 // The expansion failed: either there were no libcalls at all for
2018 // the operation (min/max), or there were only size-specialized
2019 // libcalls (add/sub/etc) and we needed a generic. So, expand to a
2020 // CAS libcall, via a CAS loop, instead.
2021 if (!Success) {
2022 expandAtomicRMWToCmpXchg(
2023 I, [this, I](IRBuilderBase &Builder, Value *Addr, Value *Loaded,
2024 Value *NewVal, Align Alignment, AtomicOrdering MemOpOrder,
2025 SyncScope::ID SSID, bool IsVolatile, Value *&Success,
2026 Value *&NewLoaded, Instruction *MetadataSrc) {
2027 // Create the CAS instruction normally...
2028 AtomicCmpXchgInst *Pair = Builder.CreateAtomicCmpXchg(
2029 Addr, Loaded, NewVal, Alignment, MemOpOrder,
2031 Pair->setVolatile(IsVolatile);
2032 if (MetadataSrc)
2033 copyMetadataForAtomic(*Pair, *MetadataSrc);
2034
2035 Success = Builder.CreateExtractValue(Pair, 1, "success");
2036 NewLoaded = Builder.CreateExtractValue(Pair, 0, "newloaded");
2037
2038 // ...and then expand the CAS into a libcall.
2039 expandAtomicCASToLibcall(
2040 Pair,
2041 "atomicrmw " + AtomicRMWInst::getOperationName(I->getOperation()),
2042 MetadataSrc);
2043 });
2044 }
2045}
2046
2047// A helper routine for the above expandAtomic*ToLibcall functions.
2048//
2049// 'Libcalls' contains an array of enum values for the particular
2050// ATOMIC libcalls to be emitted. All of the other arguments besides
2051// 'I' are extracted from the Instruction subclass by the
2052// caller. Depending on the particular call, some will be null.
2053bool AtomicExpandImpl::expandAtomicOpToLibcall(
2054 Instruction *I, unsigned Size, Align Alignment, Value *PointerOperand,
2055 Value *ValueOperand, Value *CASExpected, AtomicOrdering Ordering,
2056 AtomicOrdering Ordering2, ArrayRef<RTLIB::Libcall> Libcalls) {
2057 assert(Libcalls.size() == 6);
2058
2059 LLVMContext &Ctx = I->getContext();
2060 Module *M = I->getModule();
2061 const DataLayout &DL = M->getDataLayout();
2062 IRBuilder<> Builder(I);
2063 IRBuilder<> AllocaBuilder(&I->getFunction()->getEntryBlock().front());
2064
2065 bool UseSizedLibcall = canUseSizedAtomicCall(Size, Alignment, DL);
2066 Type *SizedIntTy = Type::getIntNTy(Ctx, Size * 8);
2067
2068 if (M->getTargetTriple().isOSWindows() && M->getTargetTriple().isX86_64() &&
2069 Size == 16) {
2070 // x86_64 Windows passes i128 as an XMM vector; on return, it is in
2071 // XMM0, and as a parameter, it is passed indirectly. The generic lowering
2072 // rules handles this correctly if we pass it as a v2i64 rather than
2073 // i128. This is what Clang does in the frontend for such types as well
2074 // (see WinX86_64ABIInfo::classify in Clang).
2075 SizedIntTy = FixedVectorType::get(Type::getInt64Ty(Ctx), 2);
2076 }
2077
2078 const Align AllocaAlignment = DL.getPrefTypeAlign(SizedIntTy);
2079
2080 // TODO: the "order" argument type is "int", not int32. So
2081 // getInt32Ty may be wrong if the arch uses e.g. 16-bit ints.
2082 assert(Ordering != AtomicOrdering::NotAtomic && "expect atomic MO");
2083 Constant *OrderingVal =
2084 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(Ordering));
2085 Constant *Ordering2Val = nullptr;
2086 if (CASExpected) {
2087 assert(Ordering2 != AtomicOrdering::NotAtomic && "expect atomic MO");
2088 Ordering2Val =
2089 ConstantInt::get(Type::getInt32Ty(Ctx), (int)toCABI(Ordering2));
2090 }
2091 bool HasResult = I->getType() != Type::getVoidTy(Ctx);
2092
2093 RTLIB::Libcall RTLibType;
2094 if (UseSizedLibcall) {
2095 switch (Size) {
2096 case 1:
2097 RTLibType = Libcalls[1];
2098 break;
2099 case 2:
2100 RTLibType = Libcalls[2];
2101 break;
2102 case 4:
2103 RTLibType = Libcalls[3];
2104 break;
2105 case 8:
2106 RTLibType = Libcalls[4];
2107 break;
2108 case 16:
2109 RTLibType = Libcalls[5];
2110 break;
2111 }
2112 } else if (Libcalls[0] != RTLIB::UNKNOWN_LIBCALL) {
2113 RTLibType = Libcalls[0];
2114 } else {
2115 // Can't use sized function, and there's no generic for this
2116 // operation, so give up.
2117 return false;
2118 }
2119
2120 RTLIB::LibcallImpl LibcallImpl = LibcallLowering->getLibcallImpl(RTLibType);
2121 if (LibcallImpl == RTLIB::Unsupported) {
2122 // This target does not implement the requested atomic libcall so give up.
2123 return false;
2124 }
2125
2126 // Build up the function call. There's two kinds. First, the sized
2127 // variants. These calls are going to be one of the following (with
2128 // N=1,2,4,8,16):
2129 // iN __atomic_load_N(iN *ptr, int ordering)
2130 // void __atomic_store_N(iN *ptr, iN val, int ordering)
2131 // iN __atomic_{exchange|fetch_*}_N(iN *ptr, iN val, int ordering)
2132 // bool __atomic_compare_exchange_N(iN *ptr, iN *expected, iN desired,
2133 // int success_order, int failure_order)
2134 //
2135 // Note that these functions can be used for non-integer atomic
2136 // operations, the values just need to be bitcast to integers on the
2137 // way in and out.
2138 //
2139 // And, then, the generic variants. They look like the following:
2140 // void __atomic_load(size_t size, void *ptr, void *ret, int ordering)
2141 // void __atomic_store(size_t size, void *ptr, void *val, int ordering)
2142 // void __atomic_exchange(size_t size, void *ptr, void *val, void *ret,
2143 // int ordering)
2144 // bool __atomic_compare_exchange(size_t size, void *ptr, void *expected,
2145 // void *desired, int success_order,
2146 // int failure_order)
2147 //
2148 // The different signatures are built up depending on the
2149 // 'UseSizedLibcall', 'CASExpected', 'ValueOperand', and 'HasResult'
2150 // variables.
2151
2152 AllocaInst *AllocaCASExpected = nullptr;
2153 AllocaInst *AllocaValue = nullptr;
2154 AllocaInst *AllocaResult = nullptr;
2155
2156 Type *ResultTy;
2158 AttributeList Attr;
2159
2160 // 'size' argument.
2161 if (!UseSizedLibcall) {
2162 // Note, getIntPtrType is assumed equivalent to size_t.
2163 Args.push_back(ConstantInt::get(DL.getIntPtrType(Ctx), Size));
2164 }
2165
2166 // 'ptr' argument.
2167 // note: This assumes all address spaces share a common libfunc
2168 // implementation and that addresses are convertable. For systems without
2169 // that property, we'd need to extend this mechanism to support AS-specific
2170 // families of atomic intrinsics.
2171 Value *PtrVal = PointerOperand;
2172 PtrVal = Builder.CreateAddrSpaceCast(PtrVal, PointerType::getUnqual(Ctx));
2173 Args.push_back(PtrVal);
2174
2175 // 'expected' argument, if present.
2176 if (CASExpected) {
2177 AllocaCASExpected = AllocaBuilder.CreateAlloca(CASExpected->getType());
2178 AllocaCASExpected->setAlignment(AllocaAlignment);
2179 Builder.CreateLifetimeStart(AllocaCASExpected);
2180 Builder.CreateAlignedStore(CASExpected, AllocaCASExpected, AllocaAlignment);
2181 Args.push_back(AllocaCASExpected);
2182 }
2183
2184 // 'val' argument ('desired' for cas), if present.
2185 if (ValueOperand) {
2186 if (UseSizedLibcall) {
2187 Value *IntValue =
2188 Builder.CreateBitPreservingCastChain(DL, ValueOperand, SizedIntTy);
2189 Args.push_back(IntValue);
2190 } else {
2191 AllocaValue = AllocaBuilder.CreateAlloca(ValueOperand->getType());
2192 AllocaValue->setAlignment(AllocaAlignment);
2193 Builder.CreateLifetimeStart(AllocaValue);
2194 Builder.CreateAlignedStore(ValueOperand, AllocaValue, AllocaAlignment);
2195 Args.push_back(AllocaValue);
2196 }
2197 }
2198
2199 // 'ret' argument.
2200 if (!CASExpected && HasResult && !UseSizedLibcall) {
2201 AllocaResult = AllocaBuilder.CreateAlloca(I->getType());
2202 AllocaResult->setAlignment(AllocaAlignment);
2203 Builder.CreateLifetimeStart(AllocaResult);
2204 Args.push_back(AllocaResult);
2205 }
2206
2207 // 'ordering' ('success_order' for cas) argument.
2208 Args.push_back(OrderingVal);
2209
2210 // 'failure_order' argument, if present.
2211 if (Ordering2Val)
2212 Args.push_back(Ordering2Val);
2213
2214 // Now, the return type.
2215 if (CASExpected) {
2216 ResultTy = Type::getInt1Ty(Ctx);
2217 Attr = Attr.addRetAttribute(Ctx, Attribute::ZExt);
2218 } else if (HasResult && UseSizedLibcall)
2219 ResultTy = SizedIntTy;
2220 else
2221 ResultTy = Type::getVoidTy(Ctx);
2222
2223 // Done with setting up arguments and return types, create the call:
2225 for (Value *Arg : Args)
2226 ArgTys.push_back(Arg->getType());
2227 FunctionType *FnType = FunctionType::get(ResultTy, ArgTys, false);
2228 FunctionCallee LibcallFn = M->getOrInsertFunction(
2230 Attr);
2231 CallInst *Call = Builder.CreateCall(LibcallFn, Args);
2232 Call->setAttributes(Attr);
2233 Value *Result = Call;
2234
2235 // And then, extract the results...
2236 if (ValueOperand && !UseSizedLibcall)
2237 Builder.CreateLifetimeEnd(AllocaValue);
2238
2239 if (CASExpected) {
2240 // The final result from the CAS is {load of 'expected' alloca, bool result
2241 // from call}
2242 Type *FinalResultTy = I->getType();
2243 Value *V = PoisonValue::get(FinalResultTy);
2244 Value *ExpectedOut = Builder.CreateAlignedLoad(
2245 CASExpected->getType(), AllocaCASExpected, AllocaAlignment);
2246 Builder.CreateLifetimeEnd(AllocaCASExpected);
2247 V = Builder.CreateInsertValue(V, ExpectedOut, 0);
2248 V = Builder.CreateInsertValue(V, Result, 1);
2250 } else if (HasResult) {
2251 Value *V;
2252 if (UseSizedLibcall) {
2253 // Add bitcasts from Result's scalar type to I's <n x ptr> vector type
2254 auto *PtrTy = dyn_cast<PointerType>(I->getType()->getScalarType());
2255 auto *VTy = dyn_cast<VectorType>(I->getType());
2256 if (VTy && PtrTy && !Result->getType()->isVectorTy()) {
2257 unsigned AS = PtrTy->getAddressSpace();
2258 Value *BC = Builder.CreateBitCast(
2259 Result, VTy->getWithNewType(DL.getIntPtrType(Ctx, AS)));
2260 V = Builder.CreateIntToPtr(BC, I->getType());
2261 } else
2262 V = Builder.CreateBitOrPointerCast(Result, I->getType());
2263 } else {
2264 V = Builder.CreateAlignedLoad(I->getType(), AllocaResult,
2265 AllocaAlignment);
2266 Builder.CreateLifetimeEnd(AllocaResult);
2267 }
2268 I->replaceAllUsesWith(V);
2269 }
2270 I->eraseFromParent();
2271 return true;
2272}
#define Success
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 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< 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)
#define DEBUG_TYPE
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.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file provides utility for Memory Model Relaxation Annotations (MMRAs).
#define T
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file contains the declarations for profiling metadata utility functions.
const char * Msg
This file defines the SmallString class.
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
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),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
An instruction that atomically checks whether a specified value is in a memory location,...
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.
AtomicOrdering getFailureOrdering() const
Returns the failure ordering constraint of this cmpxchg instruction.
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isWeak() const
Return true if this cmpxchg may spuriously fail.
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
AtomicOrdering getSuccessOrdering() const
Returns the success ordering constraint of this cmpxchg instruction.
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this cmpxchg instruction.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
an instruction that atomically reads a memory location, combines it with another value,...
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
void setVolatile(bool V)
Specify whether this is a volatile RMW or not.
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ Add
*p = old + v
@ FAdd
*p = old + v
@ 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
@ Sub
*p = old - v
@ And
*p = old & v
@ Xor
*p = 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.
@ FSub
*p = old - v
@ 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.
@ Nand
*p = ~(old & v)
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 end()
Definition BasicBlock.h:474
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:461
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.
Definition BasicBlock.h:213
reverse_iterator rbegin()
Definition BasicBlock.h:477
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
InstListType::reverse_iterator reverse_iterator
Definition BasicBlock.h:172
reverse_iterator rend()
Definition BasicBlock.h:479
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.
Definition Constants.h:135
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.
Definition DataLayout.h:64
ArrayRef< unsigned > getIndices() const
unsigned getNumIndices() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:867
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
BasicBlockListType::iterator iterator
Definition Function.h:70
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:723
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Definition IRBuilder.h:1968
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2716
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)
Definition IRBuilder.h:1934
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Definition IRBuilder.h:1216
UnreachableInst * CreateUnreachable()
Definition IRBuilder.h:1358
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition IRBuilder.h:2709
BasicBlock::iterator GetInsertPoint() const
Definition IRBuilder.h:176
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2238
Value * CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr, FMFSource FMFSource={})
Definition IRBuilder.h:2277
BasicBlock * GetInsertBlock() const
Definition IRBuilder.h:175
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="")
Definition IRBuilder.h:2379
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Definition IRBuilder.h:1210
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2325
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Definition IRBuilder.h:2540
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:2375
void setIsFPConstrained(bool IsCon)
Enable/Disable use of constrained floating point math.
Definition IRBuilder.h:306
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2243
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition IRBuilder.h:1906
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1511
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Definition IRBuilder.h:2121
LLVMContext & getContext() const
Definition IRBuilder.h:177
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1570
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2233
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Definition IRBuilder.h:2554
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:181
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Definition IRBuilder.h:1953
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1592
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Definition IRBuilder.h:2248
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, bool Elementwise=false)
Definition IRBuilder.h:1981
Provides an 'InsertHelper' that calls a user-provided callback after performing the default insertion...
Definition IRBuilder.h:75
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
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.
Definition Type.cpp:348
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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.
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.
Metadata node.
Definition Metadata.h:1069
Record a mapping from subtarget to LibcallLoweringInfo.
const LibcallLoweringInfo & getLibcallLowering(const TargetSubtargetInfo &Subtarget) const
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:327
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...
Definition Pass.cpp:112
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.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
virtual Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const
Perform a store-conditional operation to Addr.
EVT getMemValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
virtual void emitBitTestAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a bit test atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
virtual bool shouldInsertFencesForAtomic(const Instruction *I) const
Whether AtomicExpandPass should automatically insert fences and reduce ordering for this atomic.
virtual AtomicOrdering atomicOperationOrderAfterFenceSplit(const Instruction *I) const
virtual void emitExpandAtomicCmpXchg(AtomicCmpXchgInst *CI) const
Perform a cmpxchg expansion using a target-specific method.
unsigned getMinCmpXchgSizeInBits() const
Returns the size of the smallest cmpxchg or ll/sc instruction the backend supports.
virtual Value * emitMaskedAtomicRMWIntrinsic(IRBuilderBase &Builder, AtomicRMWInst *AI, Value *AlignedAddr, Value *Incr, Value *Mask, Value *ShiftAmt, AtomicOrdering Ord) const
Perform a masked atomicrmw using a target-specific intrinsic.
virtual AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
virtual void emitExpandAtomicRMW(AtomicRMWInst *AI) const
Perform a atomicrmw expansion using a target-specific way.
virtual void emitAtomicCmpXchgNoStoreLLBalance(IRBuilderBase &Builder) const
virtual void emitExpandAtomicStore(StoreInst *SI) const
Perform a atomic store using a target-specific way.
virtual AtomicExpansionKind shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const
Returns how the given atomic atomicrmw should be cast by the IR-level AtomicExpand pass.
virtual bool shouldInsertTrailingSeqCstFenceForAtomicStore(const Instruction *I) const
Whether AtomicExpandPass should automatically insert a seq_cst trailing fence without reducing the or...
virtual AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
virtual Value * emitMaskedAtomicCmpXchgIntrinsic(IRBuilderBase &Builder, AtomicCmpXchgInst *CI, Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const
Perform a masked cmpxchg using a target-specific intrinsic.
virtual bool shouldIssueAtomicLoadForAtomicEmulationLoop(void) const
unsigned getMaxAtomicSizeInBitsSupported() const
Returns the maximum atomic operation size (in bits) supported by the backend.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
virtual void emitExpandAtomicLoad(LoadInst *LI) const
Perform a atomic load using a target-specific way.
virtual AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
virtual void emitCmpArithAtomicRMWIntrinsic(AtomicRMWInst *AI) const
Perform a atomicrmw which the result is only used by comparison, using a target-specific intrinsic.
virtual AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const
Returns how the given (atomic) store should be cast by the IR-level AtomicExpand pass into.
virtual Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
virtual AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const
Returns how the given (atomic) load should be cast by the IR-level AtomicExpand pass.
virtual Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const
Inserts in the IR a target-specific intrinsic specifying a fence.
virtual LoadInst * lowerIdempotentRMWIntoFencedLoad(AtomicRMWInst *RMWI) const
On some platforms, an AtomicRMW that never actually modifies the value (such as fetch_add of 0) can b...
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition Type.h:285
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:258
iterator_range< user_iterator > users()
Definition Value.h:426
bool use_empty() const
Definition Value.h:346
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
Changed
#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.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
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.
Definition Casting.h:643
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
AtomicOrdering
Atomic ordering for LLVM's memory model.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
LLVM_ABI bool lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Convert the given Cmpxchg into primitive load and compare.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
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...
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
Extended Value Type.
Definition ValueTypes.h:35
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
Definition ValueTypes.h:435
Matching combinators.
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.