139f15686SMatt Arsenault //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===// 239f15686SMatt Arsenault // 339f15686SMatt Arsenault // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 439f15686SMatt Arsenault // See https://llvm.org/LICENSE.txt for license information. 539f15686SMatt Arsenault // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 639f15686SMatt Arsenault // 739f15686SMatt Arsenault //===----------------------------------------------------------------------===// 839f15686SMatt Arsenault // 939f15686SMatt Arsenault // This pass lowers atomic intrinsics to non-atomic form for use in a known 1039f15686SMatt Arsenault // non-preemptible environment. 1139f15686SMatt Arsenault // 1239f15686SMatt Arsenault //===----------------------------------------------------------------------===// 1339f15686SMatt Arsenault 1439f15686SMatt Arsenault #include "llvm/Transforms/Scalar/LowerAtomicPass.h" 1539f15686SMatt Arsenault #include "llvm/IR/Function.h" 1639f15686SMatt Arsenault #include "llvm/InitializePasses.h" 1739f15686SMatt Arsenault #include "llvm/Pass.h" 1839f15686SMatt Arsenault #include "llvm/Transforms/Scalar.h" 1939f15686SMatt Arsenault #include "llvm/Transforms/Utils/LowerAtomic.h" 2039f15686SMatt Arsenault using namespace llvm; 2139f15686SMatt Arsenault 22*e390c229Spaperchalice #define DEBUG_TYPE "lower-atomic" 2339f15686SMatt Arsenault 2439f15686SMatt Arsenault static bool LowerFenceInst(FenceInst *FI) { 2539f15686SMatt Arsenault FI->eraseFromParent(); 2639f15686SMatt Arsenault return true; 2739f15686SMatt Arsenault } 2839f15686SMatt Arsenault 2939f15686SMatt Arsenault static bool LowerLoadInst(LoadInst *LI) { 3039f15686SMatt Arsenault LI->setAtomic(AtomicOrdering::NotAtomic); 3139f15686SMatt Arsenault return true; 3239f15686SMatt Arsenault } 3339f15686SMatt Arsenault 3439f15686SMatt Arsenault static bool LowerStoreInst(StoreInst *SI) { 3539f15686SMatt Arsenault SI->setAtomic(AtomicOrdering::NotAtomic); 3639f15686SMatt Arsenault return true; 3739f15686SMatt Arsenault } 3839f15686SMatt Arsenault 3939f15686SMatt Arsenault static bool runOnBasicBlock(BasicBlock &BB) { 4039f15686SMatt Arsenault bool Changed = false; 4139f15686SMatt Arsenault for (Instruction &Inst : make_early_inc_range(BB)) { 4239f15686SMatt Arsenault if (FenceInst *FI = dyn_cast<FenceInst>(&Inst)) 4339f15686SMatt Arsenault Changed |= LowerFenceInst(FI); 4439f15686SMatt Arsenault else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&Inst)) 4539f15686SMatt Arsenault Changed |= lowerAtomicCmpXchgInst(CXI); 4639f15686SMatt Arsenault else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&Inst)) 4739f15686SMatt Arsenault Changed |= lowerAtomicRMWInst(RMWI); 4839f15686SMatt Arsenault else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) { 4939f15686SMatt Arsenault if (LI->isAtomic()) 5039f15686SMatt Arsenault LowerLoadInst(LI); 5139f15686SMatt Arsenault } else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) { 5239f15686SMatt Arsenault if (SI->isAtomic()) 5339f15686SMatt Arsenault LowerStoreInst(SI); 5439f15686SMatt Arsenault } 5539f15686SMatt Arsenault } 5639f15686SMatt Arsenault return Changed; 5739f15686SMatt Arsenault } 5839f15686SMatt Arsenault 5939f15686SMatt Arsenault static bool lowerAtomics(Function &F) { 6039f15686SMatt Arsenault bool Changed = false; 6139f15686SMatt Arsenault for (BasicBlock &BB : F) { 6239f15686SMatt Arsenault Changed |= runOnBasicBlock(BB); 6339f15686SMatt Arsenault } 6439f15686SMatt Arsenault return Changed; 6539f15686SMatt Arsenault } 6639f15686SMatt Arsenault 6739f15686SMatt Arsenault PreservedAnalyses LowerAtomicPass::run(Function &F, FunctionAnalysisManager &) { 6839f15686SMatt Arsenault if (lowerAtomics(F)) 6939f15686SMatt Arsenault return PreservedAnalyses::none(); 7039f15686SMatt Arsenault return PreservedAnalyses::all(); 7139f15686SMatt Arsenault } 7239f15686SMatt Arsenault 7339f15686SMatt Arsenault namespace { 7439f15686SMatt Arsenault class LowerAtomicLegacyPass : public FunctionPass { 7539f15686SMatt Arsenault public: 7639f15686SMatt Arsenault static char ID; 7739f15686SMatt Arsenault 7839f15686SMatt Arsenault LowerAtomicLegacyPass() : FunctionPass(ID) { 7939f15686SMatt Arsenault initializeLowerAtomicLegacyPassPass(*PassRegistry::getPassRegistry()); 8039f15686SMatt Arsenault } 8139f15686SMatt Arsenault 8239f15686SMatt Arsenault bool runOnFunction(Function &F) override { 8339f15686SMatt Arsenault // Don't skip optnone functions; atomics still need to be lowered. 8439f15686SMatt Arsenault FunctionAnalysisManager DummyFAM; 8539f15686SMatt Arsenault auto PA = Impl.run(F, DummyFAM); 8639f15686SMatt Arsenault return !PA.areAllPreserved(); 8739f15686SMatt Arsenault } 8839f15686SMatt Arsenault 8939f15686SMatt Arsenault private: 9039f15686SMatt Arsenault LowerAtomicPass Impl; 9139f15686SMatt Arsenault }; 9239f15686SMatt Arsenault } 9339f15686SMatt Arsenault 9439f15686SMatt Arsenault char LowerAtomicLegacyPass::ID = 0; 9539f15686SMatt Arsenault INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic", 9639f15686SMatt Arsenault "Lower atomic intrinsics to non-atomic form", false, false) 9739f15686SMatt Arsenault 9839f15686SMatt Arsenault Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); } 99