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