LLVM API Documentation

LowerAtomic.cpp
Go to the documentation of this file.
00001 //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This pass lowers atomic intrinsics to non-atomic form for use in a known
00011 // non-preemptible environment.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Transforms/Scalar.h"
00016 #include "llvm/IR/Function.h"
00017 #include "llvm/IR/IRBuilder.h"
00018 #include "llvm/IR/IntrinsicInst.h"
00019 #include "llvm/Pass.h"
00020 using namespace llvm;
00021 
00022 #define DEBUG_TYPE "loweratomic"
00023 
00024 static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
00025   IRBuilder<> Builder(CXI->getParent(), CXI);
00026   Value *Ptr = CXI->getPointerOperand();
00027   Value *Cmp = CXI->getCompareOperand();
00028   Value *Val = CXI->getNewValOperand();
00029 
00030   LoadInst *Orig = Builder.CreateLoad(Ptr);
00031   Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
00032   Value *Res = Builder.CreateSelect(Equal, Val, Orig);
00033   Builder.CreateStore(Res, Ptr);
00034 
00035   CXI->replaceAllUsesWith(Orig);
00036   CXI->eraseFromParent();
00037   return true;
00038 }
00039 
00040 static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) {
00041   IRBuilder<> Builder(RMWI->getParent(), RMWI);
00042   Value *Ptr = RMWI->getPointerOperand();
00043   Value *Val = RMWI->getValOperand();
00044 
00045   LoadInst *Orig = Builder.CreateLoad(Ptr);
00046   Value *Res = NULL;
00047 
00048   switch (RMWI->getOperation()) {
00049   default: llvm_unreachable("Unexpected RMW operation");
00050   case AtomicRMWInst::Xchg:
00051     Res = Val;
00052     break;
00053   case AtomicRMWInst::Add:
00054     Res = Builder.CreateAdd(Orig, Val);
00055     break;
00056   case AtomicRMWInst::Sub:
00057     Res = Builder.CreateSub(Orig, Val);
00058     break;
00059   case AtomicRMWInst::And:
00060     Res = Builder.CreateAnd(Orig, Val);
00061     break;
00062   case AtomicRMWInst::Nand:
00063     Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val));
00064     break;
00065   case AtomicRMWInst::Or:
00066     Res = Builder.CreateOr(Orig, Val);
00067     break;
00068   case AtomicRMWInst::Xor:
00069     Res = Builder.CreateXor(Orig, Val);
00070     break;
00071   case AtomicRMWInst::Max:
00072     Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
00073                                Val, Orig);
00074     break;
00075   case AtomicRMWInst::Min:
00076     Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
00077                                Orig, Val);
00078     break;
00079   case AtomicRMWInst::UMax:
00080     Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
00081                                Val, Orig);
00082     break;
00083   case AtomicRMWInst::UMin:
00084     Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
00085                                Orig, Val);
00086     break;
00087   }
00088   Builder.CreateStore(Res, Ptr);
00089   RMWI->replaceAllUsesWith(Orig);
00090   RMWI->eraseFromParent();
00091   return true;
00092 }
00093 
00094 static bool LowerFenceInst(FenceInst *FI) {
00095   FI->eraseFromParent();
00096   return true;
00097 }
00098 
00099 static bool LowerLoadInst(LoadInst *LI) {
00100   LI->setAtomic(NotAtomic);
00101   return true;
00102 }
00103 
00104 static bool LowerStoreInst(StoreInst *SI) {
00105   SI->setAtomic(NotAtomic);
00106   return true;
00107 }
00108 
00109 namespace {
00110   struct LowerAtomic : public BasicBlockPass {
00111     static char ID;
00112     LowerAtomic() : BasicBlockPass(ID) {
00113       initializeLowerAtomicPass(*PassRegistry::getPassRegistry());
00114     }
00115     bool runOnBasicBlock(BasicBlock &BB) override {
00116       if (skipOptnoneFunction(BB))
00117         return false;
00118       bool Changed = false;
00119       for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
00120         Instruction *Inst = DI++;
00121         if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
00122           Changed |= LowerFenceInst(FI);
00123         else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst))
00124           Changed |= LowerAtomicCmpXchgInst(CXI);
00125         else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst))
00126           Changed |= LowerAtomicRMWInst(RMWI);
00127         else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
00128           if (LI->isAtomic())
00129             LowerLoadInst(LI);
00130         } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
00131           if (SI->isAtomic())
00132             LowerStoreInst(SI);
00133         }
00134       }
00135       return Changed;
00136     }
00137   };
00138 }
00139 
00140 char LowerAtomic::ID = 0;
00141 INITIALIZE_PASS(LowerAtomic, "loweratomic",
00142                 "Lower atomic intrinsics to non-atomic form",
00143                 false, false)
00144 
00145 Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); }