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