| 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 |