Chromium Code Reviews| Index: lib/Transforms/NaCl/RewriteAtomics.cpp |
| diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp |
| index 652635ab0a2c85028e055476f90f6fa231af639a..858a4d7ca861d1ee0bbe3d0918cd9c18cf752d12 100644 |
| --- a/lib/Transforms/NaCl/RewriteAtomics.cpp |
| +++ b/lib/Transforms/NaCl/RewriteAtomics.cpp |
| @@ -15,6 +15,7 @@ |
| // |
| //===----------------------------------------------------------------------===// |
| +#include "llvm/ADT/Triple.h" |
| #include "llvm/ADT/Twine.h" |
| #include "llvm/IR/DataLayout.h" |
| #include "llvm/IR/Function.h" |
| @@ -28,6 +29,7 @@ |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/raw_ostream.h" |
| +#include "llvm/Support/TargetRegistry.h" |
| #include "llvm/Transforms/NaCl.h" |
| #include <climits> |
| #include <string> |
| @@ -75,6 +77,8 @@ public: |
| void visitAtomicRMWInst(AtomicRMWInst &I); |
| void visitFenceInst(FenceInst &I); |
| + SmallVectorImpl<Function*>& getFunsWithExtraRMWOps() { return FunsWithExtraRMWOps; } |
| + |
| private: |
| Module &M; |
| LLVMContext &C; |
| @@ -82,6 +86,13 @@ private: |
| NaCl::AtomicIntrinsics AI; |
| bool ModifiedModule; |
| + /// These functions have atomic instructions which we expand with |
| + /// -atomic-expand. We collect them here so we don't have to check every |
| + /// instruction of every basicblock of every function in the module twice over |
| + /// the coarse of the pass (under the assumption that atomic operations are |
| + /// the expection rather than the rule). |
|
JF
2015/07/23 22:44:38
"exception"
|
| + SmallVector<Function*, 32> FunsWithExtraRMWOps; |
| + |
| AtomicVisitor() = delete; |
| AtomicVisitor(const AtomicVisitor &) = delete; |
| AtomicVisitor &operator=(const AtomicVisitor &) = delete; |
| @@ -162,9 +173,53 @@ INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics", |
| false, false) |
| bool RewriteAtomics::runOnModule(Module &M) { |
| + // rewrite nand, (u)max, (u)min rmw atomics: |
| + // First we need a target machine to appease its lordship: |
| + |
| + // Get the target specific parser. |
| + std::string Error; |
| + Triple TheTriple = Triple("i686-none-nacl"); |
| + const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, |
| + Error); |
| + if (!TheTarget) { |
| + errs() << "Looking up 'i686-none-nacl':" << ": " << Error; |
| + report_fatal_error("Did you forget to initialize the x86 target?"); |
| + } |
| + |
| + // Create the target machine: |
| + std::unique_ptr<TargetMachine> Target( |
| + TheTarget->createTargetMachine(TheTriple.getTriple(), "generic", "", |
| + TargetOptions(), Reloc::Default, |
| + CodeModel::Default, CodeGenOpt::Default)); |
| + assert(Target != nullptr); |
| + |
| + std::unique_ptr<FunctionPass> AtomicRMWExpander |
| + (createAtomicExpandPass(Target.get())); |
| + |
| + |
| AtomicVisitor AV(M, *this); |
| AV.visit(M); |
| - return AV.modifiedModule(); |
| + |
| + bool Changed = AV.modifiedModule(); |
| + |
| + // Expand any leftover RMW atomics: |
| + // This is done after because otherwise -atomic-expand will expand stuff we're |
| + // capable of expanding, leaving us with less efficient code. |
| + const size_t PrevLen = AV.getFunsWithExtraRMWOps().size(); |
| + for(auto *F : AV.getFunsWithExtraRMWOps()) { |
| + const bool Expanded = AtomicRMWExpander->runOnFunction(*F); |
| + (void)Expanded; |
| + assert(Expanded); |
| + // revisit the function, rewriting cmpxchg to the corresponding |
| + // llvm.nacl.etc.etc. |
| + AV.visit(*F); |
| + Changed = true; |
| + } |
| + // assert that -atomic-expand didn't leave things we can't expand. |
| + (void)PrevLen; |
| + assert(PrevLen == AV.getFunsWithExtraRMWOps().size()); |
| + |
| + return Changed; |
| } |
| template <class Instruction> |
| @@ -347,7 +402,11 @@ void AtomicVisitor::visitStoreInst(StoreInst &I) { |
| void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) { |
| NaCl::AtomicRMWOperation Op; |
| switch (I.getOperation()) { |
| - default: report_fatal_error("unsupported atomicrmw operation: " + ToStr(I)); |
| + default: { |
| + // delegate to -atomic-expand |
| + FunsWithExtraRMWOps.push_back(I.getParent()->getParent()); |
| + return; |
| + } |
| case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break; |
| case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break; |
| case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break; |