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

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, 4 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
« no previous file with comments | « lib/Transforms/NaCl/LLVMBuild.txt ('k') | test/Transforms/NaCl/atomic/extra-rmw-operations.ll » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/Transforms/NaCl/RewriteAtomics.cpp
diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp
index 652635ab0a2c85028e055476f90f6fa231af639a..7f8c83bc724ff8c7e1836949f981973d9eb2189b 100644
--- a/lib/Transforms/NaCl/RewriteAtomics.cpp
+++ b/lib/Transforms/NaCl/RewriteAtomics.cpp
@@ -15,7 +15,11 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/NaCl/PNaClSimplificationAnalyses.h"
+#include "llvm/CodeGen/AtomicExpandUtils.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
@@ -28,6 +32,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 +46,15 @@ static cl::opt<bool> PNaClMemoryOrderSeqCstOnly(
namespace {
-class RewriteAtomics : public ModulePass {
+class RewriteAtomicsPass {
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"; }
- virtual bool runOnModule(Module &M);
+ RewriteAtomicsPass() { }
+ RewriteAtomicsPass(RewriteAtomicsPass &&Rhs) { }
+ RewriteAtomicsPass &operator=(RewriteAtomicsPass &&Rhs) { return *this; }
+
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
};
template <class T> std::string ToStr(const T &V) {
@@ -62,12 +66,10 @@ 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; }
void visitLoadInst(LoadInst &I);
void visitStoreInst(StoreInst &I);
@@ -80,7 +82,7 @@ private:
LLVMContext &C;
const DataLayout TD;
NaCl::AtomicIntrinsics AI;
- bool ModifiedModule;
+ bool Modified = false;
AtomicVisitor() = delete;
AtomicVisitor(const AtomicVisitor &) = delete;
@@ -93,13 +95,13 @@ private:
template <class Instruction>
ConstantInt *freezeMemoryOrder(const Instruction &I, AtomicOrdering O) const;
std::pair<ConstantInt *, ConstantInt *>
- freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S,
+ freezeMemoryOrder(const Instruction &I, AtomicOrdering S,
AtomicOrdering F) const;
/// Sanity-check that instruction \p I which has pointer and value
/// parameters have matching sizes \p BitSize for the type-pointed-to
/// and the value's type \p T.
- void checkSizeMatchesType(const Instruction &I, unsigned BitSize,
+ void checkSizeMatchesType(const Value &I, unsigned BitSize,
const Type *T) const;
/// Verify that loads and stores are at least naturally aligned. Use
@@ -132,7 +134,8 @@ private:
Type *OriginalPET;
Type *PET;
unsigned BitSize;
- PointerHelper(const AtomicVisitor &AV, Instruction &I)
+ PointerHelper(const AtomicVisitor &AV, Instruction &I,
+ IRBuilder<> *Builder = nullptr)
: P(I.getPointerOperand()) {
if (I.getPointerAddressSpace() != 0)
report_fatal_error("unhandled pointer address space " +
@@ -146,7 +149,11 @@ private:
// terms of integers, so bitcast the pointer to an integer of
// the proper width.
Type *IntNPtr = Type::getIntNPtrTy(AV.C, BitSize);
- P = AV.createCast(I, P, IntNPtr, P->getName() + ".cast");
+ if(!Builder) {
+ P = AV.createCast(I, P, IntNPtr, P->getName() + ".cast");
+ } else {
+ P = Builder->CreateBitOrPointerCast(P, IntNPtr, P->getName() + ".cast");
+ }
PET = P->getType()->getPointerElementType();
}
AV.checkSizeMatchesType(I, BitSize, PET);
@@ -155,16 +162,53 @@ 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, 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;
+ }
+
+ return Changed;
+}
+
+PreservedAnalyses RewriteAtomicsPass::run(Function &F,
+ AnalysisManager<Function> *AM) {
+ auto &Info = AM->getResult<AtomicAnalysis>(F);
+
+ if (ExpandAtomicInstructions(F, Info)) {
+ return PreservedAnalyses::none();
+ } else {
+ return PreservedAnalyses::all();
+ }
}
template <class Instruction>
@@ -184,17 +228,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;
}
}
@@ -206,7 +262,7 @@ ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I,
}
std::pair<ConstantInt *, ConstantInt *>
-AtomicVisitor::freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S,
+AtomicVisitor::freezeMemoryOrder(const Instruction &I, AtomicOrdering S,
AtomicOrdering F) const {
if (S == Release || (S == AcquireRelease && F != Acquire))
// According to C++11's [atomics.types.operations.req], cmpxchg with release
@@ -220,7 +276,7 @@ AtomicVisitor::freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S,
return std::make_pair(freezeMemoryOrder(I, S), freezeMemoryOrder(I, F));
}
-void AtomicVisitor::checkSizeMatchesType(const Instruction &I, unsigned BitSize,
+void AtomicVisitor::checkSizeMatchesType(const Value &I, unsigned BitSize,
const Type *T) const {
Type *IntType = Type::getIntNTy(C, BitSize);
if (IntType && T == IntType)
@@ -297,7 +353,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 +403,52 @@ 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: {
+ auto Factory = [this, &I] (IRBuilder<> &Builder, Value *Addr,
+ Value *Loaded, Value *NewVal,
+ AtomicOrdering MemOpOrder,
+ Value *&Success, Value *&NewLoaded) {
+ PointerHelper<AtomicRMWInst> PH(*this, I, &Builder);
+
+ const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
+ findAtomicIntrinsic(I, Intrinsic::nacl_atomic_cmpxchg, PH.PET);
+
+ auto Order = freezeMemoryOrder(I, MemOpOrder, MemOpOrder);
+ Value *Args[] = {PH.P, Loaded, NewVal,
+ Order.first, Order.second};
+
+ Function *F = Intrinsic->getDeclaration(&this->M);
+
+ Value* UnCastedValue = Builder.CreateCall(F, Args, "");
+ if(PH.P->getType() != Addr->getType()) {
+ NewLoaded = Builder.CreateBitOrPointerCast(UnCastedValue, Addr->getType(),
+ "cast." + Addr->getName());
+ } else {
+ NewLoaded = UnCastedValue;
+ }
+ Success = Builder.CreateICmp(CmpInst::ICMP_EQ, NewLoaded, Loaded, "success");
+ };
+ Modified = expandAtomicRMWToCmpXchg(&I, Factory) || Modified;
+ 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 +521,32 @@ 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());
+ }
+
+ bool runOnFunction(Function &F) override {
+ auto &Info = getAnalysis<AtomicAnalysisWrapperPass>().getInfo();
+ return ExpandAtomicInstructions(F, 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(); }
« no previous file with comments | « lib/Transforms/NaCl/LLVMBuild.txt ('k') | test/Transforms/NaCl/atomic/extra-rmw-operations.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698