blob: 8ced4946c83225ffa594ca1b13f098225f314ac1 [file] [log] [blame]
Peter Collingbourne3bababf2010-08-03 16:19:16 +00001//===- 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"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000017#include "llvm/IR/Function.h"
18#include "llvm/IR/IRBuilder.h"
19#include "llvm/IR/IntrinsicInst.h"
Peter Collingbourne3bababf2010-08-03 16:19:16 +000020#include "llvm/Pass.h"
Peter Collingbourne3bababf2010-08-03 16:19:16 +000021using namespace llvm;
22
Benjamin Kramera67f14b2011-08-19 01:42:18 +000023static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
Eli Friedman55ba8162011-07-29 03:05:32 +000024 IRBuilder<> Builder(CXI->getParent(), CXI);
25 Value *Ptr = CXI->getPointerOperand();
26 Value *Cmp = CXI->getCompareOperand();
27 Value *Val = CXI->getNewValOperand();
Nadav Rotema94d6e82012-07-24 10:51:42 +000028
Eli Friedman55ba8162011-07-29 03:05:32 +000029 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);
Nadav Rotema94d6e82012-07-24 10:51:42 +000033
Eli Friedman55ba8162011-07-29 03:05:32 +000034 CXI->replaceAllUsesWith(Orig);
35 CXI->eraseFromParent();
36 return true;
37}
38
Benjamin Kramera67f14b2011-08-19 01:42:18 +000039static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) {
Eli Friedman55ba8162011-07-29 03:05:32 +000040 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
Eli Friedman8a552bb2011-07-27 01:08:30 +000093static bool LowerFenceInst(FenceInst *FI) {
94 FI->eraseFromParent();
95 return true;
96}
97
Eli Friedman21006d42011-08-09 23:02:53 +000098static 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
Chris Lattnerbdabacd2010-09-05 20:10:47 +0000108namespace {
109 struct LowerAtomic : public BasicBlockPass {
110 static char ID;
Owen Anderson081c34b2010-10-19 17:21:58 +0000111 LowerAtomic() : BasicBlockPass(ID) {
112 initializeLowerAtomicPass(*PassRegistry::getPassRegistry());
113 }
Chris Lattnerbdabacd2010-09-05 20:10:47 +0000114 bool runOnBasicBlock(BasicBlock &BB) {
115 bool Changed = false;
Eli Friedman8a552bb2011-07-27 01:08:30 +0000116 for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
117 Instruction *Inst = DI++;
Eli Friedman85401012011-10-06 23:20:49 +0000118 if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
Eli Friedman8a552bb2011-07-27 01:08:30 +0000119 Changed |= LowerFenceInst(FI);
Eli Friedman55ba8162011-07-29 03:05:32 +0000120 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);
Eli Friedman21006d42011-08-09 23:02:53 +0000124 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 }
Eli Friedman8a552bb2011-07-27 01:08:30 +0000131 }
Chris Lattnerbdabacd2010-09-05 20:10:47 +0000132 return Changed;
Peter Collingbourne3bababf2010-08-03 16:19:16 +0000133 }
Chris Lattnerbdabacd2010-09-05 20:10:47 +0000134 };
Peter Collingbourne3bababf2010-08-03 16:19:16 +0000135}
136
137char LowerAtomic::ID = 0;
Owen Anderson02dd53e2010-08-23 17:52:01 +0000138INITIALIZE_PASS(LowerAtomic, "loweratomic",
139 "Lower atomic intrinsics to non-atomic form",
Owen Andersonce665bd2010-10-07 22:25:06 +0000140 false, false)
Peter Collingbourne3bababf2010-08-03 16:19:16 +0000141
142Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); }