LowerAtomic.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This pass lowers atomic intrinsics to non-atomic form for use in a known 11// non-preemptible environment. 12// 13//===----------------------------------------------------------------------===// 14 15#define DEBUG_TYPE "loweratomic" 16#include "llvm/Transforms/Scalar.h" 17#include "llvm/IR/Function.h" 18#include "llvm/IR/IRBuilder.h" 19#include "llvm/IR/IntrinsicInst.h" 20#include "llvm/Pass.h" 21using namespace llvm; 22 23static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) { 24 IRBuilder<> Builder(CXI->getParent(), CXI); 25 Value *Ptr = CXI->getPointerOperand(); 26 Value *Cmp = CXI->getCompareOperand(); 27 Value *Val = CXI->getNewValOperand(); 28 29 LoadInst *Orig = Builder.CreateLoad(Ptr); 30 Value *Equal = Builder.CreateICmpEQ(Orig, Cmp); 31 Value *Res = Builder.CreateSelect(Equal, Val, Orig); 32 Builder.CreateStore(Res, Ptr); 33 34 CXI->replaceAllUsesWith(Orig); 35 CXI->eraseFromParent(); 36 return true; 37} 38 39static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) { 40 IRBuilder<> Builder(RMWI->getParent(), RMWI); 41 Value *Ptr = RMWI->getPointerOperand(); 42 Value *Val = RMWI->getValOperand(); 43 44 LoadInst *Orig = Builder.CreateLoad(Ptr); 45 Value *Res = NULL; 46 47 switch (RMWI->getOperation()) { 48 default: llvm_unreachable("Unexpected RMW operation"); 49 case AtomicRMWInst::Xchg: 50 Res = Val; 51 break; 52 case AtomicRMWInst::Add: 53 Res = Builder.CreateAdd(Orig, Val); 54 break; 55 case AtomicRMWInst::Sub: 56 Res = Builder.CreateSub(Orig, Val); 57 break; 58 case AtomicRMWInst::And: 59 Res = Builder.CreateAnd(Orig, Val); 60 break; 61 case AtomicRMWInst::Nand: 62 Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val)); 63 break; 64 case AtomicRMWInst::Or: 65 Res = Builder.CreateOr(Orig, Val); 66 break; 67 case AtomicRMWInst::Xor: 68 Res = Builder.CreateXor(Orig, Val); 69 break; 70 case AtomicRMWInst::Max: 71 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val), 72 Val, Orig); 73 break; 74 case AtomicRMWInst::Min: 75 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val), 76 Orig, Val); 77 break; 78 case AtomicRMWInst::UMax: 79 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val), 80 Val, Orig); 81 break; 82 case AtomicRMWInst::UMin: 83 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val), 84 Orig, Val); 85 break; 86 } 87 Builder.CreateStore(Res, Ptr); 88 RMWI->replaceAllUsesWith(Orig); 89 RMWI->eraseFromParent(); 90 return true; 91} 92 93static bool LowerFenceInst(FenceInst *FI) { 94 FI->eraseFromParent(); 95 return true; 96} 97 98static bool LowerLoadInst(LoadInst *LI) { 99 LI->setAtomic(NotAtomic); 100 return true; 101} 102 103static bool LowerStoreInst(StoreInst *SI) { 104 SI->setAtomic(NotAtomic); 105 return true; 106} 107 108namespace { 109 struct LowerAtomic : public BasicBlockPass { 110 static char ID; 111 LowerAtomic() : BasicBlockPass(ID) { 112 initializeLowerAtomicPass(*PassRegistry::getPassRegistry()); 113 } 114 bool runOnBasicBlock(BasicBlock &BB) override { 115 if (skipOptnoneFunction(BB)) 116 return false; 117 bool Changed = false; 118 for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) { 119 Instruction *Inst = DI++; 120 if (FenceInst *FI = dyn_cast<FenceInst>(Inst)) 121 Changed |= LowerFenceInst(FI); 122 else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst)) 123 Changed |= LowerAtomicCmpXchgInst(CXI); 124 else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst)) 125 Changed |= LowerAtomicRMWInst(RMWI); 126 else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { 127 if (LI->isAtomic()) 128 LowerLoadInst(LI); 129 } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { 130 if (SI->isAtomic()) 131 LowerStoreInst(SI); 132 } 133 } 134 return Changed; 135 } 136 }; 137} 138 139char LowerAtomic::ID = 0; 140INITIALIZE_PASS(LowerAtomic, "loweratomic", 141 "Lower atomic intrinsics to non-atomic form", 142 false, false) 143 144Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); } 145