OLD | NEW |
1 //===- RewriteAtomics.cpp - Stabilize instructions used for concurrency ---===// | 1 //===- RewriteAtomics.cpp - Stabilize instructions used for concurrency ---===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This pass encodes atomics, volatiles and fences using NaCl intrinsics | 10 // This pass encodes atomics, volatiles and fences using NaCl intrinsics |
11 // instead of LLVM's regular IR instructions. | 11 // instead of LLVM's regular IR instructions. |
12 // | 12 // |
13 // All of the above are transformed into one of the | 13 // All of the above are transformed into one of the |
14 // @llvm.nacl.atomic.* intrinsics. | 14 // @llvm.nacl.atomic.* intrinsics. |
15 // | 15 // |
16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
17 | 17 |
18 #include "llvm/ADT/Twine.h" | 18 #include "llvm/ADT/Twine.h" |
19 #include "llvm/IR/DataLayout.h" | 19 #include "llvm/IR/DataLayout.h" |
20 #include "llvm/IR/Function.h" | 20 #include "llvm/IR/Function.h" |
21 #include "llvm/IR/InlineAsm.h" | 21 #include "llvm/IR/InlineAsm.h" |
| 22 #include "llvm/IR/InstVisitor.h" |
22 #include "llvm/IR/Instructions.h" | 23 #include "llvm/IR/Instructions.h" |
23 #include "llvm/IR/Intrinsics.h" | 24 #include "llvm/IR/Intrinsics.h" |
24 #include "llvm/IR/Module.h" | 25 #include "llvm/IR/Module.h" |
25 #include "llvm/IR/NaClAtomicIntrinsics.h" | 26 #include "llvm/IR/NaClAtomicIntrinsics.h" |
26 #include "llvm/IR/InstVisitor.h" | |
27 #include "llvm/Pass.h" | 27 #include "llvm/Pass.h" |
| 28 #include "llvm/Support/CommandLine.h" |
28 #include "llvm/Support/Compiler.h" | 29 #include "llvm/Support/Compiler.h" |
29 #include "llvm/Support/raw_ostream.h" | 30 #include "llvm/Support/raw_ostream.h" |
30 #include "llvm/Transforms/NaCl.h" | 31 #include "llvm/Transforms/NaCl.h" |
31 #include <climits> | 32 #include <climits> |
32 #include <string> | 33 #include <string> |
33 | 34 |
34 using namespace llvm; | 35 using namespace llvm; |
35 | 36 |
| 37 // TODO(jfb) Keep the default of this option to true for Chrome 42, and change |
| 38 // it to false for Chrome 43. This allows the PNaCl translator to be |
| 39 // updated before the SDK starts emitting atomic memory orders that |
| 40 // the old translator rejected. |
| 41 static cl::opt<bool> PNaClMemoryOrderSeqCstOnly( |
| 42 "pnacl-memory-order-seq-cst-only", |
| 43 cl::desc("PNaCl should upgrade all atomic memory orders to seq_cst"), |
| 44 cl::init(true)); |
| 45 |
36 namespace { | 46 namespace { |
| 47 |
37 class RewriteAtomics : public ModulePass { | 48 class RewriteAtomics : public ModulePass { |
38 public: | 49 public: |
39 static char ID; // Pass identification, replacement for typeid | 50 static char ID; // Pass identification, replacement for typeid |
40 RewriteAtomics() : ModulePass(ID) { | 51 RewriteAtomics() : ModulePass(ID) { |
41 // This is a module pass because it may have to introduce | 52 // This is a module pass because it may have to introduce |
42 // intrinsic declarations into the module and modify a global function. | 53 // intrinsic declarations into the module and modify a global function. |
43 initializeRewriteAtomicsPass(*PassRegistry::getPassRegistry()); | 54 initializeRewriteAtomicsPass(*PassRegistry::getPassRegistry()); |
44 } | 55 } |
45 | 56 |
46 virtual bool runOnModule(Module &M); | 57 virtual bool runOnModule(Module &M); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 // TODO Consume is currently unspecified by LLVM's internal IR. | 199 // TODO Consume is currently unspecified by LLVM's internal IR. |
189 case Acquire: AO = NaCl::MemoryOrderAcquire; break; | 200 case Acquire: AO = NaCl::MemoryOrderAcquire; break; |
190 case Release: AO = NaCl::MemoryOrderRelease; break; | 201 case Release: AO = NaCl::MemoryOrderRelease; break; |
191 case AcquireRelease: AO = NaCl::MemoryOrderAcquireRelease; break; | 202 case AcquireRelease: AO = NaCl::MemoryOrderAcquireRelease; break; |
192 case SequentiallyConsistent: | 203 case SequentiallyConsistent: |
193 AO = NaCl::MemoryOrderSequentiallyConsistent; break; | 204 AO = NaCl::MemoryOrderSequentiallyConsistent; break; |
194 } | 205 } |
195 } | 206 } |
196 | 207 |
197 // TODO For now only acquire/release/acq_rel/seq_cst are allowed. | 208 // TODO For now only acquire/release/acq_rel/seq_cst are allowed. |
198 if (AO == NaCl::MemoryOrderRelaxed) | 209 if (PNaClMemoryOrderSeqCstOnly || AO == NaCl::MemoryOrderRelaxed) |
199 AO = NaCl::MemoryOrderSequentiallyConsistent; | 210 AO = NaCl::MemoryOrderSequentiallyConsistent; |
200 | 211 |
201 return ConstantInt::get(Type::getInt32Ty(C), AO); | 212 return ConstantInt::get(Type::getInt32Ty(C), AO); |
202 } | 213 } |
203 | 214 |
204 std::pair<ConstantInt *, ConstantInt *> | 215 std::pair<ConstantInt *, ConstantInt *> |
205 AtomicVisitor::freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S, | 216 AtomicVisitor::freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S, |
206 AtomicOrdering F) const { | 217 AtomicOrdering F) const { |
207 if (S == Release || (S == AcquireRelease && F != Acquire)) | 218 if (S == Release || (S == AcquireRelease && F != Acquire)) |
208 // According to C++11's [atomics.types.operations.req], cmpxchg with release | 219 // According to C++11's [atomics.types.operations.req], cmpxchg with release |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 ArrayRef<Value *>()); | 427 ArrayRef<Value *>()); |
417 } else { | 428 } else { |
418 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = | 429 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = |
419 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T); | 430 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T); |
420 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())}; | 431 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())}; |
421 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args); | 432 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args); |
422 } | 433 } |
423 } | 434 } |
424 | 435 |
425 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); } | 436 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); } |
OLD | NEW |