Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Unified Diff: lib/Transforms/NaCl/RewriteAtomics.cpp

Issue 927493002: PNaCl: Impl the other atomicrmw operations: nand, max, min, umax, and umin. Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/Transforms/NaCl/RewriteAtomics.cpp
diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp
index 652635ab0a2c85028e055476f90f6fa231af639a..c4892aa91592fd8f20fd955cb5862d067b88f133 100644
--- a/lib/Transforms/NaCl/RewriteAtomics.cpp
+++ b/lib/Transforms/NaCl/RewriteAtomics.cpp
@@ -15,7 +15,9 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/NaCl/PNaClSimplificationAnalyses.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
@@ -28,6 +30,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>
@@ -41,16 +44,67 @@ static cl::opt<bool> PNaClMemoryOrderSeqCstOnly(
namespace {
-class RewriteAtomics : public ModulePass {
+struct Initer {
+ Initer() {}
+ Initer(Initer &&Rhs)
+ : Initialized(Rhs.Initialized), Target(std::move(Rhs.Target)),
+ AtomicRMWExpander(std::move(Rhs.AtomicRMWExpander)) {}
+ Initer &operator=(Initer &&Rhs) {
+ Initialized = Rhs.Initialized;
+ Target = std::move(Rhs.Target);
+ AtomicRMWExpander = std::move(Rhs.AtomicRMWExpander);
+ return *this;
+ }
+
+ bool Initialized = false;
+ std::unique_ptr<TargetMachine> Target = nullptr;
+ std::unique_ptr<FunctionPass> AtomicRMWExpander = nullptr;
+
+ bool initialize() {
+ if (!Initialized) {
+ // For rewritting nand, (u)max, (u)min rmw atomics:
Richard Diamond 2015/07/30 11:47:08 Note to (re)views: once http://reviews.llvm.org/D1
Richard Diamond 2015/07/30 11:48:08 reviewers*
+ // 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 llvm::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:
+ Target.reset(TheTarget->createTargetMachine(
+ TheTriple.getTriple(), "generic", "", TargetOptions(), Reloc::Default,
+ CodeModel::Default, CodeGenOpt::Default));
+ assert(Target != nullptr);
+ AtomicRMWExpander.reset(createAtomicExpandPass(Target.get()));
JF 2015/07/27 19:49:28 Now that you have an analysis pass, can you move t
+
+ Initialized = true;
+ return true;
+ } else {
+ return false;
+ }
+ }
+};
+
+class RewriteAtomicsPass {
+ Initer Init;
+
public:
- static char ID; // Pass identification, replacement for typeid
- RewriteAtomics() : ModulePass(ID) {
- // This is a module pass because it may have to introduce
- // intrinsic declarations into the module and modify a global function.
- initializeRewriteAtomicsPass(*PassRegistry::getPassRegistry());
+ static StringRef name() { return "RewriteAtomicsPass"; }
+
+ RewriteAtomicsPass() { Init.initialize(); }
+ RewriteAtomicsPass(RewriteAtomicsPass &&Rhs) : Init(std::move(Rhs.Init)) {}
+ RewriteAtomicsPass &operator=(RewriteAtomicsPass &&Rhs) {
+ Init = std::move(Rhs.Init);
+ return *this;
}
- virtual bool runOnModule(Module &M);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
};
template <class T> std::string ToStr(const T &V) {
@@ -62,12 +116,11 @@ template <class T> std::string ToStr(const T &V) {
class AtomicVisitor : public InstVisitor<AtomicVisitor> {
public:
- AtomicVisitor(Module &M, Pass &P)
- : M(M), C(M.getContext()),
- TD(M.getDataLayout()), AI(C),
- ModifiedModule(false) {}
+ AtomicVisitor(Module &M)
+ : M(M), C(M.getContext()), TD(M.getDataLayout()), AI(C) {}
~AtomicVisitor() {}
- bool modifiedModule() const { return ModifiedModule; }
+ bool modifiedFunction() const { return Modified; }
+ bool needsAtomicExpand() const { return NeedsAtomicExpand; }
void visitLoadInst(LoadInst &I);
void visitStoreInst(StoreInst &I);
@@ -80,7 +133,8 @@ private:
LLVMContext &C;
const DataLayout TD;
NaCl::AtomicIntrinsics AI;
- bool ModifiedModule;
+ bool Modified = false;
+ bool NeedsAtomicExpand = false;
AtomicVisitor() = delete;
AtomicVisitor(const AtomicVisitor &) = delete;
@@ -155,16 +209,67 @@ private:
};
}
-char RewriteAtomics::ID = 0;
-INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics",
- "rewrite atomics, volatiles and fences into stable "
- "@llvm.nacl.atomics.* intrinsics",
- false, false)
-
-bool RewriteAtomics::runOnModule(Module &M) {
- AtomicVisitor AV(M, *this);
- AV.visit(M);
- return AV.modifiedModule();
+static bool
+ExpandAtomicInstructions(Function &F,
+ std::unique_ptr<FunctionPass> &AtomicRMWExpander,
+ AtomicInfo &Info) {
+ bool Changed = false;
+ AtomicVisitor AV(*F.getParent());
+
+ auto &CmpXchgs = Info.getCmpXchgs();
+ for (auto *CmpXchg : CmpXchgs) {
+ AV.visitAtomicCmpXchgInst(*CmpXchg);
+ Changed = true;
+ }
+
+ auto &Loads = Info.getLoads();
+ for (auto *Load : Loads) {
+ AV.visitLoadInst(*Load);
+ Changed = true;
+ }
+
+ auto &Stores = Info.getStores();
+ for (auto *Store : Stores) {
+ AV.visitStoreInst(*Store);
+ Changed = true;
+ }
+
+ auto &RMWs = Info.getRMWs();
+ for (auto *RMW : RMWs) {
+ AV.visitAtomicRMWInst(*RMW);
+ Changed = true;
+ }
+
+ auto &Fences = Info.getFences();
+ for (auto *Fence : Fences) {
+ AV.visitFenceInst(*Fence);
+ Changed = true;
+ }
+
+ // 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.
+ if (Info.needsAtomicExpand()) {
+ const bool Expanded = AtomicRMWExpander->runOnFunction(F);
JF 2015/07/27 19:49:28 Once the target is present, this can be done autom
+ (void)Expanded;
+ assert(Expanded);
+ // revisit the function, rewriting cmpxchg to the corresponding
+ // llvm.nacl.etc.etc.
+ AV.visit(F);
+ Changed = true;
+ }
+ return Changed;
+}
+
+PreservedAnalyses RewriteAtomicsPass::run(Function &F,
+ AnalysisManager<Function> *AM) {
+ auto &Info = AM->getResult<AtomicAnalysis>(F);
+
+ if (ExpandAtomicInstructions(F, Init.AtomicRMWExpander, Info)) {
+ return PreservedAnalyses::none();
+ } else {
+ return PreservedAnalyses::all();
+ }
}
template <class Instruction>
@@ -184,17 +289,29 @@ ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I,
if (AO == NaCl::MemoryOrderInvalid) {
switch (O) {
- case NotAtomic: llvm_unreachable("unexpected memory order");
+ case NotAtomic:
+ llvm_unreachable("unexpected memory order");
// Monotonic is a strict superset of Unordered. Both can therefore
// map to Relaxed ordering, which is in the C11/C++11 standard.
- case Unordered: AO = NaCl::MemoryOrderRelaxed; break;
- case Monotonic: AO = NaCl::MemoryOrderRelaxed; break;
+ case Unordered:
+ AO = NaCl::MemoryOrderRelaxed;
+ break;
+ case Monotonic:
+ AO = NaCl::MemoryOrderRelaxed;
+ break;
// TODO Consume is currently unspecified by LLVM's internal IR.
- case Acquire: AO = NaCl::MemoryOrderAcquire; break;
- case Release: AO = NaCl::MemoryOrderRelease; break;
- case AcquireRelease: AO = NaCl::MemoryOrderAcquireRelease; break;
+ case Acquire:
+ AO = NaCl::MemoryOrderAcquire;
+ break;
+ case Release:
+ AO = NaCl::MemoryOrderRelease;
+ break;
+ case AcquireRelease:
+ AO = NaCl::MemoryOrderAcquireRelease;
+ break;
case SequentiallyConsistent:
- AO = NaCl::MemoryOrderSequentiallyConsistent; break;
+ AO = NaCl::MemoryOrderSequentiallyConsistent;
+ break;
}
}
@@ -297,7 +414,7 @@ void AtomicVisitor::replaceInstructionWithIntrinsicCall(
I.replaceAllUsesWith(Res);
I.eraseFromParent();
Call->setName(Name);
- ModifiedModule = true;
+ Modified = true;
}
/// %res = load {atomic|volatile} T* %ptr memory_order, align sizeof(T)
@@ -347,13 +464,25 @@ 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));
- case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break;
- case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break;
- case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break;
- case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break;
- case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break;
- case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break;
+ default: { return; }
+ case AtomicRMWInst::Add:
+ Op = NaCl::AtomicAdd;
+ break;
+ case AtomicRMWInst::Sub:
+ Op = NaCl::AtomicSub;
+ break;
+ case AtomicRMWInst::And:
+ Op = NaCl::AtomicAnd;
+ break;
+ case AtomicRMWInst::Or:
+ Op = NaCl::AtomicOr;
+ break;
+ case AtomicRMWInst::Xor:
+ Op = NaCl::AtomicXor;
+ break;
+ case AtomicRMWInst::Xchg:
+ Op = NaCl::AtomicExchange;
+ break;
}
PointerHelper<AtomicRMWInst> PH(*this, I);
const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
@@ -426,4 +555,40 @@ void AtomicVisitor::visitFenceInst(FenceInst &I) {
}
}
-ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); }
+/// Wrapper for the legacy pass manager.
+class RewriteAtomics : public FunctionPass {
+public:
+ static char ID; // Pass identification, replacement for typeid
+ RewriteAtomics() : FunctionPass(ID) {
+ initializeRewriteAtomicsPass(*PassRegistry::getPassRegistry());
+ }
+
+ Initer Init;
+
+ using llvm::Pass::doInitialization;
+ bool doInitialization(Module &M) override {
+ (void)M;
+ return Init.initialize();
+ }
+
+ bool runOnFunction(Function &F) override {
+ auto &Info = getAnalysis<AtomicAnalysisWrapperPass>().getInfo();
+ return ExpandAtomicInstructions(F, Init.AtomicRMWExpander, Info);
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<AtomicAnalysisWrapperPass>();
+ }
+};
+char RewriteAtomics::ID = 0;
+INITIALIZE_PASS_BEGIN(RewriteAtomics, "nacl-rewrite-atomics",
+ "rewrite atomics, volatiles and fences into stable "
+ "@llvm.nacl.atomics.* intrinsics",
+ false, false)
+INITIALIZE_PASS_DEPENDENCY(AtomicAnalysisWrapperPass);
+INITIALIZE_PASS_END(RewriteAtomics, "nacl-rewrite-atomics",
+ "rewrite atomics, volatiles and fences into stable "
+ "@llvm.nacl.atomics.* intrinsics",
+ false, false)
+
+FunctionPass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); }

Powered by Google App Engine
This is Rietveld 408576698