| Index: lib/Transforms/NaCl/RewriteAtomics.cpp
 | 
| diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp
 | 
| index 26c834a87432b61e152b135c035ba3422c71a4f9..e22e9fdac95c2612ce4ee8a60ce65567fe2c17f3 100644
 | 
| --- a/lib/Transforms/NaCl/RewriteAtomics.cpp
 | 
| +++ b/lib/Transforms/NaCl/RewriteAtomics.cpp
 | 
| @@ -18,6 +18,7 @@
 | 
|  #include "llvm/ADT/Twine.h"
 | 
|  #include "llvm/IR/DataLayout.h"
 | 
|  #include "llvm/IR/Function.h"
 | 
| +#include "llvm/IR/InlineAsm.h"
 | 
|  #include "llvm/IR/Instructions.h"
 | 
|  #include "llvm/IR/Intrinsics.h"
 | 
|  #include "llvm/IR/Module.h"
 | 
| @@ -241,9 +242,9 @@ void AtomicVisitor::replaceInstructionWithIntrinsicCall(
 | 
|    ModifiedModule = true;
 | 
|  }
 | 
|  
 | 
| -/// %res = load {atomic|volatile} T* %ptr memory_order, align sizeof(T)
 | 
| +///   %res = load {atomic|volatile} T* %ptr memory_order, align sizeof(T)
 | 
|  /// becomes:
 | 
| -/// %res = call T @llvm.nacl.atomic.load.i<size>(%ptr, memory_order)
 | 
| +///   %res = call T @llvm.nacl.atomic.load.i<size>(%ptr, memory_order)
 | 
|  void AtomicVisitor::visitLoadInst(LoadInst &I) {
 | 
|    if (I.isSimple())
 | 
|      return;
 | 
| @@ -254,9 +255,9 @@ void AtomicVisitor::visitLoadInst(LoadInst &I) {
 | 
|                                        PH.OriginalPET, PH.PET, Args);
 | 
|  }
 | 
|  
 | 
| -/// store {atomic|volatile} T %val, T* %ptr memory_order, align sizeof(T)
 | 
| +///   store {atomic|volatile} T %val, T* %ptr memory_order, align sizeof(T)
 | 
|  /// becomes:
 | 
| -/// call void @llvm.nacl.atomic.store.i<size>(%val, %ptr, memory_order)
 | 
| +///   call void @llvm.nacl.atomic.store.i<size>(%val, %ptr, memory_order)
 | 
|  void AtomicVisitor::visitStoreInst(StoreInst &I) {
 | 
|    if (I.isSimple())
 | 
|      return;
 | 
| @@ -278,9 +279,9 @@ void AtomicVisitor::visitStoreInst(StoreInst &I) {
 | 
|                                        PH.OriginalPET, PH.PET, Args);
 | 
|  }
 | 
|  
 | 
| -/// %res = atomicrmw OP T* %ptr, T %val memory_order
 | 
| +///   %res = atomicrmw OP T* %ptr, T %val memory_order
 | 
|  /// becomes:
 | 
| -/// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order)
 | 
| +///   %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order)
 | 
|  void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
 | 
|    NaCl::AtomicRMWOperation Op;
 | 
|    switch (I.getOperation()) {
 | 
| @@ -300,11 +301,11 @@ void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
 | 
|                                        PH.OriginalPET, PH.PET, Args);
 | 
|  }
 | 
|  
 | 
| -/// %res = cmpxchg T* %ptr, T %old, T %new memory_order
 | 
| +///   %res = cmpxchg T* %ptr, T %old, T %new memory_order
 | 
|  /// becomes:
 | 
| -/// %res = call T @llvm.nacl.atomic.cmpxchg.i<size>(
 | 
| -///     %object, %expected, %desired, memory_order_success,
 | 
| -///     memory_order_failure)
 | 
| +///   %res = call T @llvm.nacl.atomic.cmpxchg.i<size>(
 | 
| +///       %object, %expected, %desired, memory_order_success,
 | 
| +///       memory_order_failure)
 | 
|  void AtomicVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
 | 
|    PointerHelper<AtomicCmpXchgInst> PH(*this, I);
 | 
|    checkSizeMatchesType(I, PH.BitSize, I.getCompareOperand()->getType());
 | 
| @@ -319,14 +320,38 @@ void AtomicVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
 | 
|                                        PH.OriginalPET, PH.PET, Args);
 | 
|  }
 | 
|  
 | 
| -/// fence memory_order
 | 
| +///   fence memory_order
 | 
|  /// becomes:
 | 
| -/// call void @llvm.nacl.atomic.fence(memory_order)
 | 
| +///   call void @llvm.nacl.atomic.fence(memory_order)
 | 
| +/// and
 | 
| +///   call void asm sideeffect "", "~{memory}"()
 | 
| +///   fence seq_cst
 | 
| +///   call void asm sideeffect "", "~{memory}"()
 | 
| +/// becomes:
 | 
| +///   call void asm sideeffect "", "~{memory}"()
 | 
| +///   call void @llvm.nacl.atomic.fence.all()
 | 
| +///   call void asm sideeffect "", "~{memory}"()
 | 
| +/// Note that the assembly gets eliminated by the -remove-asm-memory pass.
 | 
|  void AtomicVisitor::visitFenceInst(FenceInst &I) {
 | 
|    Type *T = Type::getInt32Ty(C); // Fences aren't overloaded on type.
 | 
| -  Value *Args[] = { freezeMemoryOrder(I) };
 | 
| -  replaceInstructionWithIntrinsicCall(I, Intrinsic::nacl_atomic_fence, T, T,
 | 
| -                                      Args);
 | 
| +  BasicBlock::InstListType &IL(I.getParent()->getInstList());
 | 
| +  bool isFirst = IL.empty() || &*I.getParent()->getInstList().begin() == &I;
 | 
| +  bool isLast = IL.empty() || &*I.getParent()->getInstList().rbegin() == &I;
 | 
| +  CallInst *PrevC = isFirst ? 0 : dyn_cast<CallInst>(I.getPrevNode());
 | 
| +  CallInst *NextC = isLast ? 0 : dyn_cast<CallInst>(I.getNextNode());
 | 
| +
 | 
| +  if ((PrevC && PrevC->isInlineAsm() &&
 | 
| +       cast<InlineAsm>(PrevC->getCalledValue())->isAsmMemory()) &&
 | 
| +      (NextC && NextC->isInlineAsm() &&
 | 
| +       cast<InlineAsm>(NextC->getCalledValue())->isAsmMemory()) &&
 | 
| +      I.getOrdering() == SequentiallyConsistent) {
 | 
| +    replaceInstructionWithIntrinsicCall(I, Intrinsic::nacl_atomic_fence_all, T,
 | 
| +                                        T, ArrayRef<Value *>());
 | 
| +  } else {
 | 
| +    Value *Args[] = { freezeMemoryOrder(I) };
 | 
| +    replaceInstructionWithIntrinsicCall(I, Intrinsic::nacl_atomic_fence, T, T,
 | 
| +                                        Args);
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); }
 | 
| 
 |