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