1//===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
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 pass lowers atomic intrinsics to non-atomic form for use in a known
10// non-preemptible environment.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
15#include "llvm/IR/Function.h"
16#include "llvm/InitializePasses.h"
17#include "llvm/Pass.h"
18#include "llvm/Transforms/Scalar.h"
19#include "llvm/Transforms/Utils/LowerAtomic.h"
20using namespace llvm;
21
22#define DEBUG_TYPE "lower-atomic"
23
24static bool LowerFenceInst(FenceInst *FI) {
25 FI->eraseFromParent();
26 return true;
27}
28
29static bool LowerLoadInst(LoadInst *LI) {
30 LI->setAtomic(Ordering: AtomicOrdering::NotAtomic);
31 LI->setElementwise(false);
32 return true;
33}
34
35static bool LowerStoreInst(StoreInst *SI) {
36 SI->setAtomic(Ordering: AtomicOrdering::NotAtomic);
37 SI->setElementwise(false);
38 return true;
39}
40
41static bool runOnBasicBlock(BasicBlock &BB) {
42 bool Changed = false;
43 for (Instruction &Inst : make_early_inc_range(Range&: BB)) {
44 if (FenceInst *FI = dyn_cast<FenceInst>(Val: &Inst))
45 Changed |= LowerFenceInst(FI);
46 else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Val: &Inst))
47 Changed |= lowerAtomicCmpXchgInst(CXI);
48 else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Val: &Inst))
49 Changed |= lowerAtomicRMWInst(RMWI);
50 else if (LoadInst *LI = dyn_cast<LoadInst>(Val: &Inst)) {
51 if (LI->isAtomic())
52 LowerLoadInst(LI);
53 } else if (StoreInst *SI = dyn_cast<StoreInst>(Val: &Inst)) {
54 if (SI->isAtomic())
55 LowerStoreInst(SI);
56 }
57 }
58 return Changed;
59}
60
61static bool lowerAtomics(Function &F) {
62 bool Changed = false;
63 for (BasicBlock &BB : F) {
64 Changed |= runOnBasicBlock(BB);
65 }
66 return Changed;
67}
68
69PreservedAnalyses LowerAtomicPass::run(Function &F, FunctionAnalysisManager &) {
70 if (lowerAtomics(F))
71 return PreservedAnalyses::none();
72 return PreservedAnalyses::all();
73}
74
75namespace {
76class LowerAtomicLegacyPass : public FunctionPass {
77public:
78 static char ID;
79
80 LowerAtomicLegacyPass() : FunctionPass(ID) {
81 initializeLowerAtomicLegacyPassPass(*PassRegistry::getPassRegistry());
82 }
83
84 bool runOnFunction(Function &F) override {
85 // Don't skip optnone functions; atomics still need to be lowered.
86 FunctionAnalysisManager DummyFAM;
87 auto PA = Impl.run(F, DummyFAM);
88 return !PA.areAllPreserved();
89 }
90
91private:
92 LowerAtomicPass Impl;
93 };
94}
95
96char LowerAtomicLegacyPass::ID = 0;
97INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic",
98 "Lower atomic intrinsics to non-atomic form", false, false)
99
100Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); }
101