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