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