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