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