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

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

Issue 17777004: Concurrency support for PNaCl ABI (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Created 7 years, 6 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/ResolvePNaClIntrinsics.cpp
diff --git a/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp b/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp
index e4efeb67c3c3c24c5ca1103f960338dea0c134f6..39126f0fbe5c6b9c27dfc5b2b470cc86bb7704c0 100644
--- a/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp
+++ b/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp
@@ -17,10 +17,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Constant.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/NaCl.h"
+#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/NaCl.h"
using namespace llvm;
@@ -37,14 +41,16 @@ namespace {
private:
// Some intrinsic calls are resolved simply by replacing the call with a
// call to an alternative function with exactly the same type.
- bool resolveSimpleCall(Function &F, Intrinsic::ID IntrinsicID,
- const char *TargetFunctionName);
+ bool resolveSimpleCall(Function &F, Intrinsic::ID IntrinsicID);
+ // All atomic calls are rewritten to a single instruction, and the
+ // call is removed.
+ void rewriteAtomicCall(Module *M, Function &F, Intrinsic::ID IntrinsicID,
+ CallInst *Call);
};
}
bool ResolvePNaClIntrinsics::resolveSimpleCall(Function &F,
- Intrinsic::ID IntrinsicID,
- const char *TargetFunctionName) {
+ Intrinsic::ID IntrinsicID) {
Module *M = F.getParent();
bool Changed = false;
Function *IntrinsicFunction = Intrinsic::getDeclaration(M, IntrinsicID);
@@ -53,12 +59,18 @@ bool ResolvePNaClIntrinsics::resolveSimpleCall(Function &F,
return false;
}
- // Expect to find the target function for this intrinsic already declared
- Function *TargetFunction = M->getFunction(TargetFunctionName);
- if (!TargetFunction) {
- report_fatal_error(
- std::string("Expected to find external declaration of ") +
- TargetFunctionName);
+ Function *TargetFunction = NULL;
+ if (IntrinsicID == Intrinsic::nacl_setjmp ||
eliben 2013/06/26 16:20:57 No no no no no :-) resolveSimpleCall's comment is
JF 2013/06/26 22:23:12 Done: rewrote to use one class per type of rewrite
+ IntrinsicID == Intrinsic::nacl_longjmp) {
+ // Expect to find the target function for this intrinsic already declared.
+ const char *TargetFunctionName = IntrinsicID == Intrinsic::nacl_setjmp
+ ? "setjmp" : "longjmp";
+ TargetFunction = M->getFunction(TargetFunctionName);
+ if (!TargetFunction) {
+ report_fatal_error(
+ std::string("Expected to find external declaration of ") +
+ TargetFunctionName);
+ }
}
for (Value::use_iterator UI = IntrinsicFunction->use_begin(),
@@ -77,7 +89,11 @@ bool ResolvePNaClIntrinsics::resolveSimpleCall(Function &F,
// functions. These will be handled when the pass manager gets to those
// functions.
if (Call->getParent()->getParent() == &F) {
- Call->setCalledFunction(TargetFunction);
+ if (IntrinsicID == Intrinsic::nacl_setjmp ||
+ IntrinsicID == Intrinsic::nacl_longjmp)
+ Call->setCalledFunction(TargetFunction);
+ else
+ rewriteAtomicCall(M, F, IntrinsicID, Call);
Changed = true;
}
}
@@ -85,9 +101,97 @@ bool ResolvePNaClIntrinsics::resolveSimpleCall(Function &F,
return Changed;
}
+void ResolvePNaClIntrinsics::rewriteAtomicCall(Module *M, Function &F,
+ Intrinsic::ID IntrinsicID,
+ CallInst *Call) {
+ // Assume the @nacl.atomic.<size> intrinsics follow the PNaCl
+ // ABI: this should have been checked by the verifier.
+ uint64_t Op(cast<Constant>(
+ Call->getArgOperand(0))->getUniqueInteger().getLimitedValue());
+ Value *Ptr(Call->getArgOperand(1));
Mark Seaborn 2013/06/26 14:33:41 Just write "Ptr = Call->getArgOperand(1)"? Using
JF 2013/06/26 15:52:29 Done.
+ Value *Val(Call->getArgOperand(2));
+ Value *Old(Call->getArgOperand(3));
+ uint64_t MemoryOrder(cast<Constant>(
+ Call->getArgOperand(4))->getUniqueInteger().getLimitedValue());
+
+ AtomicRMWInst::BinOp RMWOp;
+ switch (Op) {
+ default: RMWOp = AtomicRMWInst::BAD_BINOP; break;
+ case NaCl::AtomicAdd: RMWOp = AtomicRMWInst::Add; break;
+ case NaCl::AtomicSub: RMWOp = AtomicRMWInst::Sub; break;
+ case NaCl::AtomicOr: RMWOp = AtomicRMWInst::Or; break;
+ case NaCl::AtomicAnd: RMWOp = AtomicRMWInst::And; break;
+ case NaCl::AtomicXor: RMWOp = AtomicRMWInst::Xor; break;
+ case NaCl::AtomicXchg: RMWOp = AtomicRMWInst::Xchg; break;
+ }
+ AtomicOrdering Order;
+ switch (MemoryOrder) {
+ default:
+ // Conservatively use the strongest ordering.
+ Order = SequentiallyConsistent; break;
+ case NaCl::MemoryOrderRelaxed: Order = Unordered; break;
+ case NaCl::MemoryOrderConsume:
+ // TODO Unspecified by LLVM's internal IR.
+ Order = SequentiallyConsistent; break;
+ case NaCl::MemoryOrderAcquire: Order = Acquire; break;
+ case NaCl::MemoryOrderRelease: Order = Release; break;
+ case NaCl::MemoryOrderAcquireRelease: Order = AcquireRelease; break;
+ case NaCl::MemoryOrderSequentiallyConsistent:
+ Order = SequentiallyConsistent; break;
+ }
+ const Twine Name("");
+ bool isVolatile = false;
+ SynchronizationScope SS = CrossThread;
+ bool hasUses;
+ Instruction *I;
+
+ for (size_t II = 0; II != NaCl::NumAtomicIntrinsics; ++II) {
+ if (IntrinsicID != NaCl::AtomicIntrinsics[II].ID)
+ continue;
+
+ unsigned BitSize = NaCl::AtomicIntrinsics[II].BitSize;
+ unsigned Align = 1 << (CountTrailingZeros_32(BitSize) - 3);
+ switch (Op) {
+ default: llvm_unreachable("invalid atomic operation");
+ case NaCl::AtomicLoad:
+ hasUses = true;
+ I = new LoadInst(Ptr, Name, isVolatile, Align, Order, SS, Call);
+ break;
+ case NaCl::AtomicStore:
+ hasUses = false;
+ I = new StoreInst(Val, Ptr, isVolatile, Align, Order, SS, Call);
+ break;
+ case NaCl::AtomicAdd:
+ case NaCl::AtomicSub:
+ case NaCl::AtomicOr:
+ case NaCl::AtomicAnd:
+ case NaCl::AtomicXor:
+ case NaCl::AtomicXchg:
+ hasUses = true;
+ I = new AtomicRMWInst(RMWOp, Ptr, Val, Order, SS, Call);
+ break;
+ case NaCl::AtomicCmpXchg:
+ hasUses = true;
+ I = new AtomicCmpXchgInst(Ptr, Old, Val, Order, SS, Call);
+ break;
+ case NaCl::AtomicFence:
+ hasUses = false;
+ I = new FenceInst(M->getContext(), Order, SS, Call);
+ break;
+ }
+ I->setDebugLoc(Call->getDebugLoc());
+ if (hasUses)
Mark Seaborn 2013/06/26 14:33:41 I think you can do the RAUW unconditionally
JF 2013/06/26 15:52:29 No: assert(New->getType() == getType() &&
+ Call->replaceAllUsesWith(I);
+ Call->eraseFromParent();
+ }
+}
+
bool ResolvePNaClIntrinsics::runOnFunction(Function &F) {
- bool Changed = resolveSimpleCall(F, Intrinsic::nacl_setjmp, "setjmp");
- Changed |= resolveSimpleCall(F, Intrinsic::nacl_longjmp, "longjmp");
+ bool Changed = resolveSimpleCall(F, Intrinsic::nacl_setjmp);
+ Changed |= resolveSimpleCall(F, Intrinsic::nacl_longjmp);
+ for (size_t II = 0; II != NaCl::NumAtomicIntrinsics; ++II) {
+ Changed |= resolveSimpleCall(F, NaCl::AtomicIntrinsics[II].ID);
+ }
return Changed;
}

Powered by Google App Engine
This is Rietveld 408576698