LLVM API Documentation
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) { 00115 bool Changed = false; 00116 for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) { 00117 Instruction *Inst = DI++; 00118 if (FenceInst *FI = dyn_cast<FenceInst>(Inst)) 00119 Changed |= LowerFenceInst(FI); 00120 else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst)) 00121 Changed |= LowerAtomicCmpXchgInst(CXI); 00122 else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst)) 00123 Changed |= LowerAtomicRMWInst(RMWI); 00124 else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { 00125 if (LI->isAtomic()) 00126 LowerLoadInst(LI); 00127 } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { 00128 if (SI->isAtomic()) 00129 LowerStoreInst(SI); 00130 } 00131 } 00132 return Changed; 00133 } 00134 }; 00135 } 00136 00137 char LowerAtomic::ID = 0; 00138 INITIALIZE_PASS(LowerAtomic, "loweratomic", 00139 "Lower atomic intrinsics to non-atomic form", 00140 false, false) 00141 00142 Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); }