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