Index: lib/Transforms/NaCl/RewriteAtomics.cpp |
diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp |
index 652635ab0a2c85028e055476f90f6fa231af639a..88adb97957e3d64fa67f7be464acdd637e3e2b5c 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> |
@@ -162,9 +164,47 @@ 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())); |
JF
2015/07/10 18:07:32
Could the pass instead go in lib/Transforms/NaCl/P
Richard Diamond
2015/07/10 21:08:17
No, because -atomic-expand will expand stuff that
|
+ |
+ |
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. |
+ for(auto &F : M.functions()) { |
+ if (AtomicRMWExpander->runOnFunction(F)) { |
+ // revisit the function, rewriting cmpxchg to the corresponding |
+ // llvm.nacl.etc.etc. |
+ AV.visit(F); |
+ Changed = true; |
+ } |
+ } |
+ return Changed; |
} |
template <class Instruction> |
@@ -347,7 +387,7 @@ 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: return; // -atomic-expand will handle it. |
case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break; |
case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break; |
case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break; |