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