LowerAtomic.cpp revision 218893
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/Function.h" 18#include "llvm/IntrinsicInst.h" 19#include "llvm/Pass.h" 20#include "llvm/Support/IRBuilder.h" 21using namespace llvm; 22 23static bool LowerAtomicIntrinsic(IntrinsicInst *II) { 24 IRBuilder<> Builder(II->getParent(), II); 25 unsigned IID = II->getIntrinsicID(); 26 switch (IID) { 27 case Intrinsic::memory_barrier: 28 break; 29 30 case Intrinsic::atomic_load_add: 31 case Intrinsic::atomic_load_sub: 32 case Intrinsic::atomic_load_and: 33 case Intrinsic::atomic_load_nand: 34 case Intrinsic::atomic_load_or: 35 case Intrinsic::atomic_load_xor: 36 case Intrinsic::atomic_load_max: 37 case Intrinsic::atomic_load_min: 38 case Intrinsic::atomic_load_umax: 39 case Intrinsic::atomic_load_umin: { 40 Value *Ptr = II->getArgOperand(0), *Delta = II->getArgOperand(1); 41 42 LoadInst *Orig = Builder.CreateLoad(Ptr); 43 Value *Res = NULL; 44 switch (IID) { 45 default: assert(0 && "Unrecognized atomic modify operation"); 46 case Intrinsic::atomic_load_add: 47 Res = Builder.CreateAdd(Orig, Delta); 48 break; 49 case Intrinsic::atomic_load_sub: 50 Res = Builder.CreateSub(Orig, Delta); 51 break; 52 case Intrinsic::atomic_load_and: 53 Res = Builder.CreateAnd(Orig, Delta); 54 break; 55 case Intrinsic::atomic_load_nand: 56 Res = Builder.CreateNot(Builder.CreateAnd(Orig, Delta)); 57 break; 58 case Intrinsic::atomic_load_or: 59 Res = Builder.CreateOr(Orig, Delta); 60 break; 61 case Intrinsic::atomic_load_xor: 62 Res = Builder.CreateXor(Orig, Delta); 63 break; 64 case Intrinsic::atomic_load_max: 65 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Delta), 66 Delta, Orig); 67 break; 68 case Intrinsic::atomic_load_min: 69 Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Delta), 70 Orig, Delta); 71 break; 72 case Intrinsic::atomic_load_umax: 73 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Delta), 74 Delta, Orig); 75 break; 76 case Intrinsic::atomic_load_umin: 77 Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Delta), 78 Orig, Delta); 79 break; 80 } 81 Builder.CreateStore(Res, Ptr); 82 83 II->replaceAllUsesWith(Orig); 84 break; 85 } 86 87 case Intrinsic::atomic_swap: { 88 Value *Ptr = II->getArgOperand(0), *Val = II->getArgOperand(1); 89 LoadInst *Orig = Builder.CreateLoad(Ptr); 90 Builder.CreateStore(Val, Ptr); 91 II->replaceAllUsesWith(Orig); 92 break; 93 } 94 95 case Intrinsic::atomic_cmp_swap: { 96 Value *Ptr = II->getArgOperand(0), *Cmp = II->getArgOperand(1); 97 Value *Val = II->getArgOperand(2); 98 99 LoadInst *Orig = Builder.CreateLoad(Ptr); 100 Value *Equal = Builder.CreateICmpEQ(Orig, Cmp); 101 Value *Res = Builder.CreateSelect(Equal, Val, Orig); 102 Builder.CreateStore(Res, Ptr); 103 II->replaceAllUsesWith(Orig); 104 break; 105 } 106 107 default: 108 return false; 109 } 110 111 assert(II->use_empty() && 112 "Lowering should have eliminated any uses of the intrinsic call!"); 113 II->eraseFromParent(); 114 115 return true; 116} 117 118namespace { 119 struct LowerAtomic : public BasicBlockPass { 120 static char ID; 121 LowerAtomic() : BasicBlockPass(ID) { 122 initializeLowerAtomicPass(*PassRegistry::getPassRegistry()); 123 } 124 bool runOnBasicBlock(BasicBlock &BB) { 125 bool Changed = false; 126 for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) 127 if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(DI++)) 128 Changed |= LowerAtomicIntrinsic(II); 129 return Changed; 130 } 131 }; 132} 133 134char LowerAtomic::ID = 0; 135INITIALIZE_PASS(LowerAtomic, "loweratomic", 136 "Lower atomic intrinsics to non-atomic form", 137 false, false) 138 139Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); } 140