diff options
author | JF Bastien <jfb@chromium.org> | 2013-08-07 15:50:54 -0700 |
---|---|---|
committer | JF Bastien <jfb@chromium.org> | 2013-08-07 15:50:54 -0700 |
commit | 10c5d2cb2f5611441dae3114e3803526340e4b4b (patch) | |
tree | 4c2738773744746b2d690574e8f7663fc1e6bf10 /lib/Transforms/NaCl/RemoveAsmMemory.cpp | |
parent | 0791551c99b041c83413ff78c29cded7730cf601 (diff) |
Add the new @llvm.nacl.atomic.fence.all intrinsic
This is a follow-up to:
https://codereview.chromium.org/22240002/
And requires the Clang changes from:
https://codereview.chromium.org/22294002/
This new intrinsic represents ``asm("":::"~{memory}")`` as well as ``__sync_synchronize()``, and in IR it corresponds to a sequentially-consistent fence surrounded by ``call void asm sideeffect "", "~{memory}"()``.
R=jvoung@chromium.org
TEST= ninja check-all
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3475
Review URL: https://codereview.chromium.org/22474008
Diffstat (limited to 'lib/Transforms/NaCl/RemoveAsmMemory.cpp')
-rw-r--r-- | lib/Transforms/NaCl/RemoveAsmMemory.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/Transforms/NaCl/RemoveAsmMemory.cpp b/lib/Transforms/NaCl/RemoveAsmMemory.cpp new file mode 100644 index 0000000000..5295fe5ff8 --- /dev/null +++ b/lib/Transforms/NaCl/RemoveAsmMemory.cpp @@ -0,0 +1,84 @@ +//===- RemoveAsmMemory.cpp - Remove ``asm("":::"memory")`` ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass removes all instances of ``asm("":::"memory")``. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/InstVisitor.h" +#include "llvm/Pass.h" +#include <string> + +using namespace llvm; + +namespace { +class RemoveAsmMemory : public FunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + RemoveAsmMemory() : FunctionPass(ID) { + initializeRemoveAsmMemoryPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F); +}; + +class AsmDirectivesVisitor : public InstVisitor<AsmDirectivesVisitor> { +public: + AsmDirectivesVisitor(Function &F) + : F(F), C(F.getParent()->getContext()), ModifiedFunction(false) {} + ~AsmDirectivesVisitor() {} + bool modifiedFunction() const { return ModifiedFunction; } + + /// Only Call Instructions are ever inline assembly directives. + void visitCallInst(CallInst &CI); + +private: + Function &F; + LLVMContext &C; + bool ModifiedFunction; + + AsmDirectivesVisitor() LLVM_DELETED_FUNCTION; + AsmDirectivesVisitor(const AsmDirectivesVisitor &) LLVM_DELETED_FUNCTION; + AsmDirectivesVisitor &operator=( + const AsmDirectivesVisitor &) LLVM_DELETED_FUNCTION; +}; +} + +char RemoveAsmMemory::ID = 0; +INITIALIZE_PASS(RemoveAsmMemory, "remove-asm-memory", + "remove all instances of ``asm(\"\":::\"memory\")``", false, + false) + +bool RemoveAsmMemory::runOnFunction(Function &F) { + AsmDirectivesVisitor AV(F); + AV.visit(F); + return AV.modifiedFunction(); +} + +void AsmDirectivesVisitor::visitCallInst(CallInst &CI) { + if (!CI.isInlineAsm() || + !cast<InlineAsm>(CI.getCalledValue())->isAsmMemory()) + return; + + // In NaCl ``asm("":::"memory")`` always comes in pairs, straddling a + // sequentially consistent fence. Other passes rewrite this fence to + // an equivalent stable NaCl intrinsic, meaning that this assembly can + // be removed. + CI.eraseFromParent(); + ModifiedFunction = true; +} + +namespace llvm { +FunctionPass *createRemoveAsmMemoryPass() { return new RemoveAsmMemory(); } +} |