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