LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LowerAtomic.cpp
Go to the documentation of this file.
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"
21 using namespace llvm;
22 
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 
39 static 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");
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;
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;
79  Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
80  Val, Orig);
81  break;
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 
93 static bool LowerFenceInst(FenceInst *FI) {
94  FI->eraseFromParent();
95  return true;
96 }
97 
98 static bool LowerLoadInst(LoadInst *LI) {
99  LI->setAtomic(NotAtomic);
100  return true;
101 }
102 
103 static bool LowerStoreInst(StoreInst *SI) {
104  SI->setAtomic(NotAtomic);
105  return true;
106 }
107 
108 namespace {
109  struct LowerAtomic : public BasicBlockPass {
110  static char ID;
111  LowerAtomic() : BasicBlockPass(ID) {
113  }
114  bool runOnBasicBlock(BasicBlock &BB) {
115  bool Changed = false;
116  for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
117  Instruction *Inst = DI++;
118  if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
119  Changed |= LowerFenceInst(FI);
120  else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst))
121  Changed |= LowerAtomicCmpXchgInst(CXI);
122  else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst))
123  Changed |= LowerAtomicRMWInst(RMWI);
124  else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
125  if (LI->isAtomic())
126  LowerLoadInst(LI);
127  } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
128  if (SI->isAtomic())
129  LowerStoreInst(SI);
130  }
131  }
132  return Changed;
133  }
134  };
135 }
136 
137 char LowerAtomic::ID = 0;
138 INITIALIZE_PASS(LowerAtomic, "loweratomic",
139  "Lower atomic intrinsics to non-atomic form",
140  false, false)
141 
142 Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); }
static PassRegistry * getPassRegistry()
*p = old <signed v ? old : v
Definition: Instructions.h:583
*p = old <unsigned v ? old : v
Definition: Instructions.h:587
static bool LowerLoadInst(LoadInst *LI)
Definition: LowerAtomic.cpp:98
*p = old >unsigned v ? old : v
Definition: Instructions.h:585
static bool LowerFenceInst(FenceInst *FI)
Definition: LowerAtomic.cpp:93
*p = old >signed v ? old : v
Definition: Instructions.h:581
LoopInfoBase< BlockT, LoopT > * LI
Definition: LoopInfoImpl.h:411
iterator begin()
Definition: BasicBlock.h:193
#define llvm_unreachable(msg)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:421
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
Definition: Instructions.h:212
static bool LowerStoreInst(StoreInst *SI)
void replaceAllUsesWith(Value *V)
Definition: Value.cpp:303
LLVM Basic Block Representation.
Definition: BasicBlock.h:72
static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI)
Definition: LowerAtomic.cpp:39
void initializeLowerAtomicPass(PassRegistry &)
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
Definition: Instructions.h:332
Value * getValOperand()
Definition: Instructions.h:662
iterator end()
Definition: BasicBlock.h:195
Pass * createLowerAtomicPass()
BinOp getOperation() const
Definition: Instructions.h:605
Value * getPointerOperand()
Definition: Instructions.h:658
INITIALIZE_PASS(LowerAtomic,"loweratomic","Lower atomic intrinsics to non-atomic form", false, false) Pass *llvm
LLVM Value Representation.
Definition: Value.h:66
static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Definition: LowerAtomic.cpp:23
const BasicBlock * getParent() const
Definition: Instruction.h:52