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