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 #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(); }