xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/LowerAtomicPass.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This pass lowers atomic intrinsics to non-atomic form for use in a known
1081ad6265SDimitry Andric // non-preemptible environment.
1181ad6265SDimitry Andric //
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "llvm/Transforms/Scalar/LowerAtomicPass.h"
1581ad6265SDimitry Andric #include "llvm/IR/Function.h"
1681ad6265SDimitry Andric #include "llvm/IR/IRBuilder.h"
1781ad6265SDimitry Andric #include "llvm/InitializePasses.h"
1881ad6265SDimitry Andric #include "llvm/Pass.h"
1981ad6265SDimitry Andric #include "llvm/Transforms/Scalar.h"
2081ad6265SDimitry Andric #include "llvm/Transforms/Utils/LowerAtomic.h"
2181ad6265SDimitry Andric using namespace llvm;
2281ad6265SDimitry Andric 
23*0fca6ea1SDimitry Andric #define DEBUG_TYPE "lower-atomic"
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric static bool LowerFenceInst(FenceInst *FI) {
2681ad6265SDimitry Andric   FI->eraseFromParent();
2781ad6265SDimitry Andric   return true;
2881ad6265SDimitry Andric }
2981ad6265SDimitry Andric 
3081ad6265SDimitry Andric static bool LowerLoadInst(LoadInst *LI) {
3181ad6265SDimitry Andric   LI->setAtomic(AtomicOrdering::NotAtomic);
3281ad6265SDimitry Andric   return true;
3381ad6265SDimitry Andric }
3481ad6265SDimitry Andric 
3581ad6265SDimitry Andric static bool LowerStoreInst(StoreInst *SI) {
3681ad6265SDimitry Andric   SI->setAtomic(AtomicOrdering::NotAtomic);
3781ad6265SDimitry Andric   return true;
3881ad6265SDimitry Andric }
3981ad6265SDimitry Andric 
4081ad6265SDimitry Andric static bool runOnBasicBlock(BasicBlock &BB) {
4181ad6265SDimitry Andric   bool Changed = false;
4281ad6265SDimitry Andric   for (Instruction &Inst : make_early_inc_range(BB)) {
4381ad6265SDimitry Andric     if (FenceInst *FI = dyn_cast<FenceInst>(&Inst))
4481ad6265SDimitry Andric       Changed |= LowerFenceInst(FI);
4581ad6265SDimitry Andric     else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&Inst))
4681ad6265SDimitry Andric       Changed |= lowerAtomicCmpXchgInst(CXI);
4781ad6265SDimitry Andric     else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&Inst))
4881ad6265SDimitry Andric       Changed |= lowerAtomicRMWInst(RMWI);
4981ad6265SDimitry Andric     else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) {
5081ad6265SDimitry Andric       if (LI->isAtomic())
5181ad6265SDimitry Andric         LowerLoadInst(LI);
5281ad6265SDimitry Andric     } else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) {
5381ad6265SDimitry Andric       if (SI->isAtomic())
5481ad6265SDimitry Andric         LowerStoreInst(SI);
5581ad6265SDimitry Andric     }
5681ad6265SDimitry Andric   }
5781ad6265SDimitry Andric   return Changed;
5881ad6265SDimitry Andric }
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric static bool lowerAtomics(Function &F) {
6181ad6265SDimitry Andric   bool Changed = false;
6281ad6265SDimitry Andric   for (BasicBlock &BB : F) {
6381ad6265SDimitry Andric     Changed |= runOnBasicBlock(BB);
6481ad6265SDimitry Andric   }
6581ad6265SDimitry Andric   return Changed;
6681ad6265SDimitry Andric }
6781ad6265SDimitry Andric 
6881ad6265SDimitry Andric PreservedAnalyses LowerAtomicPass::run(Function &F, FunctionAnalysisManager &) {
6981ad6265SDimitry Andric   if (lowerAtomics(F))
7081ad6265SDimitry Andric     return PreservedAnalyses::none();
7181ad6265SDimitry Andric   return PreservedAnalyses::all();
7281ad6265SDimitry Andric }
7381ad6265SDimitry Andric 
7481ad6265SDimitry Andric namespace {
7581ad6265SDimitry Andric class LowerAtomicLegacyPass : public FunctionPass {
7681ad6265SDimitry Andric public:
7781ad6265SDimitry Andric   static char ID;
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric   LowerAtomicLegacyPass() : FunctionPass(ID) {
8081ad6265SDimitry Andric     initializeLowerAtomicLegacyPassPass(*PassRegistry::getPassRegistry());
8181ad6265SDimitry Andric   }
8281ad6265SDimitry Andric 
8381ad6265SDimitry Andric   bool runOnFunction(Function &F) override {
8481ad6265SDimitry Andric     // Don't skip optnone functions; atomics still need to be lowered.
8581ad6265SDimitry Andric     FunctionAnalysisManager DummyFAM;
8681ad6265SDimitry Andric     auto PA = Impl.run(F, DummyFAM);
8781ad6265SDimitry Andric     return !PA.areAllPreserved();
8881ad6265SDimitry Andric   }
8981ad6265SDimitry Andric 
9081ad6265SDimitry Andric private:
9181ad6265SDimitry Andric   LowerAtomicPass Impl;
9281ad6265SDimitry Andric   };
9381ad6265SDimitry Andric }
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric char LowerAtomicLegacyPass::ID = 0;
9681ad6265SDimitry Andric INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic",
9781ad6265SDimitry Andric                 "Lower atomic intrinsics to non-atomic form", false, false)
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); }
100