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