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